soc: atmel_sam0: Add SAME54

This adds supoprt for the Atmel SAME54 SoC.

The SAME5x/SAMD5x is a line of Cortex-M4F MCUs that share peripherals
with the sam0 Cortex-M0+ and saml1x Cortex-M23 parts.

Signed-off-by: Benjamin Valentin <benjamin.valentin@ml-pa.com>
This commit is contained in:
Benjamin Valentin 2019-03-14 15:18:59 +01:00 committed by Kumar Gala
parent aa45d7ad77
commit 496ace1500
18 changed files with 702 additions and 0 deletions

View file

@ -185,6 +185,7 @@
/drivers/wifi/eswifi/ @loicpoulain
/dts/arc/ @vonhust @ruuddw @iriszzw
/dts/arm/atmel/samr21.dtsi @benpicco
/dts/arm/atmel/sam*5*.dtsi @benpicco
/dts/arm/st/ @erwango
/dts/arm/ti/cc13?2* @bwitherspoon
/dts/arm/ti/cc26?2* @bwitherspoon

323
dts/arm/atmel/samd5x.dtsi Normal file
View file

@ -0,0 +1,323 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <arm/armv7-m.dtsi>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/i2c/i2c.h>
/ {
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-m4";
reg = <0>;
};
};
aliases {
adc-0 = &adc0;
adc-1 = &adc1;
pinmux-a = &pinmux_a;
pinmux-b = &pinmux_b;
pinmux-c = &pinmux_c;
pinmux-d = &pinmux_d;
port-a = &porta;
port-b = &portb;
port-c = &portc;
port-d = &portd;
sercom-0 = &sercom0;
sercom-1 = &sercom1;
sercom-2 = &sercom2;
sercom-3 = &sercom3;
sercom-4 = &sercom4;
sercom-5 = &sercom5;
sercom-6 = &sercom6;
sercom-7 = &sercom7;
tc-0 = &tc0;
tc-2 = &tc2;
tc-4 = &tc4;
tc-6 = &tc6;
};
soc {
flash0: flash@0 {
compatible = "soc-nv-flash";
label = "FLASH_0";
write-block-size = <512>;
};
sram0: memory@20000000 {
compatible = "mmio-sram";
reg = <0x20000000 0x40000>;
};
backup0: memory@47000000 {
compatible = "mmio-sram";
reg = <0x47000000 0x2000>;
};
id: device_id@8061fc {
compatible = "atmel,sam0-id";
reg = <0x008061FC 0x4>,
<0x00806010 0x4>,
<0x00806014 0x4>,
<0x00806018 0x4>;
};
nvmctrl: nvmctrl@41004000 {
compatible = "atmel,sam0-nvmctrl";
label = "FLASH_CTRL";
reg = <0x41004000 0x22>;
interrupts = <29 0>, <30 0>;
lock-regions = <32>;
#address-cells = <1>;
#size-cells = <1>;
};
dma: dmac@4100A000 {
compatible = "atmel,sam0-dmac";
reg = <0x4100A000 0x50>;
interrupts = <31 0>, <32 0>, <33 0>, <34 0>, <35 0>;
label = "DMA_0";
};
eic: eic@40002800 {
compatible = "atmel,sam0-eic";
reg = <0x40002800 0x38>;
interrupts = <12 0>, <13 0>, <14 0>, <15 0>,
<16 0>, <17 0>, <18 0>, <19 0>,
<20 0>, <21 0>, <22 0>, <23 0>,
<24 0>, <25 0>, <26 0>, <27 0>;
label = "EIC";
};
pinmux_a: pinmux@41008000 {
compatible = "atmel,sam0-pinmux";
reg = <0x41008000 0x80>;
label = "PINMUX_A";
};
pinmux_b: pinmux@41008080 {
compatible = "atmel,sam0-pinmux";
reg = <0x41008080 0x80>;
label = "PINMUX_B";
};
pinmux_c: pinmux@41008100 {
compatible = "atmel,sam0-pinmux";
reg = <0x41008100 0x80>;
label = "PINMUX_C";
};
pinmux_d: pinmux@41008180 {
compatible = "atmel,sam0-pinmux";
reg = <0x41008180 0x80>;
label = "PINMUX_D";
};
wdog: watchdog@40002000 {
compatible = "atmel,sam0-watchdog";
reg = <0x40002000 13>;
interrupts = <10 0>;
label = "WATCHDOG_0";
};
sercom0: sercom@40003000 {
compatible = "atmel,sam0-sercom";
reg = <0x40003000 0x40>;
interrupts = <46 0>, <47 0>, <48 0>, <49 0>;
status = "disabled";
label = "SERCOM0";
};
sercom1: sercom@40003400 {
compatible = "atmel,sam0-sercom";
reg = <0x40003400 0x40>;
interrupts = <50 0>, <51 0>, <52 0>, <53 0>;
status = "disabled";
label = "SERCOM1";
};
sercom2: sercom@41012000 {
compatible = "atmel,sam0-sercom";
reg = <0x41012000 0x40>;
interrupts = <54 0>, <55 0>, <56 0>, <57 0>;
status = "disabled";
label = "SERCOM2";
};
sercom3: sercom@41014000 {
compatible = "atmel,sam0-sercom";
reg = <0x41014000 0x40>;
interrupts = <58 0>, <59 0>, <60 0>, <61 0>;
status = "disabled";
label = "SERCOM3";
};
sercom4: sercom@43000000 {
compatible = "atmel,sam0-sercom";
reg = <0x43000000 0x40>;
interrupts = <62 0>, <63 0>, <64 0>, <65 0>;
status = "disabled";
label = "SERCOM4";
};
sercom5: sercom@43000400 {
compatible = "atmel,sam0-sercom";
reg = <0x43000400 0x40>;
interrupts = <66 0>, <67 0>, <68 0>, <69 0>;
status = "disabled";
label = "SERCOM5";
};
sercom6: sercom@43000800 {
compatible = "atmel,sam0-sercom";
reg = <0x43000800 0x40>;
interrupts = <70 0>, <71 0>, <72 0>, <73 0>;
status = "disabled";
label = "SERCOM6";
};
sercom7: sercom@43000C00 {
compatible = "atmel,sam0-sercom";
reg = <0x43000C00 0x40>;
interrupts = <74 0>, <75 0>, <76 0>, <77 0>;
status = "disabled";
label = "SERCOM7";
};
porta: gpio@41008000 {
compatible = "atmel,sam0-gpio";
reg = <0x41008000 0x80>;
label = "PORTA";
gpio-controller;
#gpio-cells = <2>;
};
portb: gpio@41008080 {
compatible = "atmel,sam0-gpio";
reg = <0x41008080 0x80>;
label = "PORTB";
gpio-controller;
#gpio-cells = <2>;
};
portc: gpio@41008100 {
compatible = "atmel,sam0-gpio";
reg = <0x41008100 0x80>;
label = "PORTC";
gpio-controller;
#gpio-cells = <2>;
};
portd: gpio@41008180 {
compatible = "atmel,sam0-gpio";
reg = <0x41008180 0x80>;
label = "PORTD";
gpio-controller;
#gpio-cells = <2>;
};
usb0: usb@41000000 {
compatible = "atmel,sam0-usb";
status = "disabled";
reg = <0x41000000 0x1000>;
interrupts = <80 0>, <81 0>, <82 0>, <83 0>;
num-bidir-endpoints = <8>;
label = "USB0";
};
rng: rng@42002800 {
compatible = "atmel,sam0-trng";
reg = <0x42002800 0x1e>;
interrupts = <131 0>;
label = "ENTROPY_0";
};
rtc: rtc@40002400 {
compatible = "atmel,sam0-rtc";
reg = <0x40002400 0x1C>;
interrupts = <11 0>;
clock-generator = <0>;
status = "disabled";
label = "RTC";
};
adc0: adc@43001C00 {
compatible = "atmel,sam0-adc";
reg = <0x43001C00 0x4A>;
interrupts = <118 0>, <119 0>;
label = "ADC_0";
/*
* 16 MHz max, source clock must not exceed 100 MHz.
* - table 54-8, section 54.6, page 2020
* - table 54-24, section 54.10.4, page 2031
* -> 48 MHz GCLK(2) / 4 = 12 MHz
*/
gclk = <2>;
prescaler = <4>;
#io-channel-cells = <1>;
};
adc1: adc@43002000 {
compatible = "atmel,sam0-adc";
reg = <0x43002000 0x4A>;
interrupts = <120 0>, <121 0>;
label = "ADC_1";
/*
* 16 MHz max, source clock must not exceed 100 MHz.
* - table 54-8, section 54.6, page 2020
* - table 54-24, section 54.10.4, page 2031
* -> 48 MHz GCLK(2) / 4 = 12 MHz
*/
gclk = <2>;
prescaler = <4>;
#io-channel-cells = <1>;
};
tc0: tc@40003800 {
compatible = "atmel,sam0-tc32";
reg = <0x40003800 0x34>;
interrupts = <107 0>;
label = "TIMER_0";
};
tc2: tc@4101A000 {
compatible = "atmel,sam0-tc32";
reg = <0x4101A000 0x34>;
interrupts = <109 0>;
label = "TIMER_2";
};
tc4: tc@42001400 {
compatible = "atmel,sam0-tc32";
reg = <0x42001400 0x34>;
interrupts = <111 0>;
label = "TIMER_4";
};
tc6: tc@43001400 {
compatible = "atmel,sam0-tc32";
reg = <0x43001400 0x34>;
interrupts = <113 0>;
label = "TIMER_6";
};
};
};
&nvic {
arm,num-irq-priority-bits = <3>;
};

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mem.h>
#include <atmel/samd5x.dtsi>
/ {
flash0: flash@0 {
reg = <0x0 DT_SIZE_K(256)>;
};
sram0: memory@20000000 {
reg = <0x20000000 DT_SIZE_K(128)>;
};
};

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mem.h>
#include <atmel/samd5x.dtsi>
/ {
flash0: flash@0 {
reg = <0x0 DT_SIZE_K(512)>;
};
sram0: memory@20000000 {
reg = <0x20000000 DT_SIZE_K(192)>;
};
};

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mem.h>
#include <atmel/samd5x.dtsi>
/ {
flash0: flash@0 {
reg = <0x0 DT_SIZE_K(1024)>;
};
sram0: memory@20000000 {
reg = <0x20000000 DT_SIZE_K(256)>;
};
};

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <atmel/samd5xx18.dtsi>

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <atmel/samd5xx19.dtsi>

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <atmel/samd5xx20.dtsi>

