Beispiel #1
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;
}
Beispiel #2
0
cycle_t gic_read_count(void)
{
	unsigned int hi, hi2, lo;

	do {
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi);
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo);
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2);
	} while (hi2 != hi);

	return (((cycle_t) hi) << 32) + lo;
}
Beispiel #3
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);
    }
}
Beispiel #4
0
/*
 * Estimate CPU and GIC frequencies.
 */
static void __init estimate_frequencies(void)
{
	unsigned long flags;
	unsigned int count, start;
#ifdef CONFIG_IRQ_GIC
	unsigned int giccount = 0, gicstart = 0;
#endif

#if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ
	mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000;
	return;
#endif

	local_irq_save(flags);

	/* Start counter exactly on falling edge of update flag. */
	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));

	/* Initialize counters. */
	start = read_c0_count();
#ifdef CONFIG_IRQ_GIC
	if (gic_present)
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), gicstart);
#endif

	/* Read counter exactly on falling edge of update flag. */
	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));

	count = read_c0_count();
#ifdef CONFIG_IRQ_GIC
	if (gic_present)
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), giccount);
#endif

	local_irq_restore(flags);

	count -= start;
	mips_hpt_frequency = count;

#ifdef CONFIG_IRQ_GIC
	if (gic_present) {
		giccount -= gicstart;
		gic_frequency = giccount;
	}
#endif
}
Beispiel #5
0
void __init gic_init(unsigned long gic_base_addr,
             unsigned long gic_addrspace_size,
             struct gic_intr_map *intr_map, unsigned int intr_map_size,
             unsigned int irqbase)
{
    unsigned int gicconfig;

    _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
                            gic_addrspace_size);
    _irqbase = irqbase;
    _intrmap = intr_map;
    _mapsize = intr_map_size;

    GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
    numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
           GIC_SH_CONFIG_NUMINTRS_SHF;
    numintrs = ((numintrs + 1) * 8);

    numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
          GIC_SH_CONFIG_NUMVPES_SHF;

    pr_debug("%s called\n", __func__);

    gic_basic_init();
}
Beispiel #6
0
void __init gic_init(unsigned long gic_base_addr,
		     unsigned long gic_addrspace_size,
		     struct gic_intr_map *intr_map, unsigned int intr_map_size,
		     unsigned int irqbase)
{
	unsigned int gicconfig;
	int numvpes, numintrs;

	_gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
						    gic_addrspace_size);
	_irqbase = irqbase;

	GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
	numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
		   GIC_SH_CONFIG_NUMINTRS_SHF;
	numintrs = ((numintrs + 1) * 8);

	numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
		  GIC_SH_CONFIG_NUMVPES_SHF;
#ifdef CONFIG_RALINK_SOC
	numvpes = numvpes + 1;
#endif

	pr_debug("%s called\n", __func__);

	gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
}
Beispiel #7
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);
}
Beispiel #8
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
	}
}
Beispiel #9
0
void __init arch_init_irq(void)
{
	int i;
	unsigned int gic_rev;

	mips_cpu_irq_init();

	if (cpu_has_vint)
		set_vi_handler(cp0_compare_irq, mips_timer_dispatch);

	if (gcmp_present) {
		GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
		gic_present = 1;
	}

	if (gic_present) {
#if defined (CONFIG_MIPS_GIC_IPI)
		gic_call_int_base = GIC_IPI_CALL_VPE0;
		gic_resched_int_base = GIC_IPI_RESCHED_VPE0;
		fill_ipi_map();
#endif
		gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
				ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);

		GICREAD(GIC_REG(SHARED, GIC_SH_REVISIONID), gic_rev);
		printk("MIPS GIC RevID: %d.%d\n", (gic_rev >> 8) & 0xff, gic_rev & 0xff);

		if (cpu_has_vint) {
			pr_info("Setting up vectored interrupts\n");
			set_vi_handler(2 + GIC_CPU_INT0, gic_irq_dispatch);	// CPU
#if defined (CONFIG_MIPS_GIC_IPI)
			set_vi_handler(2 + GIC_CPU_INT1, gic_irq_dispatch);	// IPI resched
			set_vi_handler(2 + GIC_CPU_INT2, gic_irq_dispatch);	// IPI call
#endif
			set_vi_handler(2 + GIC_CPU_INT3, gic_irq_dispatch);	// FE
			set_vi_handler(2 + GIC_CPU_INT4, gic_irq_dispatch);	// PCIe
		}

#if defined (CONFIG_MIPS_GIC_IPI)
		set_c0_status(STATUSF_IP7 | STATUSF_IP6 | STATUSF_IP5 | STATUSF_IP2 |
			      STATUSF_IP4 | STATUSF_IP3);
		
		/* setup ipi interrupts */
		for (i = 0; i < nr_cpu_ids; i++) {
			arch_init_ipiirq(MIPS_GIC_IRQ_BASE + GIC_RESCHED_INT(i), &irq_resched);
			arch_init_ipiirq(MIPS_GIC_IRQ_BASE + GIC_CALL_INT(i), &irq_call);
		}
#else
		set_c0_status(STATUSF_IP7 | STATUSF_IP6 | STATUSF_IP5 | STATUSF_IP2);
#endif
		/* set hardware irq, mapped to GIC shared (skip 0, 1, 2, 5, 7) */
		for (i = 3; i <= 31; i++) {
			if (i != 5 && i != 7)
				irq_set_handler(MIPS_GIC_IRQ_BASE + i, handle_level_irq);
		}
		
	} else {
Beispiel #10
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);
}
Beispiel #11
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;
}
Beispiel #12
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);
        }
    }
}
Beispiel #13
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);
    }
}
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);
}
Beispiel #15
0
static int __init
of_gic_init(struct device_node *node,
				struct device_node *parent)
{
	struct irq_domain *domain;
	struct resource gcmp = { 0 }, gic = { 0 };
	unsigned int gic_rev;
	int i;

