--- a/arch/mips/ralink/mt7621.c +++ b/arch/mips/ralink/mt7621.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include @@ -175,6 +177,58 @@ bool plat_cpu_core_present(int core) return true; } +#define LPS_PREC 8 +/* +* Re-calibration lpj(loop-per-jiffy). +* (derived from kernel/calibrate.c) +*/ +static int udelay_recal(void) +{ + unsigned int i, lpj = 0; + unsigned long ticks, loopbit; + int lps_precision = LPS_PREC; + + lpj = (1<<12); + + while ((lpj <<= 1) != 0) { + /* wait for "start of" clock tick */ + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + + /* Go .. */ + ticks = jiffies; + __delay(lpj); + ticks = jiffies - ticks; + if (ticks) + break; + } + + /* + * Do a binary approximation to get lpj set to + * equal one clock (up to lps_precision bits) + */ + lpj >>= 1; + loopbit = lpj; + while (lps_precision-- && (loopbit >>= 1)) { + lpj |= loopbit; + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + ticks = jiffies; + __delay(lpj); + if (jiffies != ticks) /* longer than 1 tick */ + lpj &= ~loopbit; + } + printk(KERN_INFO "%d CPUs re-calibrate udelay(lpj = %d)\n", NR_CPUS, lpj); + + for(i=0; i< NR_CPUS; i++) + cpu_data[i].udelay_val = lpj; + + return 0; +} +device_initcall(udelay_recal); + void prom_soc_init(struct ralink_soc_info *soc_info) { void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig @@ -58,6 +58,7 @@ choice select CLKSRC_MIPS_GIC select HAVE_PCI if PCI_MT7621 select WEAK_REORDERING_BEYOND_LLSC + select GENERIC_CLOCKEVENTS_BROADCAST endchoice choice