aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergei Shtylyov <sshtylyov@ru.mvista.com>2008-03-27 09:09:31 -0400
committerRalf Baechle <ralf@linux-mips.org>2008-04-01 10:46:34 -0400
commit758e285faca4db948ecddefb523007255b29cdb7 (patch)
tree530fb34442234b04afe0972d6765bbc7f17ba0f6
parentb1ec4c8e483d0d00d3114eafdb2c85c1cf3ed4ae (diff)
[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>
-rw-r--r--arch/mips/au1000/common/cputable.c36
-rw-r--r--arch/mips/au1000/common/setup.c13
-rw-r--r--arch/mips/au1000/common/time.c24
-rw-r--r--include/asm-mips/mach-au1x00/au1000.h1
4 files changed, 43 insertions, 31 deletions
diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c
index d8df5fdb045f..5c0d35d6e22a 100644
--- a/arch/mips/au1000/common/cputable.c
+++ b/arch/mips/au1000/common/cputable.c
@@ -22,24 +22,24 @@ struct cpu_spec* cur_cpu_spec[NR_CPUS];
22/* With some thought, we can probably use the mask to reduce the 22/* With some thought, we can probably use the mask to reduce the
23 * size of the table. 23 * size of the table.
24 */ 24 */
25struct cpu_spec cpu_specs[] = { 25struct cpu_spec cpu_specs[] = {
26 { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0 }, 26 { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 },
27 { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0 }, 27 { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 },
28 { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0 }, 28 { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 },
29 { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1 }, 29 { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 },
30 { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1 }, 30 { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 },
31 { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1 }, 31 { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 },
32 { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1 }, 32 { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 },
33 { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1 }, 33 { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 },
34 { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1 }, 34 { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 },
35 { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1 }, 35 { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 },
36 { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1 }, 36 { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 },
37 { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, 37 { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 },
38 { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, 38 { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 },
39 { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, 39 { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 },
40 { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 }, 40 { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 },
41 { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0 }, 41 { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 },
42 { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, 42 { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 }
43}; 43};
44 44
45void 45void
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index d885e3848ec6..9e4ab80caab6 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -57,7 +57,7 @@ void __init plat_mem_setup(void)
57{ 57{
58 struct cpu_spec *sp; 58 struct cpu_spec *sp;
59 char *argptr; 59 char *argptr;
60 unsigned long prid, cpupll, bclk = 1; 60 unsigned long prid, cpufreq, bclk = 1;
61 61
62 set_cpuspec(); 62 set_cpuspec();
63 sp = cur_cpu_spec[0]; 63 sp = cur_cpu_spec[0];
@@ -65,8 +65,15 @@ void __init plat_mem_setup(void)
65 board_setup(); /* board specific setup */ 65 board_setup(); /* board specific setup */
66 66
67 prid = read_c0_prid(); 67 prid = read_c0_prid();
68 cpupll = (au_readl(0xB1900060) & 0x3F) * 12; 68 if (sp->cpu_pll_wo)
69 printk("(PRId %08lx) @ %ldMHZ\n", prid, cpupll); 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 bclk = sp->cpu_bclk; 78 bclk = sp->cpu_bclk;
72 if (bclk) 79 if (bclk)
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index f113b512d7b1..e122bbc6cd88 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -209,18 +209,22 @@ unsigned long cal_r4koff(void)
209 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); 209 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
210 au_writel(0, SYS_TOYWRITE); 210 au_writel(0, SYS_TOYWRITE);
211 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); 211 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
212 } else
213 no_au1xxx_32khz = 1;
212 214
213 cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * 215 /*
214 AU1000_SRC_CLK; 216 * On early Au1000, sys_cpupll was write-only. Since these
215 } 217 * silicon versions of Au1000 are not sold by AMD, we don't bend
216 else { 218 * over backwards trying to determine the frequency.
217 /* The 32KHz oscillator isn't running, so assume there 219 */
218 * isn't one and grab the processor speed from the PLL. 220 if (cur_cpu_spec[0]->cpu_pll_wo)
219 * NOTE: some old silicon doesn't allow reading the PLL. 221#ifdef CONFIG_SOC_AU1000_FREQUENCY
220 */ 222 cpu_speed = CONFIG_SOC_AU1000_FREQUENCY;
223#else
224 cpu_speed = 396000000;
225#endif
226 else
221 cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; 227 cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
222 no_au1xxx_32khz = 1;
223 }
224 mips_hpt_frequency = cpu_speed; 228 mips_hpt_frequency = cpu_speed;
225 // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) 229 // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16)
226 set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); 230 set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index cb18af989645..5bb57bf2b9d7 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -1786,6 +1786,7 @@ struct cpu_spec {
1786 char *cpu_name; 1786 char *cpu_name;
1787 unsigned char cpu_od; /* Set Config[OD] */ 1787 unsigned char cpu_od; /* Set Config[OD] */
1788 unsigned char cpu_bclk; /* Enable BCLK switching */ 1788 unsigned char cpu_bclk; /* Enable BCLK switching */
1789 unsigned char cpu_pll_wo; /* sys_cpupll reg. write-only */
1789}; 1790};
1790 1791
1791extern struct cpu_spec cpu_specs[]; 1792extern struct cpu_spec cpu_specs[];