Remove duplicate define. Put all phy chip specific defines in its
[bertos.git] / bertos / cpu / cortex-m3 / drv / clock_lm3s.c
index 2f2dfe6c811412db5451b497b8590e1801dd8020..0c79f8780c60017a4ce2673896c303b236aa9fdb 100644 (file)
  * \author Andrea Righi <arighi@develer.com>
  */
 
+#include "clock_lm3s.h"
+
 #include <cfg/compiler.h>
 #include <cfg/debug.h>
-#include "io/lm3s.h"
-#include "clock_lm3s.h"
+
+#include <io/lm3s.h>
+
 
 /* The PLL VCO frequency is 400 MHz */
 #define PLL_VCO        400000000UL
 /*
  * Very small delay: each loop takes 3 cycles.
  */
-INLINE void __delay(unsigned long iterations)
+void NAKED lm3s_busyWait(unsigned long iterations)
 {
+       register uint32_t __n asm("r0") = iterations;
+
        asm volatile (
-               "1:     subs    %0, #1\n\t"
-               "       bne 1b\n\t"
-               : "=r"(iterations) : : "memory", "cc");
+               "1: subs r0, #1\n\t"
+               "bne 1b\n\t"
+               "bx lr\n\t"
+               : : "r"(__n) : "memory", "cc");
 }
 
-unsigned long clock_get_rate(void)
+INLINE unsigned long clock_get_rate(void)
 {
        reg32_t rcc = HWREG(SYSCTL_RCC);
 
@@ -67,12 +73,51 @@ unsigned long clock_get_rate(void)
                        PLL_VCO / 2 / RCC_TO_DIV(rcc) : PLL_VCO;
 }
 
-void clock_set_rate(void)
+/*
+ * Try to evaluate the correct SYSDIV value depending on the desired CPU
+ * frequency.
+ */
+INLINE int evaluate_sysdiv(unsigned long freq)
+{
+       int i;
+
+        /*
+         * NOTE: with BYPASS=0, SYSDIV < 3 are reserved values (see LM3S1968
+         * Microcontroller DATASHEET, p.78).
+         */
+       for (i = 3; i < 16; i++)
+               if (freq >= (PLL_VCO / 2 / (i + 1)))
+                       break;
+       return i;
+}
+
+void clock_init(void)
 {
        reg32_t rcc, rcc2;
        unsigned long clk;
        int i;
 
+       /*
+        * PLL may not function properly at default LDO setting.
+        *
+        * Description:
+        *
+        * In designs that enable and use the PLL module, unstable device
+        * behavior may occur with the LDO set at its default of 2.5 volts or
+        * below (minimum of 2.25 volts). Designs that do not use the PLL
+        * module are not affected.
+        *
+        * Workaround: Prior to enabling the PLL module, it is recommended that
+        * the default LDO voltage setting of 2.5 V be adjusted to 2.75 V using
+        * the LDO Power Control (LDOPCTL) register.
+        *
+        * Silicon Revision Affected: A1, A2
+        *
+        * See also: Stellaris LM3S1968 A2 Errata documentation.
+        */
+       if (REVISION_IS_A1 | REVISION_IS_A2)
+               HWREG(SYSCTL_LDOPCTL) = SYSCTL_LDOPCTL_2_75V;
+
        rcc = HWREG(SYSCTL_RCC);
        rcc2 = HWREG(SYSCTL_RCC2);
 
@@ -92,6 +137,8 @@ void clock_set_rate(void)
        HWREG(SYSCTL_RCC) = rcc;
        HWREG(SYSCTL_RCC) = rcc2;
 
+       lm3s_busyWait(16);
+
        /*
         * Step #2: select the crystal value (XTAL) and oscillator source
         * (OSCSRC), and clear the PWRDN bit in RCC/RCC2. Setting the XTAL
@@ -116,7 +163,7 @@ void clock_set_rate(void)
         HWREG(SYSCTL_RCC) = rcc;
        HWREG(SYSCTL_RCC) = rcc2;
 
-       __delay(16);
+       lm3s_busyWait(16);
 
        /*
         * Step #3: select the desired system divider (SYSDIV) in RCC/RCC2 and
@@ -125,19 +172,12 @@ void clock_set_rate(void)
         */
        rcc &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV);
 
-       /*
-        * Try to evaluate the correct SYSDIV value depending on the desired
-        * CPU frequency.
-        *
-        * NOTE: with BYPASS=0, SYSDIV < 3 are reserved values (see LM3S1968
-        * Microcontroller DATASHEET, p.78).
-        */
        clk = PLL_VCO / 2;
        for (i = 3; i < 16; i++)
                if (CPU_FREQ >= (clk / (i + 1)))
                        break;
-       if (i)
-               rcc |= SYSCTL_RCC_USESYSDIV | (i << SYSCTL_RCC_SYSDIV_SHIFT);
+       rcc |= SYSCTL_RCC_USESYSDIV |
+                       (evaluate_sysdiv(CPU_FREQ) << SYSCTL_RCC_SYSDIV_SHIFT);
 
        /*
         * Step #4: wait for the PLL to lock by polling the PLLLRIS bit in the
@@ -155,5 +195,5 @@ void clock_set_rate(void)
 
        HWREG(SYSCTL_RCC) = rcc;
 
-       __delay(16);
+       lm3s_busyWait(16);
 }