]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/mips/alchemy/common/clocks.c
Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mv-sheeva.git] / arch / mips / alchemy / common / clocks.c
index 043429d17c5fd9ec1e3b9ccf01b7f51cf4621d4c..460c6285c1bbe00cda3f0f89b2da1b5867d6f223 100644 (file)
  */
 
 #include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/time.h>
 #include <asm/mach-au1x00/au1000.h>
 
+/*
+ * I haven't found anyone that doesn't use a 12 MHz source clock,
+ * but just in case.....
+ */
+#define AU1000_SRC_CLK 12000000
+
 static unsigned int au1x00_clock; /*  Hz */
-static unsigned int lcd_clock;    /* KHz */
 static unsigned long uart_baud_base;
 
 /*
@@ -63,31 +70,40 @@ void set_au1x00_uart_baud_base(unsigned long new_baud_base)
 }
 
 /*
- * Calculate the Au1x00's LCD clock based on the current
- * cpu clock and the system bus clock, and try to keep it
- * below 40 MHz (the Pb1000 board can lock-up if the LCD
- * clock is over 40 MHz).
+ * We read the real processor speed from the PLL.  This is important
+ * because it is more accurate than computing it from the 32 KHz
+ * counter, if it exists.  If we don't have an accurate processor
+ * speed, all of the peripherals that derive their clocks based on
+ * this advertised speed will introduce error and sometimes not work
+ * properly.  This function is futher convoluted to still allow configurations
+ * to do that in case they have really, really old silicon with a
+ * write-only PLL register.                    -- Dan
  */
-void set_au1x00_lcd_clock(void)
+unsigned long au1xxx_calc_clock(void)
 {
-       unsigned int static_cfg0;
-       unsigned int sys_busclk = (get_au1x00_speed() / 1000) /
-                                 ((int)(au_readl(SYS_POWERCTRL) & 0x03) + 2);
-
-       static_cfg0 = au_readl(MEM_STCFG0);
+       unsigned long cpu_speed;
 
-       if (static_cfg0 & (1 << 11))
-               lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */
+       /*
+        * 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 (au1xxx_cpu_has_pll_wo())
+#ifdef CONFIG_SOC_AU1000_FREQUENCY
+               cpu_speed = CONFIG_SOC_AU1000_FREQUENCY;
+#else
+               cpu_speed = 396000000;
+#endif
        else
-               lcd_clock = sys_busclk / 4;
+               cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
 
-       if (lcd_clock > 50000) /* Epson MAX */
-               printk(KERN_WARNING "warning: LCD clock too high (%u KHz)\n",
-                                   lcd_clock);
-}
+       /* On Alchemy CPU:counter ratio is 1: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));
 
-unsigned int get_au1x00_lcd_clock(void)
-{
-       return lcd_clock;
+       set_au1x00_speed(cpu_speed);
+
+       return cpu_speed;
 }
-EXPORT_SYMBOL(get_au1x00_lcd_clock);