soc: add Elan em32f967 minimal SoC support

Add initial support for the Elan em32f967 SoC based on ARM Cortex-M4.
Minimal SoC definition for upstream:
- soc.h, Kconfig, and CMakeLists.txt provided for completeness
- This PR does not implement drivers or UART functionality

Signed-off-by: Johnny Chuang <johnny.chuang@emc.com.tw>
This commit is contained in:
Johnny Chuang
2025-10-18 17:15:39 +08:00
committed by Henrik Brix Andersen
parent 6f0e2acf1e
commit 7e45f351c5
10 changed files with 521 additions and 0 deletions

269
dts/arm/elan/em32fxxx.dtsi Normal file
View File

@@ -0,0 +1,269 @@
/*
* Copyright (c) 2024 ELAN Microelectronics Corp.
* SPDX-License-Identifier: Apache-2.0
*/
#include <arm/armv7-m.dtsi>
#include <mem.h>
#include <zephyr/dt-bindings/clock/em32_clock.h>
#include <zephyr/dt-bindings/gpio/gpio.h>
#include <zephyr/dt-bindings/i2c/i2c.h>
#include <zephyr/dt-bindings/pinctrl/em32f967-pinctrl.h>
#include <zephyr/dt-bindings/pwm/pwm.h>
/ {
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-m4";
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
mpu: mpu@e000ed90 {
compatible = "arm,armv7m-mpu";
reg = <0xe000ed90 0x40>;
};
};
};
sram0: memory@20000000 {
compatible = "mmio-sram";
reg = <0x20000000 DT_SIZE_K(272)>;
};
clocks {
#size-cells = <0>;
clk_ahb: clk-ahb {
compatible = "elan,em32-ahb";
#clock-cells = <0>;
clock-source = <EM32_CLK_SRC_IRCHIGH>;
clock-frequency = <EM32_CLK_FREQ_IRCHIGH96>;
clock-divider = <EM32_AHB_CLK_DIV1>;
status = "disabled";
};
clk_apb: clk-apb {
compatible = "elan,em32-apb";
#clock-cells = <0>;
clocks = <&clk_ahb>;
status = "disabled";
};
};
system-clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <96000000>;
};
soc {
/* Pin Controller */
pinctrl: pin-controller@40030200 {
compatible = "elan,em32-pinctrl";
reg = <0x40030200 0x100>;
reg-names = "iomux";
#address-cells = <1>;
#size-cells = <1>;
#pinctrl-cells = <1>;
status = "okay";
/* GPIO Controllers - EM32F967 hardware */
gpioa: gpio@40020000 {
compatible = "elan,em32-gpio";
reg = <0x40020000 0x1000>;
port-id = <0>;
interrupts = <0 0>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <16>;
clocks = <&clk_ahb>;
status = "disabled";
};
gpiob: gpio@40021000 {
compatible = "elan,em32-gpio";
reg = <0x40021000 0x1000>;
port-id = <1>;
interrupts = <1 0>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <16>;
clocks = <&clk_ahb>;
status = "disabled";
};
};
uart1: serial@40002000 {
compatible = "elan,elandev-uart";
reg = <0x40002000 0x4c>;
clocks = <&clk_apb>;
status = "disabled";
};
spi2: spi@40013000 {
compatible = "elan,elandev-spi2";
reg = <0x40013000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <25 0>;
clocks = <&clk_apb>;
status = "disabled";
};
em32_flash_controller: flash-controller@40034000 {
compatible = "elan,em32-flash-controller";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x40034000 DT_SIZE_K(4)>;
status = "disabled";
flash0: flash@10000000 {
compatible = "soc-nv-flash";
reg = <0x10000000 DT_SIZE_K(536)>;
erase-block-size = <DT_SIZE_K(8)>;
write-block-size = <16>;
};
flash1: flash@10094000 {
compatible = "mcuboot";
reg = <0x10094000 DT_SIZE_K(48)>;
};
};
usbd: usbd@40038000 {
compatible = "elan,elandev-usbd";
reg = <0x40038000 0x1000>;
num-bidir-endpoints = <5>;
status = "disabled";
};
uid: device_uid@40030f00 {
compatible = "elan,em32-uid";
reg = <0x40030f00 0x4 /* Chip ID */
0x100A6020 0x4 /* Device ID */
0x100A6024 0x4 /* IC Version */ >;
reg-names = "chip_id", "device_id", "ic_version";
status = "disabled";
};
bbram0: bbram@40033000 {
compatible = "elan,em32-bbram";
reg = <0x40033000 0x40>;
backup-regs-count = <16>;
status = "disabled";
};
trng0: trng@40018000 {
compatible = "elan,em32-trng";
reg = <0x40018000 0x100>;
interrupts = <41 0>;
clocks = <&clk_apb>;
status = "disabled";
};
wdt0: watchdog@40035000 {
compatible = "elan,em32-wdt";
reg = <0x40035000 0x1000>;
interrupts = <2 0>;
clocks = <&clk_apb>;
status = "disabled";
};
crypto0: crypto@40016000 {
compatible = "elan,em32-crypto";
reg = <0x40016000 0x1000>;
interrupts = <40 0>;
clocks = <&clk_apb>;
status = "disabled";
};
/* Timer Controllers */
timer1: timer@40000000 {
compatible = "elan,em32-timer";
reg = <0x40000000 0x1000>;
clocks = <&clk_apb>;
interrupts = <16 0>;
status = "disabled";
};
timer2: timer@40001000 {
compatible = "elan,em32-timer";
reg = <0x40001000 0x1000>;
clocks = <&clk_apb>;
interrupts = <17 0>;
status = "disabled";
};
timer3: timer@40010000 {
compatible = "elan,em32-timer";
reg = <0x40010000 0x1000>;
clocks = <&clk_apb>;
interrupts = <18 0>;
status = "disabled";
};
timer4: timer@40011000 {
compatible = "elan,em32-timer";
reg = <0x40011000 0x1000>;
clocks = <&clk_apb>;
interrupts = <19 0>;
status = "disabled";
};
/* Real-Time Clock */
rtc0: rtc@40032000 {
compatible = "elan,em32-rtc";
reg = <0x40032000 0x1000>;
clocks = <&clk_apb>;
interrupts = <21 0>;
clock-frequency = <32768>;
status = "disabled";
};
/* PWM Controller */
pwm0: pwm@40006000 {
compatible = "elan,em32-pwm";
reg = <0x40006000 0x1000>;
clocks = <&clk_apb>;
interrupts = <27 0>, <28 0>, <29 0>,
<78 0>, <79 0>, <80 0>;
interrupt-names = "pwma", "pwmb", "pwmc",
"pwmd", "pwme", "pwmf";
#pwm-cells = <3>;
status = "disabled";
};
/* System control */
sysctrl: syscon@40030000 {
compatible = "syscon";
reg = <0x40030000 0x1000>;
reg-io-width = <4>;
status = "disabled";
};
/* Power control */
pwrctrl: syscon@40031000 {
compatible = "syscon";
reg = <0x40031000 0x1000>;
reg-io-width = <4>;
status = "disabled";
};
/* Clock control */
clkctrl: syscon@40036000 {
compatible = "syscon";
reg = <0x40036000 0x1000>;
reg-io-width = <4>;
status = "disabled";
};
};
};
&nvic {
arm,num-irq-priority-bits = <3>;
};

View File

@@ -0,0 +1,6 @@
# Copyright (c) 2025 Elan Microelectronics Corp.
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "")

View File

@@ -0,0 +1,7 @@
# Copyright (c) 2025 Elan Microelectronics Corps.
# SPDX-License-Identifier: Apache-2.0
config SOC_EM32F967
select ARM
select CPU_CORTEX_M4
select CPU_HAS_ARM_MPU

View File

@@ -0,0 +1,18 @@
# Copyright (c) 2025 Elan Microelectronics Corps.
# SPDX-License-Identifier: Apache-2.0
if SOC_EM32F967
config NUM_IRQS
default 64
config SYS_CLOCK_HW_CYCLES_PER_SEC
default $(dt_node_int_prop_int,/system-clock,clock-frequency)
config BUILD_OUTPUT_BIN
default y
config BUILD_OUTPUT_HEX
default y
endif # SOC_EM32F967

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2025 Elan Microelectronics Corp.
# SPDX-License-Identifier: Apache-2.0
config SOC_EM32F967
bool
help
ELAN EM32F967
config SOC
default "em32f967" if SOC_EM32F967

18
soc/elan/em32f967/soc.h Normal file
View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2025 Elan Microelectronics Corp.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_SOC_ELAN_EM32F967_SOC_H_
#define ZEPHYR_SOC_ELAN_EM32F967_SOC_H_
#include <zephyr/init.h>
#include <zephyr/devicetree.h>
#include <cmsis_core_m_defaults.h>
#include "soc_sysctrl.h"
#include "soc_pwrctrl.h"
#include "soc_clkctrl.h"
#endif /* ZEPHYR_SOC_ELAN_EM32F967_SOC_H_ */

View File

@@ -0,0 +1,2 @@
socs:
- name: em32f967

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2025 Elan Microelectronics Corp.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_SOC_ELAN_EM32F967_SOC_CLKCTRL_H_
#define ZEPHYR_SOC_ELAN_EM32F967_SOC_CLKCTRL_H_
#include <zephyr/devicetree.h>
#include <zephyr/sys/util.h>
/* Devicetree node label */
#define CLKCTRL_DT_NODE DT_NODELABEL(clkctrl)
/* Register Offsets */
#define CLKCTRL_MIRC_CTRL_OFF 0x0000
#define CLKCTRL_MIRC_CTRL2_OFF 0x0000
#define CLKCTRL_LJIRC_CTRL_OFF 0x0004
#define CLKCTRL_XTAL_CTRL_OFF 0x0200
#define CLKCTRL_LDO_PLL_OFF 0x030c
#define CLKCTRL_USB_PLL_CTRL_OFF 0x0400
#define CLKCTRL_SYS_PLL_CTRL_OFF 0x0404
#define CLKCTRL_PHY_CTRL_OFF 0x0700
/* Field Masks for MIRC_CTRL */
#define CLKCTRL_MIRC_PD BIT(0) /* [0] MIRCPD */
#define CLKCTRL_HIRC_TESTV BIT(1) /* [1] HIRC_TESTV */
#define CLKCTRL_MIRC_RCM_MASK GENMASK(4, 2) /* [4:2] MIRCRCM */
#define CLKCTRL_MIRC_CA_MASK GENMASK(10, 5) /* [10:5] MIRCCA */
#define CLKCTRL_MIRC_TBG_MASK GENMASK(12, 11) /* [12:11] MIRCTBG */
#define CLKCTRL_MIRC_TCF_MASK GENMASK(14, 13) /* [14:13] MIRCTCF */
#define CLKCTRL_MIRC_TV12_MASK GENMASK(17, 15) /* [17:15] MIRCTV12 */
/* Field Masks for MIRC_CTRL2 */
#define CLKCTRL_MIRC2_PD BIT(0) /* [0] MIRCPD */
#define CLKCTRL_HIRC2_TESTV BIT(1) /* [1] HIRC_TESTV */
#define CLKCTRL_MIRC2_RCM_MASK GENMASK(4, 2) /* [4:2] MIRCRCM */
#define CLKCTRL_MIRC2_TALL_MASK GENMASK(14, 5) /* [14:5] MIRCTall */
#define CLKCTRL_MIRC2_TV12_MASK GENMASK(17, 15) /* [17:15] MIRCTV12 */
/* Field Masks for LJIRC_CTRL */
#define CLKCTRL_LJIRC_PD BIT(0) /* [0] LJIRCPD */
#define CLKCTRL_LJIRC_RCM_MASK GENMASK(2, 1) /* [2:1] LJIRCRCM */
#define CLKCTRL_LJIRC_FR_MASK GENMASK(6, 3) /* [6:3] LJIRCFR */
#define CLKCTRL_LJIRC_CA_MASK GENMASK(11, 7) /* [11:7] LJIRCCA */
#define CLKCTRL_LJIRC_FC_MASK GENMASK(14, 12) /* [14:12] LJIRCFC */
#define CLKCTRL_LJIRC_TMV10_MASK GENMASK(16, 15) /* [16:15] LJIRCTMV10 */
#define CLKCTRL_LJIRC_TESTV10B BIT(17) /* [17] LJIRCTESTV10B */
/* Field Masks for XTAL_CTRL */
#define CLKCTRL_XTAL_FREQ_SEL_MASK GENMASK(1, 0) /* [1:0] XTALFREQSEL */
#define CLKCTRL_XTAL_PD BIT(2) /* [2] XTALPD */
#define CLKCTRL_XTAL_HZ BIT(3) /* [3] XTALHZ */
#define CLKCTRL_XTAL_STABLE BIT(4) /* [4] XTALSTABLE */
#define CLKCTRL_XTAL_COUNTER_MASK GENMASK(6, 5) /* [6:5] XTALCounter */
/* Field Masks for LDO_PLL */
#define CLKCTRL_PLL_LDO_PD BIT(0) /* [0] PLLLDO_PD */
#define CLKCTRL_PLL_LDO_VP_SEL BIT(1) /* [1] PLLLDO_VP_SEL */
#define CLKCTRL_PLL_LDO_VS_MASK GENMASK(4, 2) /* [4:2] PLLLDO_VS */
#define CLKCTRL_PLL_LDO_TV12_MASK GENMASK(8, 5) /* [8:5] PLLLDO_TV12 */
/* Field Masks for USB_PLL_CTRL */
#define CLKCTRL_USB_PLL_PD BIT(0) /* [0] USBPLLPD */
#define CLKCTRL_USB_PLL_FAST_LOCK BIT(1) /* [1] USBPLLFASTLOCK */
#define CLKCTRL_USB_PLL_PSET_MASK GENMASK(4, 2) /* [4:2]USBPLLPSET */
#define CLKCTRL_USB_PLL_STABLE_CNT_MASK GENMASK(6, 5) /* [6:5]USBPLLSTABLECNT */
#define CLKCTRL_USB_PLL_STABLE BIT(7) /* [7] USBPLLSTABLE */
/* Field Masks for SYS_PLL_CTRL */
#define CLKCTRL_SYS_PLL_PD BIT(0) /* [0] SYSPLLPD */
#define CLKCTRL_SYS_PLL_PSET_MASK GENMASK(2, 1) /* [2:1]SYSPLLPSET */
#define CLKCTRL_SYS_PLL_FSET_MASK GENMASK(6, 3) /* [6:3]SYSPLLFSET */
#define CLKCTRL_SYS_PLL_STABLE_CNT_MASK GENMASK(8, 7) /* [8:7]SYSPLLSTABLECNT */
#define CLKCTRL_SYS_PLL_STABLE BIT(9) /* [9] SYSPLLSTABLE */
/* Field Masks for PHY_CTRL */
#define CLKCTRL_PHY_BUF_NSEL_MASK GENMASK(1, 0) /* [1:0] PHYBUFNSEL */
#define CLKCTRL_PHY_BUF_PSEL_MASK GENMASK(3, 2) /* [3:2] PHYBUFPSEL */
#define CLKCTRL_PHY_RTRIM_MASK GENMASK(7, 4) /* [7:4] PHYRTRIM */
#define CLKCTRL_USB_PHY_PDB BIT(8) /* [8] USBPHYPDB */
#define CLKCTRL_USB_PHY_RESET BIT(9) /* [9] USBPHYRESET */
#define CLKCTRL_USB_PHY_RSW BIT(10) /* [10] USBPHYRSW */
#endif /* ZEPHYR_SOC_ELAN_EM32F967_SOC_CLKCTRL_H_ */

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2025 Elan Microelectronics Corp.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_SOC_ELAN_EM32F967_SOC_PWRCTRL_H_
#define ZEPHYR_SOC_ELAN_EM32F967_SOC_PWRCTRL_H_
#include <zephyr/devicetree.h>
#include <zephyr/sys/util.h>
/* Devicetree node label */
#define PWRCTRL_DT_NODE DT_NODELABEL(pwrctrl)
/* Register Offsets */
#define PWRCTRL_POWER_SW_CTRL_OFF 0x0000
/* Field Masks for POWER_SW_CTRL */
#define PWRCTRL_POWER_SW_MASK GENMASK(2, 0) /* [2:0] POWERSW */
#define PWRCTRL_WARMUP_CNT_MASK GENMASK(5, 3) /* [5:3] WARMUPCNT */
#define PWRCTRL_PD_SW_ACK_EN BIT(6) /* [6] PD_SW_ACK_EN */
#define PWRCTRL_STANDBY1_S BIT(7) /* [7] StandBy1_S */
#define PWRCTRL_STANDBY2_S BIT(8) /* [8] StandBy2_S */
#define PWRCTRL_SIP_PD_ENABLE BIT(9) /* [9] SIPPDEnable */
#define PWRCTRL_LDO_IDLE BIT(10) /* [10] LDOIdle */
#define PWRCTRL_HIRC_PD BIT(11) /* [11] HIRCPD */
#define PWRCTRL_SIRC32_PD BIT(12) /* [12] SIRC32PD */
#define PWRCTRL_BOR_PD BIT(13) /* [13] BORPD */
#define PWRCTRL_LDO2_PD BIT(14) /* [14] LDO2PD */
#define PWRCTRL_RAM_PD_ENABLE BIT(15) /* [15] RAMPDEnable */
#endif /* ZEPHYR_SOC_ELAN_EM32F967_SOC_PWRCTRL_H_ */

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2025 Elan Microelectronics Corp.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_SOC_ELAN_EM32F967_SOC_SYSCTRL_H_
#define ZEPHYR_SOC_ELAN_EM32F967_SOC_SYSCTRL_H_
#include <zephyr/devicetree.h>
#include <zephyr/sys/util.h>
/* Devicetree node label */
#define SYSCTRL_DT_NODE DT_NODELABEL(sysctrl)
/* Register Offsets */
#define SYSCTRL_SYS_REG_CTRL_OFF 0x0000
#define SYSCTRL_SYS_STATUS_CTRL_OFF 0x0004
#define SYSCTRL_MISC_REG_CTRL_OFF 0x0008
#define SYSCTRL_CLK_GATE_REG_OFF 0x0100
#define SYSCTRL_CLK_GATE_REG2_OFF 0x0104
/* Field Masks for SYS_REG_CTRL */
#define SYSCTRL_XTAL_HIRC_SEL BIT(0) /* [0] XTALHIRCSEL */
#define SYSCTRL_XTAL_LJIRC_SEL BIT(1) /* [1] XTALLJIRCSEL */
#define SYSCTRL_HCLK_SEL_MASK GENMASK(3, 2) /* [3:2] HCLKSEL */
#define SYSCTRL_USB_CLK_SEL BIT(4) /* [4] USBCLKSEL */
#define SYSCTRL_HCLK_DIV_MASK GENMASK(7, 5) /* [7:5] HCLKDIV */
#define SYSCTRL_QSPI_CLK_SEL BIT(8) /* [8] QSPICLK_SEL */
#define SYSCTRL_ACC1_CLK_SEL BIT(9) /* [9] ACC1CLK_SEL */
#define SYSCTRL_ENCRYPT_SEL BIT(10) /* [10] ENCRYPT_SEL */
#define SYSCTRL_TIMER1_SEL BIT(11) /* [11] Timer1_SEL */
#define SYSCTRL_TIMER2_SEL BIT(12) /* [12] Timer2_SEL */
#define SYSCTRL_TIMER3_SEL BIT(13) /* [13] Timer3_SEL */
#define SYSCTRL_TIMER4_SEL BIT(14) /* [14] Timer4_SEL */
#define SYSCTRL_QSPI_CLK_DIV BIT(15) /* [15] QSPICLK_DIV */
#define SYSCTRL_ACC1_CLK_DIV BIT(16) /* [16] ACC1CLK_DIV */
#define SYSCTRL_ENCRYPT_CLK_DIV BIT(17) /* [17] EncryptCLK_DIV */
#define SYSCTRL_RTC_SEL BIT(18) /* [18] RTC_SEL */
#define SYSCTRL_I2C1_RESET_SEL BIT(19) /* [19] I2C1Reset_SEL */
#define SYSCTRL_USB_RESET_SEL BIT(20) /* [20] USBReset_SEL */
#define SYSCTRL_HIRC_TESTV BIT(21) /* [21] HIRC_TESTV */
#define SYSCTRL_SW_RESTN BIT(22) /* [22] SWRESTN */
#define SYSCTRL_DEEP_SLP_CLK_OFF BIT(23) /* [23] DEEPSLPCLKOFF */
#define SYSCTRL_CLEAR_ECC_KEY BIT(24) /* [24] ClearECCKey */
#define SYSCTRL_POW_EN BIT(25) /* [25] POWEN */
#define SYSCTRL_RESET_OP BIT(26) /* [26] RESETOP */
#define SYSCTRL_PMU_CTRL BIT(27) /* [27] PMUCTRL */
#define SYSCTRL_REAMP_MODE_MASK GENMASK(31, 28) /* [31:28] REAMPMODE */
/* Field Masks for SYS_STATUS_CTRL */
#define SYSCTRL_LEVEL_RSTS BIT(0) /* [0] LEVELRSTS */
#define SYSCTRL_WDT_RESETS BIT(1) /* [1] WDTRESETS */
#define SYSCTRL_SW_RESETS BIT(2) /* [2] SWRESETS */
#define SYSCTRL_SYSREQ_RST_STATUS BIT(3) /* [3] SYSREQ_RST_STATUS */
#define SYSCTRL_LOCKUP_RST_STATUS BIT(4) /* [4] LOCKUP_RST_STATUS */
#define SYSCTRL_FLASHW_COUNT_MASK GENMASK(7, 5) /* [7:5] FLASHWCOUNTS */
#define SYSCTRL_BOR_RESETS BIT(8) /* [8] BORRESETS */
#define SYSCTRL_LVD_FLASH_RSTS BIT(9) /* [9] LVDFlashRSTS */
/* Field Masks for MISC_REG_CTRL */
#define SYSCTRL_WAIT_COUNT_MASK GENMASK(2, 0) /* [2:0] WaitCount */
#define SYSCTRL_WAIT_COUNT_SET BIT(3) /* [3] WaitCountSet */
#define SYSCTRL_WAIT_COUNT_PASS_MASK GENMASK(7, 4) /* [7:4] WaitCountPass */
#define SYSCTRL_REMAP_SYSR_BOOT BIT(26) /* [26] Remap_SYSR_Boot */
#define SYSCTRL_REMAP_IDR_BOOT BIT(27) /* [27] Remap_IDR_Boot */
#define SYSCTRL_GATING_CPU_CLK BIT(28) /* [28] Gating_CPU_CLK */
#define SYSCTRL_REMAP_SWITCH BIT(29) /* [29] Remap_Switch */
#define SYSCTRL_CPUREADY_SKIP_ARBITER BIT(30) /* [30] CPUReady_SkipArbiter */
#define SYSCTRL_SW_RESTEN BIT(31) /* [31] SWRESTEN */
#endif /* ZEPHYR_SOC_ELAN_EM32F967_SOC_SYSCTRL_H_ */