blob: 1ddbcba2e1f3441c7521ae7d8013279601f3014d [file] [log] [blame]
Kévin Redon93717e42018-07-08 13:26:15 +02001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2009, Atmel Corporation
Kévin Redonad0958e2018-09-06 22:49:56 +02005 * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
Kévin Redon93717e42018-07-08 13:26:15 +02006 *
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 conditions are 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
31/**
32 * \file
33 *
34 * Provides the low-level initialization function that called on chip startup.
35 */
36
37/*----------------------------------------------------------------------------
38 * Headers
39 *----------------------------------------------------------------------------*/
40
41#include "board.h"
42
43/*----------------------------------------------------------------------------
44 * Local definitions
45 *----------------------------------------------------------------------------*/
46
47#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
48#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
49
Kévin Redone2b0f972018-08-28 19:13:06 +020050/** configure PLL to generate main clock based on main oscillator frequency */
51#if (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 48000000)
Kévin Redon93717e42018-07-08 13:26:15 +020052#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
Kévin Redon33d1eb72018-07-08 13:58:12 +020053 | CKGR_PLLAR_MULA(8-1) \
54 | CKGR_PLLAR_PLLACOUNT(0x1) \
55 | CKGR_PLLAR_DIVA(2))
Kévin Redone2b0f972018-08-28 19:13:06 +020056#elif (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 58000000)
Kévin Redon93717e42018-07-08 13:26:15 +020057#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
Kévin Redone2b0f972018-08-28 19:13:06 +020058 | CKGR_PLLAR_MULA(29-1) \
Kévin Redon33d1eb72018-07-08 13:58:12 +020059 | CKGR_PLLAR_PLLACOUNT(0x1) \
Kévin Redone2b0f972018-08-28 19:13:06 +020060 | CKGR_PLLAR_DIVA(6))
61#elif (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 60000000)
Kévin Redon93717e42018-07-08 13:26:15 +020062#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
Kévin Redon33d1eb72018-07-08 13:58:12 +020063 | CKGR_PLLAR_MULA(10-1) \
64 | CKGR_PLLAR_PLLACOUNT(0x1) \
65 | CKGR_PLLAR_DIVA(2))
Kévin Redone2b0f972018-08-28 19:13:06 +020066#elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 47923200)
67#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
68 | CKGR_PLLAR_MULA(13-1) \
69 | CKGR_PLLAR_PLLACOUNT(0x1) \
70 | CKGR_PLLAR_DIVA(5))
71#elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 58982400)
72#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
73 | CKGR_PLLAR_MULA(16-1) \
74 | CKGR_PLLAR_PLLACOUNT(0x1) \
75 | CKGR_PLLAR_DIVA(5))
76#elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 64512000)
77#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
78 | CKGR_PLLAR_MULA(7-1) \
79 | CKGR_PLLAR_PLLACOUNT(0x1) \
80 | CKGR_PLLAR_DIVA(2))
Kévin Redon93717e42018-07-08 13:26:15 +020081#else
Kévin Redone2b0f972018-08-28 19:13:06 +020082 #error "Please define PLLA config for your BOARD_MCK/MAINOSC frequency"
Kévin Redon93717e42018-07-08 13:26:15 +020083#endif
84
85#if (BOARD_MAINOSC == 12000000)
86#define PLLB_CFG (CKGR_PLLBR_DIVB(2)|CKGR_PLLBR_MULB(8-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
87#elif (BOARD_MAINOSC == 18432000)
88#define PLLB_CFG (CKGR_PLLBR_DIVB(5)|CKGR_PLLBR_MULB(13-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
89#else
90#error "Please configure PLLB for your MAINOSC freq"
91#endif
92
93/* Define clock timeout */
94#define CLOCK_TIMEOUT 0xFFFFFFFF
95
96/**
97 * \brief Configure 48MHz Clock for USB
98 */
99static void _ConfigureUsbClock(void)
100{
101 /* Enable PLLB for USB */
102 PMC->CKGR_PLLBR = PLLB_CFG;
103 while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0) ;
104
105 /* USB Clock uses PLLB */
106 PMC->PMC_USB = PMC_USB_USBDIV(0) /* /1 (no divider) */
107 | PMC_USB_USBS; /* PLLB */
108}
109
110/*----------------------------------------------------------------------------
111 * Exported functions
112 *----------------------------------------------------------------------------*/
113
114/**
115 * \brief Performs the low-level initialization of the chip.
116 * This includes EFC and master clock configuration.
117 * It also enable a low level on the pin NRST triggers a user reset.
118 */
119extern WEAK void LowLevelInit( void )
120{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200121 uint32_t timeout = 0;
Kévin Redon93717e42018-07-08 13:26:15 +0200122
Kévin Redon33d1eb72018-07-08 13:58:12 +0200123 /* Configure the Supply Monitor to reset the CPU in case VDDIO is
124 * lower than 3.0V. As we run the board on 3.3V, any lower voltage
125 * might be some kind of leakage that creeps in some way, but is not
126 * the "official" power supply */
127 SUPC->SUPC_SMMR = SUPC_SMMR_SMTH_3_0V | SUPC_SMMR_SMSMPL_CSM |
Kévin Redon93717e42018-07-08 13:26:15 +0200128 SUPC_SMMR_SMRSTEN_ENABLE;
129
Kévin Redonacb7bd92019-08-12 20:49:04 +0200130 /* disable ERASE pin to prevent accidental flash erase */
131 MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO12;
132
Kévin Redon33d1eb72018-07-08 13:58:12 +0200133 /* enable both LED and green LED */
134 PIOA->PIO_PER |= PIO_LED_RED | PIO_LED_GREEN;
135 PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN;
136 PIOA->PIO_CODR |= PIO_LED_RED | PIO_LED_GREEN;
Kévin Redon93717e42018-07-08 13:26:15 +0200137
Kévin Redon33d1eb72018-07-08 13:58:12 +0200138 /* Set 3 FWS for Embedded Flash Access */
139 EFC->EEFC_FMR = EEFC_FMR_FWS(3);
Kévin Redon93717e42018-07-08 13:26:15 +0200140
Kévin Redon33d1eb72018-07-08 13:58:12 +0200141 /* Select external slow clock */
Kévin Redon93717e42018-07-08 13:26:15 +0200142/* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST)
Kévin Redon33d1eb72018-07-08 13:58:12 +0200143 {
144 SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5));
145 timeout = 0;
146 while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) );
147 }
Kévin Redon93717e42018-07-08 13:26:15 +0200148*/
149
150#ifndef qmod
Kévin Redon33d1eb72018-07-08 13:58:12 +0200151 /* Initialize main oscillator */
152 if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
153 {
154 PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
155 timeout = 0;
156 while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT));
157 }
Kévin Redon93717e42018-07-08 13:26:15 +0200158
Kévin Redon33d1eb72018-07-08 13:58:12 +0200159 /* Switch to 3-20MHz Xtal oscillator */
160 PIOB->PIO_PDR = (1 << 8) | (1 << 9);
161 PIOB->PIO_PUDR = (1 << 8) | (1 << 9);
162 PIOB->PIO_PPDDR = (1 << 8) | (1 << 9);
163 PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
164 /* wait for Main XTAL oscillator stabilization */
165 timeout = 0;
166 while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT));
Kévin Redon93717e42018-07-08 13:26:15 +0200167#else
Kévin Redon33d1eb72018-07-08 13:58:12 +0200168 /* QMOD has external 12MHz clock source */
169 PIOB->PIO_PDR = (1 << 9);
170 PIOB->PIO_PUDR = (1 << 9);
171 PIOB->PIO_PPDDR = (1 << 9);
172 PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL;
Kévin Redon93717e42018-07-08 13:26:15 +0200173#endif
174
Kévin Redon33d1eb72018-07-08 13:58:12 +0200175 /* disable the red LED after main clock initialization */
176 PIOA->PIO_SODR = PIO_LED_RED;
Kévin Redon93717e42018-07-08 13:26:15 +0200177
Kévin Redon33d1eb72018-07-08 13:58:12 +0200178 /* "switch" to main clock as master clock source (should already be the case */
179 PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
180 /* wait for master clock to be ready */
181 for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
Kévin Redon93717e42018-07-08 13:26:15 +0200182
Kévin Redon33d1eb72018-07-08 13:58:12 +0200183 /* Initialize PLLA */
184 PMC->CKGR_PLLAR = BOARD_PLLAR;
185 /* Wait for PLLA to lock */
186 timeout = 0;
187 while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT));
Kévin Redon93717e42018-07-08 13:26:15 +0200188
Kévin Redon33d1eb72018-07-08 13:58:12 +0200189 /* Switch to main clock (again ?!?) */
190 PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
191 /* wait for master clock to be ready */
192 for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
Kévin Redon93717e42018-07-08 13:26:15 +0200193
Kévin Redon33d1eb72018-07-08 13:58:12 +0200194 /* switch to PLLA as master clock source */
195 PMC->PMC_MCKR = BOARD_MCKR ;
196 /* wait for master clock to be ready */
197 for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
Kévin Redon93717e42018-07-08 13:26:15 +0200198
Kévin Redon33d1eb72018-07-08 13:58:12 +0200199 /* Configure SysTick for 1ms */
200 SysTick_Config(BOARD_MCK/1000);
Kévin Redon93717e42018-07-08 13:26:15 +0200201
Kévin Redon33d1eb72018-07-08 13:58:12 +0200202 _ConfigureUsbClock();
Kévin Redon93717e42018-07-08 13:26:15 +0200203}
204
205/* SysTick based delay function */
206
207volatile uint32_t jiffies;
208
209/* Interrupt handler for SysTick interrupt */
210void SysTick_Handler(void)
211{
212 jiffies++;
213}
214
215void mdelay(unsigned int msecs)
216{
217 uint32_t jiffies_start = jiffies;
218 do {
219 } while ((jiffies - jiffies_start) < msecs);
220}
Eric Wild19cd3b02020-04-03 21:33:30 +0200221
222void abort() {
223 NVIC_SystemReset();
224 while(1) {};
225}