soc: atmel: add SAMR21

Adds Atmel SAMR21 soc which is based on SAMD21, but with a AT86RF233
radio connected internally via SPI.

The AT86RF233 is not yet supprted by Zephyr at this point.

This code is very much copy & paste from atmel_sam0/samd21

Signed-off-by: Benjamin Valentin <benpicco@googlemail.com>
This commit is contained in:
Benjamin Valentin 2019-02-19 23:14:54 +01:00 committed by Anas Nashif
commit 770233dd10
12 changed files with 546 additions and 1 deletions

View file

@ -144,3 +144,15 @@ DEVICE_AND_API_INIT(gpio_sam0_1, DT_GPIO_SAM0_PORTB_LABEL, gpio_sam0_init,
NULL, &gpio_sam0_config_1, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &gpio_sam0_api);
#endif
/* Port C */
#ifdef DT_GPIO_SAM0_PORTC_BASE_ADDRESS
static const struct gpio_sam0_config gpio_sam0_config_2 = {
.regs = (PortGroup *)DT_GPIO_SAM0_PORTC_BASE_ADDRESS,
};
DEVICE_AND_API_INIT(gpio_sam0_2, DT_GPIO_SAM0_PORTC_LABEL, gpio_sam0_init,
NULL, &gpio_sam0_config_2, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &gpio_sam0_api);
#endif

View file

@ -90,3 +90,14 @@ DEVICE_AND_API_INIT(pinmux_sam0_1, DT_PINMUX_SAM0_B_LABEL,
PRE_KERNEL_1, CONFIG_PINMUX_INIT_PRIORITY,
&pinmux_sam0_api);
#endif
#if DT_PINMUX_SAM0_C_BASE_ADDRESS
static const struct pinmux_sam0_config pinmux_sam0_config_2 = {
.regs = (PortGroup *)DT_PINMUX_SAM0_C_BASE_ADDRESS,
};
DEVICE_AND_API_INIT(pinmux_sam0_2, DT_PINMUX_SAM0_C_LABEL,
pinmux_sam0_init, NULL, &pinmux_sam0_config_2,
PRE_KERNEL_1, CONFIG_PINMUX_INIT_PRIORITY,
&pinmux_sam0_api);
#endif

58
dts/arm/atmel/samr21.dtsi Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 Benjamin Valentin
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <atmel/samd.dtsi>
/ {
soc {
usb0: usb@41005000 {
compatible = "atmel,sam0-usb";
status = "disabled";
reg = <0x41005000 0x1000>;
interrupts = <7 0>;
num-bidir-endpoints = <8>;
label = "USB0";
};
portc: gpio@41004500 {
compatible = "atmel,sam0-gpio";
reg = <0x41004500 0x80>;
label = "PORTC";
gpio-controller;
#gpio-cells = <2>;
};
pinmux_c: pinmux@41004500 {
compatible = "atmel,sam0-pinmux";
reg = <0x41004500 0x80>;
label = "PINMUX_C";
};
};
};
&sercom0 {
interrupts = <9 0>;
};
&sercom1 {
interrupts = <10 0>;
};
&sercom2 {
interrupts = <11 0>;
};
&sercom3 {
interrupts = <12 0>;
};
&sercom4 {
interrupts = <13 0>;
};
&sercom5 {
interrupts = <14 0>;
};

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: Apache-2.0
if SOC_SERIES_SAMD20 || SOC_SERIES_SAMD21
if SOC_SERIES_SAMD20 || SOC_SERIES_SAMD21 || SOC_SERIES_SAMR21
config SOC_ATMEL_SAMD_XOSC32K
bool "Enable the external 32 kHz crystal oscillator"

View file

@ -0,0 +1,6 @@
# Makefile - Atmel SAMR21 MCU series.
#
# Copyright (c) 2017 Google LLC.
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(soc.c)

View file

