[MIPS] Alchemy: work around clock misdetection on early Au1000

Work around the CPU clock miscalculation on Au1000DA/HA/HB due the
sys_cpupll register being write-only, i.e. actually do what the comment
before cal_r4off() function advertised for years but the code failed at.
This is achieved by just giving user a chance to define the clock
explicitly in the board config. via CONFIG_SOC_AU1000_FREQUENCY option,
defaulting to 396 MHz if the option is not given...

The patch is based on the AMD's big unpublished patch, the issue seems to
be an undocumented errata (or feature :-)...

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by Sergei Shtylyov and committed by Ralf Baechle 758e285f b1ec4c8e

+44 -32
+18 -18
arch/mips/au1000/common/cputable.c
··· 22 22 /* With some thought, we can probably use the mask to reduce the 23 23 * size of the table. 24 24 */ 25 - struct cpu_spec cpu_specs[] = { 26 - { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0 }, 27 - { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0 }, 28 - { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0 }, 29 - { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1 }, 30 - { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1 }, 31 - { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1 }, 32 - { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1 }, 33 - { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1 }, 34 - { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1 }, 35 - { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1 }, 36 - { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1 }, 37 - { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, 38 - { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, 39 - { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, 40 - { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 }, 41 - { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0 }, 42 - { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, 25 + struct cpu_spec cpu_specs[] = { 26 + { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 }, 27 + { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 }, 28 + { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 }, 29 + { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 }, 30 + { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 }, 31 + { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 }, 32 + { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 }, 33 + { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 }, 34 + { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 }, 35 + { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 }, 36 + { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 }, 37 + { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 }, 38 + { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 }, 39 + { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 }, 40 + { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 }, 41 + { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 }, 42 + { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 } 43 43 }; 44 44 45 45 void
+10 -3
arch/mips/au1000/common/setup.c
··· 57 57 { 58 58 struct cpu_spec *sp; 59 59 char *argptr; 60 - unsigned long prid, cpupll, bclk = 1; 60 + unsigned long prid, cpufreq, bclk = 1; 61 61 62 62 set_cpuspec(); 63 63 sp = cur_cpu_spec[0]; ··· 65 65 board_setup(); /* board specific setup */ 66 66 67 67 prid = read_c0_prid(); 68 - cpupll = (au_readl(0xB1900060) & 0x3F) * 12; 69 - printk("(PRId %08lx) @ %ldMHZ\n", prid, cpupll); 68 + if (sp->cpu_pll_wo) 69 + #ifdef CONFIG_SOC_AU1000_FREQUENCY 70 + cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000; 71 + #else 72 + cpufreq = 396; 73 + #endif 74 + else 75 + cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12; 76 + printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq); 70 77 71 78 bclk = sp->cpu_bclk; 72 79 if (bclk)
+15 -11
arch/mips/au1000/common/time.c
··· 209 209 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); 210 210 au_writel(0, SYS_TOYWRITE); 211 211 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); 212 - 213 - cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * 214 - AU1000_SRC_CLK; 215 - } 216 - else { 217 - /* The 32KHz oscillator isn't running, so assume there 218 - * isn't one and grab the processor speed from the PLL. 219 - * NOTE: some old silicon doesn't allow reading the PLL. 220 - */ 221 - cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; 212 + } else 222 213 no_au1xxx_32khz = 1; 223 - } 214 + 215 + /* 216 + * On early Au1000, sys_cpupll was write-only. Since these 217 + * silicon versions of Au1000 are not sold by AMD, we don't bend 218 + * over backwards trying to determine the frequency. 219 + */ 220 + if (cur_cpu_spec[0]->cpu_pll_wo) 221 + #ifdef CONFIG_SOC_AU1000_FREQUENCY 222 + cpu_speed = CONFIG_SOC_AU1000_FREQUENCY; 223 + #else 224 + cpu_speed = 396000000; 225 + #endif 226 + else 227 + cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; 224 228 mips_hpt_frequency = cpu_speed; 225 229 // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) 226 230 set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
+1
include/asm-mips/mach-au1x00/au1000.h
··· 1786 1786 char *cpu_name; 1787 1787 unsigned char cpu_od; /* Set Config[OD] */ 1788 1788 unsigned char cpu_bclk; /* Enable BCLK switching */ 1789 + unsigned char cpu_pll_wo; /* sys_cpupll reg. write-only */ 1789 1790 }; 1790 1791 1791 1792 extern struct cpu_spec cpu_specs[];