Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:44

0001 /* ---------------------------------------------------------------------------- */
0002 /*                  Atmel Microcontroller Software Support                      */
0003 /*                       SAM Software Package License                           */
0004 /* ---------------------------------------------------------------------------- */
0005 /* Copyright (c) 2015, Atmel Corporation                                        */
0006 /*                                                                              */
0007 /* All rights reserved.                                                         */
0008 /*                                                                              */
0009 /* Redistribution and use in source and binary forms, with or without           */
0010 /* modification, are permitted provided that the following condition is met:    */
0011 /*                                                                              */
0012 /* - Redistributions of source code must retain the above copyright notice,     */
0013 /* this list of conditions and the disclaimer below.                            */
0014 /*                                                                              */
0015 /* Atmel's name may not be used to endorse or promote products derived from     */
0016 /* this software without specific prior written permission.                     */
0017 /*                                                                              */
0018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
0019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
0020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
0021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
0022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
0023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
0024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
0025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
0026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
0027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
0028 /* ---------------------------------------------------------------------------- */
0029 
0030 #ifndef __rtems__
0031 #include "samv71.h"
0032 #else /* __rtems__ */
0033 #include <chip.h>
0034 #endif /* __rtems__ */
0035 
0036 /* @cond 0 */
0037 /**INDENT-OFF**/
0038 #ifdef __cplusplus
0039 extern "C" {
0040 #endif
0041 /**INDENT-ON**/
0042     /* @endcond */
0043 
0044     /* %ATMEL_SYSTEM% */
0045     /* Clock Settings (600MHz PLL VDDIO 3.3V and VDDCORE 1.2V) */
0046     /* Clock Settings (300MHz HCLK, 150MHz MCK)=> PRESC = 2, MDIV = 2 */
0047 #define SYS_BOARD_OSCOUNT   (CKGR_MOR_MOSCXTST(0x8U))
0048 #ifndef __rtems__
0049 #if BOARD_MCK == 123000000
0050     /* For example usb_video, PLLA/HCLK/MCK clock is set to 492/246/123MHz to achieve
0051        the maximum performance, for other examples the clock is set to 300/300/150MHz */
0052     #define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x28U) | \
0053                                  CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
0054 
0055 #define SYS_BOARD_MCKR_MDIV (PMC_MCKR_MDIV_PCK_DIV2)
0056     #define SYS_BOARD_MCKR      (PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK \
0057                                  | SYS_BOARD_MCKR_MDIV)
0058 #elif BOARD_MCK == 150000000
0059     #define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x18U) | \
0060                                  CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
0061 
0062 #define SYS_BOARD_MCKR_MDIV (PMC_MCKR_MDIV_PCK_DIV2)
0063     #define SYS_BOARD_MCKR      (PMC_MCKR_PRES_CLK_1 | PMC_MCKR_CSS_PLLA_CLK \
0064                                  | SYS_BOARD_MCKR_MDIV)
0065 #else
0066     #error "unexpected Main Clock (MCK) frequency"
0067 #endif
0068 
0069     uint32_t SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
0070 #else /* __rtems__ */
0071 #define SYS_BOARD_MCKR_MDIV ((atsam_clock_config.mckr_init) & PMC_MCKR_MDIV_Msk)
0072 #define SYS_BOARD_MCKR (atsam_clock_config.mckr_init)
0073 #define SYS_BOARD_PLLAR (atsam_clock_config.pllar_init)
0074 #endif /* __rtems__ */
0075 #define USBCLK_DIV          10
0076 
0077     /**
0078      * \brief Setup the microcontroller system.
0079      * Initialize the System and update the SystemFrequency variable.
0080      */
0081 #ifndef __rtems__
0082     void SystemInit(void)
0083 #else /* __rtems__ */
0084     void ATSAM_START_SRAM_SECTION SystemInit(void)
0085 #endif /* __rtems__ */
0086 {
0087     uint32_t read_MOR;
0088     /* Set FWS according to SYS_BOARD_MCKR configuration */
0089     EFC->EEFC_FMR = EEFC_FMR_FWS(5);
0090 
0091     /* Before switching MAIN OSC on external crystal : enable it and don't
0092      * disable at the same time RC OSC in case of if MAIN OSC is still using RC
0093      * OSC
0094      */
0095 
0096 #if ATSAM_SLOWCLOCK_USE_XTAL == 1
0097     read_MOR = PMC->CKGR_MOR;
0098     /* enable external crystal - enable RC OSC */
0099     read_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_XT32KFME);
0100     PMC->CKGR_MOR = read_MOR;
0101 
0102     /* Select XTAL 32k instead of internal slow RC 32k for slow clock */
0103     if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) {
0104         SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL;
0105 
0106         while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL));
0107     }
0108 #endif
0109 
0110     /* Initialize main oscillator */
0111     if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {
0112         PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN |
0113                         CKGR_MOR_MOSCXTEN;
0114 
0115         while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) {
0116         }
0117     }
0118 
0119     /* Switch to 3-20MHz Xtal oscillator */
0120     PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN |
0121                     CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
0122 
0123     while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) {
0124     }
0125 
0126     PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) |
0127                     PMC_MCKR_CSS_MAIN_CLK;
0128 
0129     while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
0130     }
0131 
0132     /* Initialize PLLA */
0133     PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
0134 
0135     while (!(PMC->PMC_SR & PMC_SR_LOCKA)) {
0136     }
0137 
0138     /* Switch to main clock: DO NOT modify MDIV and CSS feild at the same access */
0139     PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_MDIV_Msk) |
0140                     SYS_BOARD_MCKR_MDIV;
0141     PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
0142 
0143     while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
0144     }
0145 
0146     /* Switch to PLLA */
0147     PMC->PMC_MCKR = SYS_BOARD_MCKR;
0148 
0149     while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
0150     }
0151 
0152 #ifndef __rtems__
0153     SystemCoreClock = CHIP_FREQ_CPU_MAX;
0154 #endif /* __rtems__ */
0155 }
0156 
0157 #ifndef __rtems__
0158 void SystemCoreClockUpdate(void)
0159 {
0160     /* Determine clock frequency according to clock register values */
0161     switch (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk) {
0162     case PMC_MCKR_CSS_SLOW_CLK: /* Slow clock */
0163         if (SUPC->SUPC_SR & SUPC_SR_OSCSEL)
0164             SystemCoreClock = CHIP_FREQ_XTAL_32K;
0165         else
0166             SystemCoreClock = CHIP_FREQ_SLCK_RC;
0167 
0168         break;
0169 
0170     case PMC_MCKR_CSS_MAIN_CLK: /* Main clock */
0171         if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
0172             SystemCoreClock = CHIP_FREQ_XTAL_12M;
0173         else {
0174             SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
0175 
0176             switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
0177             case CKGR_MOR_MOSCRCF_4_MHz:
0178                 break;
0179 
0180             case CKGR_MOR_MOSCRCF_8_MHz:
0181                 SystemCoreClock *= 2U;
0182                 break;
0183 
0184             case CKGR_MOR_MOSCRCF_12_MHz:
0185                 SystemCoreClock *= 3U;
0186                 break;
0187 
0188             default:
0189                 break;
0190             }
0191         }
0192 
0193         break;
0194 
0195     case PMC_MCKR_CSS_PLLA_CLK: /* PLLA clock */
0196         if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
0197             SystemCoreClock = CHIP_FREQ_XTAL_12M;
0198         else {
0199             SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
0200 
0201             switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
0202             case CKGR_MOR_MOSCRCF_4_MHz:
0203                 break;
0204 
0205             case CKGR_MOR_MOSCRCF_8_MHz:
0206                 SystemCoreClock *= 2U;
0207                 break;
0208 
0209             case CKGR_MOR_MOSCRCF_12_MHz:
0210                 SystemCoreClock *= 3U;
0211                 break;
0212 
0213             default:
0214                 break;
0215             }
0216         }
0217 
0218         if ((uint32_t) (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk) ==
0219              PMC_MCKR_CSS_PLLA_CLK) {
0220             SystemCoreClock *= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_MULA_Msk) >>
0221                                  CKGR_PLLAR_MULA_Pos) + 1U);
0222             SystemCoreClock /= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_DIVA_Msk) >>
0223                                  CKGR_PLLAR_DIVA_Pos));
0224         }
0225 
0226         break;
0227 
0228     default:
0229         break;
0230     }
0231 
0232     if ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) == PMC_MCKR_PRES_CLK_3)
0233         SystemCoreClock /= 3U;
0234     else
0235         SystemCoreClock >>= ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) >> PMC_MCKR_PRES_Pos);
0236 }
0237 #endif /* __rtems__ */
0238 /**
0239  * Initialize flash.
0240  */
0241 void system_init_flash(uint32_t ul_clk)
0242 {
0243     /* Set FWS for embedded Flash access according to operating frequency */
0244     if (ul_clk < CHIP_FREQ_FWS_0)
0245         EFC->EEFC_FMR = EEFC_FMR_FWS(0) | EEFC_FMR_CLOE;
0246     else {
0247         if (ul_clk < CHIP_FREQ_FWS_1)
0248             EFC->EEFC_FMR = EEFC_FMR_FWS(1) | EEFC_FMR_CLOE;
0249         else {
0250             if (ul_clk < CHIP_FREQ_FWS_2)
0251                 EFC->EEFC_FMR = EEFC_FMR_FWS(2) | EEFC_FMR_CLOE;
0252             else {
0253                 if (ul_clk < CHIP_FREQ_FWS_3)
0254                     EFC->EEFC_FMR = EEFC_FMR_FWS(3) | EEFC_FMR_CLOE;
0255                 else {
0256                     if (ul_clk < CHIP_FREQ_FWS_4)
0257                         EFC->EEFC_FMR = EEFC_FMR_FWS(4) | EEFC_FMR_CLOE;
0258                     else
0259                         EFC->EEFC_FMR = EEFC_FMR_FWS(5) | EEFC_FMR_CLOE;
0260                 }
0261             }
0262         }
0263     }
0264 }
0265 
0266 /**
0267  * \brief Enable  USB clock.
0268  *
0269  * \param pll_id Source of the USB clock.
0270  * \param div Actual clock divisor. Must be superior to 0.
0271  */
0272 void sysclk_enable_usb(void)
0273 {
0274     /* Disable FS USB clock*/
0275     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
0276 
0277     /* Enable PLL 480 MHz */
0278     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
0279 
0280     /* Wait that PLL is considered locked by the PMC */
0281     while (!(PMC->PMC_SR & PMC_SR_LOCKU));
0282 
0283     /* USB clock register: USB Clock Input is UTMI PLL */
0284     PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1));
0285 
0286     PMC->PMC_SCER = PMC_SCER_USBCLK;
0287 }
0288 
0289 
0290 /**
0291  * \brief Disables USB clock.
0292  *
0293  *
0294  * \param pll_id Source of the USB clock.
0295  * \param div Actual clock divisor. Must be superior to 0.
0296  */
0297 void sysclk_disable_usb(void)
0298 {
0299     /* Disable FS USB clock*/
0300     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
0301 
0302     /* Enable PLL 480 MHz */
0303     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
0304 
0305     /* Wait that PLL is considered locked by the PMC */
0306     while (!(PMC->PMC_SR & PMC_SR_LOCKU));
0307 
0308     /* USB clock register: USB Clock Input is UTMI PLL */
0309     PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1));
0310 }
0311 
0312 /* @cond 0 */
0313 /**INDENT-OFF**/
0314 #ifdef __cplusplus
0315 }
0316 #endif
0317 /**INDENT-ON**/
0318 /* @endcond */