@ -0,0 +1,30 @@
# Kconfig - Atmel SAMR21 MCU series configuration options
#
# Copyright (c) 2019 Benjamin Valentin
# SPDX-License-Identifier: Apache-2.0
if SOC_SERIES_SAMR21
config SOC_SERIES
string
default "samr21"
config SOC_PART_NUMBER
string
default "samr21e16a" if SOC_PART_NUMBER_SAMR21E16A
default "samr21e17a" if SOC_PART_NUMBER_SAMR21E17A
default "samr21e18a" if SOC_PART_NUMBER_SAMR21E18A
default "samr21e19a" if SOC_PART_NUMBER_SAMR21E19A
default "samr21g16a" if SOC_PART_NUMBER_SAMR21G16A
default "samr21g17a" if SOC_PART_NUMBER_SAMR21G17A
default "samr21g18a" if SOC_PART_NUMBER_SAMR21G18A
config NUM_IRQS
int
default 28
config SYS_CLOCK_HW_CYCLES_PER_SEC
int
default 48000000
endif # SOC_SERIES_SAMR21

View file

@ -0,0 +1,14 @@
# Kconfig - Atmel SAMR21 MCU series
#
# Copyright (c) 2017 Google LLC.
# SPDX-License-Identifier: Apache-2.0
config SOC_SERIES_SAMR21
bool "Atmel SAMR21 MCU"
select CPU_CORTEX_M0PLUS
select SOC_FAMILY_SAM0
select CPU_CORTEX_M_HAS_SYSTICK
select CPU_CORTEX_M_HAS_VTOR
select ASF
help
Enable support for Atmel SAMR21 Cortex-M0+ microcontrollers.

View file

@ -0,0 +1,31 @@
# Kconfig - Atmel SAMR21 MCU series
#
# Copyright (c) 2017 Google LLC.
# SPDX-License-Identifier: Apache-2.0
choice
prompt "Atmel SAMR21 MCU Selection"
depends on SOC_SERIES_SAMR21
config SOC_PART_NUMBER_SAMR21E16A
bool "SAMR21E16A"
config SOC_PART_NUMBER_SAMR21E17A
bool "SAMR21E17A"
config SOC_PART_NUMBER_SAMR21E18A
bool "SAMR21E18A"
config SOC_PART_NUMBER_SAMR21E19A
bool "SAMR21E19A"
config SOC_PART_NUMBER_SAMR21G16A
bool "SAMR21G16A"
config SOC_PART_NUMBER_SAMR21G17A
bool "SAMR21G17A"
config SOC_PART_NUMBER_SAMR21G18A
bool "SAMR21G18A"
endchoice

View file

