]> rtime.felk.cvut.cz Git - sysless.git/blob - arch/arm/mach-lpc13xx/libs/hal/hal_machperiph.c
Added arch for lpc13xx
[sysless.git] / arch / arm / mach-lpc13xx / libs / hal / hal_machperiph.c
1 #include <system_def.h>
2 #include <cpu_def.h>
3 #include <hal_machperiph.h>
4
5 //#include <stdint.h>
6 #include "LPC13xx.h"
7
8
9 /*----------------------------------------------------------------------------
10   Check the register settings
11  *----------------------------------------------------------------------------*/
12 #define CHECK_RANGE(val, min, max)                ((val < min) || (val > max))
13 #define CHECK_RSVD(val, mask)                     (val & mask)
14
15 /* Clock Configuration -------------------------------------------------------*/
16 #if (CHECK_RSVD((SYSOSCCTRL_Val),  ~0x00000003))
17    #error "SYSOSCCTRL: Invalid values of reserved bits!"
18 #endif
19
20 #if (CHECK_RSVD((WDTOSCCTRL_Val),  ~0x000001FF))
21    #error "WDTOSCCTRL: Invalid values of reserved bits!"
22 #endif
23
24 #if (CHECK_RANGE((SYSPLLCLKSEL_Val), 0, 2))
25    #error "SYSPLLCLKSEL: Value out of range!"
26 #endif
27
28 #if (CHECK_RSVD((SYSPLLCTRL_Val),  ~0x000001FF))
29    #error "SYSPLLCTRL: Invalid values of reserved bits!"
30 #endif
31
32 #if (CHECK_RSVD((MAINCLKSEL_Val),  ~0x00000003))
33    #error "MAINCLKSEL: Invalid values of reserved bits!"
34 #endif
35
36 #if (CHECK_RANGE((USBPLLCLKSEL_Val), 0, 1))
37    #error "USBPLLCLKSEL: Value out of range!"
38 #endif
39
40 #if (CHECK_RSVD((USBPLLCTRL_Val),  ~0x000001FF))
41    #error "USBPLLCTRL: Invalid values of reserved bits!"
42 #endif
43
44 #if (CHECK_RSVD((USBPLLUEN_Val),   ~0x00000001))
45    #error "USBPLLUEN: Invalid values of reserved bits!"
46 #endif
47
48 #if (CHECK_RANGE((SYSAHBCLKDIV_Val), 0, 255))
49    #error "SYSAHBCLKDIV: Value out of range!"
50 #endif
51
52 #if (CHECK_RSVD((AHBCLKCTRL_Val),  ~0x0001FFFF))
53    #error "AHBCLKCTRL: Invalid values of reserved bits!"
54 #endif
55
56 #if (CHECK_RSVD((SYSMEMREMAP_Val), ~0x00000003))
57    #error "SYSMEMREMAP: Invalid values of reserved bits!"
58 #endif
59
60
61 /*----------------------------------------------------------------------------
62   Clock Variable definitions
63  *----------------------------------------------------------------------------*/
64 unsigned int system_frequency = __SYSTEM_CLOCK; /*!< System Clock Frequency (Core Clock)  */
65
66 /*----------------------------------------------------------------------------
67   Clock functions
68  *----------------------------------------------------------------------------*/
69 void system_core_clock_update (void)            /* Get Core Clock Frequency      */
70 {
71   uint32_t wdt_osc = 0;
72
73   /* Determine clock frequency according to clock register values             */
74   switch ((LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F) {
75     case 0:  wdt_osc =  400000; break;
76     case 1:  wdt_osc =  500000; break;
77     case 2:  wdt_osc =  800000; break;
78     case 3:  wdt_osc = 1100000; break;
79     case 4:  wdt_osc = 1400000; break;
80     case 5:  wdt_osc = 1600000; break;
81     case 6:  wdt_osc = 1800000; break;
82     case 7:  wdt_osc = 2000000; break;
83     case 8:  wdt_osc = 2200000; break;
84     case 9:  wdt_osc = 2400000; break;
85     case 10: wdt_osc = 2600000; break;
86     case 11: wdt_osc = 2700000; break;
87     case 12: wdt_osc = 2900000; break;
88     case 13: wdt_osc = 3100000; break;
89     case 14: wdt_osc = 3200000; break;
90     case 15: wdt_osc = 3400000; break;
91   }
92   wdt_osc /= ((LPC_SYSCON->WDTOSCCTRL & 0x1F) << 1) + 2;
93  
94   switch (LPC_SYSCON->MAINCLKSEL & 0x03) {
95     case 0:                             /* Internal RC oscillator             */
96       system_frequency = __IRC_OSC_CLK;
97       break;
98     case 1:                             /* Input Clock to System PLL          */
99       switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
100           case 0:                       /* Internal RC oscillator             */
101             system_frequency = __IRC_OSC_CLK;
102             break;
103           case 1:                       /* System oscillator                  */
104             system_frequency = __SYS_OSC_CLK;
105             break;
106           case 2:                       /* WDT Oscillator                     */
107             system_frequency = wdt_osc;
108             break;
109           case 3:                       /* Reserved                           */
110             system_frequency = 0;
111             break;
112       }
113       break;
114     case 2:                             /* WDT Oscillator                     */
115       system_frequency = wdt_osc;
116       break;
117     case 3:                             /* System PLL Clock Out               */
118       switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
119           case 0:                       /* Internal RC oscillator             */
120             if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
121               system_frequency = __IRC_OSC_CLK;
122             } else {
123               system_frequency = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
124             }
125             break;
126           case 1:                       /* System oscillator                  */
127             if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
128               system_frequency = __SYS_OSC_CLK;
129             } else {
130               system_frequency = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
131             }
132             break;
133           case 2:                       /* WDT Oscillator                     */
134             if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
135               system_frequency = wdt_osc;
136             } else {
137               system_frequency = wdt_osc * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
138             }
139             break;
140           case 3:                       /* Reserved                           */
141             system_frequency = 0;
142             break;
143       }
144       break;
145   }
146
147   system_frequency /= LPC_SYSCON->SYSAHBCLKDIV;  
148
149 }
150
151 void system_clock_init(void)
152 {
153 #if (CLOCK_SETUP)                                 /* Clock Setup              */
154 #if (SYSCLK_SETUP)                                /* System Clock Setup       */
155
156 #if (SYSOSC_SETUP)                                /* System Oscillator Setup  */
157   uint32_t i;
158
159   LPC_SYSCON->PDRUNCFG     &= ~PDRUNCFG_SYSOSC_PD;          /* Power-up System Osc      */
160   LPC_SYSCON->SYSOSCCTRL    = SYSOSCCTRL_Val;
161   for (i = 0; i < 200; i++) __NOP();
162 #endif /* SYSOSC_SETUP */
163
164 #if (SYSPLL_SETUP)                                /* System PLL Setup         */
165   LPC_SYSCON->SYSPLLCLKSEL  = SYSPLLCLKSEL_Val;   /* Select PLL Input         */
166   LPC_SYSCON->SYSPLLCLKUEN  = 0x01;               /* Update Clock Source      */
167   LPC_SYSCON->SYSPLLCLKUEN  = 0x00;               /* Toggle Update Register   */
168   LPC_SYSCON->SYSPLLCLKUEN  = 0x01;
169   while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01));     /* Wait Until Updated       */
170   LPC_SYSCON->SYSPLLCTRL    = SYSPLLCTRL_Val;
171   LPC_SYSCON->PDRUNCFG     &= ~PDRUNCFG_SYSPLL_PD;          /* Power-up SYSPLL          */
172   while (!(LPC_SYSCON->SYSPLLSTAT & 0x01));           /* Wait Until PLL Locked    */
173 #else
174   LPC_SYSCON->PDRUNCFG     |=  PDRUNCFG_SYSPLL_PD; /* if PLL is not used, power-down PLL */
175 #endif /* SYSPLL_SETUP */
176
177   LPC_SYSCON->MAINCLKSEL    = MAINCLKSEL_Val;     /* Select Clock */
178   LPC_SYSCON->MAINCLKUEN    = 0x01;               /* Update MCLK Clock Source */
179   LPC_SYSCON->MAINCLKUEN    = 0x00;               /* Toggle Update Register   */
180   LPC_SYSCON->MAINCLKUEN    = 0x01;
181   while (!(LPC_SYSCON->MAINCLKUEN & 0x01));       /* Wait Until Updated       */
182
183 #endif /* SYSCLK_SETUP */
184
185 #if (USBCLK_SETUP)                                /* USB Clock Setup          */
186   LPC_SYSCON->PDRUNCFG     &= ~PDRUNCFG_USBPAD_PD;         /* Power-up USB PHY         */
187
188   #if (USBPLL_SETUP)                                /* USB PLL Setup            */
189   LPC_SYSCON->PDRUNCFG     &= ~PDRUNCFG_USBPLL_PD;         /* Power-up USB PLL         */
190   LPC_SYSCON->USBPLLCLKSEL  = USBPLLCLKSEL_Val;   /* Select PLL Input         */
191   LPC_SYSCON->USBPLLCLKUEN  = 0x01;               /* Update Clock Source      */
192   LPC_SYSCON->USBPLLCLKUEN  = 0x00;               /* Toggle Update Register   */
193   LPC_SYSCON->USBPLLCLKUEN  = 0x01;
194   while (!(LPC_SYSCON->USBPLLCLKUEN & 0x01));     /* Wait Until Updated       */
195   LPC_SYSCON->USBPLLCTRL    = USBPLLCTRL_Val;
196   while (!(LPC_SYSCON->USBPLLSTAT   & 0x01));     /* Wait Until PLL Locked    */
197   LPC_SYSCON->USBCLKSEL     = 0x00;               /* Select USB PLL           */
198 #else /* USBPLL_SETUP */
199   LPC_SYSCON->USBCLKSEL     = 0x01;               /* Select Main Clock        */
200 #endif /* USBPLL_SETUP */
201
202 #else /* USBCLK_SETUP */
203   LPC_SYSCON->PDRUNCFG     |=  PDRUNCFG_USBPAD_PD;         /* Power-down USB PHY       */
204   LPC_SYSCON->PDRUNCFG     |=  PDRUNCFG_USBPLL_PD;         /* Power-down USB PLL       */
205 #endif /* USBCLK_SETUP */
206
207   LPC_SYSCON->SYSAHBCLKDIV  = SYSAHBCLKDIV_Val;
208 #endif /* CLOCK_SETUP */
209
210   LPC_SYSCON->SYSAHBCLKCTRL = AHBCLKCTRL_Val;
211   LPC_SYSCON->PDRUNCFG     |= PDRUNCFG_WDTOSC_PD;                       /* Power down WDT, if it will be used, it should be enabled egain*/
212 }
213
214 //TODO: check WDT settings
215 void lpc_watchdog_feed()
216 {
217         unsigned long flags;
218
219         save_and_cli(flags);
220         LPC_WDT->FEED = 0xAA;
221         LPC_WDT->FEED = 0x55;
222         restore_flags(flags);
223 }
224
225 void lpc_watchdog_init(int on,int timeout_ms)
226 {
227         if (!on) return;
228         LPC_SYSCON->WDTOSCCTRL    = WDTOSCCTRL_Val;
229         LPC_SYSCON->WDTCLKDIV           = 1;                            //preddelic musi byt >0 (0 je disable, 1= deleni 1 atd.)
230         LPC_SYSCON->PDRUNCFG     &= ~PDRUNCFG_WDTOSC_PD;        // Power-up WDT Clock (kdyby byl nahodou vyputy, vychozi je ale zapnuto)
231         LPC_SYSCON->SYSAHBCLKCTRL |= SAHBCCTRL_WDT;     // je nutne povolit hodiny WDT v SYSAHBCLKCTRL
232
233         LPC_SYSCON->WDTCLKSEL = 2; //zdroj hodin bude WDT oscilator
234         LPC_SYSCON->WDTCLKUEN = 1;
235         LPC_SYSCON->WDTCLKUEN = 0;
236         LPC_SYSCON->WDTCLKUEN = 1;
237         while(!(LPC_SYSCON->WDTCLKUEN & 1));//prechozi 4 radky jsou nutne, aby se zmenil zdroj hodin
238         LPC_WDT->TC  = (((__WDT_OSC_CLK) / 1000) * (timeout_ms / 4));
239         //LPC_WDT->TC = 1000;//(__WDT_OSC_CLK/4)*(1000/timeout_ms);
240         LPC_WDT->MOD = 0x03;                               /* Enable watchdog timer and reset */
241 }
242
243 void power_down_unused_periph(void)
244 {
245         if ((LPC_SYSCON->MAINCLKSEL > 0) && (LPC_SYSCON->WDTCLKSEL > 0) && ((LPC_SYSCON->SYSPLLCLKSEL > 0) || (LPC_SYSCON->PDAWAKECFG & PDRUNCFG_SYSPLL_PD)))
246                 LPC_SYSCON->PDRUNCFG |=  PDRUNCFG_IRCOUT_PD | PDRUNCFG_IRC_PD; /* if IRC is not used, power-down IRC */
247
248         //vypnu nepotrebne periferie, pokud je budu potrebovat, zapnou se v initu dane periferie
249         LPC_SYSCON->PDRUNCFG     |=  PDRUNCFG_ADC_PD;                   /* power-down ADC */
250 }