4 * \brief Chip-specific system clock management functions
\r
6 * Copyright (c) 2012-2013 Atmel Corporation. All rights reserved.
\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
15 * 1. Redistributions of source code must retain the above copyright notice,
\r
16 * this list of conditions and the following disclaimer.
\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
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
25 * 4. This software may only be redistributed and used in connection with an
\r
26 * Atmel microcontroller product.
\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
44 #include <compiler.h>
\r
45 #include <stdbool.h>
\r
47 #include <flashcalw.h>
\r
52 * \weakgroup sysclk_group
\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
65 * \defgroup sysclk_internals_group System Clock internals
\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
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
83 * \name Initial module clock masks
\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
97 //! \brief Initial value of CPUMASK
\r
98 #define SYSCLK_INIT_MINIMAL_CPUMASK 0
\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
109 //! \brief Initial value of PBAMASK
\r
110 #define SYSCLK_INIT_MINIMAL_PBAMASK 0
\r
113 //! \brief Initial value of PBBMASK
\r
114 #define SYSCLK_INIT_MINIMAL_PBBMASK (1 << SYSCLK_HFLASHC_REGS)
\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
124 //! \brief Initial value of PBDMASK
\r
125 #define SYSCLK_INIT_MINIMAL_PBDMASK \
\r
126 ((1 << SYSCLK_BPM) \
\r
127 | (1 << SYSCLK_BSCIF))
\r
130 #if defined(CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
\r
132 * \brief boolean signalling that the sysclk_init is done.
\r
134 bool sysclk_initialized = false;
\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
144 void sysclk_priv_enable_module(uint32_t bus_id, uint32_t module_index)
\r
149 flags = cpu_irq_save();
\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
158 cpu_irq_restore(flags);
\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
168 void sysclk_priv_disable_module(uint32_t bus_id, uint32_t module_index)
\r
173 flags = cpu_irq_save();
\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
182 cpu_irq_restore(flags);
\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
191 void sysclk_enable_pba_module(uint32_t index)
\r
195 /* Enable the bridge if necessary */
\r
196 flags = cpu_irq_save();
\r
198 if (PM->PM_PBAMASK == 0) {
\r
199 sysclk_enable_hsb_module(SYSCLK_PBA_BRIDGE);
\r
202 cpu_irq_restore(flags);
\r
204 /* Enable the module */
\r
205 sysclk_priv_enable_module(PM_CLK_GRP_PBA, index);
\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
212 void sysclk_disable_pba_module(uint32_t index)
\r
216 /* Disable the module */
\r
217 sysclk_priv_disable_module(PM_CLK_GRP_PBA, index);
\r
219 /* Disable the bridge if possible */
\r
220 flags = cpu_irq_save();
\r
222 if (PM->PM_PBAMASK == 0) {
\r
223 sysclk_disable_hsb_module(SYSCLK_PBA_BRIDGE);
\r
226 cpu_irq_restore(flags);
\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
233 void sysclk_enable_pbb_module(uint32_t index)
\r
237 /* Enable the bridge if necessary */
\r
238 flags = cpu_irq_save();
\r
240 if (PM->PM_PBBMASK == 0) {
\r
241 sysclk_enable_hsb_module(SYSCLK_PBB_BRIDGE);
\r
244 cpu_irq_restore(flags);
\r
246 /* Enable the module */
\r
247 sysclk_priv_enable_module(PM_CLK_GRP_PBB, index);
\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
254 void sysclk_disable_pbb_module(uint32_t index)
\r
258 /* Disable the module */
\r
259 sysclk_priv_disable_module(PM_CLK_GRP_PBB, index);
\r
261 /* Disable the bridge if possible */
\r
262 flags = cpu_irq_save();
\r
264 if (PM->PM_PBBMASK == 0) {
\r
265 sysclk_disable_hsb_module(SYSCLK_PBB_BRIDGE);
\r
268 cpu_irq_restore(flags);
\r
272 * \brief Retrieves the current rate in Hz of the Peripheral Bus clock attached
\r
273 * to the specified peripheral.
\r
275 * \param module Pointer to the module's base address.
\r
277 * \return Frequency of the bus attached to the specified peripheral, in Hz.
\r
279 uint32_t sysclk_get_peripheral_bus_hz(const volatile void *module)
\r
281 /* Fallthroughs intended for modules sharing the same peripheral bus. */
\r
282 switch ((uintptr_t)module) {
\r
306 return sysclk_get_pba_hz();
\r
315 return sysclk_get_pbb_hz();
\r
322 return sysclk_get_pbc_hz();
\r
329 case PICOUART_ADDR:
\r
330 return sysclk_get_pbd_hz();
\r
339 * \brief Enable a peripheral's clock from its base address.
\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
344 * \param module Pointer to the module's base address.
\r
346 void sysclk_enable_peripheral_clock(const volatile void *module)
\r
348 switch ((uintptr_t)module) {
\r
350 sysclk_enable_hsb_module(SYSCLK_AESA_HSB);
\r
354 sysclk_enable_pba_module(SYSCLK_IISC);
\r
358 sysclk_enable_pba_module(SYSCLK_SPI);
\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
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
380 sysclk_enable_pba_module(SYSCLK_TWIM0);
\r
384 sysclk_enable_pba_module(SYSCLK_TWIS0);
\r
388 sysclk_enable_pba_module(SYSCLK_TWIM1);
\r
392 sysclk_enable_pba_module(SYSCLK_TWIS1);
\r
396 sysclk_enable_pba_module(SYSCLK_USART0);
\r
397 sysclk_enable_pba_divmask(PBA_DIVMASK_CLK_USART);
\r
401 sysclk_enable_pba_module(SYSCLK_USART1);
\r
402 sysclk_enable_pba_divmask(PBA_DIVMASK_CLK_USART);
\r
406 sysclk_enable_pba_module(SYSCLK_USART2);
\r
407 sysclk_enable_pba_divmask(PBA_DIVMASK_CLK_USART);
\r
411 sysclk_enable_pba_module(SYSCLK_USART3);
\r
412 sysclk_enable_pba_divmask(PBA_DIVMASK_CLK_USART);
\r
416 sysclk_enable_pba_module(SYSCLK_ADCIFE);
\r
420 sysclk_enable_pba_module(SYSCLK_DACC);
\r
424 sysclk_enable_pba_module(SYSCLK_ACIFC);
\r
428 sysclk_enable_pba_module(SYSCLK_GLOC);
\r
432 sysclk_enable_pba_module(SYSCLK_ABDACB);
\r
436 sysclk_enable_pba_module(SYSCLK_TRNG);
\r
440 sysclk_enable_pba_module(SYSCLK_PARC);
\r
444 sysclk_enable_pba_module(SYSCLK_CATB);
\r
448 sysclk_enable_pba_module(SYSCLK_TWIM2);
\r
452 sysclk_enable_pba_module(SYSCLK_TWIM3);
\r
456 sysclk_enable_pba_module(SYSCLK_LCDCA);
\r
460 sysclk_enable_hsb_module(SYSCLK_HFLASHC_DATA);
\r
461 sysclk_enable_pbb_module(SYSCLK_HFLASHC_REGS);
\r
465 sysclk_enable_hsb_module(SYSCLK_HRAMC1_DATA);
\r
466 sysclk_enable_pbb_module(SYSCLK_HRAMC1_REGS);
\r
470 sysclk_enable_pbb_module(SYSCLK_HMATRIX);
\r
474 sysclk_enable_hsb_module(SYSCLK_PDCA_HSB);
\r
475 sysclk_enable_pbb_module(SYSCLK_PDCA_PB);
\r
479 sysclk_enable_hsb_module(SYSCLK_CRCCU_DATA);
\r
480 sysclk_enable_pbb_module(SYSCLK_CRCCU_REGS);
\r
484 sysclk_enable_hsb_module(SYSCLK_USBC_DATA);
\r
485 sysclk_enable_pbb_module(SYSCLK_USBC_REGS);
\r
489 sysclk_enable_pbb_module(SYSCLK_PEVC);
\r
493 sysclk_enable_pbc_module(SYSCLK_PM);
\r
497 sysclk_enable_pbc_module(SYSCLK_CHIPID);
\r
501 sysclk_enable_pbc_module(SYSCLK_SCIF);
\r
505 sysclk_enable_pbc_module(SYSCLK_FREQM);
\r
509 sysclk_enable_pbc_module(SYSCLK_GPIO);
\r
513 sysclk_enable_pbd_module(SYSCLK_BPM);
\r
517 sysclk_enable_pbd_module(SYSCLK_BSCIF);
\r
521 sysclk_enable_pbd_module(SYSCLK_AST);
\r
525 sysclk_enable_pbd_module(SYSCLK_WDT);
\r
529 sysclk_enable_pbd_module(SYSCLK_EIC);
\r
532 case PICOUART_ADDR:
\r
533 sysclk_enable_pbd_module(SYSCLK_PICOUART);
\r
543 * \brief Disable a peripheral's clock from its base address.
\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
548 * \param module Pointer to the module's base address.
\r
550 void sysclk_disable_peripheral_clock(const volatile void *module)
\r
552 switch ((uintptr_t)module) {
\r
554 sysclk_disable_hsb_module(SYSCLK_AESA_HSB);
\r
558 sysclk_disable_pba_module(SYSCLK_IISC);
\r
562 sysclk_disable_pba_module(SYSCLK_SPI);
\r
566 sysclk_disable_pba_module(SYSCLK_TC0);
\r
570 sysclk_disable_pba_module(SYSCLK_TC1);
\r
574 sysclk_disable_pba_module(SYSCLK_TWIM0);
\r
578 sysclk_disable_pba_module(SYSCLK_TWIS0);
\r
582 sysclk_disable_pba_module(SYSCLK_TWIM1);
\r
586 sysclk_disable_pba_module(SYSCLK_TWIS1);
\r
590 sysclk_disable_pba_module(SYSCLK_USART0);
\r
594 sysclk_disable_pba_module(SYSCLK_USART1);
\r
598 sysclk_disable_pba_module(SYSCLK_USART2);
\r
602 sysclk_disable_pba_module(SYSCLK_USART3);
\r
606 sysclk_disable_pba_module(SYSCLK_ADCIFE);
\r
610 sysclk_disable_pba_module(SYSCLK_DACC);
\r
614 sysclk_disable_pba_module(SYSCLK_ACIFC);
\r
618 sysclk_disable_pba_module(SYSCLK_GLOC);
\r
622 sysclk_disable_pba_module(SYSCLK_ABDACB);
\r
626 sysclk_disable_pba_module(SYSCLK_TRNG);
\r
630 sysclk_disable_pba_module(SYSCLK_PARC);
\r
634 sysclk_disable_pba_module(SYSCLK_CATB);
\r
638 sysclk_disable_pba_module(SYSCLK_TWIM2);
\r
642 sysclk_disable_pba_module(SYSCLK_TWIM3);
\r
646 sysclk_disable_pba_module(SYSCLK_LCDCA);
\r
650 sysclk_disable_pbb_module(SYSCLK_HFLASHC_REGS);
\r
654 sysclk_disable_hsb_module(SYSCLK_HRAMC1_DATA);
\r
655 sysclk_disable_pbb_module(SYSCLK_HRAMC1_REGS);
\r
659 sysclk_disable_pbb_module(SYSCLK_HMATRIX);
\r
663 sysclk_disable_hsb_module(SYSCLK_PDCA_HSB);
\r
664 sysclk_disable_pbb_module(SYSCLK_PDCA_PB);
\r
668 sysclk_disable_hsb_module(SYSCLK_CRCCU_DATA);
\r
669 sysclk_disable_pbb_module(SYSCLK_CRCCU_REGS);
\r
673 sysclk_disable_hsb_module(SYSCLK_USBC_DATA);
\r
674 sysclk_disable_pbb_module(SYSCLK_USBC_REGS);
\r
678 sysclk_disable_pbb_module(SYSCLK_PEVC);
\r
682 sysclk_disable_pbc_module(SYSCLK_PM);
\r
686 sysclk_disable_pbc_module(SYSCLK_CHIPID);
\r
690 sysclk_disable_pbc_module(SYSCLK_SCIF);
\r
694 sysclk_disable_pbc_module(SYSCLK_FREQM);
\r
698 sysclk_disable_pbc_module(SYSCLK_GPIO);
\r
702 sysclk_disable_pbd_module(SYSCLK_BPM);
\r
706 sysclk_disable_pbd_module(SYSCLK_BSCIF);
\r
710 sysclk_disable_pbd_module(SYSCLK_AST);
\r
714 sysclk_disable_pbd_module(SYSCLK_WDT);
\r
718 sysclk_disable_pbd_module(SYSCLK_EIC);
\r
721 case PICOUART_ADDR:
\r
722 sysclk_disable_pbd_module(SYSCLK_PICOUART);
\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
740 * \brief Set system clock prescaler configuration
\r
742 * This function will change the system clock prescaler configuration to
\r
743 * match the parameters.
\r
745 * \note The parameters to this function are device-specific.
\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
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
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
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
769 if (cpu_shift > 0) {
\r
770 cpu_cksel = (PM_CPUSEL_CPUSEL(cpu_shift - 1))
\r
771 | PM_CPUSEL_CPUDIV;
\r
774 if (pba_shift > 0) {
\r
775 pba_cksel = (PM_PBASEL_PBSEL(pba_shift - 1))
\r
779 if (pbb_shift > 0) {
\r
780 pbb_cksel = (PM_PBBSEL_PBSEL(pbb_shift - 1))
\r
784 if (pbc_shift > 0) {
\r
785 pbc_cksel = (PM_PBCSEL_PBSEL(pbc_shift - 1))
\r
789 if (pbd_shift > 0) {
\r
790 pbd_cksel = (PM_PBDSEL_PBSEL(pbd_shift - 1))
\r
794 flags = cpu_irq_save();
\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
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
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
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
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
816 cpu_irq_restore(flags);
\r
820 * \brief Change the source of the main system clock.
\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
825 void sysclk_set_source(uint32_t src)
\r
828 Assert(src <= SYSCLK_SRC_RC1M);
\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
837 #if defined(CONFIG_USBCLK_SOURCE) || defined(__DOXYGEN__)
\r
839 * \brief Enable the USB generic clock
\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
845 void sysclk_enable_usb(void)
\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
852 genclk_enable_config(7, CONFIG_USBCLK_SOURCE, CONFIG_USBCLK_DIV);
\r
856 * \brief Disable the USB generic clock
\r
858 void sysclk_disable_usb(void)
\r
862 #endif // CONFIG_USBCLK_SOURCE
\r
864 void sysclk_init(void)
\r
866 uint32_t ps_value = 0;
\r
867 bool is_fwu_enabled = false;
\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
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
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
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
900 ps_value = BPM_PS_0;
\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
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
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
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
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
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
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
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
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
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
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
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
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
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
1000 cpu_irq_restore(flags);
\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