source: rtems/c/src/lib/libbsp/arm/atsam/libraries/libboard/resources_v71/system_samv71.c @ d00a7d1c

5
Last change on this file since d00a7d1c was d00a7d1c, checked in by Christian Mauderer <Christian.Mauderer@…>, on 11/17/17 at 08:21:59

bsp/atsam: Move clock and SDRAM init to SRAM.

If necessary, the BSP can now have it's clock and SDRAM initialization
in the SRAM instead of the SDRAM. This allows to change the clock
frequency during the startup of an SDRAM application.

  • Property mode set to 100644
File size: 9.6 KB
Line 
1/* ---------------------------------------------------------------------------- */
2/*                  Atmel Microcontroller Software Support                      */
3/*                       SAM Software Package License                           */
4/* ---------------------------------------------------------------------------- */
5/* Copyright (c) 2015, Atmel Corporation                                        */
6/*                                                                              */
7/* All rights reserved.                                                         */
8/*                                                                              */
9/* Redistribution and use in source and binary forms, with or without           */
10/* modification, are permitted provided that the following condition is met:    */
11/*                                                                              */
12/* - Redistributions of source code must retain the above copyright notice,     */
13/* this list of conditions and the disclaimer below.                            */
14/*                                                                              */
15/* Atmel's name may not be used to endorse or promote products derived from     */
16/* this software without specific prior written permission.                     */
17/*                                                                              */
18/* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
19/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
20/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
21/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
22/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
23/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
24/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
25/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
26/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
27/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
28/* ---------------------------------------------------------------------------- */
29
30#ifndef __rtems__
31#include "samv71.h"
32#else /* __rtems__ */
33#include <chip.h>
34#endif /* __rtems__ */
35
36/* @cond 0 */
37/**INDENT-OFF**/
38#ifdef __cplusplus
39extern "C" {
40#endif
41/**INDENT-ON**/
42        /* @endcond */
43
44        /* %ATMEL_SYSTEM% */
45        /* Clock Settings (600MHz PLL VDDIO 3.3V and VDDCORE 1.2V) */
46        /* Clock Settings (300MHz HCLK, 150MHz MCK)=> PRESC = 2, MDIV = 2 */
47#define SYS_BOARD_OSCOUNT   (CKGR_MOR_MOSCXTST(0x8U))
48#ifndef __rtems__
49#if BOARD_MCK == 123000000
50        /* For example usb_video, PLLA/HCLK/MCK clock is set to 492/246/123MHz to achieve
51           the maximum performance, for other examples the clock is set to 300/300/150MHz */
52        #define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x28U) | \
53                                                                 CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
54
55#define SYS_BOARD_MCKR_MDIV (PMC_MCKR_MDIV_PCK_DIV2)
56        #define SYS_BOARD_MCKR      (PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK \
57                                                                 | SYS_BOARD_MCKR_MDIV)
58#elif BOARD_MCK == 150000000
59        #define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x18U) | \
60                                                                 CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
61
62#define SYS_BOARD_MCKR_MDIV (PMC_MCKR_MDIV_PCK_DIV2)
63        #define SYS_BOARD_MCKR      (PMC_MCKR_PRES_CLK_1 | PMC_MCKR_CSS_PLLA_CLK \
64                                                                 | SYS_BOARD_MCKR_MDIV)
65#else
66        #error "unexpected Main Clock (MCK) frequency"
67#endif
68
69        uint32_t SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
70#else /* __rtems__ */
71#define SYS_BOARD_MCKR_MDIV ((atsam_clock_config.mckr_init) & PMC_MCKR_MDIV_Msk)
72#define SYS_BOARD_MCKR (atsam_clock_config.mckr_init)
73#define SYS_BOARD_PLLAR (atsam_clock_config.pllar_init)
74#endif /* __rtems__ */
75#define USBCLK_DIV          10
76
77        /**
78         * \brief Setup the microcontroller system.
79         * Initialize the System and update the SystemFrequency variable.
80         */
81#ifndef __rtems__
82        void SystemInit(void)
83#else /* __rtems__ */
84        void ATSAM_START_SRAM_SECTION SystemInit(void)
85#endif /* __rtems__ */
86{
87        uint32_t read_MOR;
88        /* Set FWS according to SYS_BOARD_MCKR configuration */
89        EFC->EEFC_FMR = EEFC_FMR_FWS(5);
90
91        /* Before switching MAIN OSC on external crystal : enable it and don't
92         * disable at the same time RC OSC in case of if MAIN OSC is still using RC
93         * OSC
94         */
95
96        read_MOR = PMC->CKGR_MOR;
97        /* enable external crystal - enable RC OSC */
98        read_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_XT32KFME);
99        PMC->CKGR_MOR = read_MOR;
100
101        /* Select XTAL 32k instead of internal slow RC 32k for slow clock */
102        if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) {
103                SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL;
104
105                while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL));
106        }
107
108        /* Initialize main oscillator */
109        if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {
110                PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN |
111                                                CKGR_MOR_MOSCXTEN;
112
113                while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) {
114                }
115        }
116
117        /* Switch to 3-20MHz Xtal oscillator */
118        PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN |
119                                        CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
120
121        while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) {
122        }
123
124        PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) |
125                                        PMC_MCKR_CSS_MAIN_CLK;
126
127        while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
128        }
129
130        /* Initialize PLLA */
131        PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
132
133        while (!(PMC->PMC_SR & PMC_SR_LOCKA)) {
134        }
135
136        /* Switch to main clock: DO NOT modify MDIV and CSS feild at the same access */
137        PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_MDIV_Msk) |
138                                        SYS_BOARD_MCKR_MDIV;
139        PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
140
141        while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
142        }
143
144        /* Switch to PLLA */
145        PMC->PMC_MCKR = SYS_BOARD_MCKR;
146
147        while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
148        }
149
150#ifndef __rtems__
151        SystemCoreClock = CHIP_FREQ_CPU_MAX;
152#endif /* __rtems__ */
153}
154
155#ifndef __rtems__
156void SystemCoreClockUpdate(void)
157{
158        /* Determine clock frequency according to clock register values */
159        switch (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk) {
160        case PMC_MCKR_CSS_SLOW_CLK: /* Slow clock */
161                if (SUPC->SUPC_SR & SUPC_SR_OSCSEL)
162                        SystemCoreClock = CHIP_FREQ_XTAL_32K;
163                else
164                        SystemCoreClock = CHIP_FREQ_SLCK_RC;
165
166                break;
167
168        case PMC_MCKR_CSS_MAIN_CLK: /* Main clock */
169                if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
170                        SystemCoreClock = CHIP_FREQ_XTAL_12M;
171                else {
172                        SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
173
174                        switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
175                        case CKGR_MOR_MOSCRCF_4_MHz:
176                                break;
177
178                        case CKGR_MOR_MOSCRCF_8_MHz:
179                                SystemCoreClock *= 2U;
180                                break;
181
182                        case CKGR_MOR_MOSCRCF_12_MHz:
183                                SystemCoreClock *= 3U;
184                                break;
185
186                        default:
187                                break;
188                        }
189                }
190
191                break;
192
193        case PMC_MCKR_CSS_PLLA_CLK: /* PLLA clock */
194                if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
195                        SystemCoreClock = CHIP_FREQ_XTAL_12M;
196                else {
197                        SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
198
199                        switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
200                        case CKGR_MOR_MOSCRCF_4_MHz:
201                                break;
202
203                        case CKGR_MOR_MOSCRCF_8_MHz:
204                                SystemCoreClock *= 2U;
205                                break;
206
207                        case CKGR_MOR_MOSCRCF_12_MHz:
208                                SystemCoreClock *= 3U;
209                                break;
210
211                        default:
212                                break;
213                        }
214                }
215
216                if ((uint32_t) (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk) ==
217                         PMC_MCKR_CSS_PLLA_CLK) {
218                        SystemCoreClock *= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_MULA_Msk) >>
219                                                                 CKGR_PLLAR_MULA_Pos) + 1U);
220                        SystemCoreClock /= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_DIVA_Msk) >>
221                                                                 CKGR_PLLAR_DIVA_Pos));
222                }
223
224                break;
225
226        default:
227                break;
228        }
229
230        if ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) == PMC_MCKR_PRES_CLK_3)
231                SystemCoreClock /= 3U;
232        else
233                SystemCoreClock >>= ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) >> PMC_MCKR_PRES_Pos);
234}
235#endif /* __rtems__ */
236/**
237 * Initialize flash.
238 */
239void system_init_flash(uint32_t ul_clk)
240{
241        /* Set FWS for embedded Flash access according to operating frequency */
242        if (ul_clk < CHIP_FREQ_FWS_0)
243                EFC->EEFC_FMR = EEFC_FMR_FWS(0) | EEFC_FMR_CLOE;
244        else {
245                if (ul_clk < CHIP_FREQ_FWS_1)
246                        EFC->EEFC_FMR = EEFC_FMR_FWS(1) | EEFC_FMR_CLOE;
247                else {
248                        if (ul_clk < CHIP_FREQ_FWS_2)
249                                EFC->EEFC_FMR = EEFC_FMR_FWS(2) | EEFC_FMR_CLOE;
250                        else {
251                                if (ul_clk < CHIP_FREQ_FWS_3)
252                                        EFC->EEFC_FMR = EEFC_FMR_FWS(3) | EEFC_FMR_CLOE;
253                                else {
254                                        if (ul_clk < CHIP_FREQ_FWS_4)
255                                                EFC->EEFC_FMR = EEFC_FMR_FWS(4) | EEFC_FMR_CLOE;
256                                        else
257                                                EFC->EEFC_FMR = EEFC_FMR_FWS(5) | EEFC_FMR_CLOE;
258                                }
259                        }
260                }
261        }
262}
263
264/**
265 * \brief Enable  USB clock.
266 *
267 * \param pll_id Source of the USB clock.
268 * \param div Actual clock divisor. Must be superior to 0.
269 */
270void sysclk_enable_usb(void)
271{
272        /* Disable FS USB clock*/
273        PMC->PMC_SCDR = PMC_SCDR_USBCLK;
274
275        /* Enable PLL 480 MHz */
276        PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
277
278        /* Wait that PLL is considered locked by the PMC */
279        while (!(PMC->PMC_SR & PMC_SR_LOCKU));
280
281        /* USB clock register: USB Clock Input is UTMI PLL */
282        PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1));
283
284        PMC->PMC_SCER = PMC_SCER_USBCLK;
285}
286
287
288/**
289 * \brief Disables USB clock.
290 *
291 *
292 * \param pll_id Source of the USB clock.
293 * \param div Actual clock divisor. Must be superior to 0.
294 */
295void sysclk_disable_usb(void)
296{
297        /* Disable FS USB clock*/
298        PMC->PMC_SCDR = PMC_SCDR_USBCLK;
299
300        /* Enable PLL 480 MHz */
301        PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
302
303        /* Wait that PLL is considered locked by the PMC */
304        while (!(PMC->PMC_SR & PMC_SR_LOCKU));
305
306        /* USB clock register: USB Clock Input is UTMI PLL */
307        PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1));
308}
309
310/* @cond 0 */
311/**INDENT-OFF**/
312#ifdef __cplusplus
313}
314#endif
315/**INDENT-ON**/
316/* @endcond */
Note: See TracBrowser for help on using the repository browser.