View file

@ -14,6 +14,7 @@ config SOC_FAMILY
default "atmel_sam0"
source "soc/arm/atmel_sam0/common/Kconfig.samd2x"
source "soc/arm/atmel_sam0/common/Kconfig.samd5x"
source "soc/arm/atmel_sam0/*/Kconfig.soc"
endif

View file

@ -6,3 +6,7 @@
zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAMD20 soc_samd2x.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAMD21 soc_samd2x.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAMR21 soc_samd2x.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAME54 soc_samd5x.c)
zephyr_include_directories(.)

View file

@ -0,0 +1,28 @@
# Copyright (c) 2019 ML!PA Consulting GmbH
# SPDX-License-Identifier: Apache-2.0
if SOC_SERIES_SAMD51 || SOC_SERIES_SAME51 || SOC_SERIES_SAME53 || SOC_SERIES_SAME54
config SOC_ATMEL_SAMD5X_XOSC32K
bool "Enable the external 32 kHz crystal oscillator"
help
Say y to enable the external 32 kHZ crystal oscillator at
startup. This can then be selected as the main clock source
for the SOC.
choice
prompt "Main clock source"
help
Selects the clock that the main clocks, such as the CPU
clock and AHB clock, will be derived from.
config SOC_ATMEL_SAMD5X_XOSC32K_AS_MAIN
depends on SOC_ATMEL_SAMD5X_XOSC32K
bool "XOSC32K"
config SOC_ATMEL_SAMD5X_OSCULP32K_AS_MAIN
bool "OSCULP32K"
endchoice
endif

