]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/common/services/clock/sam4l/sysclk.c
Add SAM4L demo.
[freertos] / FreeRTOS / Demo / CORTEX_M4_ATSAM4L_Atmel_Studio / src / asf / common / services / clock / sam4l / sysclk.c
1 /**\r
2  * \file\r
3  *\r
4  * \brief Chip-specific system clock management functions\r
5  *\r
6  * Copyright (c) 2012-2013 Atmel Corporation. All rights reserved.\r
7  *\r
8  * \asf_license_start\r
9  *\r
10  * \page License\r
11  *\r
12  * Redistribution and use in source and binary forms, with or without\r
13  * modification, are permitted provided that the following conditions are met:\r
14  *\r
15  * 1. Redistributions of source code must retain the above copyright notice,\r
16  *    this list of conditions and the following disclaimer.\r
17  *\r
18  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
19  *    this list of conditions and the following disclaimer in the documentation\r
20  *    and/or other materials provided with the distribution.\r
21  *\r
22  * 3. The name of Atmel may not be used to endorse or promote products derived\r
23  *    from this software without specific prior written permission.\r
24  *\r
25  * 4. This software may only be redistributed and used in connection with an\r
26  *    Atmel microcontroller product.\r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
38  * POSSIBILITY OF SUCH DAMAGE.\r
39  *\r
40  * \asf_license_stop\r
41  *\r
42  */\r
43 \r
44 #include <compiler.h>\r
45 #include <stdbool.h>\r
46 #include <sysclk.h>\r
47 #include <flashcalw.h>\r
48 #include <bpm.h>\r
49 #include <osc.h>\r
50 \r
51 /**\r
52  * \weakgroup sysclk_group\r
53  * @{\r
54  */\r
55 \r
56 #if ((CONFIG_SYSCLK_CPU_DIV > CONFIG_SYSCLK_PBA_DIV) || \\r
57      (CONFIG_SYSCLK_CPU_DIV > CONFIG_SYSCLK_PBB_DIV) || \\r
58      (CONFIG_SYSCLK_CPU_DIV > CONFIG_SYSCLK_PBC_DIV) || \\r
59      (CONFIG_SYSCLK_CPU_DIV > CONFIG_SYSCLK_PBD_DIV))\r
60 # error CONFIG_SYSCLK_PBx_DIV must be equal to or more than CONFIG_SYSCLK_CPU_DIV.\r
61 #endif\r
62 \r
63 /**\r
64  * \internal\r
65  * \defgroup sysclk_internals_group System Clock internals\r
66  *\r
67  * System clock management is fairly straightforward apart from one\r
68  * thing: Enabling and disabling bus bridges. When all peripherals on a\r
69  * given bus are disabled, the bridge to the bus may be disabled. Only\r
70  * the PBA and PBB busses support this, and it is not practical to\r
71  * disable the PBA bridge as it includes the PM and SCIF modules, so turning\r
72  * it off would make it impossible to turn anything back on again.\r
73  *\r
74  * The system clock implementation keeps track of a reference count for\r
75  * PBB. When the reference count is zero, the bus bridge is disabled, otherwise\r
76  * it is enabled.\r
77  *\r
78  * @{\r
79  */\r
80 \r
81 /**\r
82  * \internal\r
83  * \name Initial module clock masks\r
84  *\r
85  * These are the mask values written to the xxxMASK registers during\r
86  * initialization if the user has overridden the default behavior of all clocks\r
87  * left enabled. These values assume that:\r
88  *   - Debugging should be possible\r
89  *   - The program may be running from flash\r
90  *   - The PM should be available to unmask other clocks\r
91  *   - All on-chip RAM should be available\r
92  *   - SCIF, BPM, BSCIF and GPIO are made permanently available for now; this\r
93  *     may change in the future.\r
94  */\r
95 //@{\r
96 //! \internal\r
97 //! \brief Initial value of CPUMASK\r
98 #define SYSCLK_INIT_MINIMAL_CPUMASK       0\r
99 \r
100 //! \internal\r
101 //! \brief Initial value of HSBMASK\r
102 #define SYSCLK_INIT_MINIMAL_HSBMASK                                    \\r
103         ((1 << SYSCLK_HFLASHC_DATA)                                        \\r
104                 | (1 << SYSCLK_PBB_BRIDGE)                                     \\r
105                 | (1 << SYSCLK_PBC_BRIDGE)                                     \\r
106                 | (1 << SYSCLK_PBD_BRIDGE))\r
107 \r
108 //! \internal\r
109 //! \brief Initial value of PBAMASK\r
110 #define SYSCLK_INIT_MINIMAL_PBAMASK       0\r
111 \r
112 //! \internal\r
113 //! \brief Initial value of PBBMASK\r
114 #define SYSCLK_INIT_MINIMAL_PBBMASK       (1 << SYSCLK_HFLASHC_REGS)\r
115 \r
116 //! \internal\r
117 //! \brief Initial value of PBCMASK\r
118 #define SYSCLK_INIT_MINIMAL_PBCMASK                                    \\r
119         ((1 << SYSCLK_PM)                                                  \\r
120                 | (1 << SYSCLK_GPIO)                                           \\r
121                 | (1 << SYSCLK_SCIF))\r
122 \r
123 //! \internal\r
124 //! \brief Initial value of PBDMASK\r
125 #define SYSCLK_INIT_MINIMAL_PBDMASK                                    \\r
126         ((1 << SYSCLK_BPM)                                                 \\r
127                 | (1 << SYSCLK_BSCIF))\r
128 //@}\r
129 \r
130 #if defined(CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)\r
131 /**\r
132  * \brief boolean signalling that the sysclk_init is done.\r
133  */\r
134 bool sysclk_initialized = false;\r
135 #endif\r
136 \r
137 /**\r
138  * \internal\r
139  * \brief Enable a maskable module clock.\r
140  * \param bus_id Bus index, given by the \c PM_CLK_GRP_xxx definitions.\r
141  * \param module_index Index of the module to be enabled. This is the\r
142  * bit number in the corresponding xxxMASK register.\r
143  */\r
144 void sysclk_priv_enable_module(uint32_t bus_id, uint32_t module_index)\r
145 {\r
146         irqflags_t flags;\r
147         uint32_t   mask;\r
148 \r
149         flags = cpu_irq_save();\r
150 \r
151         /* Enable the clock */\r
152         mask = *(&PM->PM_CPUMASK + bus_id);\r
153         mask |= 1U << module_index;\r
154         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu) |\r
155                 BPM_UNLOCK_ADDR(((uint32_t)&PM->PM_CPUMASK - (uint32_t)PM) + (4 * bus_id));\r
156         *(&PM->PM_CPUMASK + bus_id) = mask;\r
157 \r
158         cpu_irq_restore(flags);\r
159 }\r
160 \r
161 /**\r
162  * \internal\r
163  * \brief Disable a maskable module clock.\r
164  * \param bus_id Bus index, given by the \c PM_CLK_GRP_xxx definitions.\r
165  * \param module_index Index of the module to be disabled. This is the\r
166  * bit number in the corresponding xxxMASK register.\r
167  */\r
168 void sysclk_priv_disable_module(uint32_t bus_id, uint32_t module_index)\r
169 {\r
170         irqflags_t flags;\r
171         uint32_t   mask;\r
172 \r
173         flags = cpu_irq_save();\r
174 \r
175         /* Disable the clock */\r
176         mask = *(&PM->PM_CPUMASK + bus_id);\r
177         mask &= ~(1U << module_index);\r
178         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu) |\r
179                 BPM_UNLOCK_ADDR(((uint32_t)&PM->PM_CPUMASK - (uint32_t)PM) + (4 * bus_id));\r
180         *(&PM->PM_CPUMASK + bus_id) = mask;\r
181 \r
182         cpu_irq_restore(flags);\r
183 }\r
184 \r
185 //! @}\r
186 \r
187 /**\r
188  * \brief Enable a module clock derived from the PBA clock\r
189  * \param index Index of the module clock in the PBAMASK register\r
190  */\r
191 void sysclk_enable_pba_module(uint32_t index)\r
192 {\r
193         irqflags_t flags;\r
194 \r
195         /* Enable the bridge if necessary */\r
196         flags = cpu_irq_save();\r
197 \r
198         if (PM->PM_PBAMASK == 0) {\r
199                 sysclk_enable_hsb_module(SYSCLK_PBA_BRIDGE);\r
200         }\r
201 \r
202         cpu_irq_restore(flags);\r
203 \r
204         /* Enable the module */\r
205         sysclk_priv_enable_module(PM_CLK_GRP_PBA, index);\r
206 }\r
207 \r
208 /**\r
209  * \brief Disable a module clock derived from the PBA clock\r
210  * \param index Index of the module clock in the PBAMASK register\r
211  */\r
212 void sysclk_disable_pba_module(uint32_t index)\r
213 {\r
214         irqflags_t flags;\r
215 \r
216         /* Disable the module */\r
217         sysclk_priv_disable_module(PM_CLK_GRP_PBA, index);\r
218 \r
219         /* Disable the bridge if possible */\r
220         flags = cpu_irq_save();\r
221 \r
222         if (PM->PM_PBAMASK == 0) {\r
223                 sysclk_disable_hsb_module(SYSCLK_PBA_BRIDGE);\r
224         }\r
225 \r
226         cpu_irq_restore(flags);\r
227 }\r
228 \r
229 /**\r
230  * \brief Enable a module clock derived from the PBB clock\r
231  * \param index Index of the module clock in the PBBMASK register\r
232  */\r
233 void sysclk_enable_pbb_module(uint32_t index)\r
234 {\r
235         irqflags_t flags;\r
236 \r
237         /* Enable the bridge if necessary */\r
238         flags = cpu_irq_save();\r
239 \r
240         if (PM->PM_PBBMASK == 0) {\r
241                 sysclk_enable_hsb_module(SYSCLK_PBB_BRIDGE);\r
242         }\r
243 \r
244         cpu_irq_restore(flags);\r
245 \r
246         /* Enable the module */\r
247         sysclk_priv_enable_module(PM_CLK_GRP_PBB, index);\r
248 }\r
249 \r
250 /**\r
251  * \brief Disable a module clock derived from the PBB clock\r
252  * \param index Index of the module clock in the PBBMASK register\r
253  */\r
254 void sysclk_disable_pbb_module(uint32_t index)\r
255 {\r
256         irqflags_t flags;\r
257 \r
258         /* Disable the module */\r
259         sysclk_priv_disable_module(PM_CLK_GRP_PBB, index);\r
260 \r
261         /* Disable the bridge if possible */\r
262         flags = cpu_irq_save();\r
263 \r
264         if (PM->PM_PBBMASK == 0) {\r
265                 sysclk_disable_hsb_module(SYSCLK_PBB_BRIDGE);\r
266         }\r
267 \r
268         cpu_irq_restore(flags);\r
269 }\r
270 \r
271 /**\r
272  * \brief Retrieves the current rate in Hz of the Peripheral Bus clock attached\r
273  *        to the specified peripheral.\r
274  *\r
275  * \param module Pointer to the module's base address.\r
276  *\r
277  * \return Frequency of the bus attached to the specified peripheral, in Hz.\r
278  */\r
279 uint32_t sysclk_get_peripheral_bus_hz(const volatile void *module)\r
280 {\r
281         /* Fallthroughs intended for modules sharing the same peripheral bus. */\r
282         switch ((uintptr_t)module) {\r
283         case IISC_ADDR:\r
284         case SPI_ADDR:\r
285         case TC0_ADDR:\r
286         case TC1_ADDR:\r
287         case TWIM0_ADDR:\r
288         case TWIS0_ADDR:\r
289         case TWIM1_ADDR:\r
290         case TWIS1_ADDR:\r
291         case USART0_ADDR:\r
292         case USART1_ADDR:\r
293         case USART2_ADDR:\r
294         case USART3_ADDR:\r
295         case ADCIFE_ADDR:\r
296         case DACC_ADDR:\r
297         case ACIFC_ADDR:\r
298         case GLOC_ADDR:\r
299         case ABDACB_ADDR:\r
300         case TRNG_ADDR:\r
301         case PARC_ADDR:\r
302         case CATB_ADDR:\r
303         case TWIM2_ADDR:\r
304         case TWIM3_ADDR:\r
305         case LCDCA_ADDR:\r
306                 return sysclk_get_pba_hz();\r
307 \r
308         case HFLASHC_ADDR:\r
309         case HCACHE_ADDR:\r
310         case HMATRIX_ADDR:\r
311         case PDCA_ADDR:\r
312         case CRCCU_ADDR:\r
313         case USBC_ADDR:\r
314         case PEVC_ADDR:\r
315                 return sysclk_get_pbb_hz();\r
316 \r
317         case PM_ADDR:\r
318         case CHIPID_ADDR:\r
319         case SCIF_ADDR:\r
320         case FREQM_ADDR:\r
321         case GPIO_ADDR:\r
322                 return sysclk_get_pbc_hz();\r
323 \r
324         case BPM_ADDR:\r
325         case BSCIF_ADDR:\r
326         case AST_ADDR:\r
327         case WDT_ADDR:\r
328         case EIC_ADDR:\r
329         case PICOUART_ADDR:\r
330                 return sysclk_get_pbd_hz();\r
331 \r
332         default:\r
333                 Assert(false);\r
334                 return 0;\r
335         }\r
336 }\r
337 \r
338 /**\r
339  * \brief Enable a peripheral's clock from its base address.\r
340  *\r
341  *  Enables the clock to a peripheral, given its base address. If the peripheral\r
342  *  has an associated clock on the HSB bus, this will be enabled also.\r
343  *\r
344  * \param module Pointer to the module's base address.\r
345  */\r
346 void sysclk_enable_peripheral_clock(const volatile void *module)\r
347 {\r
348         switch ((uintptr_t)module) {\r
349         case AESA_ADDR:\r
350                 sysclk_enable_hsb_module(SYSCLK_AESA_HSB);\r
351                 break;\r
352 \r
353         case IISC_ADDR:\r
354                 sysclk_enable_pba_module(SYSCLK_IISC);\r
355                 break;\r
356 \r
357         case SPI_ADDR:\r
358                 sysclk_enable_pba_module(SYSCLK_SPI);\r
359                 break;\r
360 \r
361         case TC0_ADDR:\r
362                 sysclk_enable_pba_module(SYSCLK_TC0);\r
363                 sysclk_enable_pba_divmask(PBA_DIVMASK_TIMER_CLOCK2\r
364                         | PBA_DIVMASK_TIMER_CLOCK3\r
365                         | PBA_DIVMASK_TIMER_CLOCK4\r
366                         | PBA_DIVMASK_TIMER_CLOCK5\r
367                         );\r
368                 break;\r
369 \r
370         case TC1_ADDR:\r
371                 sysclk_enable_pba_module(SYSCLK_TC1);\r
372                 sysclk_enable_pba_divmask(PBA_DIVMASK_TIMER_CLOCK2\r
373                         | PBA_DIVMASK_TIMER_CLOCK3\r
374                         | PBA_DIVMASK_TIMER_CLOCK4\r
375                         | PBA_DIVMASK_TIMER_CLOCK5\r
376                         );\r
377                 break;\r
378 \r
379         case TWIM0_ADDR:\r
380                 sysclk_enable_pba_module(SYSCLK_TWIM0);\r
381                 break;\r
382 \r
383         case TWIS0_ADDR:\r
384                 sysclk_enable_pba_module(SYSCLK_TWIS0);\r
385                 break;\r
386 \r
387         case TWIM1_ADDR:\r
388                 sysclk_enable_pba_module(SYSCLK_TWIM1);\r
389                 break;\r
390 \r
391         case TWIS1_ADDR:\r
392                 sysclk_enable_pba_module(SYSCLK_TWIS1);\r
393                 break;\r
394 \r
395         case USART0_ADDR:\r
396                 sysclk_enable_pba_module(SYSCLK_USART0);\r
397                 sysclk_enable_pba_divmask(PBA_DIVMASK_CLK_USART);\r
398                 break;\r
399 \r
400         case USART1_ADDR:\r
401                 sysclk_enable_pba_module(SYSCLK_USART1);\r
402                 sysclk_enable_pba_divmask(PBA_DIVMASK_CLK_USART);\r
403                 break;\r
404 \r
405         case USART2_ADDR:\r
406                 sysclk_enable_pba_module(SYSCLK_USART2);\r
407                 sysclk_enable_pba_divmask(PBA_DIVMASK_CLK_USART);\r
408                 break;\r
409 \r
410         case USART3_ADDR:\r
411                 sysclk_enable_pba_module(SYSCLK_USART3);\r
412                 sysclk_enable_pba_divmask(PBA_DIVMASK_CLK_USART);\r
413                 break;\r
414 \r
415         case ADCIFE_ADDR:\r
416                 sysclk_enable_pba_module(SYSCLK_ADCIFE);\r
417                 break;\r
418 \r
419         case DACC_ADDR:\r
420                 sysclk_enable_pba_module(SYSCLK_DACC);\r
421                 break;\r
422 \r
423         case ACIFC_ADDR:\r
424                 sysclk_enable_pba_module(SYSCLK_ACIFC);\r
425                 break;\r
426 \r
427         case GLOC_ADDR:\r
428                 sysclk_enable_pba_module(SYSCLK_GLOC);\r
429                 break;\r
430 \r
431         case ABDACB_ADDR:\r
432                 sysclk_enable_pba_module(SYSCLK_ABDACB);\r
433                 break;\r
434 \r
435         case TRNG_ADDR:\r
436                 sysclk_enable_pba_module(SYSCLK_TRNG);\r
437                 break;\r
438 \r
439         case PARC_ADDR:\r
440                 sysclk_enable_pba_module(SYSCLK_PARC);\r
441                 break;\r
442 \r
443         case CATB_ADDR:\r
444                 sysclk_enable_pba_module(SYSCLK_CATB);\r
445                 break;\r
446 \r
447         case TWIM2_ADDR:\r
448                 sysclk_enable_pba_module(SYSCLK_TWIM2);\r
449                 break;\r
450 \r
451         case TWIM3_ADDR:\r
452                 sysclk_enable_pba_module(SYSCLK_TWIM3);\r
453                 break;\r
454 \r
455         case LCDCA_ADDR:\r
456                 sysclk_enable_pba_module(SYSCLK_LCDCA);\r
457                 break;\r
458 \r
459         case HFLASHC_ADDR:\r
460                 sysclk_enable_hsb_module(SYSCLK_HFLASHC_DATA);\r
461                 sysclk_enable_pbb_module(SYSCLK_HFLASHC_REGS);\r
462                 break;\r
463 \r
464         case HCACHE_ADDR:\r
465                 sysclk_enable_hsb_module(SYSCLK_HRAMC1_DATA);\r
466                 sysclk_enable_pbb_module(SYSCLK_HRAMC1_REGS);\r
467                 break;\r
468 \r
469         case HMATRIX_ADDR:\r
470                 sysclk_enable_pbb_module(SYSCLK_HMATRIX);\r
471                 break;\r
472 \r
473         case PDCA_ADDR:\r
474                 sysclk_enable_hsb_module(SYSCLK_PDCA_HSB);\r
475                 sysclk_enable_pbb_module(SYSCLK_PDCA_PB);\r
476                 break;\r
477 \r
478         case CRCCU_ADDR:\r
479                 sysclk_enable_hsb_module(SYSCLK_CRCCU_DATA);\r
480                 sysclk_enable_pbb_module(SYSCLK_CRCCU_REGS);\r
481                 break;\r
482 \r
483         case USBC_ADDR:\r
484                 sysclk_enable_hsb_module(SYSCLK_USBC_DATA);\r
485                 sysclk_enable_pbb_module(SYSCLK_USBC_REGS);\r
486                 break;\r
487 \r
488         case PEVC_ADDR:\r
489                 sysclk_enable_pbb_module(SYSCLK_PEVC);\r
490                 break;\r
491 \r
492         case PM_ADDR:\r
493                 sysclk_enable_pbc_module(SYSCLK_PM);\r
494                 break;\r
495 \r
496         case CHIPID_ADDR:\r
497                 sysclk_enable_pbc_module(SYSCLK_CHIPID);\r
498                 break;\r
499 \r
500         case SCIF_ADDR:\r
501                 sysclk_enable_pbc_module(SYSCLK_SCIF);\r
502                 break;\r
503 \r
504         case FREQM_ADDR:\r
505                 sysclk_enable_pbc_module(SYSCLK_FREQM);\r
506                 break;\r
507 \r
508         case GPIO_ADDR:\r
509                 sysclk_enable_pbc_module(SYSCLK_GPIO);\r
510                 break;\r
511 \r
512         case BPM_ADDR:\r
513                 sysclk_enable_pbd_module(SYSCLK_BPM);\r
514                 break;\r
515 \r
516         case BSCIF_ADDR:\r
517                 sysclk_enable_pbd_module(SYSCLK_BSCIF);\r
518                 break;\r
519 \r
520         case AST_ADDR:\r
521                 sysclk_enable_pbd_module(SYSCLK_AST);\r
522                 break;\r
523 \r
524         case WDT_ADDR:\r
525                 sysclk_enable_pbd_module(SYSCLK_WDT);\r
526                 break;\r
527 \r
528         case EIC_ADDR:\r
529                 sysclk_enable_pbd_module(SYSCLK_EIC);\r
530                 break;\r
531 \r
532         case PICOUART_ADDR:\r
533                 sysclk_enable_pbd_module(SYSCLK_PICOUART);\r
534                 break;\r
535 \r
536         default:\r
537                 Assert(false);\r
538                 return;\r
539         }\r
540 }\r
541 \r
542 /**\r
543  * \brief Disable a peripheral's clock from its base address.\r
544  *\r
545  *  Disables the clock to a peripheral, given its base address. If the peripheral\r
546  *  has an associated clock on the HSB bus, this will be disabled also.\r
547  *\r
548  * \param module Pointer to the module's base address.\r
549  */\r
550 void sysclk_disable_peripheral_clock(const volatile void *module)\r
551 {\r
552         switch ((uintptr_t)module) {\r
553         case AESA_ADDR:\r
554                 sysclk_disable_hsb_module(SYSCLK_AESA_HSB);\r
555                 break;\r
556 \r
557         case IISC_ADDR:\r
558                 sysclk_disable_pba_module(SYSCLK_IISC);\r
559                 break;\r
560 \r
561         case SPI_ADDR:\r
562                 sysclk_disable_pba_module(SYSCLK_SPI);\r
563                 break;\r
564 \r
565         case TC0_ADDR:\r
566                 sysclk_disable_pba_module(SYSCLK_TC0);\r
567                 break;\r
568 \r
569         case TC1_ADDR:\r
570                 sysclk_disable_pba_module(SYSCLK_TC1);\r
571                 break;\r
572 \r
573         case TWIM0_ADDR:\r
574                 sysclk_disable_pba_module(SYSCLK_TWIM0);\r
575                 break;\r
576 \r
577         case TWIS0_ADDR:\r
578                 sysclk_disable_pba_module(SYSCLK_TWIS0);\r
579                 break;\r
580 \r
581         case TWIM1_ADDR:\r
582                 sysclk_disable_pba_module(SYSCLK_TWIM1);\r
583                 break;\r
584 \r
585         case TWIS1_ADDR:\r
586                 sysclk_disable_pba_module(SYSCLK_TWIS1);\r
587                 break;\r
588 \r
589         case USART0_ADDR:\r
590                 sysclk_disable_pba_module(SYSCLK_USART0);\r
591                 break;\r
592 \r
593         case USART1_ADDR:\r
594                 sysclk_disable_pba_module(SYSCLK_USART1);\r
595                 break;\r
596 \r
597         case USART2_ADDR:\r
598                 sysclk_disable_pba_module(SYSCLK_USART2);\r
599                 break;\r
600 \r
601         case USART3_ADDR:\r
602                 sysclk_disable_pba_module(SYSCLK_USART3);\r
603                 break;\r
604 \r
605         case ADCIFE_ADDR:\r
606                 sysclk_disable_pba_module(SYSCLK_ADCIFE);\r
607                 break;\r
608 \r
609         case DACC_ADDR:\r
610                 sysclk_disable_pba_module(SYSCLK_DACC);\r
611                 break;\r
612 \r
613         case ACIFC_ADDR:\r
614                 sysclk_disable_pba_module(SYSCLK_ACIFC);\r
615                 break;\r
616 \r
617         case GLOC_ADDR:\r
618                 sysclk_disable_pba_module(SYSCLK_GLOC);\r
619                 break;\r
620 \r
621         case ABDACB_ADDR:\r
622                 sysclk_disable_pba_module(SYSCLK_ABDACB);\r
623                 break;\r
624 \r
625         case TRNG_ADDR:\r
626                 sysclk_disable_pba_module(SYSCLK_TRNG);\r
627                 break;\r
628 \r
629         case PARC_ADDR:\r
630                 sysclk_disable_pba_module(SYSCLK_PARC);\r
631                 break;\r
632 \r
633         case CATB_ADDR:\r
634                 sysclk_disable_pba_module(SYSCLK_CATB);\r
635                 break;\r
636 \r
637         case TWIM2_ADDR:\r
638                 sysclk_disable_pba_module(SYSCLK_TWIM2);\r
639                 break;\r
640 \r
641         case TWIM3_ADDR:\r
642                 sysclk_disable_pba_module(SYSCLK_TWIM3);\r
643                 break;\r
644 \r
645         case LCDCA_ADDR:\r
646                 sysclk_disable_pba_module(SYSCLK_LCDCA);\r
647                 break;\r
648 \r
649         case HFLASHC_ADDR:\r
650                 sysclk_disable_pbb_module(SYSCLK_HFLASHC_REGS);\r
651                 break;\r
652 \r
653         case HCACHE_ADDR:\r
654                 sysclk_disable_hsb_module(SYSCLK_HRAMC1_DATA);\r
655                 sysclk_disable_pbb_module(SYSCLK_HRAMC1_REGS);\r
656                 break;\r
657 \r
658         case HMATRIX_ADDR:\r
659                 sysclk_disable_pbb_module(SYSCLK_HMATRIX);\r
660                 break;\r
661 \r
662         case PDCA_ADDR:\r
663                 sysclk_disable_hsb_module(SYSCLK_PDCA_HSB);\r
664                 sysclk_disable_pbb_module(SYSCLK_PDCA_PB);\r
665                 break;\r
666 \r
667         case CRCCU_ADDR:\r
668                 sysclk_disable_hsb_module(SYSCLK_CRCCU_DATA);\r
669                 sysclk_disable_pbb_module(SYSCLK_CRCCU_REGS);\r
670                 break;\r
671 \r
672         case USBC_ADDR:\r
673                 sysclk_disable_hsb_module(SYSCLK_USBC_DATA);\r
674                 sysclk_disable_pbb_module(SYSCLK_USBC_REGS);\r
675                 break;\r
676 \r
677         case PEVC_ADDR:\r
678                 sysclk_disable_pbb_module(SYSCLK_PEVC);\r
679                 break;\r
680 \r
681         case PM_ADDR:\r
682                 sysclk_disable_pbc_module(SYSCLK_PM);\r
683                 break;\r
684 \r
685         case CHIPID_ADDR:\r
686                 sysclk_disable_pbc_module(SYSCLK_CHIPID);\r
687                 break;\r
688 \r
689         case SCIF_ADDR:\r
690                 sysclk_disable_pbc_module(SYSCLK_SCIF);\r
691                 break;\r
692 \r
693         case FREQM_ADDR:\r
694                 sysclk_disable_pbc_module(SYSCLK_FREQM);\r
695                 break;\r
696 \r
697         case GPIO_ADDR:\r
698                 sysclk_disable_pbc_module(SYSCLK_GPIO);\r
699                 break;\r
700 \r
701         case BPM_ADDR:\r
702                 sysclk_disable_pbd_module(SYSCLK_BPM);\r
703                 break;\r
704 \r
705         case BSCIF_ADDR:\r
706                 sysclk_disable_pbd_module(SYSCLK_BSCIF);\r
707                 break;\r
708 \r
709         case AST_ADDR:\r
710                 sysclk_disable_pbd_module(SYSCLK_AST);\r
711                 break;\r
712 \r
713         case WDT_ADDR:\r
714                 sysclk_disable_pbd_module(SYSCLK_WDT);\r
715                 break;\r
716 \r
717         case EIC_ADDR:\r
718                 sysclk_disable_pbd_module(SYSCLK_EIC);\r
719                 break;\r
720 \r
721         case PICOUART_ADDR:\r
722                 sysclk_disable_pbd_module(SYSCLK_PICOUART);\r
723                 break;\r
724 \r
725         default:\r
726                 Assert(false);\r
727                 return;\r
728         }\r
729 \r
730         // Disable PBA divided clock if possible.\r
731 #define PBADIV_CLKSRC_MASK (SYSCLK_TC0 | SYSCLK_TC1 \\r
732                 | SYSCLK_USART0 | SYSCLK_USART1 | SYSCLK_USART2 | SYSCLK_USART3)\r
733         if ((PM->PM_PBAMASK & PBADIV_CLKSRC_MASK) == 0) {\r
734                 sysclk_disable_pba_divmask(PBA_DIVMASK_Msk);\r
735         }\r
736 }\r
737 \r
738 \r
739 /**\r
740  * \brief Set system clock prescaler configuration\r
741  *\r
742  * This function will change the system clock prescaler configuration to\r
743  * match the parameters.\r
744  *\r
745  * \note The parameters to this function are device-specific.\r
746  *\r
747  * \param cpu_shift The CPU clock will be divided by \f$2^{cpu\_shift}\f$\r
748  * \param pba_shift The PBA clock will be divided by \f$2^{pba\_shift}\f$\r
749  * \param pbb_shift The PBB clock will be divided by \f$2^{pbb\_shift}\f$\r
750  * \param pbc_shift The PBC clock will be divided by \f$2^{pbc\_shift}\f$\r
751  * \param pbd_shift The PBD clock will be divided by \f$2^{pbd\_shift}\f$\r
752  */\r
753 void sysclk_set_prescalers(uint32_t cpu_shift,\r
754                 uint32_t pba_shift, uint32_t pbb_shift,\r
755                 uint32_t pbc_shift, uint32_t pbd_shift)\r
756 {\r
757         irqflags_t flags;\r
758         uint32_t   cpu_cksel = 0;\r
759         uint32_t   pba_cksel = 0;\r
760         uint32_t   pbb_cksel = 0;\r
761         uint32_t   pbc_cksel = 0;\r
762         uint32_t   pbd_cksel = 0;\r
763 \r
764         Assert(cpu_shift <= pba_shift);\r
765         Assert(cpu_shift <= pbb_shift);\r
766         Assert(cpu_shift <= pbc_shift);\r
767         Assert(cpu_shift <= pbd_shift);\r
768 \r
769         if (cpu_shift > 0) {\r
770                 cpu_cksel = (PM_CPUSEL_CPUSEL(cpu_shift - 1))\r
771                                 | PM_CPUSEL_CPUDIV;\r
772         }\r
773 \r
774         if (pba_shift > 0) {\r
775                 pba_cksel = (PM_PBASEL_PBSEL(pba_shift - 1))\r
776                                 | PM_PBASEL_PBDIV;\r
777         }\r
778 \r
779         if (pbb_shift > 0) {\r
780                 pbb_cksel = (PM_PBBSEL_PBSEL(pbb_shift - 1))\r
781                                 | PM_PBBSEL_PBDIV;\r
782         }\r
783 \r
784         if (pbc_shift > 0) {\r
785                 pbc_cksel = (PM_PBCSEL_PBSEL(pbc_shift - 1))\r
786                                 | PM_PBCSEL_PBDIV;\r
787         }\r
788 \r
789         if (pbd_shift > 0) {\r
790                 pbd_cksel = (PM_PBDSEL_PBSEL(pbd_shift - 1))\r
791                                 | PM_PBDSEL_PBDIV;\r
792         }\r
793 \r
794         flags = cpu_irq_save();\r
795 \r
796         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
797                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_CPUSEL - (uint32_t)PM);\r
798         PM->PM_CPUSEL = cpu_cksel;\r
799 \r
800         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
801                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBASEL - (uint32_t)PM);\r
802         PM->PM_PBASEL = pba_cksel;\r
803 \r
804         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
805                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBBSEL - (uint32_t)PM);\r
806         PM->PM_PBBSEL = pbb_cksel;\r
807 \r
808         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
809                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBCSEL - (uint32_t)PM);\r
810         PM->PM_PBCSEL = pbc_cksel;\r
811 \r
812         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
813                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBDSEL - (uint32_t)PM);\r
814         PM->PM_PBDSEL = pbd_cksel;\r
815 \r
816         cpu_irq_restore(flags);\r
817 }\r
818 \r
819 /**\r
820  * \brief Change the source of the main system clock.\r
821  *\r
822  * \param src The new system clock source. Must be one of the constants\r
823  * from the <em>System Clock Sources</em> section.\r
824  */\r
825 void sysclk_set_source(uint32_t src)\r
826 {\r
827         irqflags_t flags;\r
828         Assert(src <= SYSCLK_SRC_RC1M);\r
829 \r
830         flags = cpu_irq_save();\r
831         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
832                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_MCCTRL - (uint32_t)PM);\r
833         PM->PM_MCCTRL = src;\r
834         cpu_irq_restore(flags);\r
835 }\r
836 \r
837 #if defined(CONFIG_USBCLK_SOURCE) || defined(__DOXYGEN__)\r
838 /**\r
839  * \brief Enable the USB generic clock\r
840  *\r
841  * \pre The USB generic clock must be configured to 48MHz.\r
842  * CONFIG_USBCLK_SOURCE and CONFIG_USBCLK_DIV must be defined with proper\r
843  * configuration. The selected clock source must also be configured.\r
844  */\r
845 void sysclk_enable_usb(void)\r
846 {\r
847         // Note: the SYSCLK_PBB_BRIDGE clock is enabled by\r
848         // sysclk_enable_pbb_module().\r
849         sysclk_enable_pbb_module(SYSCLK_USBC_REGS);\r
850         sysclk_enable_hsb_module(SYSCLK_USBC_DATA);\r
851 \r
852         genclk_enable_config(7, CONFIG_USBCLK_SOURCE, CONFIG_USBCLK_DIV);\r
853 }\r
854 \r
855 /**\r
856  * \brief Disable the USB generic clock\r
857  */\r
858 void sysclk_disable_usb(void)\r
859 {\r
860    genclk_disable(7);\r
861 }\r
862 #endif // CONFIG_USBCLK_SOURCE\r
863 \r
864 void sysclk_init(void)\r
865 {\r
866         uint32_t ps_value = 0;\r
867         bool is_fwu_enabled = false;\r
868 \r
869 #if CONFIG_HCACHE_ENABLE == 1\r
870         /* Enable HCACHE */\r
871         sysclk_enable_peripheral_clock(HCACHE);\r
872         HCACHE->HCACHE_CTRL = HCACHE_CTRL_CEN_YES;\r
873         while (!(HCACHE->HCACHE_SR & HCACHE_SR_CSTS_EN));\r
874 #endif\r
875 \r
876         /* Set up system clock dividers if different from defaults */\r
877         if ((CONFIG_SYSCLK_CPU_DIV > 0) || (CONFIG_SYSCLK_PBA_DIV > 0) ||\r
878                         (CONFIG_SYSCLK_PBB_DIV > 0) || (CONFIG_SYSCLK_PBC_DIV > 0) ||\r
879                         (CONFIG_SYSCLK_PBD_DIV > 0)) {\r
880                 sysclk_set_prescalers(CONFIG_SYSCLK_CPU_DIV,\r
881                                 CONFIG_SYSCLK_PBA_DIV,\r
882                                 CONFIG_SYSCLK_PBB_DIV,\r
883                                 CONFIG_SYSCLK_PBC_DIV,\r
884                                 CONFIG_SYSCLK_PBD_DIV\r
885                                 );\r
886         }\r
887 \r
888         /* Automatically select best power scaling mode */\r
889 #ifdef CONFIG_FLASH_READ_MODE_HIGH_SPEED_ENABLE\r
890         ps_value = BPM_PS_2;\r
891         is_fwu_enabled = false;\r
892 #else\r
893         if (sysclk_get_cpu_hz() <= FLASH_FREQ_PS1_FWS_1_MAX_FREQ) {\r
894                 ps_value = BPM_PS_1;\r
895                 if (sysclk_get_cpu_hz() > FLASH_FREQ_PS1_FWS_0_MAX_FREQ) {\r
896                         bpm_enable_fast_wakeup(BPM);\r
897                         is_fwu_enabled = true;\r
898                 }\r
899         } else {\r
900                 ps_value = BPM_PS_0;\r
901         }\r
902 #endif\r
903 \r
904         /* Switch to system clock selected by user */\r
905         if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RCSYS) {\r
906                 /* Already running from RCSYS */\r
907         }\r
908 #ifdef BOARD_OSC0_HZ\r
909         else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_OSC0) {\r
910                 osc_enable(OSC_ID_OSC0);\r
911                 osc_wait_ready(OSC_ID_OSC0);\r
912                 // Set a flash wait state depending on the new cpu frequency.\r
913                 flash_set_bus_freq(sysclk_get_cpu_hz(), ps_value, is_fwu_enabled);\r
914                 sysclk_set_source(SYSCLK_SRC_OSC0);\r
915         }\r
916 #endif\r
917 #ifdef CONFIG_DFLL0_SOURCE\r
918         else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_DFLL) {\r
919                 dfll_enable_config_defaults(0);\r
920                 // Set a flash wait state depending on the new cpu frequency.\r
921                 flash_set_bus_freq(sysclk_get_cpu_hz(), ps_value, is_fwu_enabled);\r
922                 sysclk_set_source(SYSCLK_SRC_DFLL);\r
923         }\r
924 #endif\r
925 #ifdef CONFIG_PLL0_SOURCE\r
926         else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_PLL0) {\r
927                 pll_enable_config_defaults(0);\r
928                 // Set a flash wait state depending on the new cpu frequency.\r
929                 flash_set_bus_freq(sysclk_get_cpu_hz(), ps_value, is_fwu_enabled);\r
930                 sysclk_set_source(SYSCLK_SRC_PLL0);\r
931         }\r
932 #endif\r
933         else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RC80M) {\r
934                 osc_enable(OSC_ID_RC80M);\r
935                 osc_wait_ready(OSC_ID_RC80M);\r
936                 // Set a flash wait state depending on the new cpu frequency.\r
937                 flash_set_bus_freq(sysclk_get_cpu_hz(), ps_value, is_fwu_enabled);\r
938                 sysclk_set_source(SYSCLK_SRC_RC80M);\r
939         }\r
940         else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RCFAST) {\r
941                 osc_enable(OSC_ID_RCFAST);\r
942                 osc_wait_ready(OSC_ID_RCFAST);\r
943                 // Set a flash wait state depending on the new cpu frequency.\r
944                 flash_set_bus_freq(sysclk_get_cpu_hz(), ps_value, is_fwu_enabled);\r
945                 sysclk_set_source(SYSCLK_SRC_RCFAST);\r
946         }\r
947         else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RC1M) {\r
948                 osc_enable(OSC_ID_RC1M);\r
949                 osc_wait_ready(OSC_ID_RC1M);\r
950                 // Set a flash wait state depending on the new cpu frequency.\r
951                 flash_set_bus_freq(sysclk_get_cpu_hz(), ps_value, is_fwu_enabled);\r
952                 sysclk_set_source(SYSCLK_SRC_RC1M);\r
953         }\r
954         else {\r
955                 Assert(false);\r
956         }\r
957 \r
958         /* Automatically switch to low power mode */\r
959         bpm_configure_power_scaling(BPM, ps_value, BPM_PSCM_CPU_NOT_HALT);\r
960         while ((bpm_get_status(BPM) & BPM_SR_PSOK) == 0);\r
961 \r
962         /* If the user has specified clock masks, enable only requested clocks */\r
963         irqflags_t const flags = cpu_irq_save();\r
964 #if defined(CONFIG_SYSCLK_INIT_CPUMASK)\r
965         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
966                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_CPUMASK - (uint32_t)PM);\r
967         PM->PM_CPUMASK = SYSCLK_INIT_MINIMAL_CPUMASK | CONFIG_SYSCLK_INIT_CPUMASK;\r
968 #endif\r
969 \r
970 #if defined(CONFIG_SYSCLK_INIT_HSBMASK)\r
971         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
972                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_HSBMASK - (uint32_t)PM);\r
973         PM->PM_HSBMASK = SYSCLK_INIT_MINIMAL_HSBMASK | CONFIG_SYSCLK_INIT_HSBMASK;\r
974 #endif\r
975 \r
976 #if defined(CONFIG_SYSCLK_INIT_PBAMASK)\r
977         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
978                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBAMASK - (uint32_t)PM);\r
979         PM->PM_PBAMASK = SYSCLK_INIT_MINIMAL_PBAMASK | CONFIG_SYSCLK_INIT_PBAMASK;\r
980 #endif\r
981 \r
982 #if defined(CONFIG_SYSCLK_INIT_PBBMASK)\r
983         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
984                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBBMASK - (uint32_t)PM);\r
985         PM->PM_PBBMASK = SYSCLK_INIT_MINIMAL_PBBMASK | CONFIG_SYSCLK_INIT_PBBMASK;\r
986 #endif\r
987 \r
988 #if defined(CONFIG_SYSCLK_INIT_PBCMASK)\r
989         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
990                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBCMASK - (uint32_t)PM);\r
991         PM->PM_PBCMASK = SYSCLK_INIT_MINIMAL_PBCMASK | CONFIG_SYSCLK_INIT_PBCMASK;\r
992 #endif\r
993 \r
994 #if defined(CONFIG_SYSCLK_INIT_PBDMASK)\r
995         PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu)\r
996                 | PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBDMASK - (uint32_t)PM);\r
997         PM->PM_PBDMASK = SYSCLK_INIT_MINIMAL_PBDMASK | CONFIG_SYSCLK_INIT_PBDMASK;\r
998 #endif\r
999 \r
1000         cpu_irq_restore(flags);\r
1001 \r
1002 #if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)\r
1003         /* Signal that the internal frequencies are setup */\r
1004         sysclk_initialized = true;\r
1005 #endif\r
1006 }\r
1007 \r
1008 //! @}\r