static void __init setup_intr(unsigned int intr, unsigned int cpu, unsigned int pin, unsigned int polarity, unsigned int trigtype) { /* Setup Intr to Pin mapping */ if (pin & GIC_MAP_TO_NMI_MSK) { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); /* FIXME: hack to route NMI to all cpu's */ for (cpu = 0; cpu < NR_CPUS; cpu += 32) { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)), 0xffffffff); } } else { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), GIC_MAP_TO_PIN_MSK | pin); /* Setup Intr to CPU mapping */ GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); } /* Setup Intr Polarity */ GIC_SET_POLARITY(intr, polarity); /* Setup Intr Trigger Type */ GIC_SET_TRIGGER(intr, trigtype); /* Init Intr Masks */ GIC_SET_INTR_MASK(intr, 0); }
int __init ra_systick_clockevent_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq, i __maybe_unused; unsigned long _gic_base __maybe_unused; /* * With vectored interrupts things are getting platform specific. * get_c0_compare_int is a hook to allow a platform to return the * interrupt number of it's liking. */ irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; cd = &ra_systick; cd->features = CLOCK_EVT_FEAT_ONESHOT; cd->name = "Ralink System Tick Counter"; clockevent_set_clock(cd, 50000); cd->max_delta_ns = clockevent_delta2ns(0x7fff, cd); cd->min_delta_ns = clockevent_delta2ns(0x3, cd); #ifdef CONFIG_RALINK_MT7621 /* must be lower than MIPS original cd rating(300) to activate "broadcast mode" */ cd->rating = 250; #else /* must be higher than MIPS original cd rating(300). */ cd->rating = 350; #endif cd->irq = irq; cd->cpumask = cpumask_of(cpu); cd->set_next_event = ra_systick_next_event; cd->set_mode = ra_systick_set_clock_mode; cd->event_handler = ra_systick_event_handler; #ifdef CONFIG_RALINK_MT7621 /* Program MIPS GIC to turn off(mask) each VPE's local timer interrupt. * "_gic_base" is for GIC read/write macro. */ _gic_base = (unsigned long) ioremap_nocache(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ); for (i = 0; i < NR_CPUS /* numvpes */; i++) { GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i); GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), GIC_VPE_SMASK_TIMER_MSK); } #endif /* install timer irq handler before MIPS BSP code. */ if (!cp0_timer_irq_installed){ cp0_timer_irq_installed = 1; setup_irq(irq, &ra_c0_compare_irqaction); } clockevents_register_device(cd); /* Enable ralink system count register */ (*((volatile u32 *)(RALINK_MCNT_CFG))) = 0x3; return 0; }
static void gic_unmask_irq(unsigned int irq) { pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */ GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))), 1 << (irq % 32)); }
void gic_irq_ack(struct irq_data *d) { int irq = (d->irq - gic_irq_base); GIC_CLR_INTR_MASK(irq); if (gic_irq_flags[irq] & GIC_TRIG_EDGE) GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); }
/* This is Malta specific and needs to be exported */ static void __init vpe_local_setup(unsigned int numvpes) { int i; #ifdef CONFIG_RALINK_SOC unsigned long timer_interrupt = GIC_INT_TMR, perf_interrupt = GIC_INT_PERFCTR; #else unsigned long timer_interrupt = 5, perf_interrupt = 5; #endif unsigned int vpe_ctl; #ifdef CONFIG_RALINK_SOC if (cpu_has_veic) { /* GIC timer interrupt -> CPU HW Int X (vector X+2) -> map to pin X+2-1 (since GIC adds 1) */ timer_interrupt += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); /* GIC perfcnt interrupt -> CPU HW Int X (vector X+2) -> map to pin X+2-1 (since GIC adds 1) */ perf_interrupt += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); } #endif /* * Setup the default performance counter timer interrupts * for all VPEs */ for (i = 0; i < numvpes; i++) { GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i); /* Are Interrupts locally routable? */ GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl); if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK) GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), GIC_MAP_TO_PIN_MSK | timer_interrupt); #ifdef CONFIG_RALINK_SOC if (cpu_has_veic) { set_vi_handler(timer_interrupt+GIC_PIN_TO_VEC_OFFSET, gic_eic_tmr_irq_dispatch); } #endif if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), GIC_MAP_TO_PIN_MSK | perf_interrupt); #ifdef CONFIG_RALINK_SOC if (cpu_has_veic) { set_vi_handler(perf_interrupt+GIC_PIN_TO_VEC_OFFSET, gic_eic_tmr_irq_dispatch); } #endif } }
static void gic_irq_ack(unsigned int irq) { irq -= _irqbase; pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); GIC_CLR_INTR_MASK(irq); if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE) GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); }
int __cpuinit gic_clockevent_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq; if (!cpu_has_counter || !gic_frequency) return -ENXIO; irq = MIPS_GIC_IRQ_BASE; cd = &per_cpu(gic_clockevent_device, cpu); cd->name = "MIPS GIC"; cd->features = CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, gic_frequency); /* Calculate the min / max delta */ cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); cd->min_delta_ns = clockevent_delta2ns(0x300, cd); cd->rating = 300; cd->irq = irq; cd->cpumask = cpumask_of(cpu); cd->set_next_event = gic_next_event; cd->set_mode = gic_set_clock_mode; cd->event_handler = gic_event_handler; clockevents_register_device(cd); GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_MAP), 0x80000002); GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), GIC_VPE_SMASK_CMP_MSK); if (gic_timer_irq_installed) return 0; gic_timer_irq_installed = 1; setup_irq(irq, &gic_compare_irqaction); irq_set_handler(irq, handle_percpu_irq); return 0; }
static void gic_irq_ack(unsigned int irq) { #if gic_wedgeb2bok == 0 unsigned long flags; #endif pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))), 1 << (irq % 32)); if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) { if (!gic_wedgeb2bok) spin_lock_irqsave(&gic_wedgeb2b_lock, flags); GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); if (!gic_wedgeb2bok) { (void) GIC_REG(SHARED, GIC_SH_CONFIG); spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags); } } }
static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, unsigned int pin, unsigned int polarity, unsigned int trigtype, unsigned int flags) { /* Setup Intr to Pin mapping */ if (pin & GIC_MAP_TO_NMI_MSK) { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); /* FIXME: hack to route NMI to all cpu's */ for (cpu = 0; cpu < NR_CPUS; cpu += 32) { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)), 0xffffffff); } } else { GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), GIC_MAP_TO_PIN_MSK | pin); /* Setup Intr to CPU mapping */ GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); } /* Setup Intr Polarity */ GIC_SET_POLARITY(intr, polarity); /* Setup Intr Trigger Type */ GIC_SET_TRIGGER(intr, trigtype); /* Init Intr Masks */ GIC_CLR_INTR_MASK(intr); /* Initialise per-cpu Interrupt software masks */ if (flags & GIC_FLAG_IPI) set_bit(intr, pcpu_masks[cpu].pcpu_mask); #ifdef CONFIG_RALINK_SOC if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0)) #else if (flags & GIC_FLAG_TRANSPARENT) #endif GIC_SET_INTR_MASK(intr); if (trigtype == GIC_TRIG_EDGE) gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE; }
/* This is Malta specific and needs to be exported */ static void vpe_local_setup(unsigned int numvpes) { int i; unsigned long timer_interrupt = 5, perf_interrupt = 5; unsigned int vpe_ctl; /* * Setup the default performance counter timer interrupts * for all VPEs */ for (i = 0; i < numvpes; i++) { GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i); /* Are Interrupts locally routable? */ GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl); if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK) GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), GIC_MAP_TO_PIN_MSK | timer_interrupt); if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), GIC_MAP_TO_PIN_MSK | perf_interrupt); } }
void gic_send_ipi(unsigned int intr) { #if gic_wedgeb2bok == 0 unsigned long flags; #endif pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__, read_c0_status()); if (!gic_wedgeb2bok) spin_lock_irqsave(&gic_wedgeb2b_lock, flags); GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); if (!gic_wedgeb2bok) { (void) GIC_REG(SHARED, GIC_SH_CONFIG); spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags); } }
void gic_send_ipi(unsigned int intr) { pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__, read_c0_status()); GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); }