1 /* 2 * Copyright (c) 2013-2015 Wind River Systems, Inc. 3 * Copyright (c) 2016 Intel Corporation. 4 * Copyright (c) 2017 Justin Watson 5 * Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com> 6 * 7 * SPDX-License-Identifier: Apache-2.0 8 */ 9 10 /** 11 * @file 12 * @brief Atmel SAM4S MCU series initialization code 13 * 14 * This module provides routines to initialize and support board-level hardware 15 * for the Atmel SAM4S series processor. 16 */ 17 18 #include <zephyr/device.h> 19 #include <zephyr/init.h> 20 #include <soc.h> 21 22 /** 23 * @brief Setup various clock on SoC at boot time. 24 * 25 * Setup the SoC clocks according to section 28.12 in datasheet. 26 * 27 * Setup Slow, Main, PLLA, Processor and Master clocks during the device boot. 28 * It is assumed that the relevant registers are at their reset value. 29 */ clock_init(void)30static ALWAYS_INLINE void clock_init(void) 31 { 32 uint32_t reg_val; 33 34 #ifdef CONFIG_SOC_ATMEL_SAM4S_EXT_SLCK 35 /* Switch slow clock to the external 32 KHz crystal oscillator. */ 36 SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL; 37 38 /* Wait for oscillator to be stabilized. */ 39 while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL)) { 40 ; 41 } 42 43 #endif /* CONFIG_SOC_ATMEL_SAM4S_EXT_SLCK */ 44 45 #ifdef CONFIG_SOC_ATMEL_SAM4S_EXT_MAINCK 46 /* 47 * Setup main external crystal oscillator. 48 */ 49 50 /* Start the external crystal oscillator. */ 51 PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD 52 /* Fast RC oscillator frequency is at 4 MHz. */ 53 | CKGR_MOR_MOSCRCF_4_MHz 54 /* 55 * We select maximum setup time. While start up time 56 * could be shortened this optimization is not deemed 57 * critical right now. 58 */ 59 | CKGR_MOR_MOSCXTST(0xFFu) 60 /* RC oscillator must stay on. */ 61 | CKGR_MOR_MOSCRCEN 62 | CKGR_MOR_MOSCXTEN; 63 64 /* Wait for oscillator to be stabilized. */ 65 while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) { 66 ; 67 } 68 69 /* Select the external crystal oscillator as the main clock source. */ 70 PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD 71 | CKGR_MOR_MOSCRCF_4_MHz 72 | CKGR_MOR_MOSCRCEN 73 | CKGR_MOR_MOSCXTEN 74 | CKGR_MOR_MOSCXTST(0xFFu) 75 | CKGR_MOR_MOSCSEL; 76 77 /* Wait for external oscillator to be selected. */ 78 while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) { 79 ; 80 } 81 82 /* Turn off RC oscillator, not used any longer, to save power */ 83 PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD 84 | CKGR_MOR_MOSCSEL 85 | CKGR_MOR_MOSCXTST(0xFFu) 86 | CKGR_MOR_MOSCXTEN; 87 88 /* Wait for the RC oscillator to be turned off. */ 89 while (PMC->PMC_SR & PMC_SR_MOSCRCS) { 90 ; 91 } 92 93 #ifdef CONFIG_SOC_ATMEL_SAM4S_WAIT_MODE 94 /* 95 * Instruct CPU to enter Wait mode instead of Sleep mode to 96 * keep Processor Clock (HCLK) and thus be able to debug 97 * CPU using JTAG. 98 */ 99 PMC->PMC_FSMR |= PMC_FSMR_LPM; 100 #endif 101 #else 102 /* Setup main fast RC oscillator. */ 103 104 /* 105 * NOTE: MOSCRCF must be changed only if MOSCRCS is set in the PMC_SR 106 * register, should normally be the case. 107 */ 108 while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)) { 109 ; 110 } 111 112 /* Set main fast RC oscillator to 12 MHz. */ 113 PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD 114 | CKGR_MOR_MOSCRCF_12_MHz 115 | CKGR_MOR_MOSCRCEN; 116 117 /* Wait for RC oscillator to stabilize. */ 118 while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)) { 119 ; 120 } 121 #endif /* CONFIG_SOC_ATMEL_SAM4S_EXT_MAINCK */ 122 123 /* 124 * Setup PLLA 125 */ 126 127 /* Switch MCK (Master Clock) to the main clock first. */ 128 reg_val = PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk; 129 PMC->PMC_MCKR = reg_val | PMC_MCKR_CSS_MAIN_CLK; 130 131 /* Wait for clock selection to complete. */ 132 while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) { 133 ; 134 } 135 136 /* Setup PLLA. */ 137 PMC->CKGR_PLLAR = CKGR_PLLAR_ONE 138 | CKGR_PLLAR_MULA(CONFIG_SOC_ATMEL_SAM4S_PLLA_MULA) 139 | CKGR_PLLAR_PLLACOUNT(0x3Fu) 140 | CKGR_PLLAR_DIVA(CONFIG_SOC_ATMEL_SAM4S_PLLA_DIVA); 141 142 /* 143 * NOTE: Both MULA and DIVA must be set to a value greater than 0 or 144 * otherwise PLL will be disabled. In this case we would get stuck in 145 * the following loop. 146 */ 147 148 /* Wait for PLL lock. */ 149 while (!(PMC->PMC_SR & PMC_SR_LOCKA)) { 150 ; 151 } 152 153 /* 154 * Final setup of the Master Clock 155 */ 156 157 /* 158 * NOTE: PMC_MCKR must not be programmed in a single write operation. 159 * If CSS or PRES are modified we must wait for MCKRDY bit to be 160 * set again. 161 */ 162 163 /* Setup prescaler - PLLA Clock / Processor Clock (HCLK). */ 164 reg_val = PMC->PMC_MCKR & ~PMC_MCKR_PRES_Msk; 165 PMC->PMC_MCKR = reg_val | PMC_MCKR_PRES_CLK_1; 166 167 /* Wait for Master Clock setup to complete */ 168 while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) { 169 ; 170 } 171 172 /* Finally select PLL as Master Clock source. */ 173 reg_val = PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk; 174 PMC->PMC_MCKR = reg_val | PMC_MCKR_CSS_PLLA_CLK; 175 176 /* Wait for Master Clock setup to complete. */ 177 while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) { 178 ; 179 } 180 } 181 z_arm_platform_init(void)182void z_arm_platform_init(void) 183 { 184 /* 185 * Set FWS (Flash Wait State) value before increasing Master Clock 186 * (MCK) frequency. Look at table 44.73 in the SAM4S datasheet. 187 * This is set to the highest number of read cycles because it won't 188 * hurt lower clock frequencies. However, a high frequency with too 189 * few read cycles could cause flash read problems. FWS 5 (6 cycles) 190 * is the safe setting for all of this SoCs usable frequencies. 191 * TODO: Add code to handle SAM4SD devices that have 2 EFCs. 192 */ 193 EFC0->EEFC_FMR = EEFC_FMR_FWS(5); 194 195 /* Setup system clocks. */ 196 clock_init(); 197 } 198