* [PATCH] Alchemy: work around clock misdetection on early Au1000 (take 2)
@ 2008-03-27 13:09 Sergei Shtylyov
2008-03-27 13:17 ` Sergei Shtylyov
2008-03-27 13:37 ` Ralf Baechle
0 siblings, 2 replies; 4+ messages in thread
From: Sergei Shtylyov @ 2008-03-27 13:09 UTC (permalink / raw)
To: ralf; +Cc: linux-mips
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>
---
That's what happens to a dozen line (and incorrect) change when you do it
properly. ;-)
This should theoretically apply to all stable branches, but as AMD claimed that
the guilty chips were not sold, it's up to the maintainer.
In this revision I decided to revert to CONFIG_SOC_AU1000_FREQUENCY option name
and defer the copyright update till the big cleanup patch that's coming...
arch/mips/au1000/common/cputable.c | 36 +++++++++++++++++-----------------
arch/mips/au1000/common/setup.c | 13 +++++++++---
arch/mips/au1000/common/time.c | 24 +++++++++++++---------
include/asm-mips/mach-au1x00/au1000.h | 1
4 files changed, 43 insertions(+), 31 deletions(-)
Index: linux-2.6/arch/mips/au1000/common/cputable.c
===================================================================
--- linux-2.6.orig/arch/mips/au1000/common/cputable.c
+++ linux-2.6/arch/mips/au1000/common/cputable.c
@@ -22,24 +22,24 @@ struct cpu_spec* cur_cpu_spec[NR_CPUS];
/* With some thought, we can probably use the mask to reduce the
* size of the table.
*/
-struct cpu_spec cpu_specs[] = {
- { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0 },
- { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0 },
- { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0 },
- { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1 },
- { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1 },
- { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1 },
- { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1 },
- { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1 },
- { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1 },
- { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1 },
- { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1 },
- { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 },
- { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 },
- { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 },
- { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 },
- { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0 },
- { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 },
+struct cpu_spec cpu_specs[] = {
+ { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 },
+ { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 },
+ { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 },
+ { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 },
+ { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 },
+ { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 },
+ { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 },
+ { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 },
+ { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 },
+ { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 },
+ { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 },
+ { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 },
+ { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 },
+ { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 },
+ { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 },
+ { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 },
+ { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 }
};
void
Index: linux-2.6/arch/mips/au1000/common/setup.c
===================================================================
--- linux-2.6.orig/arch/mips/au1000/common/setup.c
+++ linux-2.6/arch/mips/au1000/common/setup.c
@@ -57,7 +57,7 @@ void __init plat_mem_setup(void)
{
struct cpu_spec *sp;
char *argptr;
- unsigned long prid, cpupll, bclk = 1;
+ unsigned long prid, cpufreq, bclk = 1;
set_cpuspec();
sp = cur_cpu_spec[0];
@@ -65,8 +65,15 @@ void __init plat_mem_setup(void)
board_setup(); /* board specific setup */
prid = read_c0_prid();
- cpupll = (au_readl(0xB1900060) & 0x3F) * 12;
- printk("(PRId %08lx) @ %ldMHZ\n", prid, cpupll);
+ if (cur_cpu_spec[0]->cpu_pll_wo)
+#ifdef CONFIG_SOC_AU1000_FREQUENCY
+ cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000;
+#else
+ cpufreq = 396;
+#endif
+ else
+ cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12;
+ printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq);
bclk = sp->cpu_bclk;
if (bclk)
Index: linux-2.6/arch/mips/au1000/common/time.c
===================================================================
--- linux-2.6.orig/arch/mips/au1000/common/time.c
+++ linux-2.6/arch/mips/au1000/common/time.c
@@ -209,18 +209,22 @@ unsigned long cal_r4koff(void)
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
au_writel(0, SYS_TOYWRITE);
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
+ } else
+ no_au1xxx_32khz = 1;
- cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) *
- AU1000_SRC_CLK;
- }
- else {
- /* The 32KHz oscillator isn't running, so assume there
- * isn't one and grab the processor speed from the PLL.
- * NOTE: some old silicon doesn't allow reading the PLL.
- */
+ /*
+ * On early Au1000, sys_cpupll was write-only. Since these
+ * silicon versions of Au1000 are not sold by AMD, we don't bend
+ * over backwards trying to determine the frequency.
+ */
+ if (cur_cpu_spec[0]->cpu_pll_wo)
+#ifdef CONFIG_SOC_AU1000_FREQUENCY
+ cpu_speed = CONFIG_SOC_AU1000_FREQUENCY;
+#else
+ cpu_speed = 396000000;
+#endif
+ else
cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
- no_au1xxx_32khz = 1;
- }
mips_hpt_frequency = cpu_speed;
// Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16)
set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
Index: linux-2.6/include/asm-mips/mach-au1x00/au1000.h
===================================================================
--- linux-2.6.orig/include/asm-mips/mach-au1x00/au1000.h
+++ linux-2.6/include/asm-mips/mach-au1x00/au1000.h
@@ -1778,6 +1778,7 @@ struct cpu_spec {
char *cpu_name;
unsigned char cpu_od; /* Set Config[OD] */
unsigned char cpu_bclk; /* Enable BCLK switching */
+ unsigned char cpu_pll_wo; /* sys_cpupll reg. write-only */
};
extern struct cpu_spec cpu_specs[];
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] Alchemy: work around clock misdetection on early Au1000 (take 2)
2008-03-27 13:09 [PATCH] Alchemy: work around clock misdetection on early Au1000 (take 2) Sergei Shtylyov
@ 2008-03-27 13:17 ` Sergei Shtylyov
2008-03-27 13:34 ` Ralf Baechle
2008-03-27 13:37 ` Ralf Baechle
1 sibling, 1 reply; 4+ messages in thread
From: Sergei Shtylyov @ 2008-03-27 13:17 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: ralf, linux-mips
I just wrote:
> Index: linux-2.6/arch/mips/au1000/common/setup.c
> ===================================================================
> --- linux-2.6.orig/arch/mips/au1000/common/setup.c
> +++ linux-2.6/arch/mips/au1000/common/setup.c
> @@ -57,7 +57,7 @@ void __init plat_mem_setup(void)
> {
> struct cpu_spec *sp;
> char *argptr;
> - unsigned long prid, cpupll, bclk = 1;
> + unsigned long prid, cpufreq, bclk = 1;
>
> set_cpuspec();
> sp = cur_cpu_spec[0];
> @@ -65,8 +65,15 @@ void __init plat_mem_setup(void)
> board_setup(); /* board specific setup */
>
> prid = read_c0_prid();
> - cpupll = (au_readl(0xB1900060) & 0x3F) * 12;
> - printk("(PRId %08lx) @ %ldMHZ\n", prid, cpupll);
> + if (cur_cpu_spec[0]->cpu_pll_wo)
Oops! Ralf, could you change 'cur_cpu_spec[0]' to just 'sp' here before
committing?
WBR, Sergei
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] Alchemy: work around clock misdetection on early Au1000 (take 2)
2008-03-27 13:09 [PATCH] Alchemy: work around clock misdetection on early Au1000 (take 2) Sergei Shtylyov
2008-03-27 13:17 ` Sergei Shtylyov
@ 2008-03-27 13:37 ` Ralf Baechle
1 sibling, 0 replies; 4+ messages in thread
From: Ralf Baechle @ 2008-03-27 13:37 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: linux-mips
On Thu, Mar 27, 2008 at 04:09:31PM +0300, Sergei Shtylyov wrote:
> 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 :-)...
Applied, thanks,
Ralf
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-03-27 13:41 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-27 13:09 [PATCH] Alchemy: work around clock misdetection on early Au1000 (take 2) Sergei Shtylyov
2008-03-27 13:17 ` Sergei Shtylyov
2008-03-27 13:34 ` Ralf Baechle
2008-03-27 13:37 ` Ralf Baechle
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox