diff --git a/arch/arm/soc/silabs_exx32/Kbuild b/arch/arm/soc/silabs_exx32/Kbuild new file mode 100644 index 00000000000..7f391a83161 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/Kbuild @@ -0,0 +1 @@ +obj-y += $(SOC_SERIES)/ common/ diff --git a/arch/arm/soc/silabs_exx32/Kconfig b/arch/arm/soc/silabs_exx32/Kconfig new file mode 100644 index 00000000000..d1e17ecb121 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/Kconfig @@ -0,0 +1,71 @@ +# +# Copyright (c) 2017 Christian Taedcke +# +# SPDX-License-Identifier: Apache-2.0 +# + +config SOC_FAMILY_EXX32 + bool + # omit prompt to signify a "hidden" option + default n + +if SOC_FAMILY_EXX32 +config SOC_FAMILY + string + default "silabs_exx32" +endif + +source "arch/arm/soc/silabs_exx32/*/Kconfig.soc" + +config SOC_PART_NUMBER + string + default SOC_PART_NUMBER_EXX32_EFM32WG if SOC_SERIES_EFM32WG + help + This string holds the full part number of the SoC. It is a hidden option + that you should not set directly. The part number selection choice defines + the default value for this string. + +config HAS_CMU + bool + default n + help + Set if the clock management unit (CMU) is present in the SoC. + +if HAS_CMU + +choice + prompt "High Frequency Clock Selection" + default CMU_HFCLK_HFXO + +config CMU_HFCLK_HFXO + bool "External high frequency crystal oscillator" + help + Set this option to use the external high frequency crystal oscillator + as high frequency clock. + +config CMU_HFCLK_LFXO + bool "External low frequency crystal oscillator" + help + Set this option to use the external low frequency crystal oscillator + as high frequency clock. + +config CMU_HFCLK_HFRCO + bool "Internal high frequency RC oscillator" + help + Set this option to use the internal high frequency RC oscillator as high frequency clock. + +endchoice + +config CMU_HFXO_FREQ + int "External high frequency oscillator frequency" + help + Set the external high frequency oscillator frequency in Hz. This should be set by the + board's defconfig. + +config CMU_LFXO_FREQ + int "External low frequency oscillator frequency" + help + Set the external low frequency oscillator frequency in Hz. This should be set by the + board's defconfig. + +endif # HAS_CMU diff --git a/arch/arm/soc/silabs_exx32/Kconfig.defconfig b/arch/arm/soc/silabs_exx32/Kconfig.defconfig new file mode 100644 index 00000000000..129445c29c7 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/Kconfig.defconfig @@ -0,0 +1 @@ +source "arch/arm/soc/silabs_exx32/*/Kconfig.defconfig.series" diff --git a/arch/arm/soc/silabs_exx32/Kconfig.soc b/arch/arm/soc/silabs_exx32/Kconfig.soc new file mode 100644 index 00000000000..dc332fdb10b --- /dev/null +++ b/arch/arm/soc/silabs_exx32/Kconfig.soc @@ -0,0 +1,7 @@ +# +# Copyright (c) 2017 Christian Taedcke +# +# SPDX-License-Identifier: Apache-2.0 +# + +source "arch/arm/soc/silabs_exx32/*/Kconfig.series" diff --git a/arch/arm/soc/silabs_exx32/common/Makefile b/arch/arm/soc/silabs_exx32/common/Makefile new file mode 100644 index 00000000000..70862008daf --- /dev/null +++ b/arch/arm/soc/silabs_exx32/common/Makefile @@ -0,0 +1 @@ +obj-y += soc_gpio.o diff --git a/arch/arm/soc/silabs_exx32/common/soc_gpio.c b/arch/arm/soc/silabs_exx32/common/soc_gpio.c new file mode 100644 index 00000000000..e38cad7f0a1 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/common/soc_gpio.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017 Christian Taedcke + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief Silabs EXX32 MCU family General Purpose Input Output (GPIO) + * module HAL driver. + */ + +#include "soc_gpio.h" + +void soc_gpio_configure(const struct soc_gpio_pin *pin) +{ + GPIO_PinModeSet(pin->port, pin->pin, pin->mode, pin->out); +} diff --git a/arch/arm/soc/silabs_exx32/common/soc_gpio.h b/arch/arm/soc/silabs_exx32/common/soc_gpio.h new file mode 100644 index 00000000000..406be31df18 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/common/soc_gpio.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Christian Taedcke + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief Silabs EXX32 MCU family General Purpose Input Output (GPIO) + * module HAL driver. + */ + +#ifndef _SILABS_EXX32_SOC_GPIO_H_ +#define _SILABS_EXX32_SOC_GPIO_H_ + +#include +#include + +struct soc_gpio_pin { + GPIO_Port_TypeDef port; /** GPIO port */ + unsigned int pin; /** GPIO pin on the port */ + GPIO_Mode_TypeDef mode; /** mode of the pin, e.g. gpioModeInput */ + unsigned int out; /** out register value */ +}; + +/** + * @brief Configure GPIO pin + * @param[in] pin configuration data + */ +void soc_gpio_configure(const struct soc_gpio_pin *pin); + +#endif /* _SILABS_EXX32_SOC_GPIO_H_ */ diff --git a/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.defconfig.efm32wg b/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.defconfig.efm32wg new file mode 100644 index 00000000000..2dc61ac7394 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.defconfig.efm32wg @@ -0,0 +1,32 @@ +# Kconfig - Silicon Labs EFM32WG-STK3800 platform configuration options + +# +# Copyright (c) 2017 Christian Taedcke +# +# SPDX-License-Identifier: Apache-2.0 +# + +if SOC_EFM32WG + +config SOC + string + default efm32wg + +config GPIO + def_bool y + +if GPIO + +config GPIO_GECKO + def_bool y + +endif # GPIO + +if SERIAL + +config UART_GECKO + def_bool y + +endif # SERIAL + +endif # SOC_EFM32 diff --git a/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.defconfig.series b/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.defconfig.series new file mode 100644 index 00000000000..fe18fe6d81f --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.defconfig.series @@ -0,0 +1,21 @@ +# Kconfig - EFM32WG series configuration options + +# +# Copyright (c) 2017 Christian Taedcke +# +# SPDX-License-Identifier: Apache-2.0 +# + +if SOC_SERIES_EFM32WG + +config SOC_SERIES + default efm32wg + +config NUM_IRQS + int + # must be >= the highest interrupt number used + default 39 + +source "arch/arm/soc/silabs_exx32/efm32wg/Kconfig.defconfig.e*" + +endif # SOC_SERIES_EFM32WG diff --git a/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.series b/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.series new file mode 100644 index 00000000000..0daa217cf08 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.series @@ -0,0 +1,17 @@ +# Kconfig - EFM32WG MCU line +# +# Copyright (c) 2017 Christian Taedcke +# +# SPDX-License-Identifier: Apache-2.0 +# + +config SOC_SERIES_EFM32WG + bool "EFM32WG Series MCU" + select CPU_CORTEX_M + select CPU_CORTEX_M4 + select CPU_HAS_FPU + select SOC_FAMILY_EXX32 + select SYS_POWER_LOW_POWER_STATE_SUPPORTED + select CPU_HAS_SYSTICK + help + Enable support for EFM32 WonderGecko MCU series diff --git a/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.soc b/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.soc new file mode 100644 index 00000000000..410e4a0e92e --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/Kconfig.soc @@ -0,0 +1,33 @@ +# Kconfig - EFM32WG MCU line +# +# Copyright (c) 2017 Christian Taedcke +# +# SPDX-License-Identifier: Apache-2.0 +# + +choice +prompt "EFM32 Wonder Gecko MCU Selection" +depends on SOC_SERIES_EFM32WG + +config SOC_EFM32WG + bool "SOC_EFM32WG" + select HAS_SILABS_GECKO + select HAS_CMU + select CPU_HAS_FPU + +endchoice + +if SOC_SERIES_EFM32WG + +config SOC_PART_NUMBER_EFM32WG990F256 + bool + +config SOC_PART_NUMBER_EXX32_EFM32WG + string + default "EFM32WG990F256" if SOC_PART_NUMBER_EFM32WG990F256 + help + This string holds the full part number of the SoC. It is a hidden option + that you should not set directly. The part number selection choice defines + the default value for this string. + +endif # SOC_SERIES_EFM32WG diff --git a/arch/arm/soc/silabs_exx32/efm32wg/Makefile b/arch/arm/soc/silabs_exx32/efm32wg/Makefile new file mode 100644 index 00000000000..52341f86c0b --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/Makefile @@ -0,0 +1 @@ +obj-y += soc.o diff --git a/arch/arm/soc/silabs_exx32/efm32wg/linker.ld b/arch/arm/soc/silabs_exx32/efm32wg/linker.ld new file mode 100644 index 00000000000..5542d34df11 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/linker.ld @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017 Christian Taedcke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * This is the linker script for both standard images. + */ + +#include + +#include diff --git a/arch/arm/soc/silabs_exx32/efm32wg/soc.c b/arch/arm/soc/silabs_exx32/efm32wg/soc.c new file mode 100644 index 00000000000..ed31b7e05f4 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/soc.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017, Christian Taedcke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief SoC initialization for the EFM32WG + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_CMU_HFCLK_HFXO +/** + * @brief Initialization parameters for the external high frequency oscillator + */ +static const CMU_HFXOInit_TypeDef hfxoInit = CMU_HFXOINIT_DEFAULT; +#elif (defined CONFIG_CMU_HFCLK_LFXO) +/** + * @brief Initialization parameters for the external low frequency oscillator + */ +static const CMU_LFXOInit_TypeDef lfxoInit = CMU_LFXOINIT_DEFAULT; +#endif + +/** + * @brief Initialize the system clock + * + * @return N/A + * + */ +static ALWAYS_INLINE void clkInit(void) +{ +#ifdef CONFIG_CMU_HFCLK_HFXO + CMU_HFXOInit(&hfxoInit); + CMU_OscillatorEnable(cmuOsc_HFXO, true, true); + CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); + CMU_OscillatorEnable(cmuOsc_HFRCO, false, false); + SystemHFXOClockSet(CONFIG_CMU_HFXO_FREQ); +#elif (defined CONFIG_CMU_HFCLK_LFXO) + CMU_LFXOInit(&lfxoInit); + CMU_OscillatorEnable(cmuOsc_LFXO, true, true); + CMU_ClockSelectSet(cmuClock_HF, cmuSelect_LFXO); + CMU_OscillatorEnable(cmuOsc_HFRCO, false, false); + SystemLFXOClockSet(CONFIG_CMU_LFXO_FREQ); +#elif (defined CONFIG_CMU_HFCLK_HFRCO) + /* + * This is the default clock, the controller starts with, so nothing to + * do here. + */ +#else +#error "Unsupported clock source for HFCLK selected" +#endif + + /* Enable the High Frequency Peripheral Clock */ + CMU_ClockEnable(cmuClock_HFPER, true); + +#ifdef CONFIG_GPIO_GECKO + CMU_ClockEnable(cmuClock_GPIO, true); +#endif +} + +/** + * @brief Perform basic hardware initialization + * + * Initialize the interrupt controller device drivers. + * Also initialize the timer device driver, if required. + * + * @return 0 + */ +static int silabs_efm32wg_init(struct device *arg) +{ + ARG_UNUSED(arg); + + int oldLevel; /* old interrupt lock level */ + + /* disable interrupts */ + oldLevel = irq_lock(); + + /* handle chip errata */ + CHIP_Init(); + + _ClearFaults(); + + /* Initialize system clock according to CONFIG_CMU settings */ + clkInit(); + + /* + * install default handler that simply resets the CPU + * if configured in the kernel, NOP otherwise + */ + NMI_INIT(); + + /* restore interrupt state */ + irq_unlock(oldLevel); + return 0; +} + +SYS_INIT(silabs_efm32wg_init, PRE_KERNEL_1, 0); diff --git a/arch/arm/soc/silabs_exx32/efm32wg/soc.h b/arch/arm/soc/silabs_exx32/efm32wg/soc.h new file mode 100644 index 00000000000..ca228062fa9 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/soc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Christian Taedcke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Board configuration macros for the efm32wg soc + * + */ + +#ifndef _SOC__H_ +#define _SOC__H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASMLANGUAGE + +#include +#include + +#include "soc_pinmap.h" +#include "../common/soc_gpio.h" + +#endif /* !_ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC__H_ */ diff --git a/arch/arm/soc/silabs_exx32/efm32wg/soc_pinmap.h b/arch/arm/soc/silabs_exx32/efm32wg/soc_pinmap.h new file mode 100644 index 00000000000..8f3fb5a3d32 --- /dev/null +++ b/arch/arm/soc/silabs_exx32/efm32wg/soc_pinmap.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017 Christian Taedcke + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief Silabs EFM32WG MCU pin definitions. + * + * This file contains pin configuration data required by different MCU + * modules to correctly configure GPIO controller. + */ + +#ifndef _SILABS_EFM32WG_SOC_PINMAP_H_ +#define _SILABS_EFM32WG_SOC_PINMAP_H_ + +#include +#include + +#ifdef CONFIG_SOC_PART_NUMBER_EFM32WG990F256 +#ifdef CONFIG_UART_GECKO_0 +#if (CONFIG_UART_GECKO_0_GPIO_LOC == 0) +#define PIN_UART0_TXD {gpioPortF, 6, gpioModePushPull, 1} +#define PIN_UART0_RXD {gpioPortF, 7, gpioModeInput, 1} +#elif (CONFIG_UART_GECKO_0_GPIO_LOC == 1) +#define PIN_UART0_TXD {gpioPortE, 0, gpioModePushPull, 1} +#define PIN_UART0_RXD {gpioPortE, 1, gpioModeInput, 1} +#elif (CONFIG_UART_GECKO_0_GPIO_LOC == 2) +#define PIN_UART0_TXD {gpioPortA, 3, gpioModePushPull, 1} +#define PIN_UART0_RXD {gpioPortA, 4, gpioModeInput, 1} +#else +#error ("Serial Driver for Gecko MCUs not implemented for this location index") +#endif +#endif /* CONFIG_UART_GECKO_0 */ + +#ifdef CONFIG_UART_GECKO_1 +#if (CONFIG_UART_GECKO_1_GPIO_LOC == 0) +#error ("Serial Driver for Gecko MCUs not implemented for this location index") +#elif (CONFIG_UART_GECKO_1_GPIO_LOC == 1) +#define PIN_UART1_TXD {gpioPortF, 10, gpioModePushPull, 1} +#define PIN_UART1_RXD {gpioPortF, 11, gpioModeInput, 1} +#elif (CONFIG_UART_GECKO_1_GPIO_LOC == 2) +#define PIN_UART1_TXD {gpioPortB, 9, gpioModePushPull, 1} +#define PIN_UART1_RXD {gpioPortB, 10, gpioModeInput, 1} +#elif (CONFIG_UART_GECKO_1_GPIO_LOC == 3) +#define PIN_UART1_TXD {gpioPortE, 2, gpioModePushPull, 1} +#define PIN_UART1_RXD {gpioPortE, 3, gpioModeInput, 1} +#else +#error ("Serial Driver for Gecko MCUs not implemented for this location index") +#endif +#endif /* CONFIG_UART_GECKO_0 */ +#else +#error ("Pinmap not available for this for Wonder Gecko MCU") +#endif /* SOC_PART_NUMBER_EFM32WG990F256*/ + +#endif /* _SILABS_EFM32WG_SOC_PINMAP_H_ */ diff --git a/dts/arm/silabs/efm32wg.dtsi b/dts/arm/silabs/efm32wg.dtsi new file mode 100644 index 00000000000..3878cc6de6b --- /dev/null +++ b/dts/arm/silabs/efm32wg.dtsi @@ -0,0 +1,64 @@ +#include +#include + +/ { + cpus { + cpu@0 { + compatible = "arm,cortex-m4f"; + }; + }; + + flash0: flash { + reg = <0 DT_FLASH_SIZE>; + }; + + sram0: memory { + reg = <0x20000000 DT_SRAM_SIZE>; + }; + + soc { + uart0: uart@4000c000 { /* USART0 */ + compatible = "silabs,efm32-usart"; + reg = <0x4000c000 0x400>; + interrupts = <3 0 4 0>; + status = "disabled"; + label = "UART_0"; + }; + + uart1: uart@4000c400 { /* USART1 */ + compatible = "silabs,efm32-usart"; + reg = <0x4000c400 0x400>; + interrupts = <15 0 16 0>; + status = "disabled"; + label = "UART_1"; + }; + + uart2: uart@4000c800 { /* USART2 */ + compatible = "silabs,efm32-usart"; + reg = <0x4000c800 0x400>; + interrupts = <18 0 19 0>; + status = "disabled"; + label = "UART_2"; + }; + + uart3: uart@4000e000 { /* UART0 */ + compatible = "silabs,efm32-uart"; + reg = <0x4000e000 0x400>; + interrupts = <20 0 21 0>; + status = "disabled"; + label = "UART_3"; + }; + + uart4: uart@4000e400 { /* UART1 */ + compatible = "silabs,efm32-uart"; + reg = <0x4000e400 0x400>; + interrupts = <22 0 23 0>; + status = "disabled"; + label = "UART_4"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/arm/silabs/mem.h b/dts/arm/silabs/mem.h new file mode 100644 index 00000000000..ddbc90c6021 --- /dev/null +++ b/dts/arm/silabs/mem.h @@ -0,0 +1,13 @@ +#ifndef __DT_BINDING_ST_MEM_H +#define __DT_BINDING_ST_MEM_H + +#define __SIZE_K(x) (x * 1024) + +#if defined(CONFIG_SOC_PART_NUMBER_EFM32WG990F256) +#define DT_FLASH_SIZE __SIZE_K(256) +#define DT_SRAM_SIZE __SIZE_K(32) +#else +#error "Flash and RAM sizes not defined for this chip" +#endif + +#endif /* __DT_BINDING_ST_MEM_H */ diff --git a/dts/arm/yaml/silabs,efm32-uart.yaml b/dts/arm/yaml/silabs,efm32-uart.yaml new file mode 100644 index 00000000000..78153b4ecdb --- /dev/null +++ b/dts/arm/yaml/silabs,efm32-uart.yaml @@ -0,0 +1,30 @@ +--- +title: EFM32 UART +id: silabs,efm32-uart +version: 0.1 + +description: > + This binding gives a base representation of the EFM32 UART + +inherits: + - !include uart.yaml + +properties: + - compatible: + type: string + category: required + description: compatible strings + constraint: "silabs,efm32-uart" + + - reg: + type: array + description: mmio register space + generation: define + category: required + + - interrupts: + type: array + category: required + description: required interrupts + generation: define +... diff --git a/dts/arm/yaml/silabs,efm32-usart.yaml b/dts/arm/yaml/silabs,efm32-usart.yaml new file mode 100644 index 00000000000..0ab9a7c0e03 --- /dev/null +++ b/dts/arm/yaml/silabs,efm32-usart.yaml @@ -0,0 +1,30 @@ +--- +title: EFM32 USART +id: silabs,efm32-usart +version: 0.1 + +description: > + This binding gives a base representation of the EFM32 USART + +inherits: + - !include uart.yaml + +properties: + - compatible: + type: string + category: required + description: compatible strings + constraint: "silabs,efm32-usart" + + - reg: + type: array + description: mmio register space + generation: define + category: required + + - interrupts: + type: array + category: required + description: required interrupts + generation: define +...