View file

@ -0,0 +1,142 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Atmel SAMD 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>
#define SAM0_DFLL_FREQ_HZ (48000000U)
#define SAM0_DPLL_FREQ_MIN_HZ (96000000U)
#define SAM0_DPLL_FREQ_MAX_HZ (200000000U)
#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_AS_MAIN
static void osc32k_init(void)
{
OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_XTALEN
| OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_RUNSTDBY
| OSC32KCTRL_XOSC32K_STARTUP(7);
while (!OSC32KCTRL->STATUS.bit.XOSC32KRDY) {
}
GCLK->GENCTRL[1].reg = GCLK_GENCTRL_SRC(GCLK_SOURCE_XOSC32K)
| GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN;
}
#elif CONFIG_SOC_ATMEL_SAMD5X_OSCULP32K_AS_MAIN
static void osc32k_init(void)
{
GCLK->GENCTRL[1].reg = GCLK_GENCTRL_SRC(GCLK_SOURCE_OSCULP32K)
| GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN;
}
#else
#error "No Clock Source selected."
#endif
static void dpll_init(u8_t n, u32_t f_cpu)
{
/* We source the DPLL from 32kHz GCLK1 */
const u32_t LDR = ((f_cpu << 5) / SOC_ATMEL_SAM0_OSC32K_FREQ_HZ);
/* disable the DPLL before changing the configuration */
OSCCTRL->Dpll[n].DPLLCTRLA.bit.ENABLE = 0;
while (OSCCTRL->Dpll[n].DPLLSYNCBUSY.reg) {
}
/* set DPLL clock source to 32kHz GCLK1 */
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + n].reg = GCLK_PCHCTRL_GEN(1) | GCLK_PCHCTRL_CHEN;
while (!(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + n].reg & GCLK_PCHCTRL_CHEN)) {
}
OSCCTRL->Dpll[n].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(LDR & 0x1F)
| OSCCTRL_DPLLRATIO_LDR((LDR >> 5) - 1);
/* Without LBYPASS, startup takes very long, see errata section 2.13. */
OSCCTRL->Dpll[n].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_GCLK
| OSCCTRL_DPLLCTRLB_WUF
| OSCCTRL_DPLLCTRLB_LBYPASS;
OSCCTRL->Dpll[n].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
while (OSCCTRL->Dpll[n].DPLLSYNCBUSY.reg) {
}
while (!(OSCCTRL->Dpll[n].DPLLSTATUS.bit.CLKRDY &&
OSCCTRL->Dpll[n].DPLLSTATUS.bit.LOCK)) {
}
}
static void dfll_init(void)
{
u32_t reg = OSCCTRL_DFLLCTRLB_QLDIS
#ifdef OSCCTRL_DFLLCTRLB_WAITLOCK
| OSCCTRL_DFLLCTRLB_WAITLOCK
#endif
;
OSCCTRL->DFLLCTRLB.reg = reg;
OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_ENABLE;
while (!OSCCTRL->STATUS.bit.DFLLRDY) {
}
}
static void gclk_connect(u8_t gclk, u8_t src, u8_t div)
{
GCLK->GENCTRL[gclk].reg = GCLK_GENCTRL_SRC(src)
| GCLK_GENCTRL_DIV(div)
| GCLK_GENCTRL_GENEN;
}
static int atmel_samd_init(struct device *arg)
{
u32_t key;
u8_t dfll_div;
if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC < SAM0_DFLL_FREQ_HZ) {
dfll_div = 3;
} else if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC < SAM0_DPLL_FREQ_MIN_HZ) {
dfll_div = 2;
} else {
dfll_div = 1;
}
ARG_UNUSED(arg);
key = irq_lock();
/* enable the Cortex M Cache Controller */
CMCC->CTRL.bit.CEN = 1;
osc32k_init();
dfll_init();
dpll_init(0, dfll_div * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
/* use DPLL for main clock */
gclk_connect(0, GCLK_SOURCE_DPLL0, dfll_div);
/* connect GCLK2 to 48 MHz DFLL for USB */
gclk_connect(2, GCLK_SOURCE_DFLL48M, 0);
/* 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_samd_init, PRE_KERNEL_1, 0);

View file

@ -0,0 +1,27 @@
# Kconfig - Atmel SAME MCU series configuration options
#
# Copyright (c) 2019 ML!PA Consulting GmbH
# SPDX-License-Identifier: Apache-2.0
if SOC_SERIES_SAME54
config SOC_SERIES
string
default "same54"
config SOC_PART_NUMBER
string
default "same54n19a" if SOC_PART_NUMBER_SAME54N19A
default "same54n20a" if SOC_PART_NUMBER_SAME54N20A
default "same54p19a" if SOC_PART_NUMBER_SAME54P19A
default "same54p20a" if SOC_PART_NUMBER_SAME54P20A
config NUM_IRQS
int
default 137
config SYS_CLOCK_HW_CYCLES_PER_SEC
int
default 120000000
endif # SOC_SERIES_SAME54

View file

@ -0,0 +1,14 @@
# Kconfig - Atmel SAME54 MCU series
#
# Copyright (c) 2019 ML!PA Consulting GmbH
# SPDX-License-Identifier: Apache-2.0
config SOC_SERIES_SAME54
bool "Atmel SAME54 MCU"
select CPU_CORTEX_M4
select SOC_FAMILY_SAM0
select CPU_CORTEX_M_HAS_SYSTICK
select CPU_CORTEX_M_HAS_VTOR
select ASF
help
Enable support for Atmel SAME54 Cortex-M4F microcontrollers.

View file

@ -0,0 +1,22 @@
# Kconfig - Atmel SAME MCU series
#
# Copyright (c) 2019 ML!PA Consulting GmbH
# SPDX-License-Identifier: Apache-2.0
choice
prompt "Atmel SAME54 MCU Selection"
depends on SOC_SERIES_SAME54
config SOC_PART_NUMBER_SAME54N19A
bool "SAME54N19A"
config SOC_PART_NUMBER_SAME54N20A
bool "SAME54N20A"
config SOC_PART_NUMBER_SAME54P19A
bool "SAME54P19A"
config SOC_PART_NUMBER_SAME54P20A
bool "SAME54P20A"
endchoice

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
/* SoC level DTS fixup file */
#define DT_FLASH_DEV_NAME DT_ATMEL_SAM0_NVMCTRL_0_LABEL
#define CONFIG_ENTROPY_NAME DT_ATMEL_SAM0_TRNG_0_LABEL
#define DT_NUM_IRQ_PRIO_BITS DT_ARM_V7M_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,42 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ATMEL_SAME54_SOC_H_
#define _ATMEL_SAME54_SOC_H_
#ifndef _ASMLANGUAGE
#define DONT_USE_CMSIS_INIT
#include <zephyr/types.h>
#if defined(CONFIG_SOC_PART_NUMBER_SAME54N19A)
#include <same54n19a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAME54N20A)
#include <same54n20a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAME54P19A)
#include <same54p19a.h>
#elif defined(CONFIG_SOC_PART_NUMBER_SAME54P20A)
#include <same54p20a.h>
#else
#error Library does not support the specified device.
#endif
#endif /* _ASMLANGUAGE */
#include "sercom_fixup_samd5x.h"
#include "tc_fixup_samd5x.h"
#define SOC_ATMEL_SAM0_OSC32K_FREQ_HZ 32768
/** 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_GCLK0_FREQ_HZ SOC_ATMEL_SAM0_MCK_FREQ_HZ
#define SOC_ATMEL_SAM0_GCLK2_FREQ_HZ 48000000
#endif /* _ATMEL_SAME54_SOC_H_ */