	if (of_address_to_resource(node, 0, &gic))
		panic("Failed to get gic memory range");
	if (request_mem_region(gic.start, resource_size(&gic),
				gic.name) < 0)
		panic("Failed to request gic memory");
	if (of_address_to_resource(node, 2, &gcmp))
		panic("Failed to get gic memory range");
	if (request_mem_region(gcmp.start, resource_size(&gcmp),
				gcmp.name) < 0)
		panic("Failed to request gcmp memory");

	_gcmp_base = (unsigned long) ioremap_nocache(gcmp.start, resource_size(&gcmp));
	if (!_gcmp_base)
		panic("Failed to remap gcmp memory\n");

	if ((GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) != gcmp.start)
		panic("Failed to find gcmp core\n");

	/* tell the gcmp where to find the gic */
	GCMPGCB(GICBA) = gic.start | GCMP_GCB_GICBA_EN_MSK;
	gic_present = 1;
	if (cpu_has_vint) {
		set_vi_handler(2, gic_irqdispatch);
		set_vi_handler(3, gic_irqdispatch);
		set_vi_handler(4, gic_irqdispatch);
		set_vi_handler(7, vi_timer_irqdispatch);
	}

	gic_fill_map();

	gic_init(gic.start, resource_size(&gic), gic_intr_map,
		ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);

	GICREAD(GIC_REG(SHARED, GIC_SH_REVISIONID), gic_rev);
	pr_info("gic: revision %d.%d\n", (gic_rev >> 8) & 0xff, gic_rev & 0xff);

	domain = irq_domain_add_legacy(node, GIC_NUM_INTRS, MIPS_GIC_IRQ_BASE,
			0, &irq_domain_ops, NULL);
	if (!domain)
		panic("Failed to add irqdomain");

#if defined(CONFIG_MIPS_MT_SMP)
	for (i = 0; i < nr_cpu_ids; i++) {
		setup_irq(MIPS_GIC_IRQ_BASE + GIC_RESCHED_INT(i), &irq_resched);
		setup_irq(MIPS_GIC_IRQ_BASE + GIC_CALL_INT(i), &irq_call);
	}
#endif

	change_c0_status(ST0_IM, STATUSF_IP7 | STATUSF_IP4 | STATUSF_IP3 |
				STATUSF_IP2);
	return 0;
}
Beispiel #16
0
cycle_t gic_read_count(void)
{
	unsigned int hi, hi2, lo;

	do {
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi);
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo);
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2);
	} while (hi2 != hi);

	return (((cycle_t) hi) << 32) + lo;
}

void gic_write_compare(cycle_t cnt)
{
	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
				(int)(cnt >> 32));
	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
				(int)(cnt & 0xffffffff));
}

cycle_t gic_read_compare(void)
{
	unsigned int hi, lo;

	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI), hi);
	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO), lo);

	return (((cycle_t) hi) << 32) + lo;
}
#endif