/** * Copyright (C) 2006-2014 Ikanos Communications. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * Info : * VX180/VX185 periodic timer interrupt setup using MIPS count/compare timer */ #include #include #include #if defined(CONFIG_FUSIV_VX185) extern struct clock_values fusiv_718x_clks; #endif /* CONFIG_FUSIV_VX185 */ #if defined(CONFIG_FUSIV_VX585) extern struct fusiv_clock_values fusiv_75xx_clks; #endif /* CONFIG_FUSIV_VX585 */ #include #if defined(CONFIG_FUSIV_VX585) #include #include #include #endif /* CONFIG_FUSIV_VX585 */ extern unsigned int mips_hpt_frequency; extern int cp0_compare_irq; #if defined (CONFIG_FUSIV_VX185) #if defined (CONFIG_CPU_MIPSR2_IRQ_VI) extern void mipscpu_int_hw5_dispatch(void); static unsigned char tim_installed; #endif int gic_present = 0; #endif #if defined(CONFIG_FUSIV_VX585) extern int cp0_perfcount_irq; extern void mipscpu_int_hw5_dispatch(void); extern unsigned int gic_frequency; #endif /* CONFIG_FUSIV_VX585 */ /* * Platform hook which returns the interrupt number of the count/compare * timer. This is called by the platform-independent implementation * of the count/compare timer. */ unsigned int __cpuinit get_c0_compare_int(void) { /* Install vector interrupt handler for timer */ #if defined(CONFIG_FUSIV_VX185) #if defined (CONFIG_CPU_MIPSR2_IRQ_VI) if (cpu_has_vint) { if (!tim_installed) { set_vi_handler(FUSIV_MIPS_INT_PIT, mipscpu_int_hw5_dispatch); printk("Installed VI handler for MIPS Timer...\n"); tim_installed++; } return FUSIV_MIPS_INT_PIT; } else #endif return MIPS_TIMER_INT; #endif #if defined(CONFIG_FUSIV_VX585) if (cpu_has_vint) { set_vi_handler(FUSIV_MIPS_INT_PIT, mipscpu_int_hw5_dispatch); #ifndef CONFIG_SMP change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7); __asm__ __volatile("ehb"); #endif return FUSIV_MIPS_INT_PIT; } else return MIPS_TIMER_INT; #endif /* CONFIG_FUSIV_VX585 */ } /* * We use the platform-independent 'clockevent' device implementation of MIPS * CP0 Count/Compare timer for our periodic timer interrupt. The platform strap * code needs to provide the following information to the generic layer :- * 1.) Frequency of the CP0 count/compare timer * 2.) MIPS interrupt line (0..5) which is used by the timer interrupt. This is * used by the platform-independent code to verify the timer and its interrupt, * since interrupt processing by software is not enabled yet at this stage. * For the generic R4K CP0-timer clockevent device implementation, see: * linux/arch/mips/kernel/cevt-r4k.c & linux/kernel/time/tick-common.c */ void __init plat_time_init(void) { #if defined (CONFIG_FUSIV_VX185) struct irq_desc *desc = NULL; struct irq_data *idata = NULL; /* The counter increments every two clock cycles, * hence the frequency is half of core clock */ #ifdef CONFIG_FUSIV_MIPS_DUALCORE /* Dual Core implementation */ #ifdef CONFIG_FUSIV_MIPS_CMIPS_CORE mips_hpt_frequency = fusiv_718x_clks.cmips_cpu_clk_val / 2; /* CMIPS clock value comes from the BME PLL and its PD settings */ #else mips_hpt_frequency = fusiv_718x_clks.cpu_clk_val / 2; #endif /* CONFIG_FUSIV_MIPS_CMIPS_CORE */ #else /* Single Core implementation */ mips_hpt_frequency = fusiv_718x_clks.cpu_clk_val / 2; #endif /* CONFIG_FUSIV_MIPS_DUALCORE */ /* MIPS interrupt line 5 for periodic timer. Need to set this explicitly * for the generic code, since timer interrupt line number is not * hardwired into CP0_INTCTL[31..29]. */ #if defined (CONFIG_CPU_MIPSR2_IRQ_VI) if (cpu_has_vint) cp0_compare_irq = FUSIV_MIPS_INT_PIT; else #endif cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ; /* Enable the VX185 IPC mapping of the timer to the MIPS interrupt * line to allow verification of the timer interrupt */ #endif #if defined (CONFIG_FUSIV_VX585) /* The counter increments every two clock cycles, * hence the frequency is half of core clock */ #if defined(CONFIG_FUSIV_VX585_PALLADIUM) gic_frequency = 813000; #else gic_frequency = fusiv_75xx_clks.cpu_clk_val; /* Silicon Freq is 800 Mhz */ #endif mips_hpt_frequency = gic_frequency / 2; /* MIPS interrupt line 5 for periodic timer. Need to set this explicitly * for the generic code, since timer interrupt line number is not * hardwired into CP0_INTCTL[31..29] on VX180. */ cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ; cp0_perfcount_irq = CP0_LEGACY_PERFCNT_IRQ; gic_clocksource_init(gic_frequency); /* Enable the VX180/VX185 IPC mapping of the timer to the MIPS interrupt * line to allow verification of the timer interrupt */ #endif /* CONFIG_FUSIV_VX585 */ printk(KERN_INFO "MIPS counter frequency %dHz\n", mips_hpt_frequency); #if defined(CONFIG_FUSIV_VX185) desc = irq_to_desc(MIPS_TIMER_INT); idata = irq_desc_get_irq_data(desc); startup_ipc_src(idata); #ifdef CONFIG_SMP printk("Configuring IPC for VPE1 Timer \n\r"); desc = irq_to_desc(VPE1_MIPS_TIMER_INT); idata = irq_desc_get_irq_data(desc); startup_ipc_src(idata); #endif #endif /* CONFIG_FUSIV_VX185 */ }