@ -0,0 +1,121 @@
/*
* Copyright (c) 2017 Google LLC.
*
* SPDX-License-Identifier: Apache-2.0
*/
/* SoC level DTS fixup file */
#define DT_FLASH_DEV_BASE_ADDRESS DT_ATMEL_SAM0_NVMCTRL_41004000_BASE_ADDRESS
#define DT_FLASH_DEV_NAME DT_ATMEL_SAM0_NVMCTRL_41004000_LABEL
#define DT_GPIO_SAM0_PORTA_LABEL DT_ATMEL_SAM0_GPIO_41004400_LABEL
#define DT_GPIO_SAM0_PORTA_BASE_ADDRESS DT_ATMEL_SAM0_GPIO_41004400_BASE_ADDRESS
#define DT_GPIO_SAM0_PORTB_LABEL DT_ATMEL_SAM0_GPIO_41004480_LABEL
#define DT_GPIO_SAM0_PORTB_BASE_ADDRESS DT_ATMEL_SAM0_GPIO_41004480_BASE_ADDRESS
#define DT_GPIO_SAM0_PORTC_LABEL DT_ATMEL_SAM0_GPIO_41004500_LABEL
#define DT_GPIO_SAM0_PORTC_BASE_ADDRESS DT_ATMEL_SAM0_GPIO_41004500_BASE_ADDRESS
#define DT_UART_SAM0_SERCOM0_CURRENT_SPEED DT_ATMEL_SAM0_UART_42000800_CURRENT_SPEED
#define DT_UART_SAM0_SERCOM0_IRQ DT_ATMEL_SAM0_UART_42000800_IRQ_0
#define DT_UART_SAM0_SERCOM0_IRQ_PRIORITY DT_ATMEL_SAM0_UART_42000800_IRQ_0_PRIORITY
#define DT_UART_SAM0_SERCOM0_LABEL DT_ATMEL_SAM0_UART_42000800_LABEL
#define DT_UART_SAM0_SERCOM0_BASE_ADDRESS DT_ATMEL_SAM0_UART_42000800_BASE_ADDRESS
#define DT_UART_SAM0_SERCOM0_RXPO DT_ATMEL_SAM0_UART_42000800_RXPO
#define DT_UART_SAM0_SERCOM0_TXPO DT_ATMEL_SAM0_UART_42000800_TXPO
#define DT_UART_SAM0_SERCOM1_CURRENT_SPEED DT_ATMEL_SAM0_UART_42000C00_CURRENT_SPEED
#define DT_UART_SAM0_SERCOM1_IRQ DT_ATMEL_SAM0_UART_42000C00_IRQ_0
#define DT_UART_SAM0_SERCOM1_IRQ_PRIORITY DT_ATMEL_SAM0_UART_42000C00_IRQ_0_PRIORITY
#define DT_UART_SAM0_SERCOM1_LABEL DT_ATMEL_SAM0_UART_42000C00_LABEL
#define DT_UART_SAM0_SERCOM1_BASE_ADDRESS DT_ATMEL_SAM0_UART_42000C00_BASE_ADDRESS
#define DT_UART_SAM0_SERCOM1_RXPO DT_ATMEL_SAM0_UART_42000C00_RXPO
#define DT_UART_SAM0_SERCOM1_TXPO DT_ATMEL_SAM0_UART_42000C00_TXPO
#define DT_UART_SAM0_SERCOM2_CURRENT_SPEED DT_ATMEL_SAM0_UART_42001000_CURRENT_SPEED
#define DT_UART_SAM0_SERCOM2_IRQ DT_ATMEL_SAM0_UART_42001000_IRQ_0
#define DT_UART_SAM0_SERCOM2_IRQ_PRIORITY DT_ATMEL_SAM0_UART_42001000_IRQ_0_PRIORITY
#define DT_UART_SAM0_SERCOM2_LABEL DT_ATMEL_SAM0_UART_42001000_LABEL
#define DT_UART_SAM0_SERCOM2_BASE_ADDRESS DT_ATMEL_SAM0_UART_42001000_BASE_ADDRESS
#define DT_UART_SAM0_SERCOM2_RXPO DT_ATMEL_SAM0_UART_42001000_RXPO
#define DT_UART_SAM0_SERCOM2_TXPO DT_ATMEL_SAM0_UART_42001000_TXPO
#define DT_UART_SAM0_SERCOM3_CURRENT_SPEED DT_ATMEL_SAM0_UART_42001400_CURRENT_SPEED
#define DT_UART_SAM0_SERCOM3_IRQ DT_ATMEL_SAM0_UART_42001400_IRQ_0
#define DT_UART_SAM0_SERCOM3_IRQ_PRIORITY DT_ATMEL_SAM0_UART_42001400_IRQ_0_PRIORITY
#define DT_UART_SAM0_SERCOM3_LABEL DT_ATMEL_SAM0_UART_42001400_LABEL
#define DT_UART_SAM0_SERCOM3_BASE_ADDRESS DT_ATMEL_SAM0_UART_42001400_BASE_ADDRESS
#define DT_UART_SAM0_SERCOM3_RXPO DT_ATMEL_SAM0_UART_42001400_RXPO
#define DT_UART_SAM0_SERCOM3_TXPO DT_ATMEL_SAM0_UART_42001400_TXPO
#define DT_UART_SAM0_SERCOM4_CURRENT_SPEED DT_ATMEL_SAM0_UART_42001800_CURRENT_SPEED
#define DT_UART_SAM0_SERCOM4_IRQ DT_ATMEL_SAM0_UART_42001800_IRQ_0
#define DT_UART_SAM0_SERCOM4_IRQ_PRIORITY DT_ATMEL_SAM0_UART_42001800_IRQ_0_PRIORITY
#define DT_UART_SAM0_SERCOM4_LABEL DT_ATMEL_SAM0_UART_42001800_LABEL
#define DT_UART_SAM0_SERCOM4_BASE_ADDRESS DT_ATMEL_SAM0_UART_42001800_BASE_ADDRESS
#define DT_UART_SAM0_SERCOM4_RXPO DT_ATMEL_SAM0_UART_42001800_RXPO
#define DT_UART_SAM0_SERCOM4_TXPO DT_ATMEL_SAM0_UART_42001800_TXPO
#define DT_UART_SAM0_SERCOM5_CURRENT_SPEED DT_ATMEL_SAM0_UART_42001C00_CURRENT_SPEED
#define DT_UART_SAM0_SERCOM5_IRQ DT_ATMEL_SAM0_UART_42001C00_IRQ_0
#define DT_UART_SAM0_SERCOM5_IRQ_PRIORITY DT_ATMEL_SAM0_UART_42001C00_IRQ_0_PRIORITY
#define DT_UART_SAM0_SERCOM5_LABEL DT_ATMEL_SAM0_UART_42001C00_LABEL
#define DT_UART_SAM0_SERCOM5_BASE_ADDRESS DT_ATMEL_SAM0_UART_42001C00_BASE_ADDRESS
#define DT_UART_SAM0_SERCOM5_RXPO DT_ATMEL_SAM0_UART_42001C00_RXPO
#define DT_UART_SAM0_SERCOM5_TXPO DT_ATMEL_SAM0_UART_42001C00_TXPO
#define DT_SPI_SAM0_SERCOM0_LABEL DT_ATMEL_SAM0_SPI_42000800_LABEL
#define DT_SPI_SAM0_SERCOM0_BASE_ADDRESS DT_ATMEL_SAM0_SPI_42000800_BASE_ADDRESS
#define DT_SPI_SAM0_SERCOM0_DIPO DT_ATMEL_SAM0_SPI_42000800_DIPO
#define DT_SPI_SAM0_SERCOM0_DOPO DT_ATMEL_SAM0_SPI_42000800_DOPO
#define DT_SPI_SAM0_SERCOM1_LABEL DT_ATMEL_SAM0_SPI_42000C00_LABEL
#define DT_SPI_SAM0_SERCOM1_BASE_ADDRESS DT_ATMEL_SAM0_SPI_42000C00_BASE_ADDRESS
#define DT_SPI_SAM0_SERCOM1_DIPO DT_ATMEL_SAM0_SPI_42000C00_DIPO
#define DT_SPI_SAM0_SERCOM1_DOPO DT_ATMEL_SAM0_SPI_42000C00_DOPO
#define DT_SPI_SAM0_SERCOM2_LABEL DT_ATMEL_SAM0_SPI_42001000_LABEL
#define DT_SPI_SAM0_SERCOM2_BASE_ADDRESS DT_ATMEL_SAM0_SPI_42001000_BASE_ADDRESS
#define DT_SPI_SAM0_SERCOM2_DIPO DT_ATMEL_SAM0_SPI_42001000_DIPO
#define DT_SPI_SAM0_SERCOM2_DOPO DT_ATMEL_SAM0_SPI_42001000_DOPO
#define DT_SPI_SAM0_SERCOM3_LABEL DT_ATMEL_SAM0_SPI_42001400_LABEL
#define DT_SPI_SAM0_SERCOM3_BASE_ADDRESS DT_ATMEL_SAM0_SPI_42001400_BASE_ADDRESS
#define DT_SPI_SAM0_SERCOM3_DIPO DT_ATMEL_SAM0_SPI_42001400_DIPO
#define DT_SPI_SAM0_SERCOM3_DOPO DT_ATMEL_SAM0_SPI_42001400_DOPO
#define DT_SPI_SAM0_SERCOM4_LABEL DT_ATMEL_SAM0_SPI_42001800_LABEL
#define DT_SPI_SAM0_SERCOM4_BASE_ADDRESS DT_ATMEL_SAM0_SPI_42001800_BASE_ADDRESS
#define DT_SPI_SAM0_SERCOM4_DIPO DT_ATMEL_SAM0_SPI_42001800_DIPO
#define DT_SPI_SAM0_SERCOM4_DOPO DT_ATMEL_SAM0_SPI_42001800_DOPO
#define DT_SPI_SAM0_SERCOM5_LABEL DT_ATMEL_SAM0_SPI_42001C00_LABEL
#define DT_SPI_SAM0_SERCOM5_BASE_ADDRESS DT_ATMEL_SAM0_SPI_42001C00_BASE_ADDRESS
#define DT_SPI_SAM0_SERCOM5_DIPO DT_ATMEL_SAM0_SPI_42001C00_DIPO
#define DT_SPI_SAM0_SERCOM5_DOPO DT_ATMEL_SAM0_SPI_42001C00_DOPO
#define DT_WDT_SAM0_IRQ DT_ATMEL_SAM0_WATCHDOG_40001000_IRQ_0
#define DT_WDT_SAM0_IRQ_PRIORITY DT_ATMEL_SAM0_WATCHDOG_40001000_IRQ_0_PRIORITY
#define DT_WDT_SAM0_LABEL DT_ATMEL_SAM0_WATCHDOG_40001000_LABEL
#define DT_WDT_SAM0_BASE_ADDRESS DT_ATMEL_SAM0_WATCHDOG_40001000_BASE_ADDRESS
#define CONFIG_WDT_0_NAME DT_WDT_SAM0_LABEL
#define DT_PINMUX_SAM0_A_BASE_ADDRESS DT_ATMEL_SAM0_PINMUX_41004400_BASE_ADDRESS
#define DT_PINMUX_SAM0_A_LABEL DT_ATMEL_SAM0_PINMUX_41004400_LABEL
#define DT_PINMUX_SAM0_B_BASE_ADDRESS DT_ATMEL_SAM0_PINMUX_41004480_BASE_ADDRESS
#define DT_PINMUX_SAM0_B_LABEL DT_ATMEL_SAM0_PINMUX_41004480_LABEL
#define DT_PINMUX_SAM0_C_BASE_ADDRESS DT_ATMEL_SAM0_PINMUX_41004500_BASE_ADDRESS
#define DT_PINMUX_SAM0_C_LABEL DT_ATMEL_SAM0_PINMUX_41004500_LABEL
#define DT_USB_DC_SAM0_BASE_ADDRESS DT_ATMEL_SAM0_USB_41005000_BASE_ADDRESS
#define DT_USB_DC_SAM0_IRQ DT_ATMEL_SAM0_USB_41005000_IRQ_0
#define DT_USB_DC_SAM0_IRQ_PRIORITY DT_ATMEL_SAM0_USB_41005000_IRQ_0_PRIORITY
#define DT_USB_DC_SAM0_NUM_BIDIR_ENDPOINTS DT_ATMEL_SAM0_USB_41005000_NUM_BIDIR_ENDPOINTS
#define DT_NUM_IRQ_PRIO_BITS DT_ARM_V6M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS
/* End of SoC Level DTS fixup file */

