From 4227dadbe935c15e9326296fbc7b9b00da380811 Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Tue, 3 Dec 2024 15:58:07 -0500 Subject: [PATCH 1/9] west: west.yml pointed to in-flight PR for MSPM0 support For CI test to pass, we point to our changes for MSPM0 in hal_ti Signed-off-by: Jackson Farley --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index deecf69acfe98..9551fe736fd96 100644 --- a/west.yml +++ b/west.yml @@ -244,7 +244,7 @@ manifest: groups: - hal - name: hal_ti - revision: 2e7b95ad079e9f636884eedc6853e6ad98b85f65 + revision: pull/51/head path: modules/hal/ti groups: - hal From 24e8378a5e5c62bad1e133fb41e1ad220ea42b8f Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Thu, 16 Jan 2025 18:41:49 -0500 Subject: [PATCH 2/9] soc: added initial SOC support for TI MSPM0 Added initial SOC support for TI MSPM0 family Signed-off-by: Jackson Farley --- modules/Kconfig | 1 + modules/Kconfig.mspm0 | 7 +++ soc/ti/mspm0/CMakeLists.txt | 5 ++ soc/ti/mspm0/Kconfig | 9 ++++ soc/ti/mspm0/Kconfig.defconfig | 8 +++ soc/ti/mspm0/Kconfig.soc | 12 +++++ soc/ti/mspm0/mspm0g1x0x_g3x0x/CMakeLists.txt | 22 ++++++++ soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig | 14 +++++ .../mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig | 17 ++++++ soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.soc | 53 +++++++++++++++++++ soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h | 49 +++++++++++++++++ soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c | 25 +++++++++ soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h | 37 +++++++++++++ soc/ti/mspm0/soc.yml | 13 +++++ 14 files changed, 272 insertions(+) create mode 100644 modules/Kconfig.mspm0 create mode 100644 soc/ti/mspm0/CMakeLists.txt create mode 100644 soc/ti/mspm0/Kconfig create mode 100644 soc/ti/mspm0/Kconfig.defconfig create mode 100644 soc/ti/mspm0/Kconfig.soc create mode 100644 soc/ti/mspm0/mspm0g1x0x_g3x0x/CMakeLists.txt create mode 100644 soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig create mode 100644 soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig create mode 100644 soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.soc create mode 100644 soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h create mode 100644 soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c create mode 100644 soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h create mode 100644 soc/ti/mspm0/soc.yml diff --git a/modules/Kconfig b/modules/Kconfig index 7e0e2b2872d10..3f720d9f2fd2a 100644 --- a/modules/Kconfig +++ b/modules/Kconfig @@ -24,6 +24,7 @@ source "modules/Kconfig.libmetal" source "modules/lvgl/Kconfig" source "modules/Kconfig.mcux" source "modules/Kconfig.microchip" +source "modules/Kconfig.mspm0" source "modules/Kconfig.nuvoton" source "modules/Kconfig.open-amp" source "modules/Kconfig.picolibc" diff --git a/modules/Kconfig.mspm0 b/modules/Kconfig.mspm0 new file mode 100644 index 0000000000000..fdf1993ab53d9 --- /dev/null +++ b/modules/Kconfig.mspm0 @@ -0,0 +1,7 @@ +# MSPM0 SDK configuration + +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +config HAS_MSPM0_SDK + bool diff --git a/soc/ti/mspm0/CMakeLists.txt b/soc/ti/mspm0/CMakeLists.txt new file mode 100644 index 0000000000000..4e105fa57cfdc --- /dev/null +++ b/soc/ti/mspm0/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "SoC Linker Script") + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/ti/mspm0/Kconfig b/soc/ti/mspm0/Kconfig new file mode 100644 index 0000000000000..0010586628a80 --- /dev/null +++ b/soc/ti/mspm0/Kconfig @@ -0,0 +1,9 @@ +# Texas Instruments MSPM0 Family +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_TI_MSPM0 + +rsource "*/Kconfig" + +endif # SOC_FAMILY_TI_MSPM0 diff --git a/soc/ti/mspm0/Kconfig.defconfig b/soc/ti/mspm0/Kconfig.defconfig new file mode 100644 index 0000000000000..586a2915dd5b3 --- /dev/null +++ b/soc/ti/mspm0/Kconfig.defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Texas Instruments + +if SOC_FAMILY_TI_MSPM0 + +rsource "*/Kconfig.defconfig" + +endif # SOC_FAMILY_TI_MSPM0 diff --git a/soc/ti/mspm0/Kconfig.soc b/soc/ti/mspm0/Kconfig.soc new file mode 100644 index 0000000000000..44098415e0d1f --- /dev/null +++ b/soc/ti/mspm0/Kconfig.soc @@ -0,0 +1,12 @@ +# Texas Instruments MSPM0 Family + +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_TI_MSPM0 + bool + +config SOC_FAMILY + default "ti_mspm0" if SOC_FAMILY_TI_MSPM0 + +rsource "*/Kconfig.soc" diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/CMakeLists.txt b/soc/ti/mspm0/mspm0g1x0x_g3x0x/CMakeLists.txt new file mode 100644 index 0000000000000..f1bc1e325b675 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_SOC_MSPM0G1106) + zephyr_compile_definitions(-D__MSPM0G1106__) +elseif(CONFIG_SOC_MSPM0G1107) + zephyr_compile_definitions(-D__MSPM0G1107__) +elseif(CONFIG_SOC_MSPM0G1506) + zephyr_compile_definitions(-D__MSPM0G1506__) +elseif(CONFIG_SOC_MSPM0G1507) + zephyr_compile_definitions(-D__MSPM0G1507__) +elseif(CONFIG_SOC_MSPM0G3106) + zephyr_compile_definitions(-D__MSPM0G3106__) +elseif(CONFIG_SOC_MSPM0G3107) + zephyr_compile_definitions(-D__MSPM0G3107__) +elseif(CONFIG_SOC_MSPM0G3506) + zephyr_compile_definitions(-D__MSPM0G3506__) +elseif(CONFIG_SOC_MSPM0G3507) + zephyr_compile_definitions(-D__MSPM0G3507__) +endif() + +zephyr_sources(soc.c) +zephyr_include_directories(.) diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig new file mode 100644 index 0000000000000..2ddec387c9c1b --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig @@ -0,0 +1,14 @@ +# TI MSPM0G1X0X_G3X0X + +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_MSPM0G1X0X_G3X0X + select ARM + select CPU_CORTEX_M0PLUS + select CPU_CORTEX_M_HAS_VTOR + select CPU_HAS_ARM_MPU + select CPU_CORTEX_M_HAS_SYSTICK + select BUILD_OUTPUT_HEX + select HAS_MSPM0_SDK + select CLOCK_CONTROL diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig new file mode 100644 index 0000000000000..0ef3d3b946070 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig @@ -0,0 +1,17 @@ +# TI MSPM0G1X0X_G3X0X + +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_MSPM0G1X0X_G3X0X + +DT_MSPM0_CLKMUX_PATH := $(dt_nodelabel_path,clkmux) +DT_MSPM0_CLKMUX_CPU_FREQ := $(dt_node_int_prop_int,$(DT_MSPM0_CLKMUX_PATH),clock-frequency) + +config NUM_IRQS + default 32 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default "$(DT_MSPM0_CLKMUX_CPU_FREQ)" if "$(dt_nodelabel_enabled,clkmux)" + +endif # SOC_SERIES_MSPM0G1X0X_G3X0X diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.soc b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.soc new file mode 100644 index 0000000000000..ac09bc6852861 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.soc @@ -0,0 +1,53 @@ +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_MSPM0G1X0X_G3X0X + bool + select SOC_FAMILY_TI_MSPM0 + help + Enable support for TI MSPM0G1X0X_G3X0X SoCs + +config SOC_MSPM0G1106 + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G1107 + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G1506 + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G1507 + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G3106 + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G3107 + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G3506 + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G3507 + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_SERIES + default "mspm0g1x0x_g3x0x" if SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC + default "mspm0g1106" if SOC_MSPM0G1106 + default "mspm0g1107" if SOC_MSPM0G1107 + default "mspm0g1506" if SOC_MSPM0G1506 + default "mspm0g1507" if SOC_MSPM0G1507 + default "mspm0g3106" if SOC_MSPM0G3106 + default "mspm0g3107" if SOC_MSPM0G3107 + default "mspm0g3506" if SOC_MSPM0G3506 + default "mspm0g3507" if SOC_MSPM0G3507 diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h b/soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h new file mode 100644 index 0000000000000..bdfc3181a454b --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) (2024) Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SOC_TI_MSPM0_M0G1X0X_G3X0X_PINCTRL_SOC_H_ +#define SOC_TI_MSPM0_M0G1X0X_G3X0X_PINCTRL_SOC_H_ + +#include +#include +#include + +#define MSP_GPIO_RESISTOR_PULL_DOWN (16) +#define MSP_GPIO_RESISTOR_PULL_UP (17) +#define MSP_GPIO_INPUT_ENABLE (18) +#define MSP_GPIO_HYSTERESIS_ENABLED (19) +#define MSP_GPIO_OPEN_DRAIN_OUTPUT (25) +#define MSP_GPIO_INVERSION_ENABLED (26) + +#define MSP_GPIO_HIGH_DRIVE (20) + +#define MSP_PINMUX_INIT(node_id) DT_PROP(node_id, pinmux) + +#define MSP_PIN_CONTROL_IOMUX_INIT(node_id) \ + ((DT_PROP(node_id, bias_pull_up) << MSP_GPIO_RESISTOR_PULL_UP) | \ + (DT_PROP(node_id, bias_pull_down) << MSP_GPIO_RESISTOR_PULL_DOWN) | \ + (DT_PROP(node_id, drive_open_drain) << MSP_GPIO_OPEN_DRAIN_OUTPUT) | \ + (DT_PROP(node_id, ti_hysteresis) << MSP_GPIO_HYSTERESIS_ENABLED) | \ + (DT_PROP(node_id, ti_invert) << MSP_GPIO_INVERSION_ENABLED) | \ + (DT_PROP(node_id, input_enable) << MSP_GPIO_INPUT_ENABLE)) + +typedef struct pinctrl_soc_pin { + /* PINCM register index and pin function */ + uint32_t pinmux; + /* IOMUX Pin Control Management (direction, inversion, pullups) */ + uint32_t iomux; +} pinctrl_soc_pin_t; + +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + {.pinmux = MSP_PINMUX_INIT(DT_PROP_BY_IDX(node_id, prop, idx)), \ + .iomux = MSP_PIN_CONTROL_IOMUX_INIT(DT_PROP_BY_IDX(node_id, prop, idx))}, + +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { \ + DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT) \ + } + +#endif /* SOC_TI_MSPM0_M0G1X0X_G3X0X_PINCTRL_SOC_H_ */ diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c new file mode 100644 index 0000000000000..ed7b8c0d120a7 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +void soc_early_init_hook(void) +{ + /* Reset and enable GPIO banks */ + DL_GPIO_reset(GPIOA); + DL_GPIO_reset(GPIOB); + + DL_GPIO_enablePower(GPIOA); + DL_GPIO_enablePower(GPIOB); + + /* Allow delay time to settle */ + delay_cycles(POWER_STARTUP_DELAY); + + /* Low Power Mode is configured to be SLEEP0 */ + DL_SYSCTL_setBORThreshold(DL_SYSCTL_BOR_THRESHOLD_LEVEL_0); +} diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h new file mode 100644 index 0000000000000..326f97ee54359 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SOC_TI_MSPM0_SOC_H_ +#define SOC_TI_MSPM0_SOC_H_ + +#define SYSCONFIG_WEAK __attribute__((weak)) + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Per TRM Section 2.2.7 Peripheral Power Enable Control: + * + * After setting the ENABLE | KEY bits in the PWREN Register to enable a + * peripheral, wait at least 4 ULPCLK clock cycles before accessing the rest of + * the peripheral's memory-mapped registers. The 4 cycles allow for the bus + * isolation signals at the peripheral's bus interface to update. + * + * ULPCLK will either be equivalent or half of the main MCLK and CPUCLK, + * yielding the delay time of 8 cycles + */ +#define POWER_STARTUP_DELAY (8) + +#ifdef __cplusplus +} +#endif + +#endif /* SOC_TI_MSPM0_SOC_H_ */ diff --git a/soc/ti/mspm0/soc.yml b/soc/ti/mspm0/soc.yml new file mode 100644 index 0000000000000..d907eca563b41 --- /dev/null +++ b/soc/ti/mspm0/soc.yml @@ -0,0 +1,13 @@ +family: +- name: ti_mspm0 + series: + - name: mspm0g1x0x_g3x0x + socs: + - name: mspm0g1106 + - name: mspm0g1107 + - name: mspm0g1506 + - name: mspm0g1507 + - name: mspm0g3106 + - name: mspm0g3107 + - name: mspm0g3506 + - name: mspm0g3507 From e8f22102d87a46789e6a1cc92b02c2b025344f4f Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Thu, 21 Mar 2024 21:00:43 -0400 Subject: [PATCH 3/9] dts: add MSPM0 family to the devicetree added TI MSPM0 device support to the devicetree Signed-off-by: Jackson Farley --- dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1106.dtsi | 4 + dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1107.dtsi | 4 + dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1506.dtsi | 4 + dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1507.dtsi | 4 + .../ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi | 125 ++++++++++++++++++ dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3106.dtsi | 4 + dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3107.dtsi | 4 + dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3506.dtsi | 4 + dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3507.dtsi | 4 + dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx6.dtsi | 14 ++ dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx7.dtsi | 14 ++ dts/bindings/clock/ti,mspm0-clock-mux.yaml | 43 ++++++ dts/bindings/clock/ti,mspm0-oscillator.yaml | 13 ++ dts/bindings/clock/ti,mspm0-pll.yaml | 56 ++++++++ .../zephyr/dt-bindings/clock/mspm0_clock.h | 33 +++++ .../dt-bindings/pinctrl/mspm0-pinctrl.h | 30 +++++ 16 files changed, 360 insertions(+) create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1106.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1107.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1506.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1507.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3106.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3107.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3506.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3507.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx6.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx7.dtsi create mode 100644 dts/bindings/clock/ti,mspm0-clock-mux.yaml create mode 100644 dts/bindings/clock/ti,mspm0-oscillator.yaml create mode 100644 dts/bindings/clock/ti,mspm0-pll.yaml create mode 100644 include/zephyr/dt-bindings/clock/mspm0_clock.h create mode 100644 include/zephyr/dt-bindings/pinctrl/mspm0-pinctrl.h diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1106.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1106.dtsi new file mode 100644 index 0000000000000..f86c4db3c8fc8 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1106.dtsi @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1107.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1107.dtsi new file mode 100644 index 0000000000000..c1227ab01ef93 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1107.dtsi @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1506.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1506.dtsi new file mode 100644 index 0000000000000..f86c4db3c8fc8 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1506.dtsi @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1507.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1507.dtsi new file mode 100644 index 0000000000000..c1227ab01ef93 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1507.dtsi @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi new file mode 100644 index 0000000000000..66b3f81da17e5 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m0+"; + reg = <0>; + }; + }; + + sram0: memory@20200000 { + compatible = "mmio-sram"; + }; + + flash0: serial-flash@0 { + compatible = "serial-flash"; + }; + + sysclk: system-clock { + compatible = "fixed-clock"; + clock-frequency = ; + #clock-cells = <0>; + }; + + clkmux: clock-controller { + compatible = "ti,mspm0-clock-mux"; + mclk-div = <1>; + uclk-div = <1>; + #clock-cells = <1>; + }; + + clocks: clocks { + sysosc: sysosc { + compatible = "ti,mspm0-oscillator"; + clock-frequency = ; + #clock-cells = <0>; + }; + + lfosc: lfosc { + compatible = "fixed-clock"; + clock-frequency = <32678>; + #clock-cells = <0>; + }; + + pll: pll { + compatible = "ti,mspm0-pll"; + clocks = <&sysosc 0>; + p-div = <2>; + q-div = <5>; + clk1-div = <2>; + clk2x-div = <2>; + #clock-cells = <0>; + status = "okay"; + }; + }; + + soc { + + pinctrl: pin-controller@400a0000{ + compatible = "ti,mspm0-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x400a0000 0x4000>; + + gpioa: gpio@400a0000 { + compatible = "ti,mspm0-gpio"; + reg = <0x400a0000 0x2000>; + interrupts = <1 0>; + status = "disabled"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpiob: gpio@400a2000 { + compatible = "ti,mspm0-gpio"; + reg = <0x400a2000 0x2000>; + interrupts = <1 0>; + status = "disabled"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + uart0: uart@40108000 { + compatible = "ti,mspm0-uart"; + reg = <0x40108000 0x2000>; + interrupts = <15 0>; + current-speed = <115200>; + clocks = <&clkmux MSPM0_CLOCK_BUS_ULPCLK>; + status = "disabled"; + }; + + uart1: uart@40100000 { + compatible = "ti,mspm0-uart"; + reg = <0x40100000 0x2000>; + interrupts = <13 0>; + current-speed = <115200>; + clocks = <&clkmux MSPM0_CLOCK_BUS_ULPCLK>; + status = "disabled"; + }; + + uart2: uart@40102000 { + compatible = "ti,mspm0-uart"; + reg = <0x40102000 0x2000>; + interrupts = <14 0>; + current-speed = <115200>; + clocks = <&clkmux MSPM0_CLOCK_BUS_ULPCLK>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <2>; +}; diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3106.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3106.dtsi new file mode 100644 index 0000000000000..f86c4db3c8fc8 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3106.dtsi @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3107.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3107.dtsi new file mode 100644 index 0000000000000..c1227ab01ef93 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3107.dtsi @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3506.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3506.dtsi new file mode 100644 index 0000000000000..f86c4db3c8fc8 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3506.dtsi @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3507.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3507.dtsi new file mode 100644 index 0000000000000..c1227ab01ef93 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3507.dtsi @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx6.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx6.dtsi new file mode 100644 index 0000000000000..0b69a7e698a9f --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx6.dtsi @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include + +/ { + sram0: memory@20200000 { + reg = <0x20200000 DT_SIZE_K(32)>; + }; + + flash0: serial-flash@0 { + reg = <0x0 DT_SIZE_K(64)>; + }; +}; diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx7.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx7.dtsi new file mode 100644 index 0000000000000..5cda6550db2b8 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0gxxx7.dtsi @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include + +/ { + sram0: memory@20200000 { + reg = <0x20200000 DT_SIZE_K(32)>; + }; + + flash0: serial-flash@0 { + reg = <0x0 DT_SIZE_K(128)>; + }; +}; diff --git a/dts/bindings/clock/ti,mspm0-clock-mux.yaml b/dts/bindings/clock/ti,mspm0-clock-mux.yaml new file mode 100644 index 0000000000000..f8988833a96b7 --- /dev/null +++ b/dts/bindings/clock/ti,mspm0-clock-mux.yaml @@ -0,0 +1,43 @@ +# Copyright (c) 2024 Texas Instruments Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: TI MSPM0 Clock Mux + +compatible: "ti,mspm0-clock-mux" + +include: [clock-controller.yaml, base.yaml] + +properties: + "#clock-cells": + const: 1 + + uclk-div: + type: int + default: 1 + description: | + Divider from MCLK (system clock) to ULPCLK (low power clock). ULPCLK must + be less than or equal to 40 MHz. Valid value is 1 when sourced from SYSOSC + or LFOSC. Valid values are 1 or 2 when sourced from a high speed clock + (such as PLL or external clock). + + mclk-div: + type: int + default: 1 + description: | + Divider for MCLK (system clock) only when source with SYSOSC with a + frequency value of 4 MHz. Disabled otherwise. Valid values are 1-16. + + clock-source: + type: phandle + required: true + description: | + Clock Source for the system clock + + clock-frequency: + required: true + type: int + description: | + default frequency in Hz for clock output + +clock-cells: + - bus diff --git a/dts/bindings/clock/ti,mspm0-oscillator.yaml b/dts/bindings/clock/ti,mspm0-oscillator.yaml new file mode 100644 index 0000000000000..c12f9f4342d8b --- /dev/null +++ b/dts/bindings/clock/ti,mspm0-oscillator.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Texas Instruments Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: TI MSPM0 Oscillator + +compatible: "ti,mspm0-oscillator" + +include: [fixed-clock.yaml] + +properties: + clock-frequency: + type: int + required: true diff --git a/dts/bindings/clock/ti,mspm0-pll.yaml b/dts/bindings/clock/ti,mspm0-pll.yaml new file mode 100644 index 0000000000000..e31768a8f8a71 --- /dev/null +++ b/dts/bindings/clock/ti,mspm0-pll.yaml @@ -0,0 +1,56 @@ +# Copyright (c) 2024 Texas Instruments Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: TI MSPM0 Phase Locked Loop + +compatible: "ti,mspm0-pll" + +include: [clock-controller.yaml, base.yaml] + +properties: + clocks: + required: true + description: | + Clock reference source + + "#clock-cells": + const: 0 + + p-div: + type: int + required: true + enum: + - 1 + - 2 + - 4 + - 8 + description: | + pdiv is the pre-divider of the output. ref_in / pdiv * qdiv = VCO + + q-div: + type: int + required: true + description: | + qdiv functions as a multiplier value for the ref_in / pdiv * qdiv = VCO + Valid Range: 2 - 128 + + clk0-div: + type: int + description: | + CLK0 PLL output is only enabled if the divider is present. Use CLK0 on + the MSPM0 to output to the MCLK, UCLK, and CPUCLK + Valid Range: 1 - 16 + + clk1-div: + type: int + description: | + CLK1 PLL output is only enabled if the divider is present. Use CLK1 on + the MSPM0 to output to the CANCLK, FCC, or output via EXCLK + Valid Range: 1 - 16 + + clk2x-div: + type: int + description: | + CLK2X PLL output is only enabled if the divider is present. Use CLK2X on + the MSPM0 to output to the MCLK, UCLK, and CPUCLK instead of CLK0 + Valid Range: 1 - 16 diff --git a/include/zephyr/dt-bindings/clock/mspm0_clock.h b/include/zephyr/dt-bindings/clock/mspm0_clock.h new file mode 100644 index 0000000000000..89ead1db2abcb --- /dev/null +++ b/include/zephyr/dt-bindings/clock/mspm0_clock.h @@ -0,0 +1,33 @@ +/* + * Copyright 2024 Texas Instruments Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MSPM0_CLOCK_H +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MSPM0_CLOCK_H + +/* Clock bus references */ +#define MSPM0_CLOCK_BUS_BUSCLK + +#define MSPM0_CLOCK_BUS_LFCLK (0x02) +#define MSPM0_CLOCK_BUS_MFCLK (0x04) +#define MSPM0_CLOCK_BUS_ULPCLK (0x18) +#define MSPM0_CLOCK_BUS_MCLK (0x28) +#define MSPM0_CLOCK_BUS_MFPCLK (0x50) +#define MSPM0_CLOCK_BUS_CANCLK (0x51) + +#define MSPM0_CLOCK_SEL_MASK (0x0E) + +#define MSPM0_CLOCK_PRESCALE_DIV_1 (0) +#define MSPM0_CLOCK_PRESCALE_DIV_2 (1) +#define MSPM0_CLOCK_PRESCALE_DIV_3 (2) +#define MSPM0_CLOCK_PRESCALE_DIV_4 (3) +#define MSPM0_CLOCK_PRESCALE_DIV_5 (4) +#define MSPM0_CLOCK_PRESCALE_DIV_6 (5) +#define MSPM0_CLOCK_PRESCALE_DIV_7 (6) +#define MSPM0_CLOCK_PRESCALE_DIV_8 (7) + +#define MSPM0_PRESCALE_MASK 0x07 + +#endif diff --git a/include/zephyr/dt-bindings/pinctrl/mspm0-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/mspm0-pinctrl.h new file mode 100644 index 0000000000000..4bb582977ea82 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/mspm0-pinctrl.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _MSPM0_DT_BINDINGS_PINCTRL_H_ +#define _MSPM0_DT_BINDINGS_PINCTRL_H_ + +#define MSP_PORT_INDEX_BY_NAME(x) ((x == "PORTA") ? 0 : 1) + +/* creates a concatination of the correct pin function based on the CM + * and the function suffix. Will evaluate to the pin function number above. + */ + +#define MSPM0_PIN_FUNCTION_ANALOG (0x00000000) +#define MSPM0_PIN_FUNCTION_GPIO (0x00000001) +#define MSPM0_PIN_FUNCTION_2 (0x00000002) +#define MSPM0_PIN_FUNCTION_3 (0x00000003) +#define MSPM0_PIN_FUNCTION_4 (0x00000004) +#define MSPM0_PIN_FUNCTION_5 (0x00000005) +#define MSPM0_PIN_FUNCTION_6 (0x00000006) +#define MSPM0_PIN_FUNCTION_7 (0x00000007) +#define MSPM0_PIN_FUNCTION_8 (0x00000008) +#define MSPM0_PIN_FUNCTION_9 (0x00000009) +#define MSPM0_PIN_FUNCTION_10 (0x0000000A) + +#define MSP_PINMUX(pincm, function) (((pincm - 1) << 0x10) | function) + +#endif From 48030a7b27b02be97179da49eac7e2e8ce86228f Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Tue, 3 Dec 2024 16:13:01 -0500 Subject: [PATCH 4/9] dts: added pinctrl data for MSPM0 added pinctrl data for TI MSPM0 Family Signed-off-by: Jackson Farley --- .../mspm0g1x0x_g3x0x/mspm0g110x-pinctrl.dtsi | 1 + .../mspm0g1x0x_g3x0x/mspm0g150x-pinctrl.dtsi | 1 + .../mspm0g1x0x_g3x0x-pinctrl.dtsi | 142 ++++++++++++++++++ .../ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi | 5 + .../mspm0g1x0x_g3x0x/mspm0g310x-pinctrl.dtsi | 2 + .../mspm0g1x0x_g3x0x/mspm0g350x-pinctrl.dtsi | 2 + .../mspm0g1x0x_g3x0x/mspm0g3xxx-pinctrl.dtsi | 14 ++ 7 files changed, 167 insertions(+) create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g110x-pinctrl.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g150x-pinctrl.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x-pinctrl.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g310x-pinctrl.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g350x-pinctrl.dtsi create mode 100644 dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3xxx-pinctrl.dtsi diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g110x-pinctrl.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g110x-pinctrl.dtsi new file mode 100644 index 0000000000000..4c9e81bdacc71 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g110x-pinctrl.dtsi @@ -0,0 +1 @@ +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g150x-pinctrl.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g150x-pinctrl.dtsi new file mode 100644 index 0000000000000..4c9e81bdacc71 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g150x-pinctrl.dtsi @@ -0,0 +1 @@ +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x-pinctrl.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x-pinctrl.dtsi new file mode 100644 index 0000000000000..46a61f83c654d --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x-pinctrl.dtsi @@ -0,0 +1,142 @@ +#include + +&pinctrl { + + /omit-if-no-ref/ i2c0_scl_pa1: i2c0_scl_pa1 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c0_sda_pa0: i2c0_sda_pa0 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c1_sda_pa10: i2c1_sda_pa10 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c1_scl_pa11: i2c1_scl_pa11 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c1_scl_pb2: i2c1_scl_pb2 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c1_sda_pb3: i2c1_sda_pb3 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c1_sda_pa16: i2c1_sda_pa16 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c1_scl_pa17: i2c1_scl_pa17 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c1_scl_pa29: i2c1_scl_pa29 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c1_sda_pa30: i2c1_sda_pa30 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c0_sda_pa28: i2c0_sda_pa28 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ i2c0_scl_pa31: i2c0_scl_pa31 { + pinmux = ; + input-enable; + drive-open-drain; + }; + + /omit-if-no-ref/ uart0_tx_pa10: uart0_tx_pa10 { + pinmux = ; + drive-strength = <20>; + }; + + /omit-if-no-ref/ uart0_rx_pa11: uart0_rx_pa11 { + pinmux = ; + drive-strength = <20>; + input-enable; + }; + + /omit-if-no-ref/ uart0_rts_pa8: uart0_rts_pa8 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0_cts_pb19: uart0_cts_pb19 { + pinmux = ; + input-enable; + }; + + /omit-if-no-ref/ spi1_sclk_pb9: spi1_sclk_pb9 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_pico_pb8: spi1_pico_pb8 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_poci_pb7: spi1_poci_pb7 { + pinmux = ; + input-enable; + }; + + /omit-if-no-ref/ spi1_cs0_pb6: spi1_cs0_pb6 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_cs1_pb17: spi1_cs1_pb17 { + pinmux = ; + }; + + /omit-if-no-ref/ adc0_pa27: adc0_pa27 { + pinmux = ; + }; + + /omit-if-no-ref/ adc0_pa26: adc0_pa26 { + pinmux = ; + }; + + /omit-if-no-ref/ adc0_pa25: adc0_pa25 { + pinmux = ; + }; + + /omit-if-no-ref/ adc0_pb24: adc0_pb24 { + pinmux = ; + }; + + /omit-if-no-ref/ adc0_pb25: adc0_pb25 { + pinmux = ; + }; + + /omit-if-no-ref/ adc1_pb19: adc1_pb19 { + pinmux = ; + }; + +}; diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi index 66b3f81da17e5..fe7985dbbbcd4 100644 --- a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi @@ -76,6 +76,7 @@ compatible = "ti,mspm0-gpio"; reg = <0x400a0000 0x2000>; interrupts = <1 0>; + interrupt-parent = <&nvic>; status = "disabled"; gpio-controller; #gpio-cells = <2>; @@ -85,6 +86,7 @@ compatible = "ti,mspm0-gpio"; reg = <0x400a2000 0x2000>; interrupts = <1 0>; + interrupt-parent = <&nvic>; status = "disabled"; gpio-controller; #gpio-cells = <2>; @@ -95,6 +97,7 @@ compatible = "ti,mspm0-uart"; reg = <0x40108000 0x2000>; interrupts = <15 0>; + interrupt-parent = <&nvic>; current-speed = <115200>; clocks = <&clkmux MSPM0_CLOCK_BUS_ULPCLK>; status = "disabled"; @@ -104,6 +107,7 @@ compatible = "ti,mspm0-uart"; reg = <0x40100000 0x2000>; interrupts = <13 0>; + interrupt-parent = <&nvic>; current-speed = <115200>; clocks = <&clkmux MSPM0_CLOCK_BUS_ULPCLK>; status = "disabled"; @@ -113,6 +117,7 @@ compatible = "ti,mspm0-uart"; reg = <0x40102000 0x2000>; interrupts = <14 0>; + interrupt-parent = <&nvic>; current-speed = <115200>; clocks = <&clkmux MSPM0_CLOCK_BUS_ULPCLK>; status = "disabled"; diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g310x-pinctrl.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g310x-pinctrl.dtsi new file mode 100644 index 0000000000000..23f67d668a372 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g310x-pinctrl.dtsi @@ -0,0 +1,2 @@ +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g350x-pinctrl.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g350x-pinctrl.dtsi new file mode 100644 index 0000000000000..23f67d668a372 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g350x-pinctrl.dtsi @@ -0,0 +1,2 @@ +#include +#include diff --git a/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3xxx-pinctrl.dtsi b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3xxx-pinctrl.dtsi new file mode 100644 index 0000000000000..9127d27318cb3 --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g3xxx-pinctrl.dtsi @@ -0,0 +1,14 @@ +#include + +&pinctrl { + + can0_rx_pa13: can0_rx_pa13 { + pinmux = ; + input-enable; + }; + + can0_tx_pa12: can0_tx_pa12 { + pinmux = ; + }; + +}; From 4c0e81ddbc9a8001bb49c8114b8f8397444cf746 Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Tue, 3 Dec 2024 16:13:49 -0500 Subject: [PATCH 5/9] drivers: added clock control driver for MSPM0 added clock_control support for TI MSPM0 Family Signed-off-by: Jackson Farley --- drivers/clock_control/CMakeLists.txt | 1 + drivers/clock_control/Kconfig | 2 + drivers/clock_control/Kconfig.mspm0 | 17 +++ drivers/clock_control/clock_control_mspm0.c | 134 ++++++++++++++++++ .../clock_control/mspm0_clock_control.h | 18 +++ 5 files changed, 172 insertions(+) create mode 100644 drivers/clock_control/Kconfig.mspm0 create mode 100644 drivers/clock_control/clock_control_mspm0.c create mode 100644 include/zephyr/drivers/clock_control/mspm0_clock_control.h diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index b17dc7b86c55b..dfa79684ce43b 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -20,6 +20,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MCUX_SCG_K4 clock_cont zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MCUX_SIM clock_control_mcux_sim.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MCUX_SYSCON clock_control_mcux_syscon.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NPCM clock_control_npcm.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MSPM0 clock_control_mspm0.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NPCX clock_control_npcx.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF clock_control_nrf.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_DRIVER_CALIBRATION nrf_clock_calibration.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index 040dab163c2b4..f1292bde8f28f 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -52,6 +52,8 @@ source "drivers/clock_control/Kconfig.mcux_syscon" source "drivers/clock_control/Kconfig.npcm" +source "drivers/clock_control/Kconfig.mspm0" + source "drivers/clock_control/Kconfig.npcx" source "drivers/clock_control/Kconfig.rv32m1" diff --git a/drivers/clock_control/Kconfig.mspm0 b/drivers/clock_control/Kconfig.mspm0 new file mode 100644 index 0000000000000..55b94dd9972bc --- /dev/null +++ b/drivers/clock_control/Kconfig.mspm0 @@ -0,0 +1,17 @@ +# TI MSPM0 Family + +# Copyright (c) 2024, Texas Instruments Inc. +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_MSPM0 + bool "TI MSPM0 clock" + default y + depends on SOC_FAMILY_TI_MSPM0 + help + This option enables the TI MSPM0 Clock Control Enabler + +config CLOCK_CONTROL_MSPM0_USE_PLL + bool "TI MSPM0 Use PLL" + default n + help + This option enables the PLL on MSPM0 devices (if equipped) diff --git a/drivers/clock_control/clock_control_mspm0.c b/drivers/clock_control/clock_control_mspm0.c new file mode 100644 index 0000000000000..305a80699f634 --- /dev/null +++ b/drivers/clock_control/clock_control_mspm0.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define ULPCLK_DIV CONCAT(DL_SYSCTL_ULPCLK_DIV_, DT_PROP(DT_NODELABEL(clkmux), uclk_div)) + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(pll), okay) +#define MSPM0_PLL_ENABLED 1 +#endif + +static const DL_SYSCTL_SYSPLLConfig clock_mspm0_cfg_syspll; + +static int clock_mspm0_on(const struct device *dev, clock_control_subsys_t sys) +{ + return 0; +} + +static int clock_mspm0_off(const struct device *dev, clock_control_subsys_t sys) +{ + return 0; +} + +static enum clock_control_status clock_mspm0_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + return CLOCK_CONTROL_STATUS_UNKNOWN; +} + +static int clock_mspm0_get_rate(const struct device *dev, clock_control_subsys_t sys, + uint32_t *rate) +{ + struct mspm0_clockSys *clockSys = (struct mspm0_clockSys *)sys; + uint8_t rateNotFound = 0; + + switch (clockSys->bus) { + case MSPM0_CLOCK_BUS_LFCLK: + *rate = 32768; + break; + case MSPM0_CLOCK_BUS_ULPCLK: + *rate = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / + DT_PROP(DT_NODELABEL(clkmux), uclk_div); + break; + case MSPM0_CLOCK_BUS_MCLK: + *rate = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + break; + case MSPM0_CLOCK_BUS_MFPCLK: + *rate = 4000000; + break; + case MSPM0_CLOCK_BUS_MFCLK: + case MSPM0_CLOCK_BUS_CANCLK: + default: + rateNotFound = 1; + break; + } + if (rateNotFound == 1) { + return -ENOTSUP; + } else { + return 0; + } +} + +static int clock_mspm0_set_rate(const struct device *dev, clock_control_subsys_t sys, + clock_control_subsys_rate_t rate) +{ + return -ENOTSUP; +} + +static int clock_mspm0_configure(const struct device *dev, clock_control_subsys_t sys, void *data) +{ + return -ENOTSUP; +} + +static int clock_mspm0_init(const struct device *dev) +{ + /* setup clocks based on specific rates */ + DL_SYSCTL_setSYSOSCFreq(DL_SYSCTL_SYSOSC_FREQ_BASE); + + DL_SYSCTL_configSYSPLL((DL_SYSCTL_SYSPLLConfig *)&clock_mspm0_cfg_syspll); + + DL_SYSCTL_setULPCLKDivider(ULPCLK_DIV); + DL_SYSCTL_setMCLKSource(SYSOSC, HSCLK, DL_SYSCTL_HSCLK_SOURCE_SYSPLL); + + return 0; +} + +static const struct clock_control_driver_api clock_mspm0_driver_api = { + .on = clock_mspm0_on, + .off = clock_mspm0_off, + .get_status = clock_mspm0_get_status, + .get_rate = clock_mspm0_get_rate, + .set_rate = clock_mspm0_set_rate, + .configure = clock_mspm0_configure}; + +DEVICE_DT_DEFINE(DT_NODELABEL(clkmux), &clock_mspm0_init, NULL, NULL, NULL, PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_mspm0_driver_api); + +#if MSPM0_PLL_ENABLED + +/* basic checks of the devicetree to follow */ +#if (DT_NODE_HAS_PROP(DT_NODELABEL(pll), clk2x_div) && \ + DT_NODE_HAS_PROP(DT_NODELABEL(pll), clk0_div)) +#error "Only CLK2X or CLK0 can be enabled at a time on the PLL" +#endif + +#define GENERATE_PLL_STRUCT() \ + static const DL_SYSCTL_SYSPLLConfig clock_mspm0_cfg_syspll = { \ + .inputFreq = DL_SYSCTL_SYSPLL_INPUT_FREQ_32_48_MHZ, \ + .rDivClk2x = (DT_PROP_OR(DT_NODELABEL(pll), clk2x_div, 1) - 1), \ + .rDivClk1 = (DT_PROP_OR(DT_NODELABEL(pll), clk1_div, 1) - 1), \ + .rDivClk0 = (DT_PROP_OR(DT_NODELABEL(pll), clk0_div, 1) - 1), \ + .qDiv = (DT_PROP(DT_NODELABEL(pll), q_div) - 1), \ + .pDiv = CONCAT(DL_SYSCTL_SYSPLL_PDIV_, DT_PROP(DT_NODELABEL(pll), p_div)), \ + .sysPLLMCLK = COND_CODE_1(DT_NODE_HAS_PROP(DT_NODELABEL(pll), clk2x_div), \ + (DL_SYSCTL_SYSPLL_MCLK_CLK2X), (DL_SYSCTL_SYSPLL_MCLK_CLK0)), \ + .enableCLK2x = COND_CODE_1(DT_NODE_HAS_PROP(DT_NODELABEL(pll), clk2x_div), \ + (DL_SYSCTL_SYSPLL_CLK2X_ENABLE), (DL_SYSCTL_SYSPLL_CLK2X_DISABLE)), \ + .enableCLK1 = COND_CODE_1(DT_NODE_HAS_PROP(DT_NODELABEL(pll), clk1_div), \ + (DL_SYSCTL_SYSPLL_CLK1_ENABLE), (DL_SYSCTL_SYSPLL_CLK1_DISABLE)), \ + .enableCLK0 = COND_CODE_1(DT_NODE_HAS_PROP(DT_NODELABEL(pll), clk0_div), \ + (DL_SYSCTL_SYSPLL_CLK0_ENABLE), (DL_SYSCTL_SYSPLL_CLK0_DISABLE)), \ + .sysPLLRef = COND_CODE_1(DT_CLOCKS_CELL(DT_NODELABEL(pll), clocks), \ + (DL_SYSCTL_SYSPLL_REF_HFCLK), (DL_SYSCTL_SYSPLL_REF_SYSOSC)), \ + }; + +GENERATE_PLL_STRUCT() + +#endif /* MSPM0_PLL_ENABLED */ diff --git a/include/zephyr/drivers/clock_control/mspm0_clock_control.h b/include/zephyr/drivers/clock_control/mspm0_clock_control.h new file mode 100644 index 0000000000000..a8a69ddcde59d --- /dev/null +++ b/include/zephyr/drivers/clock_control/mspm0_clock_control.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Texas Instruments Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_MSPM0_CLOCK_CONTROL +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_MSPM0_CLOCK_CONTROL + +#include + +struct mspm0_clockSys { + uint32_t bus; +}; + +#define MSPM0_CLOCK_SUBSYS_FN(index) {.bus = DT_INST_CLOCKS_CELL(index, bus)} + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_MSPM0_CLOCK_CONTROL */ From d390b17a0ee1d2050f57408695c28e54ee5749db Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Thu, 21 Mar 2024 21:01:53 -0400 Subject: [PATCH 6/9] drivers: added pinctrl driver for MSPM0 added pinctrl driver support for MSPM0 Family Signed-off-by: Jackson Farley --- drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Kconfig.mspm0 | 9 ++ drivers/pinctrl/pinctrl_mspm0.c | 36 ++++++ dts/bindings/pinctrl/ti,mspm0-pinctrl.yaml | 119 ++++++++++++++++++++ soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h | 26 ++--- 6 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 drivers/pinctrl/Kconfig.mspm0 create mode 100644 drivers/pinctrl/pinctrl_mspm0.c create mode 100644 dts/bindings/pinctrl/ti,mspm0-pinctrl.yaml diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index d2834504eb2e0..973f2086485c1 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -33,6 +33,7 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_SILABS_DBUS pinctrl_silabs_dbus.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_K3 pinctrl_ti_k3.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_EMSDP pinctrl_emsdp.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_CC32XX pinctrl_ti_cc32xx.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_MSPM0 pinctrl_mspm0.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_NUMAKER pinctrl_numaker.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCI_IO_MUX pinctrl_mci_io_mux.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index d8621e7ad9e1d..79f71807d0eb8 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -59,6 +59,7 @@ source "drivers/pinctrl/Kconfig.nxp_s32" source "drivers/pinctrl/Kconfig.gecko" source "drivers/pinctrl/Kconfig.silabs_dbus" source "drivers/pinctrl/Kconfig.ti_k3" +source "drivers/pinctrl/Kconfig.mspm0" source "drivers/pinctrl/Kconfig.emsdp" source "drivers/pinctrl/Kconfig.ti_cc32xx" source "drivers/pinctrl/Kconfig.numaker" diff --git a/drivers/pinctrl/Kconfig.mspm0 b/drivers/pinctrl/Kconfig.mspm0 new file mode 100644 index 0000000000000..ed2a728ed5f64 --- /dev/null +++ b/drivers/pinctrl/Kconfig.mspm0 @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Texas Instruments + +config PINCTRL_MSPM0 + bool "TI pinctrl MSPM0 driver" + default y + depends on DT_HAS_TI_MSPM0_PINCTRL_ENABLED + help + Enable support for the PINCTRL on TI MSPM0 series. diff --git a/drivers/pinctrl/pinctrl_mspm0.c b/drivers/pinctrl/pinctrl_mspm0.c new file mode 100644 index 0000000000000..fffa50a39dacb --- /dev/null +++ b/drivers/pinctrl/pinctrl_mspm0.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define DT_DRV_COMPAT ti_mspm0_pinctrl + +#define MSPM0_PINCM(pinmux) (pinmux >> 0x10) +#define MSPM0_PIN_FUNCTION(pinmux) (pinmux & 0x3F) + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + uint8_t pin_function; + uint32_t pin_cm; + uint32_t iomux; + + for (int i = 0; i < pin_cnt; i++) { + pin_cm = MSPM0_PINCM(pins[i].pinmux); + pin_function = MSPM0_PIN_FUNCTION(pins[i].pinmux); + iomux = pins[i].iomux; + if (pin_function == 0x00) { + DL_GPIO_initPeripheralAnalogFunction(pin_cm); + } else { + DL_GPIO_initPeripheralFunction(pin_cm, (iomux | pin_function)); + } + } + + return 0; +} diff --git a/dts/bindings/pinctrl/ti,mspm0-pinctrl.yaml b/dts/bindings/pinctrl/ti,mspm0-pinctrl.yaml new file mode 100644 index 0000000000000..3952a8bec7f18 --- /dev/null +++ b/dts/bindings/pinctrl/ti,mspm0-pinctrl.yaml @@ -0,0 +1,119 @@ +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +description: | + TI MSPM0 pinctrl node. + + Device pin configuration should be placed in the child nodes of this node. + Populate the 'pinmux' field with a pair consisting of a pin number and its IO + functions. + + The node has the 'pinctrl' node label set in your SoC's devicetree, + so you can modify it like this: + + &pinctrl { + /* your modifications go here */ + }; + + All device pin configurations should be placed in child nodes of the + 'pinctrl' node, as in the i2c0 example shown at the end. + + Here is a list of + supported standard pin properties: + + - bias-disable: Disable pull-up/down. + - bias-pull-down: Enable pull-down resistor. + - bias-pull-up: Enable pull-up resistor. + - drive-open-drain: Output driver is open-drain. (and is thus high-impedance) + - drive-strength: Maximum current that can be sourced from the pin. + - input-enable: enable input. + - ti,invert: enable logical inversion of a digital input or output + - ti,hysteresis: enable hysteresis control on open-drain pins + + An example for MSPM0 family, include the chip level pinctrl + DTSI file in the board level DTS: + + #include + + We want to configure the I2C pins to open drain, with pullup enabled + and input enabled. + + To change a pin's pinctrl default properties add a reference to the + pin in the board's DTS file or in the project overlay and set the + properties. + + &i2c1 { + pinctrl-0 = <&i2c1_scl_pb2_pull_up &i2c1_sda_pb3_pull_up>; + pinctrl-names = "default"; + } + + The i2c1_scl_pb2_pull_up corresponds to the following pin configuration in + the board dts file: + + &pinctrl { + i2c1_scl_pb2_pull_up: i2c1_scl_pb2_pull_up { + pinmux = ; + input-enable; + bias-pull-up; + drive-open-drain; + }; + }; + + Pin pb2 refers to the device pin name that one would see printed on the + launchpad, and the number 15 in the pinmux define refers to the PINCMx. + + These are obtained from the device-specific datasheet. + +compatible: "ti,mspm0-pinctrl" + +include: base.yaml + +properties: + reg: + required: true + +child-binding: + description: | + This binding gives a base representation of the MSPM0 + pins configuration. + + include: + - name: pincfg-node.yaml + property-allowlist: + - bias-disable + - bias-pull-down + - bias-pull-up + - drive-open-drain + - drive-open-source + - drive-strength + - input-enable + + properties: + pinmux: + required: true + type: int + description: | + MSPM0 pin's configuration (IO pin, IO function). + + drive-strength: + enum: + - 6 + - 20 + default: 6 + description: | + The drive strength controls the maximum output drive strength sunk or + sourced by an I/O pin. + low is max 6 mA (SoC default) + high is max 20 mA on high-drive capable IOs only (HDIO). + + ti,invert: + type: boolean + description: | + Enables inversion of the input or output using the internal + inversion capability of the GPIO + + ti,hysteresis: + type: boolean + description: | + Enables the hysteresis control for access to CMOS logic + (on open-drain capable pins) diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h b/soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h index bdfc3181a454b..207ccc88f5e19 100644 --- a/soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/pinctrl_soc.h @@ -14,20 +14,20 @@ #define MSP_GPIO_RESISTOR_PULL_DOWN (16) #define MSP_GPIO_RESISTOR_PULL_UP (17) #define MSP_GPIO_INPUT_ENABLE (18) +#define MSP_GPIO_HIGH_DRIVE (20) #define MSP_GPIO_HYSTERESIS_ENABLED (19) #define MSP_GPIO_OPEN_DRAIN_OUTPUT (25) #define MSP_GPIO_INVERSION_ENABLED (26) -#define MSP_GPIO_HIGH_DRIVE (20) - #define MSP_PINMUX_INIT(node_id) DT_PROP(node_id, pinmux) -#define MSP_PIN_CONTROL_IOMUX_INIT(node_id) \ - ((DT_PROP(node_id, bias_pull_up) << MSP_GPIO_RESISTOR_PULL_UP) | \ - (DT_PROP(node_id, bias_pull_down) << MSP_GPIO_RESISTOR_PULL_DOWN) | \ - (DT_PROP(node_id, drive_open_drain) << MSP_GPIO_OPEN_DRAIN_OUTPUT) | \ - (DT_PROP(node_id, ti_hysteresis) << MSP_GPIO_HYSTERESIS_ENABLED) | \ - (DT_PROP(node_id, ti_invert) << MSP_GPIO_INVERSION_ENABLED) | \ +#define MSP_PIN_CONTROL_IOMUX_INIT(node_id) \ + ((DT_PROP(node_id, bias_pull_up) << MSP_GPIO_RESISTOR_PULL_UP) | \ + (DT_PROP(node_id, bias_pull_down) << MSP_GPIO_RESISTOR_PULL_DOWN) | \ + (DT_PROP(node_id, drive_open_drain) << MSP_GPIO_OPEN_DRAIN_OUTPUT) | \ + (DT_ENUM_IDX(node_id, drive_strength) << MSP_GPIO_HIGH_DRIVE) | \ + (DT_PROP(node_id, ti_hysteresis) << MSP_GPIO_HYSTERESIS_ENABLED) | \ + (DT_PROP(node_id, ti_invert) << MSP_GPIO_INVERSION_ENABLED) | \ (DT_PROP(node_id, input_enable) << MSP_GPIO_INPUT_ENABLE)) typedef struct pinctrl_soc_pin { @@ -37,13 +37,13 @@ typedef struct pinctrl_soc_pin { uint32_t iomux; } pinctrl_soc_pin_t; -#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ - {.pinmux = MSP_PINMUX_INIT(DT_PROP_BY_IDX(node_id, prop, idx)), \ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + {.pinmux = MSP_PINMUX_INIT(DT_PROP_BY_IDX(node_id, prop, idx)), \ .iomux = MSP_PIN_CONTROL_IOMUX_INIT(DT_PROP_BY_IDX(node_id, prop, idx))}, -#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ - { \ - DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT) \ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { \ + DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT) \ } #endif /* SOC_TI_MSPM0_M0G1X0X_G3X0X_PINCTRL_SOC_H_ */ From cf5480f0e197c7033a6618737345bb9186108131 Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Thu, 21 Mar 2024 21:04:42 -0400 Subject: [PATCH 7/9] drivers: added gpio driver for MSPM0 family Added GPIO driver support for TI MSPM0 family Signed-off-by: Jackson Farley --- drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 1 + drivers/gpio/Kconfig.mspm0 | 11 + drivers/gpio/Kconfig.mspm0g3xxx | 11 + drivers/gpio/gpio_mspm0.c | 300 +++++++++++++++++++++++++++ dts/bindings/gpio/ti,mspm0-gpio.yaml | 21 ++ 6 files changed, 345 insertions(+) create mode 100644 drivers/gpio/Kconfig.mspm0 create mode 100644 drivers/gpio/Kconfig.mspm0g3xxx create mode 100644 drivers/gpio/gpio_mspm0.c create mode 100644 dts/bindings/gpio/ti,mspm0-gpio.yaml diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index b1b053f90cebc..434eccad0d0d8 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -52,6 +52,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_MCUX_IGPIO gpio_mcux_igpio.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MCUX_LPC gpio_mcux_lpc.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MCUX_RGPIO gpio_mcux_rgpio.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MMIO32 gpio_mmio32.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_MSPM0 gpio_mspm0.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx_port.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX_ALERT gpio_nct38xx_alert.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6bae51f9880ee..a33b7a88d7108 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -141,6 +141,7 @@ source "drivers/gpio/Kconfig.mcux_igpio" source "drivers/gpio/Kconfig.mcux_lpc" source "drivers/gpio/Kconfig.mcux_rgpio" source "drivers/gpio/Kconfig.mmio32" +source "drivers/gpio/Kconfig.mspm0" source "drivers/gpio/Kconfig.nct38xx" source "drivers/gpio/Kconfig.neorv32" source "drivers/gpio/Kconfig.npcx" diff --git a/drivers/gpio/Kconfig.mspm0 b/drivers/gpio/Kconfig.mspm0 new file mode 100644 index 0000000000000..cb7ec576c046f --- /dev/null +++ b/drivers/gpio/Kconfig.mspm0 @@ -0,0 +1,11 @@ +# TI MSPM0 GPIO configuration options + +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_MSPM0 + bool "TI SimpleLink MSPM0 GPIO driver" + default y + depends on DT_HAS_TI_MSPM0_GPIO_ENABLED + help + Enable the TI MSPM0 GPIO driver. diff --git a/drivers/gpio/Kconfig.mspm0g3xxx b/drivers/gpio/Kconfig.mspm0g3xxx new file mode 100644 index 0000000000000..e3cd6a23bf47a --- /dev/null +++ b/drivers/gpio/Kconfig.mspm0g3xxx @@ -0,0 +1,11 @@ +# TI MSPM0G3XXX GPIO configuration options + +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_MSPM0G3XXX + bool "TI SimpleLink MSPM0G3XXX GPIO driver" + default y + depends on DT_HAS_TI_MSPM0G3XXX_GPIO_ENABLED + help + Enable the TI MSPM0G3XXX GPIO driver. diff --git a/drivers/gpio/gpio_mspm0.c b/drivers/gpio/gpio_mspm0.c new file mode 100644 index 0000000000000..a5c8447f6c4e7 --- /dev/null +++ b/drivers/gpio/gpio_mspm0.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_mspm0_gpio + +/* Zephyr includes */ +#include +#include +#include +#include + +/* Driverlib includes */ +#include + +/* GPIO defines */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) +#define GPIOA_NODE DT_NODELABEL(gpioa) + +#ifdef CONFIG_SOC_SERIES_MSPM0G1X0X_G3X0X +#define NUM_GPIOA_PIN 32 +#define gpioa_pins NUM_GPIOA_PIN +static uint32_t gpioa_pincm_lut[NUM_GPIOA_PIN] = { + IOMUX_PINCM1, IOMUX_PINCM2, IOMUX_PINCM7, IOMUX_PINCM8, IOMUX_PINCM9, IOMUX_PINCM10, + IOMUX_PINCM11, IOMUX_PINCM14, IOMUX_PINCM19, IOMUX_PINCM20, IOMUX_PINCM21, IOMUX_PINCM22, + IOMUX_PINCM34, IOMUX_PINCM35, IOMUX_PINCM36, IOMUX_PINCM37, IOMUX_PINCM38, IOMUX_PINCM39, + IOMUX_PINCM40, IOMUX_PINCM41, IOMUX_PINCM42, IOMUX_PINCM46, IOMUX_PINCM47, IOMUX_PINCM53, + IOMUX_PINCM54, IOMUX_PINCM55, IOMUX_PINCM59, IOMUX_PINCM60, IOMUX_PINCM3, IOMUX_PINCM4, + IOMUX_PINCM5, IOMUX_PINCM6, +}; +#else +#throw "series lookup table not supported" +#endif /* if config SOC_SERIES_MSPM0G1X0X_G3X0X */ + +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) */ + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) +#define GPIOB_NODE DT_NODELABEL(gpiob) +#ifdef CONFIG_SOC_SERIES_MSPM0G1X0X_G3X0X +#define NUM_GPIOB_PIN 28 +#define gpiob_pins NUM_GPIOB_PIN +static uint32_t gpiob_pincm_lut[NUM_GPIOB_PIN] = { + IOMUX_PINCM12, IOMUX_PINCM13, IOMUX_PINCM15, IOMUX_PINCM16, IOMUX_PINCM17, IOMUX_PINCM18, + IOMUX_PINCM23, IOMUX_PINCM24, IOMUX_PINCM25, IOMUX_PINCM26, IOMUX_PINCM27, IOMUX_PINCM28, + IOMUX_PINCM29, IOMUX_PINCM30, IOMUX_PINCM31, IOMUX_PINCM32, IOMUX_PINCM33, IOMUX_PINCM43, + IOMUX_PINCM44, IOMUX_PINCM45, IOMUX_PINCM48, IOMUX_PINCM49, IOMUX_PINCM50, IOMUX_PINCM51, + IOMUX_PINCM52, IOMUX_PINCM56, IOMUX_PINCM57, IOMUX_PINCM58, +}; +#endif /* CONFIG_SOC_SERIES */ +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) */ + +struct gpio_mspm0_config { + /* gpio_mspm0_config needs to be first (doesn't actually get used) */ + struct gpio_driver_config common; + /* port base address */ + GPIO_Regs *base; + /* port pincm lookup table */ + uint32_t *pincm_lut; +}; + +struct gpio_mspm0_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + sys_slist_t callbacks; /* List of interrupt callbacks */ +}; + +static int gpio_mspm0_port_set_bits_raw(const struct device *port, uint32_t mask); +static int gpio_mspm0_port_clear_bits_raw(const struct device *port, uint32_t mask); + +static int gpio_mspm0_pin_configure(const struct device *port, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_mspm0_config *config = port->config; + /* determine pull up resistor value based on flags */ + DL_GPIO_RESISTOR respull; + + if (flags & GPIO_PULL_UP) { + respull = DL_GPIO_RESISTOR_PULL_UP; + } else if (flags & GPIO_PULL_DOWN) { + respull = DL_GPIO_RESISTOR_PULL_DOWN; + } else { + respull = DL_GPIO_RESISTOR_NONE; + } + /* Config pin based on flags */ + switch (flags & (GPIO_INPUT | GPIO_OUTPUT)) { + case GPIO_INPUT: + DL_GPIO_initDigitalInputFeatures(config->pincm_lut[pin], DL_GPIO_INVERSION_DISABLE, + respull, DL_GPIO_HYSTERESIS_DISABLE, + DL_GPIO_WAKEUP_DISABLE); + break; + case GPIO_OUTPUT: + DL_GPIO_initDigitalOutputFeatures(config->pincm_lut[pin], DL_GPIO_INVERSION_DISABLE, + respull, DL_GPIO_DRIVE_STRENGTH_LOW, + DL_GPIO_HIZ_DISABLE); + + /* Set initial state */ + if (flags & GPIO_OUTPUT_INIT_HIGH) { + gpio_mspm0_port_set_bits_raw(port, BIT(pin)); + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + gpio_mspm0_port_clear_bits_raw(port, BIT(pin)); + } + /* Enable output */ + DL_GPIO_enableOutput(config->base, BIT(pin)); + break; + case GPIO_DISCONNECTED: + DL_GPIO_disableOutput(config->base, BIT(pin)); + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int gpio_mspm0_port_get_raw(const struct device *port, uint32_t *value) +{ + const struct gpio_mspm0_config *config = port->config; + + /* Read entire port */ + *value = DL_GPIO_readPins(config->base, UINT32_MAX); + + return 0; +} + +static int gpio_mspm0_port_set_masked_raw(const struct device *port, uint32_t mask, uint32_t value) +{ + const struct gpio_mspm0_config *config = port->config; + + DL_GPIO_writePinsVal(config->base, mask, value); + + return 0; +} + +static int gpio_mspm0_port_set_bits_raw(const struct device *port, uint32_t mask) +{ + const struct gpio_mspm0_config *config = port->config; + + DL_GPIO_setPins(config->base, mask); + + return 0; +} + +static int gpio_mspm0_port_clear_bits_raw(const struct device *port, uint32_t mask) +{ + const struct gpio_mspm0_config *config = port->config; + + DL_GPIO_clearPins(config->base, mask); + + return 0; +} + +static int gpio_mspm0_port_toggle_bits(const struct device *port, uint32_t mask) +{ + const struct gpio_mspm0_config *config = port->config; + + DL_GPIO_togglePins(config->base, mask); + + return 0; +} + +static int gpio_mspm0_pin_interrupt_configure(const struct device *port, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct gpio_mspm0_config *config = port->config; + + /* Config interrupt */ + switch (mode) { + case GPIO_INT_MODE_DISABLED: + DL_GPIO_clearInterruptStatus(config->base, BIT(pin)); + DL_GPIO_disableInterrupt(config->base, BIT(pin)); + break; + case GPIO_INT_MODE_EDGE: + uint32_t polarity = 0x00; + + if (trig & GPIO_INT_TRIG_LOW) { + polarity |= BIT(0); + } + if (trig & GPIO_INT_TRIG_HIGH) { + polarity |= BIT(1); + } + if (pin < 16) { + DL_GPIO_setLowerPinsPolarity(config->base, polarity << (2 * pin)); + } else { + DL_GPIO_setUpperPinsPolarity(config->base, polarity << (2 * (pin - 16))); + } + DL_GPIO_clearInterruptStatus(config->base, BIT(pin)); + DL_GPIO_enableInterrupt(config->base, BIT(pin)); + break; + case GPIO_INT_MODE_LEVEL: + return -ENOTSUP; + } + + return 0; +} + +static int gpio_mspm0_manage_callback(const struct device *port, struct gpio_callback *callback, + bool set) +{ + struct gpio_mspm0_data *data = port->data; + + return gpio_manage_callback(&data->callbacks, callback, set); +} + +static uint32_t gpio_mspm0_get_pending_int(const struct device *port) +{ + const struct gpio_mspm0_config *config = port->config; + + return DL_GPIO_getPendingInterrupt(config->base); +} + +static void gpio_mspm0_isr(const struct device *port) +{ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) + const struct device *dev_a = DEVICE_DT_GET(GPIOA_NODE); + struct gpio_mspm0_data *data_a = dev_a->data; + const struct gpio_mspm0_config *config_a = dev_a->config; + + uint32_t status_a = DL_GPIO_getRawInterruptStatus(config_a->base, 0xFFFFFFFF); + + DL_GPIO_clearInterruptStatus(config_a->base, status_a); + + gpio_fire_callbacks(&data_a->callbacks, dev_a, status_a); +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) */ + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) + const struct device *dev_b = DEVICE_DT_GET(GPIOB_NODE); + struct gpio_mspm0_data *data_b = dev_b->data; + const struct gpio_mspm0_config *config_b = dev_b->config; + + uint32_t status_b = DL_GPIO_getRawInterruptStatus(config_b->base, 0xFFFFFFFF); + + DL_GPIO_clearInterruptStatus(config_b->base, status_b); + + gpio_fire_callbacks(&data_b->callbacks, dev_b, status_b); +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) */ +} + +static bool init_irq = true; + +static int gpio_mspm0_init(const struct device *port) +{ + /* Powering up of GPIOs is part of soc.c */ + + if (init_irq) { + + init_irq = false; + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) + IRQ_CONNECT(DT_IRQN(GPIOB_NODE), DT_IRQ(GPIOB_NODE, priority), gpio_mspm0_isr, + DEVICE_DT_GET(GPIOB_NODE), 0); + irq_enable(DT_IRQN(GPIOB_NODE)); +#elif DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) + IRQ_CONNECT(DT_IRQN(GPIOA_NODE), DT_IRQ(GPIOA_NODE, priority), gpio_mspm0_isr, + DEVICE_DT_GET(GPIOA_NODE), 0); + irq_enable(DT_IRQN(GPIOA_NODE)); +#endif + } + + return 0; +} + +static const struct gpio_driver_api gpio_mspm0_driver_api = { + .pin_configure = gpio_mspm0_pin_configure, + .port_get_raw = gpio_mspm0_port_get_raw, + .port_set_masked_raw = gpio_mspm0_port_set_masked_raw, + .port_set_bits_raw = gpio_mspm0_port_set_bits_raw, + .port_clear_bits_raw = gpio_mspm0_port_clear_bits_raw, + .port_toggle_bits = gpio_mspm0_port_toggle_bits, + .pin_interrupt_configure = gpio_mspm0_pin_interrupt_configure, + .manage_callback = gpio_mspm0_manage_callback, + .get_pending_int = gpio_mspm0_get_pending_int, +}; + +#define GPIO_DEVICE_INIT(__node, __suffix, __base_addr) \ + static const struct gpio_mspm0_config gpio_mspm0_cfg_##__suffix = { \ + .common = \ + { \ + .port_pin_mask = \ + GPIO_PORT_PIN_MASK_FROM_NGPIOS(gpio##__suffix##_pins), \ + }, \ + .base = (GPIO_Regs *)__base_addr, \ + .pincm_lut = gpio##__suffix##_pincm_lut, \ + }; \ + static struct gpio_mspm0_data gpio_mspm0_data_##__suffix; \ + DEVICE_DT_DEFINE(__node, gpio_mspm0_init, NULL, &gpio_mspm0_data_##__suffix, \ + &gpio_mspm0_cfg_##__suffix, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_mspm0_driver_api) + +#define GPIO_DEVICE_INIT_MSPM0(__suffix) \ + GPIO_DEVICE_INIT(DT_NODELABEL(gpio##__suffix), __suffix, \ + DT_REG_ADDR(DT_NODELABEL(gpio##__suffix))) + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) +GPIO_DEVICE_INIT_MSPM0(a); +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) */ + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) +GPIO_DEVICE_INIT_MSPM0(b); +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) */ diff --git a/dts/bindings/gpio/ti,mspm0-gpio.yaml b/dts/bindings/gpio/ti,mspm0-gpio.yaml new file mode 100644 index 0000000000000..a08a432e4cff5 --- /dev/null +++ b/dts/bindings/gpio/ti,mspm0-gpio.yaml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 + +description: TI MSPM0 GPIO + +compatible: "ti,mspm0-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags From 8d0d1fa391c610361920e1ef1fdbe25d684d3b42 Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Tue, 19 Mar 2024 15:19:57 -0400 Subject: [PATCH 8/9] drivers: added serial driver for MSPM0 added the Serial (uart) driver for MSPM0 family Signed-off-by: Jackson Farley --- drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig | 1 + drivers/serial/Kconfig.mspm0 | 12 + drivers/serial/uart_mspm0.c | 324 +++++++++++++++++++++++++ dts/bindings/serial/ti,mspm0-uart.yaml | 18 ++ 5 files changed, 356 insertions(+) create mode 100644 drivers/serial/Kconfig.mspm0 create mode 100644 drivers/serial/uart_mspm0.c create mode 100644 dts/bindings/serial/ti,mspm0-uart.yaml diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 15afe117e477e..41ccd97b5982b 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -43,6 +43,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_MCUX_LPSCI uart_mcux_lpsci.c) zephyr_library_sources_ifdef(CONFIG_UART_MCUX_LPUART uart_mcux_lpuart.c) zephyr_library_sources_ifdef(CONFIG_UART_MIV uart_miv.c) zephyr_library_sources_ifdef(CONFIG_UART_MSP432P4XX uart_msp432p4xx.c) +zephyr_library_sources_ifdef(CONFIG_UART_MSPM0 uart_mspm0.c) zephyr_library_sources_ifdef(CONFIG_UART_NEORV32 uart_neorv32.c) zephyr_library_sources_ifdef(CONFIG_UART_NPCX uart_npcx.c) zephyr_library_sources_ifdef(CONFIG_UART_NRFX_UART uart_nrfx_uart.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 9b76ac170c704..1628239923f70 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -183,6 +183,7 @@ rsource "Kconfig.mcux_lpsci" rsource "Kconfig.mcux_lpuart" rsource "Kconfig.miv" rsource "Kconfig.msp432p4xx" +rsource "Kconfig.mspm0" rsource "Kconfig.native_posix" rsource "Kconfig.native_tty" rsource "Kconfig.neorv32" diff --git a/drivers/serial/Kconfig.mspm0 b/drivers/serial/Kconfig.mspm0 new file mode 100644 index 0000000000000..c71ef5bf8635c --- /dev/null +++ b/drivers/serial/Kconfig.mspm0 @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Texas Instruments + +config UART_MSPM0 + bool "MSPM0 UART driver" + default y + depends on DT_HAS_TI_MSPM0_UART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + select PINCTRL + help + This option enables the TI MSPM0 UART driver. diff --git a/drivers/serial/uart_mspm0.c b/drivers/serial/uart_mspm0.c new file mode 100644 index 0000000000000..165803017eb34 --- /dev/null +++ b/drivers/serial/uart_mspm0.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_mspm0_uart + +/* Zephyr includes */ +#include +#include +#include +#include +#include +#include +#include + +/* Driverlib includes */ +#include + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#define UART_MSPM0_TX_INTERRUPTS (DL_UART_MAIN_INTERRUPT_TX | DL_UART_MAIN_INTERRUPT_EOT_DONE) +#define UART_MSPM0_RX_INTERRUPTS (DL_UART_MAIN_INTERRUPT_RX) +#endif + +struct uart_mspm0_config { + UART_Regs *regs; + uint32_t clock_frequency; + uint32_t current_speed; + const struct mspm0_clockSys *clock_subsys; + const struct pinctrl_dev_config *pinctrl; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_config_func_t irq_config_func; +#endif +}; + +struct uart_mspm0_data { + /* UART clock structure */ + DL_UART_Main_ClockConfig clock_config; + /* UART config structure */ + DL_UART_Main_Config config; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uint32_t interruptState; /* Masked Interrupt Status when called by irq_update */ + uart_irq_callback_user_data_t cb; /* Callback function pointer */ + void *cb_data; /* Callback function arg */ +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static void uart_mspm0_isr(const struct device *dev); +#define MSPM0_INTERRUPT_CALLBACK_FN(index) .cb = NULL, +#else +#define MSPM0_INTERRUPT_CALLBACK_FN(index) +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static int uart_mspm0_init(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + struct uart_mspm0_data *data = dev->data; + const struct device *const clk_dev = DEVICE_DT_GET(DT_NODELABEL(clkmux)); + uint32_t clock_rate; + int ret; + + /* Reset power */ + DL_UART_Main_reset(config->regs); + DL_UART_Main_enablePower(config->regs); + delay_cycles(POWER_STARTUP_DELAY); + + /* Init UART pins */ + ret = pinctrl_apply_state(config->pinctrl, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + + /* Set UART configs */ + DL_UART_Main_setClockConfig(config->regs, + (DL_UART_Main_ClockConfig *)&data->clock_config); + DL_UART_Main_init(config->regs, (DL_UART_Main_Config *)&data->config); + + /* + * Configure baud rate by setting oversampling and baud rate divisor + * from the device tree data current-speed + */ + ret = clock_control_get_rate(clk_dev, (clock_control_subsys_t)config->clock_subsys, + &clock_rate); + + if (ret < 0) { + return ret; + } + + DL_UART_Main_configBaudRate(config->regs, clock_rate, config->current_speed); + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + config->irq_config_func(dev); +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + + /* Enable UART */ + DL_UART_Main_enable(config->regs); + + return 0; +} + +static int uart_mspm0_poll_in(const struct device *dev, unsigned char *c) +{ + const struct uart_mspm0_config *config = dev->config; + + return (DL_UART_Main_receiveDataCheck(config->regs, c)) ? 0 : -1; +} + +static void uart_mspm0_poll_out(const struct device *dev, unsigned char c) +{ + const struct uart_mspm0_config *config = dev->config; + + DL_UART_Main_transmitDataBlocking(config->regs, c); +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +static int uart_mspm0_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + const struct uart_mspm0_config *config = dev->config; + + return (int)DL_UART_Main_fillTXFIFO(config->regs, (uint8_t *)tx_data, size); +} + +static int uart_mspm0_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + const struct uart_mspm0_config *config = dev->config; + + return (int)DL_UART_Main_drainRXFIFO(config->regs, rx_data, size); +} + +static void uart_mspm0_irq_rx_enable(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + + DL_UART_Main_enableInterrupt(config->regs, UART_MSPM0_RX_INTERRUPTS); +} + +static void uart_mspm0_irq_rx_disable(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + + DL_UART_Main_disableInterrupt(config->regs, UART_MSPM0_RX_INTERRUPTS); +} + +static int uart_mspm0_irq_rx_ready(const struct device *dev) +{ + struct uart_mspm0_data *const dev_data = dev->data; + + return ((dev_data->interruptState & DL_UART_MAIN_INTERRUPT_RX) == DL_UART_MAIN_INTERRUPT_RX) + ? 1 + : 0; +} + +static void uart_mspm0_irq_tx_enable(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + + DL_UART_Main_enableInterrupt(config->regs, UART_MSPM0_TX_INTERRUPTS); +} + +static void uart_mspm0_irq_tx_disable(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + + DL_UART_Main_disableInterrupt(config->regs, UART_MSPM0_TX_INTERRUPTS); +} + +static int uart_mspm0_irq_tx_ready(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + struct uart_mspm0_data *const dev_data = dev->data; + + return (((dev_data->interruptState & DL_UART_MAIN_INTERRUPT_TX) == + DL_UART_MAIN_INTERRUPT_TX) || + DL_UART_Main_isTXFIFOEmpty(config->regs)) + ? 1 + : 0; +} + +static int uart_mspm0_irq_tx_complete(const struct device *dev) +{ + struct uart_mspm0_data *const dev_data = dev->data; + + return ((dev_data->interruptState & DL_UART_MAIN_INTERRUPT_EOT_DONE) == + DL_UART_MAIN_INTERRUPT_EOT_DONE) + ? 1 + : 0; +} + +static int uart_mspm0_irq_is_pending(const struct device *dev) +{ + struct uart_mspm0_data *const dev_data = dev->data; + + return ((dev_data->interruptState != 0) ? 1 : 0); +} + +static int uart_mspm0_irq_update(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + struct uart_mspm0_data *const dev_data = dev->data; + + dev_data->interruptState = DL_UART_Main_getEnabledInterruptStatus( + config->regs, UART_MSPM0_RX_INTERRUPTS | UART_MSPM0_TX_INTERRUPTS); + + /* + * Clear interrupts explicitly after storing all in the update. Interrupts + * can be re-set by the MIS during the ISR should they be available. + */ + + DL_UART_Main_clearInterruptStatus(config->regs, dev_data->interruptState); + + return 1; +} + +static void uart_mspm0_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *cb_data) +{ + struct uart_mspm0_data *const dev_data = dev->data; + + /* Set callback function and data */ + dev_data->cb = cb; + dev_data->cb_data = cb_data; +} + +/** + * @brief Interrupt service routine. + * + * This simply calls the callback function, if one exists. + * + * @param arg Argument to ISR. + */ +static void uart_mspm0_isr(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + struct uart_mspm0_data *const dev_data = dev->data; + uint32_t int_status; + + /* Perform callback if defined */ + if (dev_data->cb) { + dev_data->cb(dev, dev_data->cb_data); + } else { + /* error, callback necessary in order to make progress. Clear interrupts + * temporarily. + */ + int_status = DL_UART_Main_getEnabledInterruptStatus( + config->regs, UART_MSPM0_TX_INTERRUPTS | UART_MSPM0_RX_INTERRUPTS); + DL_UART_Main_clearInterruptStatus(config->regs, int_status); + } +} + +#define MSP_UART_IRQ_REGISTER(index) \ + static void uart_mspm0_##index##_irq_register(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), uart_mspm0_isr, \ + DEVICE_DT_INST_GET(index), 0); \ + irq_enable(DT_INST_IRQN(index)); \ + } +#else + +#define MSP_UART_IRQ_REGISTER(index) + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static const struct uart_driver_api uart_mspm0_driver_api = { + .poll_in = uart_mspm0_poll_in, + .poll_out = uart_mspm0_poll_out, +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_mspm0_fifo_fill, + .fifo_read = uart_mspm0_fifo_read, + .irq_tx_enable = uart_mspm0_irq_tx_enable, + .irq_tx_disable = uart_mspm0_irq_tx_disable, + .irq_tx_ready = uart_mspm0_irq_tx_ready, + .irq_rx_enable = uart_mspm0_irq_rx_enable, + .irq_rx_disable = uart_mspm0_irq_rx_disable, + .irq_tx_complete = uart_mspm0_irq_tx_complete, + .irq_rx_ready = uart_mspm0_irq_rx_ready, + .irq_is_pending = uart_mspm0_irq_is_pending, + .irq_update = uart_mspm0_irq_update, + .irq_callback_set = uart_mspm0_irq_callback_set, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +#define MSPM0_UART_INIT_FN(index) \ + \ + PINCTRL_DT_INST_DEFINE(index); \ + \ + static const struct mspm0_clockSys mspm0_uart_clockSys##index = \ + MSPM0_CLOCK_SUBSYS_FN(index); \ + \ + MSP_UART_IRQ_REGISTER(index) \ + \ + static const struct uart_mspm0_config uart_mspm0_cfg_##index = { \ + .regs = (UART_Regs *)DT_INST_REG_ADDR(index), \ + .current_speed = DT_INST_PROP(index, current_speed), \ + .pinctrl = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ + .clock_subsys = &mspm0_uart_clockSys##index, \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (.irq_config_func = uart_mspm0_##index##_irq_register,)) }; \ + \ + static struct uart_mspm0_data uart_mspm0_data_##index = { \ + .clock_config = {.clockSel = (DT_INST_CLOCKS_CELL(index, bus) & \ + MSPM0_CLOCK_SEL_MASK), \ + .divideRatio = DL_UART_MAIN_CLOCK_DIVIDE_RATIO_1}, \ + .config = \ + { \ + .mode = DL_UART_MAIN_MODE_NORMAL, \ + .direction = DL_UART_MAIN_DIRECTION_TX_RX, \ + .flowControl = (DT_INST_PROP(index, hw_flow_control) \ + ? DL_UART_MAIN_FLOW_CONTROL_RTS_CTS \ + : DL_UART_MAIN_FLOW_CONTROL_NONE), \ + .parity = DL_UART_MAIN_PARITY_NONE, \ + .wordLength = DL_UART_MAIN_WORD_LENGTH_8_BITS, \ + .stopBits = DL_UART_MAIN_STOP_BITS_ONE, \ + }, \ + MSPM0_INTERRUPT_CALLBACK_FN(index)}; \ + \ + DEVICE_DT_INST_DEFINE(index, &uart_mspm0_init, NULL, &uart_mspm0_data_##index, \ + &uart_mspm0_cfg_##index, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ + &uart_mspm0_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MSPM0_UART_INIT_FN) diff --git a/dts/bindings/serial/ti,mspm0-uart.yaml b/dts/bindings/serial/ti,mspm0-uart.yaml new file mode 100644 index 0000000000000..3fd5ba9bc69cf --- /dev/null +++ b/dts/bindings/serial/ti,mspm0-uart.yaml @@ -0,0 +1,18 @@ +description: TI MSPM0 UART + +compatible: "ti,mspm0-uart" + +include: [uart-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true From d0c9952d40848ba09c404aea7391063c35e3fa22 Mon Sep 17 00:00:00 2001 From: Jackson Farley Date: Thu, 16 Jan 2025 18:42:37 -0500 Subject: [PATCH 9/9] boards: added TI LP_MSPM0G3507 board added Texas Instruments LP_MSPM0G3507 launchpad Signed-off-by: Jackson Farley --- boards/ti/lp_mspm0g3507/Kconfig.lp_mspm0g3507 | 5 + boards/ti/lp_mspm0g3507/board.cmake | 3 + boards/ti/lp_mspm0g3507/board.yml | 5 + .../lp_mspm0g3507/docs/img/lp_mspm0g3507.webp | Bin 0 -> 44020 bytes boards/ti/lp_mspm0g3507/docs/index.rst | 194 ++++++++++++++++++ boards/ti/lp_mspm0g3507/lp_mspm0g3507.dts | 85 ++++++++ boards/ti/lp_mspm0g3507/lp_mspm0g3507.yaml | 15 ++ .../ti/lp_mspm0g3507/lp_mspm0g3507_defconfig | 16 ++ boards/ti/lp_mspm0g3507/support/openocd.cfg | 4 + 9 files changed, 327 insertions(+) create mode 100644 boards/ti/lp_mspm0g3507/Kconfig.lp_mspm0g3507 create mode 100644 boards/ti/lp_mspm0g3507/board.cmake create mode 100644 boards/ti/lp_mspm0g3507/board.yml create mode 100644 boards/ti/lp_mspm0g3507/docs/img/lp_mspm0g3507.webp create mode 100644 boards/ti/lp_mspm0g3507/docs/index.rst create mode 100644 boards/ti/lp_mspm0g3507/lp_mspm0g3507.dts create mode 100644 boards/ti/lp_mspm0g3507/lp_mspm0g3507.yaml create mode 100644 boards/ti/lp_mspm0g3507/lp_mspm0g3507_defconfig create mode 100644 boards/ti/lp_mspm0g3507/support/openocd.cfg diff --git a/boards/ti/lp_mspm0g3507/Kconfig.lp_mspm0g3507 b/boards/ti/lp_mspm0g3507/Kconfig.lp_mspm0g3507 new file mode 100644 index 0000000000000..cb20275099e27 --- /dev/null +++ b/boards/ti/lp_mspm0g3507/Kconfig.lp_mspm0g3507 @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_LP_MSPM0G3507 + select SOC_MSPM0G3507 diff --git a/boards/ti/lp_mspm0g3507/board.cmake b/boards/ti/lp_mspm0g3507/board.cmake new file mode 100644 index 0000000000000..cbeaea2e4564b --- /dev/null +++ b/boards/ti/lp_mspm0g3507/board.cmake @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/ti/lp_mspm0g3507/board.yml b/boards/ti/lp_mspm0g3507/board.yml new file mode 100644 index 0000000000000..d870b29966842 --- /dev/null +++ b/boards/ti/lp_mspm0g3507/board.yml @@ -0,0 +1,5 @@ +board: + name: lp_mspm0g3507 + vendor: ti + socs: + - name: mspm0g3507 diff --git a/boards/ti/lp_mspm0g3507/docs/img/lp_mspm0g3507.webp b/boards/ti/lp_mspm0g3507/docs/img/lp_mspm0g3507.webp new file mode 100644 index 0000000000000000000000000000000000000000..dba82b8bb91127bd697fbd6721aef176aa636477 GIT binary patch literal 44020 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�*e(Ly2;OFYmffakZ$B}LUCTX*+BRX>+B%_a)K02 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 literal 0 HcmV?d00001 diff --git a/boards/ti/lp_mspm0g3507/docs/index.rst b/boards/ti/lp_mspm0g3507/docs/index.rst new file mode 100644 index 0000000000000..74803467a709c --- /dev/null +++ b/boards/ti/lp_mspm0g3507/docs/index.rst @@ -0,0 +1,194 @@ +.. _lp_mspm0g3507: + +MSPM0G3507 LaunchPad +######################## + +Overview +******** + +MSPM0G350x microcontrollers (MCUs) are part of the MSP highly integrated, ultra-low-power 32-bit MCU +family based on the enhanced Arm® Cortex®-M0+ 32-bit core platform operating at up to 80-MHz frequency. +These cost-optimized MCUs offer high-performance analog peripheral integration, support extended temperature +ranges from -40°C to 125°C, and operate with supply voltages ranging from 1.62 V to 3.6 V. + +The MSPM0G350x devices provide up to 128KB embedded flash program memory with built-in error correction +code (ECC) and up to 32KB SRAM with a hardware parity option. These MCUs also incorporate a +memory protection unit, 7-channel DMA, math accelerator, and a variety of peripherals including +* Analog. + + * Two 12-bit 4-Msps ADCs. + + * Configurable internal shared voltage reference. + + * One 12-bit 1-Msps DAC. + + * Three high speed comparators with built-in reference DACs. + + * Two zero-drift zero-crossover op-amps with programmable gain. + +* Digital. + + * Two 16-bit advanced control timers. + + * Five general-purpose timers. + + * One 16-bit general-purpose timer for QEI interface. + + * One 32-bit high resolution general-purpose timer. + + * Two 16-bit timers with deadband support and up to 12 PWM Channels. + + * Two windowed-watchdog timers. + + * One RTC with alarm and calendar modes. + +* Data Integrity and Encryption. + + * One AES HW accelerator capable of CTR, CBC, and ECB modes. + + * One Cyclic Redundancy Check (CRC) accelerator. + + * One True Random Number Generator (TRNG). + +* Communication. + + * Four UARTs, one with support for advanced modes such as LIN and Manchester. + + * Two I2C supporting SMBUS/PMBUS and speeds up to FM+ (1Mbits/s). + + * Two SPI, one with max speed 32Mbits/s. + + * One CAN interface supporting CAN 2.0 A or B and CAN-FD. + +.. figure:: img/lp_mspm0g3507.webp + :align: center + :alt: MSPM0G3507 LaunchPad development board + +Zephyr uses the ``lp_mspm0g3507`` board configuration for building +the LP_MSPM0G3507 + +Features: +========= + +- Onboard XDS110 debug probe +- EnergyTrace technology available for ultra-low-power debugging +- 2 buttons, 1 LED and 1 RGB LED for user interaction +- Temperature sensor circuit +- Light sensor circuit +- External OPA2365 (default buffer mode) for ADC (up to 4 Msps) evaluation +- Onboard 32.768-kHz and 40-MHz crystals +- RC filter for ADC input (unpopulated by default) + +Details on the MSPM0G3507 LaunchPad can be found on the `TI LP_MSPM0G3507 Product Page`_. + +Supported Features +================== + +The MSPM0G3507 LaunchPad development board configuration supports the following hardware features: + ++-----------+------------+-----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=======================+ +| NVIC | on-chip | nested vectored | +| | | interrupt controller | ++-----------+------------+-----------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-----------------------+ +| UART | on-chip | serial | ++-----------+------------+-----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-----------------------+ +| PINMUX | on-chip | pinctrl | ++-----------+------------+-----------------------+ +| CLOCKMUX | on-chip | clockctl | ++-----------+------------+-----------------------+ + +More details about the supported peripherals are available in `MSPM0G3507 TRM`_. +Other hardware features are not currently supported by the Zephyr kernel. + +Building and Flashing +********************* + +Building +======== + +Follow the :ref:`getting_started` instructions for Zephyr application development. + +For example, to build the blinky application for the MSPM0G3507 LaunchPad: + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: lp_mspm0g3507 + :goals: build + +The resulting ``zephyr.bin`` binary in the build directory can be flashed onto +MSPM0G3507 LaunchPad using the steps mentioned below. + +Flashing +======== + +Open OCD is used to program the flash memory on the devices. It may be necessary in earlier versions to use a branch of open OCD onto the device. + +Before OpenOCD is public, one can clone `This Repo `_, and then this can be built with + +``` +cd +./bootstrap (when building from the git repository) +./configure --enable-xds110 +make +sudo make install +``` + +Then after the build, it is possible to flash the device by passing additional arguments to the flash command + +``` +west flash --openocd /src/openocd --openocd-search /tcl +``` + + +`UniFlash`_ can also be used to program the flash memory if needed. The flash utility, +however, requires the use of 8-byte aligned words, so adding alignment to the linker file is necessary. + +Debugging +========= + +The flashing method described above does not include symbols. Thus, debugging requires an additional step to load the symbols. +This section shows how to debug the MSPM0G3507 LaunchPad board using `CCS IDE`_. More information +on debugging using CCS can be found in `CCS User's Guide`_. + +In general, the steps for debugging in CCS are: + + 1. Open CCS + 2. Go to :menuselection:`Window --> Show View --> Target Configruation` + 3. Import target confguration by right clicking User Defined, selecting Import target configuration and pointing to the lp_mspm0g3507/support/MSPM0G3507.ccxml + 4. Launch target configuration by right clicking the new MSPM0G3507.ccxml file and clicking Launch target configuration + 5. Plug in the device and connect to it by going to :menuselection:`Run --> Connect Target` + 6. Go to :menuselection:`Run --> Load --> Load Symbols and load in the zephyr.elf file loaded` + 7. Use CCS to debug + +References +********** + +TI MSPM0 MCU Page: + https://www.ti.com/microcontrollers-mcus-processors/arm-based-microcontrollers/arm-cortex-m0-mcus/overview.html + +TI MSPM0G3507 Product Page: + https://www.ti.com/product/MSPM0G3507 + +TI MSPM0 SDK: + https://www.ti.com/tool/MSPM0-SDK + +.. _CCS User's Guide: + https://software-dl.ti.com/ccs/esd/documents/users_guide/index.html + +.. _MSPM0G3507 TRM: + https://www.ti.com/lit/slau846 + +.. _TI LP_MSPM0G3507 Product Page: + https://www.ti.com/tool/LP-MSPM0G3507 + +.. _UniFlash: + http://processors.wiki.ti.com/index.php/UniFlash_v4_Quick_Guide#Command_Line_Interface + +.. _CCS IDE: + http://www.ti.com/tool/ccstudio diff --git a/boards/ti/lp_mspm0g3507/lp_mspm0g3507.dts b/boards/ti/lp_mspm0g3507/lp_mspm0g3507.dts new file mode 100644 index 0000000000000..0c06c3c7b80df --- /dev/null +++ b/boards/ti/lp_mspm0g3507/lp_mspm0g3507.dts @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/dts-v1/; + +#include +#include +#include + +/ { + model = "TI LP_MSPM0G3507"; + compatible = "ti,mspm0g3507"; + + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &btn0; + sw1 = &btn1; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_2_b { + gpios = <&gpiob 22 GPIO_ACTIVE_HIGH>; + label = "Blue RBG LED"; + }; + led1: led_2_r { + gpios = <&gpiob 26 GPIO_ACTIVE_HIGH>; + label = "Red RBG LED"; + }; + led2: led_2_g { + gpios = <&gpiob 27 GPIO_ACTIVE_HIGH>; + label = "Green RBG LED"; + }; + led3: led_1 { + gpios = <&gpioa 0 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + }; + + keys { + compatible = "gpio-keys"; + btn0: btn_0 { + gpios = <&gpiob 21 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + label = "Switch 2"; + zephyr,code = ; + }; + btn1: btn_1 { + gpios = <&gpioa 18 GPIO_ACTIVE_HIGH>; + label = "Switch 1"; + zephyr,code = ; + }; + }; +}; + +&cpu0 { + clock-frequency = ; +}; + +&clkmux { + clock-source = <&pll>; + clock-frequency = ; + uclk-div = <2>; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_tx_pa10 &uart0_rx_pa11>; + pinctrl-names = "default"; +}; diff --git a/boards/ti/lp_mspm0g3507/lp_mspm0g3507.yaml b/boards/ti/lp_mspm0g3507/lp_mspm0g3507.yaml new file mode 100644 index 0000000000000..6b0cbd0800139 --- /dev/null +++ b/boards/ti/lp_mspm0g3507/lp_mspm0g3507.yaml @@ -0,0 +1,15 @@ +identifier: lp_mspm0g3507 +name: LP_MSPM0G3507 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 32 +flash: 128 +supported: + - gpio + - pinctrl + - uart +vendor: ti diff --git a/boards/ti/lp_mspm0g3507/lp_mspm0g3507_defconfig b/boards/ti/lp_mspm0g3507/lp_mspm0g3507_defconfig new file mode 100644 index 0000000000000..c5aeccf7c56df --- /dev/null +++ b/boards/ti/lp_mspm0g3507/lp_mspm0g3507_defconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_CORTEX_M_SYSTICK=y + +# Enable GPIO driver +CONFIG_GPIO=y + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable Clock Control +CONFIG_CLOCK_CONTROL=y diff --git a/boards/ti/lp_mspm0g3507/support/openocd.cfg b/boards/ti/lp_mspm0g3507/support/openocd.cfg new file mode 100644 index 0000000000000..0356c7705cf1b --- /dev/null +++ b/boards/ti/lp_mspm0g3507/support/openocd.cfg @@ -0,0 +1,4 @@ +source [find interface/xds110.cfg] +adapter speed 10000 + +source [find target/ti_mspm0.cfg]