Exemplo n.º 1
0
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);
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
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));
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
/* 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
	}
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
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);
        }
    }
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
0
/* 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);
    }
}
Exemplo n.º 11
0
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);
    }
}
Exemplo n.º 12
0
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);
}