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

5
Last change on this file since c354fac was c354fac, checked in by Sebastian Huber <sebastian.huber@…>, on 01/14/16 at 14:48:44

bsp/atsam: Port SAM Software Package to RTEMS

Update #2529.

  • Property mode set to 100644
File size: 9.3 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#if BOARD_MCK == 123000000
49        /* For example usb_video, PLLA/HCLK/MCK clock is set to 492/246/123MHz to achieve
50           the maximum performance, for other examples the clock is set to 300/300/150MHz */
51        #define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x28U) | \
52                                                                 CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
53
54#define SYS_BOARD_MCKR_MDIV (PMC_MCKR_MDIV_PCK_DIV2)
55        #define SYS_BOARD_MCKR      (PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK \
56                                                                 | SYS_BOARD_MCKR_MDIV)
57#elif BOARD_MCK == 150000000
58        #define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x18U) | \
59                                                                 CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
60
61#define SYS_BOARD_MCKR_MDIV (PMC_MCKR_MDIV_PCK_DIV2)
62        #define SYS_BOARD_MCKR      (PMC_MCKR_PRES_CLK_1 | PMC_MCKR_CSS_PLLA_CLK \
63                                                                 | SYS_BOARD_MCKR_MDIV)
64#else
65        #error "unexpected Main Clock (MCK) frequency"
66#endif
67
68#ifndef __rtems__
69        uint32_t SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
70#endif /* __rtems__ */
71#define USBCLK_DIV          10
72
73        /**
74         * \brief Setup the microcontroller system.
75         * Initialize the System and update the SystemFrequency variable.
76         */
77        void SystemInit(void)
78{
79        uint32_t read_MOR;
80        /* Set FWS according to SYS_BOARD_MCKR configuration */
81        EFC->EEFC_FMR = EEFC_FMR_FWS(5);
82
83        /* Before switching MAIN OSC on external crystal : enable it and don't
84         * disable at the same time RC OSC in case of if MAIN OSC is still using RC
85         * OSC
86         */
87
88        read_MOR = PMC->CKGR_MOR;
89        /* enable external crystal - enable RC OSC */
90        read_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_XT32KFME);
91        PMC->CKGR_MOR = read_MOR;
92
93        /* Select XTAL 32k instead of internal slow RC 32k for slow clock */
94        if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) {
95                SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL;
96
97                while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL));
98        }
99
100        /* Initialize main oscillator */
101        if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {
102                PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN |
103                                                CKGR_MOR_MOSCXTEN;
104
105                while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) {
106                }
107        }
108
109        /* Switch to 3-20MHz Xtal oscillator */
110        PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN |
111                                        CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
112
113        while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) {
114        }
115
116        PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) |
117                                        PMC_MCKR_CSS_MAIN_CLK;
118
119        while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
120        }
121
122        /* Initialize PLLA */
123        PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
124
125        while (!(PMC->PMC_SR & PMC_SR_LOCKA)) {
126        }
127
128        /* Switch to main clock: DO NOT modify MDIV and CSS feild at the same access */
129        PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_MDIV_Msk) |
130                                        SYS_BOARD_MCKR_MDIV;
131        PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
132
133        while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
134        }
135
136        /* Switch to PLLA */
137        PMC->PMC_MCKR = SYS_BOARD_MCKR;
138
139        while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
140        }
141
142#ifndef __rtems__
143        SystemCoreClock = CHIP_FREQ_CPU_MAX;
144#endif /* __rtems__ */
145}
146
147#ifndef __rtems__
148void SystemCoreClockUpdate(void)
149{
150        /* Determine clock frequency according to clock register values */
151        switch (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk) {
152        case PMC_MCKR_CSS_SLOW_CLK: /* Slow clock */
153                if (SUPC->SUPC_SR & SUPC_SR_OSCSEL)
154                        SystemCoreClock = CHIP_FREQ_XTAL_32K;
155                else
156                        SystemCoreClock = CHIP_FREQ_SLCK_RC;
157
158                break;
159
160        case PMC_MCKR_CSS_MAIN_CLK: /* Main clock */
161                if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
162                        SystemCoreClock = CHIP_FREQ_XTAL_12M;
163                else {
164                        SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
165
166                        switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
167                        case CKGR_MOR_MOSCRCF_4_MHz:
168                                break;
169
170                        case CKGR_MOR_MOSCRCF_8_MHz:
171                                SystemCoreClock *= 2U;
172                                break;
173
174                        case CKGR_MOR_MOSCRCF_12_MHz:
175                                SystemCoreClock *= 3U;
176                                break;
177
178                        default:
179                                break;
180                        }
181                }
182
183                break;
184
185        case PMC_MCKR_CSS_PLLA_CLK: /* PLLA clock */
186                if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
187                        SystemCoreClock = CHIP_FREQ_XTAL_12M;
188                else {
189                        SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
190
191                        switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
192                        case CKGR_MOR_MOSCRCF_4_MHz:
193                                break;
194
195                        case CKGR_MOR_MOSCRCF_8_MHz:
196                                SystemCoreClock *= 2U;
197                                break;
198
199                        case CKGR_MOR_MOSCRCF_12_MHz:
200                                SystemCoreClock *= 3U;
201                                break;
202
203                        default:
204                                break;
205                        }
206                }
207
208                if ((uint32_t) (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk) ==
209                         PMC_MCKR_CSS_PLLA_CLK) {
210                        SystemCoreClock *= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_MULA_Msk) >>
211                                                                 CKGR_PLLAR_MULA_Pos) + 1U);
212                        SystemCoreClock /= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_DIVA_Msk) >>
213                                                                 CKGR_PLLAR_DIVA_Pos));
214                }
215
216                break;
217
218        default:
219                break;
220        }
221
222        if ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) == PMC_MCKR_PRES_CLK_3)
223                SystemCoreClock /= 3U;
224        else
225                SystemCoreClock >>= ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) >> PMC_MCKR_PRES_Pos);
226}
227#endif /* __rtems__ */
228/**
229 * Initialize flash.
230 */
231void system_init_flash(uint32_t ul_clk)
232{
233        /* Set FWS for embedded Flash access according to operating frequency */
234        if (ul_clk < CHIP_FREQ_FWS_0)
235                EFC->EEFC_FMR = EEFC_FMR_FWS(0) | EEFC_FMR_CLOE;
236        else {
237                if (ul_clk < CHIP_FREQ_FWS_1)
238                        EFC->EEFC_FMR = EEFC_FMR_FWS(1) | EEFC_FMR_CLOE;
239                else {
240                        if (ul_clk < CHIP_FREQ_FWS_2)
241                                EFC->EEFC_FMR = EEFC_FMR_FWS(2) | EEFC_FMR_CLOE;
242                        else {
243                                if (ul_clk < CHIP_FREQ_FWS_3)
244                                        EFC->EEFC_FMR = EEFC_FMR_FWS(3) | EEFC_FMR_CLOE;
245                                else {
246                                        if (ul_clk < CHIP_FREQ_FWS_4)
247                                                EFC->EEFC_FMR = EEFC_FMR_FWS(4) | EEFC_FMR_CLOE;
248                                        else
249                                                EFC->EEFC_FMR = EEFC_FMR_FWS(5) | EEFC_FMR_CLOE;
250                                }
251                        }
252                }
253        }
254}
255
256/**
257 * \brief Enable  USB clock.
258 *
259 * \param pll_id Source of the USB clock.
260 * \param div Actual clock divisor. Must be superior to 0.
261 */
262void sysclk_enable_usb(void)
263{
264        /* Disable FS USB clock*/
265        PMC->PMC_SCDR = PMC_SCDR_USBCLK;
266
267        /* Enable PLL 480 MHz */
268        PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
269
270        /* Wait that PLL is considered locked by the PMC */
271        while (!(PMC->PMC_SR & PMC_SR_LOCKU));
272
273        /* USB clock register: USB Clock Input is UTMI PLL */
274        PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1));
275
276        PMC->PMC_SCER = PMC_SCER_USBCLK;
277}
278
279
280/**
281 * \brief Disables USB clock.
282 *
283 *
284 * \param pll_id Source of the USB clock.
285 * \param div Actual clock divisor. Must be superior to 0.
286 */
287void sysclk_disable_usb(void)
288{
289        /* Disable FS USB clock*/
290        PMC->PMC_SCDR = PMC_SCDR_USBCLK;
291
292        /* Enable PLL 480 MHz */
293        PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
294
295        /* Wait that PLL is considered locked by the PMC */
296        while (!(PMC->PMC_SR & PMC_SR_LOCKU));
297
298        /* USB clock register: USB Clock Input is UTMI PLL */
299        PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1));
300}
301
302/* @cond 0 */
303/**INDENT-OFF**/
304#ifdef __cplusplus
305}
306#endif
307/**INDENT-ON**/
308/* @endcond */
Note: See TracBrowser for help on using the repository browser.