View file

@ -0,0 +1,8 @@
/* linker.ld - Linker command/script file */
/*
* Copyright (c) 2017 Google LLC.
* SPDX-License-Identifier: Apache-2.0
*/
#include <arch/arm/cortex_m/scripts/linker.ld>

View file

@ -0,0 +1,197 @@
/*
* Copyright (c) 2017 Google LLC.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Atmel SAMR21 MCU series initialization code
*/
#include <arch/cpu.h>
#include <cortex_m/exc.h>
#include <device.h>
#include <init.h>
#include <kernel.h>
#include <soc.h>
static void flash_waitstates_init(void)
{
/* One wait state at 48 MHz. */
NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val;
}
/* Follows the same structure as the Arduino Zero, namely:
* XOSC32K -> GCLK1 -> DFLL48M -> GCLK0
* OSC8M -> 8 MHz -> GCLK3
*/
static void xosc_init(void)
{
#ifdef CONFIG_SOC_ATMEL_SAMD_XOSC
#error External oscillator support is not implemented.
#endif
}
static void wait_gclk_synchronization(void)
{
while (GCLK->STATUS.bit.SYNCBUSY) {
}
}
static void xosc32k_init(void)
{
#ifdef CONFIG_SOC_ATMEL_SAMD_XOSC32K
SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP(6) |
SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K;
SYSCTRL->XOSC32K.bit.ENABLE = 1;
/* Wait for the crystal to stabalise. */
while (!SYSCTRL->PCLKSR.bit.XOSC32KRDY) {
}
#endif
}
static void osc32k_init(void)
{
u32_t fuse = *(u32_t *)FUSES_OSC32K_CAL_ADDR;
u32_t calib = (fuse & FUSES_OSC32K_CAL_Msk) >> FUSES_OSC32K_CAL_Pos;
SYSCTRL->OSC32K.reg = SYSCTRL_OSC32K_CALIB(calib) |
SYSCTRL_OSC32K_STARTUP(0x6u) |
SYSCTRL_OSC32K_EN32K | SYSCTRL_OSC32K_ENABLE;
/* Wait for the oscillator to stabalise. */
while (!SYSCTRL->PCLKSR.bit.OSC32KRDY) {
}
}
static void dfll_init(void)
{
/* No prescaler */
GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(0);
wait_gclk_synchronization();
#if defined(CONFIG_SOC_ATMEL_SAMD_XOSC32K_AS_MAIN)
/* Route XOSC32K to GCLK1 */
GCLK->GENCTRL.reg =
GCLK_GENCTRL_ID(1) | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_GENEN;
#elif defined(CONFIG_SOC_ATMEL_SAMD_OSC8M_AS_MAIN)
/* Route OSC8M to GCLK1 */
GCLK->GENCTRL.reg =
GCLK_GENCTRL_ID(1) | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_GENEN;
#else
#error Unsupported main clock source.
#endif
wait_gclk_synchronization();
/* Route GCLK1 to multiplexer 1 */
GCLK->CLKCTRL.reg =
GCLK_CLKCTRL_ID(0) | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_CLKEN;
wait_gclk_synchronization();
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {
}
u32_t mul = (SOC_ATMEL_SAM0_MCK_FREQ_HZ +
SOC_ATMEL_SAM0_GCLK1_FREQ_HZ / 2) /
SOC_ATMEL_SAM0_GCLK1_FREQ_HZ;
SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(31) |
SYSCTRL_DFLLMUL_FSTEP(511) |
SYSCTRL_DFLLMUL_MUL(mul);
while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {
}
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE |
SYSCTRL_DFLLCTRL_WAITLOCK |
SYSCTRL_DFLLCTRL_QLDIS;
while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {
}
/* Enable the DFLL */
SYSCTRL->DFLLCTRL.bit.ENABLE = 1;
while (!SYSCTRL->PCLKSR.bit.DFLLLCKC || !SYSCTRL->PCLKSR.bit.DFLLLCKF) {
}
while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {
}
}
static void osc8m_init(void)
{
/* Turn off the prescaler */
SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_0_Val;
SYSCTRL->OSC8M.bit.ONDEMAND = 0;
}
static void gclks_init(void)
{
/* DFLL/1 -> GCLK0 */
GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(0);
wait_gclk_synchronization();
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0) | GCLK_GENCTRL_SRC_DFLL48M |
GCLK_GENCTRL_IDC | GCLK_GENCTRL_GENEN;
wait_gclk_synchronization();
/* OSC8M/1 -> GCLK3 */
GCLK->GENCTRL.reg =
GCLK_GENCTRL_ID(3) | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_GENEN;
wait_gclk_synchronization();
/* OSCULP32K/32 -> GCLK2 */
GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(32 - 1);
wait_gclk_synchronization();
GCLK->GENCTRL.reg =
GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_SRC_OSC32K | GCLK_GENCTRL_GENEN;
wait_gclk_synchronization();
}
static void dividers_init(void)
{
/* Set the CPU, APBA, B, and C dividers */
PM->CPUSEL.reg = PM_CPUSEL_CPUDIV_DIV1;
PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val;
PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val;
PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val;
/* TODO(mlhx): enable clock failure detection? */
}
static int atmel_samr_init(struct device *arg)
{
u32_t key;
ARG_UNUSED(arg);
key = irq_lock();
_ClearFaults();
flash_waitstates_init();
osc8m_init();
osc32k_init();
xosc_init();
xosc32k_init();
dfll_init();
gclks_init();
dividers_init();
/* Install default handler that simply resets the CPU
* if configured in the kernel, NOP otherwise
*/
NMI_INIT();
irq_unlock(key);
return 0;
}
SYS_INIT(atmel_samr_init, PRE_KERNEL_1, 0);

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2017 Google LLC.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_ATMEL_SAMR21_SOC_H_
#define ZEPHYR_ATMEL_SAMR21_SOC_H_
#ifndef _ASMLANGUAGE
#define DONT_USE_CMSIS_INIT
#include <zephyr/types.h>
#if defined(CONFIG_SOC_PART_NUMBER_SAMR21E16A)
#include <samr21e16a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAMR21E17A)
#include <samr21e17a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAMR21E18A)
#include <samr21e18a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAMR21E19A)
#include <samr21e19a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAMR21G16A)
#include <samr21g16a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAMR21G17A)
#include <samr21g17a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAMR21G18A)
#include <samr21g18a.h>
#else
#error Library does not support the specified device.
#endif
#endif /* _ASMLANGUAGE */
/** Processor Clock (HCLK) Frequency */
#define SOC_ATMEL_SAM0_HCLK_FREQ_HZ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC
/** Master Clock (MCK) Frequency */
#define SOC_ATMEL_SAM0_MCK_FREQ_HZ SOC_ATMEL_SAM0_HCLK_FREQ_HZ
#define SOC_ATMEL_SAM0_XOSC32K_FREQ_HZ 32768
#define SOC_ATMEL_SAM0_OSC8M_FREQ_HZ 8000000
#define SOC_ATMEL_SAM0_GCLK0_FREQ_HZ SOC_ATMEL_SAM0_MCK_FREQ_HZ
#if defined(CONFIG_SOC_ATMEL_SAMD_XOSC32K_AS_MAIN)
#define SOC_ATMEL_SAM0_GCLK1_FREQ_HZ SOC_ATMEL_SAM0_XOSC32K_FREQ_HZ
#elif defined(CONFIG_SOC_ATMEL_SAMD_OSC8M_AS_MAIN)
#define SOC_ATMEL_SAM0_GCLK1_FREQ_HZ SOC_ATMEL_SAM0_OSC8M_FREQ_HZ
#else
#error Unsupported GCLK1 clock source.
#endif
#define SOC_ATMEL_SAM0_GCLK3_FREQ_HZ SOC_ATMEL_SAM0_OSC8M_FREQ_HZ
#define SOC_ATMEL_SAM0_APBA_FREQ_HZ SOC_ATMEL_SAM0_MCK_FREQ_HZ
#define SOC_ATMEL_SAM0_APBB_FREQ_HZ SOC_ATMEL_SAM0_MCK_FREQ_HZ
#define SOC_ATMEL_SAM0_APBC_FREQ_HZ SOC_ATMEL_SAM0_MCK_FREQ_HZ
#endif /* ZEPHYR_ATMEL_SAMR21_SOC_H_ */