diff --git a/boards/ti/lp_mspm0g3507/Kconfig.lp_mspm0g3507 b/boards/ti/lp_mspm0g3507/Kconfig.lp_mspm0g3507 new file mode 100644 index 0000000000000..c03a5919a9403 --- /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_MSPM0G350X diff --git a/boards/ti/lp_mspm0g3507/board.cmake b/boards/ti/lp_mspm0g3507/board.cmake new file mode 100644 index 0000000000000..b9f242d8835b8 --- /dev/null +++ b/boards/ti/lp_mspm0g3507/board.cmake @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd "--cmd-pre-load=reset init") +# unprotect sectors before running +board_runner_args(openocd "--cmd-pre-load=flash protect 1 0 last off") +board_runner_args(openocd "--cmd-pre-load=flash erase_sector 1 0 last") + +#board_runner_args(openocd "--cmd-reset-halt=flash info 1") + +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..b93f834adabc9 --- /dev/null +++ b/boards/ti/lp_mspm0g3507/board.yml @@ -0,0 +1,5 @@ +board: + name: lp_mspm0g3507 + vendor: ti + socs: + - name: mspm0g350x diff --git a/boards/ti/lp_mspm0g3507/docs/img/lp_mspm0g3507.png b/boards/ti/lp_mspm0g3507/docs/img/lp_mspm0g3507.png new file mode 100644 index 0000000000000..e973b9948920d Binary files /dev/null and b/boards/ti/lp_mspm0g3507/docs/img/lp_mspm0g3507.png differ diff --git a/boards/ti/lp_mspm0g3507/docs/index.rst b/boards/ti/lp_mspm0g3507/docs/index.rst new file mode 100644 index 0000000000000..81285ce202e6b --- /dev/null +++ b/boards/ti/lp_mspm0g3507/docs/index.rst @@ -0,0 +1,132 @@ +.. _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 ECC and hardware parity option. These MCUs also incorporate a +memory protection unit, 7-channel DMA, math accelerator, and a variety of high-performance analog peripherals +such as 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, and one general-purpose amplifier. These devices also offer intelligent digital peripherals such as two +16-bit advanced control timers, five general-purpose timers (with one 16-bit general-purpose timer for QEI +interface, two 16-bit general-purpose timers for STANDBY mode, and one 32-bit general-purpose timer), two +windowed-watchdog timers, and one RTC with alarm and calendar modes. These devices provide data integrity +and encryption peripherals (AES, CRC, TRNG) and enhanced communication interfaces (four UART, two I2C, +two SPI, CAN 2.0/FD). + +.. figure:: img/lp_mspm0g3507.png + :align: center + :alt: MSPM0G3507 LaunchPad development board + +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 | ++-----------+------------+-----------------------+ + +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 :ref:`hello_world` application for the MSPM0G3507 LaunchPad: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :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 +======== + +`UniFlash`_ is used to program the flash memory. Only bin loading is currently supported. +Make sure to select the checkbox for binary loading. + +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 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 Run > Connect Target + 6. Go to 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..a3e96482f43fb --- /dev/null +++ b/boards/ti/lp_mspm0g3507/lp_mspm0g3507.dts @@ -0,0 +1,75 @@ +/* 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_0 { + gpios = <&gpiob 22 GPIO_ACTIVE_HIGH>; + label = "Blue LED"; + }; + led1: led_1 { + gpios = <&gpiob 26 GPIO_ACTIVE_HIGH>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpiob 27 GPIO_ACTIVE_HIGH>; + label = "Green LED"; + }; + }; + + keys { + compatible = "gpio-keys"; + btn0: btn_0 { + gpios = <&gpiob 21 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + label = "Switch 3"; + zephyr,code = ; + }; + btn1: btn_1 { + gpios = <&gpioa 18 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + label = "Switch 2"; + zephyr,code = ; + }; + }; +}; + +&cpu0 { + clock-frequency = <32000000>; +}; + +&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..1cbc935cd91cb --- /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 pinctrl +CONFIG_PINCTRL=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..119c66277f873 --- /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] \ No newline at end of file diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 2143d019cb7a0..b29f5b0161171 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -9,6 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_AXP192 gpio_axp192.c) zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_GPIO_CC13XX_CC26XX gpio_cc13xx_cc26xx.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_MSPM0 gpio_mspm0.c) zephyr_library_sources_ifdef(CONFIG_GPIO_CC32XX gpio_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_CMSDK_AHB gpio_cmsdk_ahb.c) zephyr_library_sources_ifdef(CONFIG_GPIO_DW gpio_dw.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2ca6da678c309..de5ac2da4fab6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -121,6 +121,8 @@ source "drivers/gpio/Kconfig.cc13xx_cc26xx" source "drivers/gpio/Kconfig.cc32xx" +source "drivers/gpio/Kconfig.mspm0" + source "drivers/gpio/Kconfig.sifive" source "drivers/gpio/Kconfig.esp32" 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..60cc1fe80ffa6 --- /dev/null +++ b/drivers/gpio/gpio_mspm0.c @@ -0,0 +1,340 @@ +/* + * 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, +}; +#elif defined(CONFIG_SOC_SERIES_MSPM0L2XXX) +#define NUM_GPIOB_PIN 32 +#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_PINCM27, IOMUX_PINCM28, IOMUX_PINCM29, IOMUX_PINCM30, + IOMUX_PINCM31, IOMUX_PINCM32, IOMUX_PINCM33, IOMUX_PINCM34, IOMUX_PINCM35, + IOMUX_PINCM36, IOMUX_PINCM37, IOMUX_PINCM53, IOMUX_PINCM54, IOMUX_PINCM55, + IOMUX_PINCM62, IOMUX_PINCM63, IOMUX_PINCM64, IOMUX_PINCM65, IOMUX_PINCM66, + IOMUX_PINCM70, IOMUX_PINCM71, IOMUX_PINCM72, IOMUX_PINCM21, IOMUX_PINCM22, + IOMUX_PINCM23, IOMUX_PINCM24, +}; +#else +#throw "series lookup table not supported" +#endif /* CONFIG_SOC_SERIES */ +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) */ + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioc), okay) +#define GPIOC_NODE DT_NODELABEL(gpioc) +#ifdef CONFIG_SOC_SERIES_MSPM0L2XXX +#define NUM_GPIOC_PIN 10 +#define gpioc_pins NUM_GPIOC_PIN +static uint32_t gpioc_pincm_lut[NUM_GPIOC_PIN] = { + IOMUX_PINCM43, IOMUX_PINCM44, IOMUX_PINCM45, IOMUX_PINCM46, IOMUX_PINCM47, + IOMUX_PINCM48, IOMUX_PINCM58, IOMUX_PINCM59, IOMUX_PINCM60, IOMUX_PINCM61, +}; +#else +#throw "series lookup table not supported" +#endif /* CONFIG_SOC_SERIES */ +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioc), 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; + + /* 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, + (flags & GPIO_PULL_UP) ? DL_GPIO_RESISTOR_PULL_UP + : (flags & GPIO_PULL_DOWN) ? DL_GPIO_RESISTOR_PULL_DOWN + : DL_GPIO_RESISTOR_NONE, + DL_GPIO_HYSTERESIS_DISABLE, DL_GPIO_WAKEUP_DISABLE); + break; + case GPIO_OUTPUT: + DL_GPIO_initDigitalOutputFeatures(config->pincm_lut[pin], DL_GPIO_INVERSION_DISABLE, + (flags & GPIO_PULL_UP) ? DL_GPIO_RESISTOR_PULL_UP + : (flags & GPIO_PULL_DOWN) + ? DL_GPIO_RESISTOR_PULL_DOWN + : DL_GPIO_RESISTOR_NONE, + 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, 0xFFFFFFFF); + + 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 |= 0x01; + } + if (trig & GPIO_INT_TRIG_HIGH) { + polarity |= 0x02; + } + 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; +} + +#ifdef CONFIG_GPIO_GET_DIRECTION +static int gpio_mspm0_port_get_direction(const struct device *port, gpio_port_pins_t map, + gpio_port_pins_t *inputs, gpio_port_pins_t *outputs) +{ + return -ENOTSUP; +} +#endif /* CONFIG_GPIO_GET_DIRECTION */ + +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, +#ifdef CONFIG_GPIO_GET_DIRECTION + .port_get_direction = gpio_mspm0_port_get_direction, +#endif /* CONFIG_GPIO_GET_DIRECTION */ +}; + +#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/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index c285e7d6f7f69..bbb9de3b840c9 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -32,6 +32,7 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_GECKO pinctrl_gecko.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 ab6ea86bcc9a8..1e531c43e7bfe 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -58,6 +58,7 @@ source "drivers/pinctrl/Kconfig.xmc4xxx" source "drivers/pinctrl/Kconfig.nxp_s32" source "drivers/pinctrl/Kconfig.gecko" 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/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index ef0133a5ca105..f5a634180f5a4 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -24,6 +24,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_MCUX_LPUART uart_mcux_lpuart.c) zephyr_library_sources_ifdef(CONFIG_UART_MCUX_LPSCI uart_mcux_lpsci.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_NS16550 uart_ns16550.c) zephyr_library_sources_ifdef(CONFIG_UART_NRFX_UART uart_nrfx_uart.c) if (CONFIG_UART_NRFX_UARTE) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 91b79ce6dfad4..b2d0d6499fe1b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -200,6 +200,8 @@ source "drivers/serial/Kconfig.leuart_gecko" source "drivers/serial/Kconfig.msp432p4xx" +source "drivers/serial/Kconfig.mspm0" + source "drivers/serial/Kconfig.numicro" source "drivers/serial/Kconfig.sam0" diff --git a/drivers/serial/Kconfig.mspm0 b/drivers/serial/Kconfig.mspm0 new file mode 100644 index 0000000000000..36815720ff545 --- /dev/null +++ b/drivers/serial/Kconfig.mspm0 @@ -0,0 +1,11 @@ +# 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 + 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..9cbffc4ce6a93 --- /dev/null +++ b/drivers/serial/uart_mspm0.c @@ -0,0 +1,295 @@ +/* + * 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 + +/* Defines for UART0 */ +#define UART_0_IBRD_33_kHZ_9600_BAUD (1) +#define UART_0_FBRD_33_kHZ_9600_BAUD (9) + +/* Driverlib includes */ +#include + +struct uart_mspm0_config { + UART_Regs *regs; + uint32_t clock_frequency; + uint32_t current_speed; + 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 UART_ClockConfig; + /* UART config structure */ + DL_UART_Main_Config UART_Config; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + 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; + 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->UART_ClockConfig); + DL_UART_Main_init(config->regs, (DL_UART_Main_Config *)&data->UART_Config); + + /* + * Configure baud rate by setting oversampling and baud rate divisor + * from the device tree data current-speed + */ + DL_UART_Main_configBaudRate(config->regs, 32000000, 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 + +#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) + +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_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; + + return (DL_UART_Main_getEnabledInterruptStatus( + config->regs, DL_UART_MAIN_INTERRUPT_TX)) ? 0 : 1; +} + +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_tx_complete(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + + return (DL_UART_Main_isTXFIFOEmpty(config->regs)) ? 1 : 0; +} + +static int uart_mspm0_irq_rx_ready(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + + return (DL_UART_Main_getEnabledInterruptStatus( + config->regs, UART_MSPM0_RX_INTERRUPTS)) ? 1 : 0; +} + +static int uart_mspm0_irq_is_pending(const struct device *dev) +{ + const struct uart_mspm0_config *config = dev->config; + + return (DL_UART_Main_getEnabledInterruptStatus(config->regs, + UART_MSPM0_RX_INTERRUPTS | UART_MSPM0_TX_INTERRUPTS)) ? 1 : 0; +} + +static int uart_mspm0_irq_update(const struct device *dev) +{ + ARG_UNUSED(dev); + 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; + + int int_status = DL_UART_Main_getEnabledInterruptStatus(config->regs, + UART_MSPM0_RX_INTERRUPTS | UART_MSPM0_TX_INTERRUPTS); + + /* Perform callback if defined */ + if (dev_data->cb) { + dev_data->cb(dev, dev_data->cb_data); + } + + /* + * Clear interrupts only after cb called, as Zephyr UART clients expect + * to check interrupt status during the callback. + */ + + 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); \ + \ + 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), \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (.irq_config_func = uart_mspm0_##index##_irq_register,)) \ + }; \ + \ + static struct uart_mspm0_data uart_mspm0_data_##index = { \ + .UART_ClockConfig = { \ + .clockSel = DL_UART_MAIN_CLOCK_BUSCLK, \ + .divideRatio = DL_UART_MAIN_CLOCK_DIVIDE_RATIO_1 \ + }, \ + .UART_Config = \ + { \ + .mode = DL_UART_MAIN_MODE_NORMAL, \ + .direction = DL_UART_MAIN_DIRECTION_TX_RX, \ + .flowControl = 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/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index 8bbae49d1c28f..51bbdf4fe771f 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -54,3 +54,4 @@ zephyr_library_sources_ifdef(CONFIG_SPI_INFINEON_CAT1 spi_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_SPI_SEDI spi_sedi.c) zephyr_library_sources_ifdef(CONFIG_SPI_NPCX_SPIP spi_npcx_spip.c) zephyr_library_sources_ifdef(CONFIG_SPI_GRLIB_SPIMCTRL spi_grlib_spimctrl.c) +zephyr_library_sources_ifdef(CONFIG_SPI_MSPM0 spi_mspm0.c) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index c7e40016b4e59..8d19aa9416b66 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -147,4 +147,6 @@ source "drivers/spi/Kconfig.mchp_mss" source "drivers/spi/Kconfig.grlib_spimctrl" +source "drivers/spi/Kconfig.mspm0" + endif # SPI diff --git a/drivers/spi/Kconfig.mspm0 b/drivers/spi/Kconfig.mspm0 new file mode 100644 index 0000000000000..1984a8bdde136 --- /dev/null +++ b/drivers/spi/Kconfig.mspm0 @@ -0,0 +1,9 @@ +# Copyright (C) 2024 Bang & Olufsen A/S, Denmark +# SPDX-License-Identifier: Apache-2.0 + +config SPI_MSPM0 + bool "TI MSPM0 SPI driver" + default n + depends on DT_HAS_TI_MSPM0_SPI_ENABLED + help + Enable driver for TI MSPM0 SPI. diff --git a/drivers/spi/spi_mspm0.c b/drivers/spi/spi_mspm0.c new file mode 100644 index 0000000000000..a7e496e51ad0a --- /dev/null +++ b/drivers/spi/spi_mspm0.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2024 Bang & Olufsen A/S, Denmark + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_mspm0_spi + +#include +#include +#include +#include +#include +#include + +/* DriverLib includes */ +#include + +LOG_MODULE_REGISTER(spi_mspm0, CONFIG_SPI_LOG_LEVEL); + +/* must be included after log module registration */ +#include "spi_context.h" + +#define SPI_MODE(operation) (operation & BIT(0) ? DL_SPI_MODE_PERIPHERAL : DL_SPI_MODE_CONTROLLER) +#define BIT_ORDER_MODE(operation) \ + (operation & BIT(4) ? DL_SPI_BIT_ORDER_LSB_FIRST : DL_SPI_BIT_ORDER_MSB_FIRST) +#define DATA_SIZE_MODE(operation) (SPI_WORD_SIZE_GET(operation) - 1) + +#define POLARITY_MODE(operation) \ + (SPI_MODE_GET(operation) & SPI_MODE_CPOL ? SPI_CTL0_SPO_HIGH : SPI_CTL0_SPO_LOW) +#define PHASE_MODE(operation) \ + (SPI_MODE_GET(operation) & SPI_MODE_CPHA ? SPI_CTL0_SPH_SECOND : SPI_CTL0_SPH_FIRST) +#define DUPLEX_MODE(operation) \ + (operation & BIT(11) ? SPI_CTL0_FRF_MOTOROLA_3WIRE : SPI_CTL0_FRF_MOTOROLA_4WIRE) + +/* Only motorola format requires config - TI format is a single value */ +#define FRAME_FORMAT_MODE(operation) \ + (operation & SPI_FRAME_FORMAT_TI \ + ? SPI_CTL0_FRF_TI_SYNC \ + : DUPLEX_MODE(operation) | POLARITY_MODE(operation) | PHASE_MODE(operation)) + +/* 0x38 represents the bits 8, 16 and 32. Knowing that 24 is bits 8 and 16 + * These are the bits were when you divide by 8, you keep the result as it is. + * For all the other ones, 4 to 7, 9 to 15, etc... you need a +1, + * since on such division it takes only the result above 0 + */ +#define BYTES_PER_FRAME(word_size) \ + (((word_size) & ~0x38) ? (((word_size) / 8) + 1) : ((word_size) / 8)) + +struct spi_mspm0_config { + SPI_Regs *base; + const struct pinctrl_dev_config *pinctrl; + const DL_SPI_ClockConfig clock_config; + uint32_t clock_frequency; +}; + +struct spi_mspm0_data { + struct spi_context ctx; + uint8_t dfs; +}; + +static int spi_mspm0_configure(const struct device *dev, const struct spi_config *spi_cfg) +{ + struct spi_mspm0_data *const data = dev->data; + const struct spi_mspm0_config *const cfg = dev->config; + struct spi_context *ctx = &data->ctx; + + if (spi_context_configured(ctx, spi_cfg)) { + /* this configuration is already in use */ + return 0; + } + + if (SPI_MODE(spi_cfg->operation) == DL_SPI_MODE_PERIPHERAL) { + /* todo: not yet tested so don't add support yet */ + return -ENOTSUP; + } + + if (spi_cfg->frequency > (cfg->clock_frequency / 2)) { + return -EINVAL; + } + + /* see DL_SPI_setBitRateSerialClockDivider for details */ + uint16_t clock_scr = cfg->clock_frequency / ((2 * spi_cfg->frequency) - 1); + if (!IN_RANGE(clock_scr, 0, 1023)) { + return -EINVAL; + } + + const DL_SPI_Config dl_cfg = { + .mode = SPI_MODE(spi_cfg->operation), + .frameFormat = FRAME_FORMAT_MODE(spi_cfg->operation), + .chipSelectPin = DL_SPI_CHIP_SELECT_NONE, /* spi_context controls the CS pin */ + .parity = DL_SPI_PARITY_NONE, /* currently unused in zephyr */ + .bitOrder = BIT_ORDER_MODE(spi_cfg->operation), + .dataSize = DATA_SIZE_MODE(spi_cfg->operation), + }; + + /* peripheral should always be disabled prior to applying a new configuration */ + DL_SPI_disable(cfg->base); + DL_SPI_init(cfg->base, (DL_SPI_Config *)&dl_cfg); + DL_SPI_setBitRateSerialClockDivider(cfg->base, (uint32_t)clock_scr); + + data->dfs = BYTES_PER_FRAME(SPI_WORD_SIZE_GET(spi_cfg->operation)); + if (data->dfs > 2) { + DL_SPI_enablePacking(cfg->base); + } else { + DL_SPI_disablePacking(cfg->base); + } + + if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_LOOP) { + DL_SPI_enableLoopbackMode(cfg->base); + } else { + DL_SPI_disableLoopbackMode(cfg->base); + } + + DL_SPI_enable(cfg->base); + + /* save config so it can be reused + * also it's required for the lock owner to work */ + ctx->config = spi_cfg; + + return 0; +} + +static bool spi_mspm0_transfer_ongoing(struct spi_context *ctx) +{ + return spi_context_tx_on(ctx) || spi_context_rx_on(ctx); +} + +static void spi_mspm0_frame_tx(const struct device *dev) +{ + struct spi_mspm0_data *data = dev->data; + const struct spi_mspm0_config *cfg = dev->config; + struct spi_context *ctx = &data->ctx; + + /* nop tx if no data is expected */ + uint32_t tx_frame = 0; + if (spi_context_tx_buf_on(ctx)) { + if (data->dfs == 1) { + tx_frame = UNALIGNED_GET((uint8_t *)(ctx->tx_buf)); + } else if (data->dfs == 2) { + tx_frame = UNALIGNED_GET((uint16_t *)(ctx->tx_buf)); + } else { + tx_frame = UNALIGNED_GET((uint32_t *)(ctx->tx_buf)); + } + } + + DL_SPI_transmitDataBlocking32(cfg->base, tx_frame); + while (DL_SPI_isBusy(cfg->base)) { + /* wait for tx fifo to be sent */ + } + + spi_context_update_tx(ctx, data->dfs, 1); +} + +static void spi_mspm0_frame_rx(const struct device *dev) +{ + struct spi_mspm0_data *data = dev->data; + const struct spi_mspm0_config *cfg = dev->config; + struct spi_context *ctx = &data->ctx; + + const uint32_t rx_frame = DL_SPI_receiveDataBlocking32(cfg->base); + + /* only update rx buffer if the context is configured to do so + * could be eg. if a write is triggered without a read - here the peripheral would not + * respond why stale POCI would result in 0 being read out (full duplex mode) */ + if (!spi_context_rx_buf_on(ctx)) { + return; + } + + if (data->dfs == 1) { + UNALIGNED_PUT(rx_frame, (uint8_t *)ctx->rx_buf); + } else if (data->dfs == 2) { + UNALIGNED_PUT(rx_frame, (uint16_t *)ctx->rx_buf); + } else { + UNALIGNED_PUT(rx_frame, (uint32_t *)ctx->rx_buf); + } + + spi_context_update_rx(ctx, data->dfs, 1); +} + +static void spi_mspm0_start_transfer(const struct device *dev) +{ + struct spi_mspm0_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + spi_context_cs_control(ctx, true); + + while (spi_mspm0_transfer_ongoing(ctx)) { + spi_mspm0_frame_tx(dev); + spi_mspm0_frame_rx(dev); + } + + spi_context_cs_control(ctx, false); + spi_context_complete(ctx, dev, 0); +} + +static int spi_mspm0_transceive(const struct device *dev, const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + struct spi_mspm0_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + spi_context_lock(ctx, false, NULL, NULL, spi_cfg); + + int ret = spi_mspm0_configure(dev, spi_cfg); + if (ret != 0) { + spi_context_release(ctx, ret); + return ret; + } + + spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, data->dfs); + spi_mspm0_start_transfer(dev); + + ret = spi_context_wait_for_completion(ctx); + spi_context_release(ctx, ret); + + return ret; +} + +static int spi_mspm0_release(const struct device *dev, const struct spi_config *config) +{ + struct spi_mspm0_data *data = dev->data; + const struct spi_mspm0_config *cfg = dev->config; + struct spi_context *ctx = &data->ctx; + + if (!spi_context_configured(ctx, config)) { + return -EINVAL; + } + + if (DL_SPI_isBusy(cfg->base)) { + return -EBUSY; + } + + spi_context_unlock_unconditionally(ctx); + return 0; +} + +static const struct spi_driver_api spi_mspm0_api = { + .transceive = spi_mspm0_transceive, + .release = spi_mspm0_release, +}; + +static int spi_mspm0_init(const struct device *dev) +{ + struct spi_mspm0_data *data = dev->data; + const struct spi_mspm0_config *cfg = dev->config; + struct spi_context *ctx = &data->ctx; + + DL_SPI_reset(cfg->base); + DL_SPI_enablePower(cfg->base); + delay_cycles(POWER_STARTUP_DELAY); + + int ret = pinctrl_apply_state(cfg->pinctrl, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("Failed to apply pinctrl, err: %d", ret); + return ret; + } + + ret = spi_context_cs_configure_all(ctx); + if (ret < 0) { + return ret; + } + + DL_SPI_setClockConfig(cfg->base, (DL_SPI_ClockConfig *)&cfg->clock_config); + DL_SPI_enable(cfg->base); + + spi_context_unlock_unconditionally(ctx); + + return ret; +} + +#define MSPM0_SPI_INIT(inst) \ + PINCTRL_DT_INST_DEFINE(inst); \ + \ + static struct spi_mspm0_config spi_mspm0_##inst##_cfg = { \ + .base = (SPI_Regs *)DT_INST_REG_ADDR(inst), \ + .pinctrl = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .clock_config = {.clockSel = DL_SPI_CLOCK_BUSCLK, \ + .divideRatio = DL_SPI_CLOCK_DIVIDE_RATIO_1}, \ + .clock_frequency = DT_PROP(DT_INST_CLOCKS_CTLR(inst), clock_frequency), \ + }; \ + \ + static struct spi_mspm0_data spi_mspm0_##inst##_data = { \ + SPI_CONTEXT_INIT_LOCK(spi_mspm0_##inst##_data, ctx), \ + SPI_CONTEXT_INIT_SYNC(spi_mspm0_##inst##_data, ctx), \ + SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), ctx)}; \ + \ + DEVICE_DT_INST_DEFINE(inst, spi_mspm0_init, NULL, &spi_mspm0_##inst##_data, \ + &spi_mspm0_##inst##_cfg, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ + &spi_mspm0_api); + +DT_INST_FOREACH_STATUS_OKAY(MSPM0_SPI_INIT) 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..3d65a263ab61c --- /dev/null +++ b/dts/arm/ti/mspm0g1x0x_g3x0x/mspm0g1x0x_g3x0x.dtsi @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include + +/ { + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-m0plus"; + reg = <0>; + }; + }; + + sram0: memory@20200000 { + compatible = "mmio-sram"; + }; + + flash0: serial-flash@0 { + compatible = "serial-flash"; + }; + + sysclk: system-clock { + compatible = "fixed-clock"; + clock-frequency = <32000000>; + #clock-cells = <0>; + }; + + 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 = <&sysclk>; + status = "disabled"; + }; + + uart1: uart@40100000 { + compatible = "ti,mspm0-uart"; + reg = <0x40100000 0x2000>; + interrupts = <13 0>; + current-speed = <115200>; + clocks = <&sysclk>; + status = "disabled"; + }; + + uart2: uart@40102000 { + compatible = "ti,mspm0-uart"; + reg = <0x40102000 0x2000>; + interrupts = <14 0>; + current-speed = <115200>; + clocks = <&sysclk>; + status = "disabled"; + }; + + spi0: spi@40468000 { + compatible = "ti,mspm0-spi"; + clocks = <&sysclk>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40468000 0x2000>; + interrupts = <9 0>; + status = "disabled"; + }; + + spi1: spi@4046a000 { + compatible = "ti,mspm0-spi"; + clocks = <&sysclk>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x4046a000 0x2000>; + interrupts = <10 0>; + status = "disabled"; + }; + + }; +}; + +&nvic { + arm,num-irq-priority-bits = <2>; +}; 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/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/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 diff --git a/dts/bindings/pinctrl/ti,mspm0-pinctrl.yaml b/dts/bindings/pinctrl/ti,mspm0-pinctrl.yaml new file mode 100644 index 0000000000000..cdb63850d5c70 --- /dev/null +++ b/dts/bindings/pinctrl/ti,mspm0-pinctrl.yaml @@ -0,0 +1,120 @@ +# 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. + - drive-open-drain: Output driver is open-source. + - drive-strength: Maximum current that can be sourced from the pin. + - input-enable: enable input. + - ti,invert-enable: enable logical inversion of a digital input or output + - ti,hysteresis-enable: 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. + 6: max 6 mA (SoC default) + 20: max 20 mA on high-drive capable IOs only (HDIO). + + ti,invert-enable: + type: boolean + description: | + Enables inversion of the input or output using the internal + inversion capability of the GPIO + + ti,hysteresis-enable: + type: boolean + description: | + Enables the hysteresis control for access to CMOS logic + (on open-drain capable pins) 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 diff --git a/dts/bindings/spi/ti,mspm0-spi.yaml b/dts/bindings/spi/ti,mspm0-spi.yaml new file mode 100644 index 0000000000000..aad0b1afe0b26 --- /dev/null +++ b/dts/bindings/spi/ti,mspm0-spi.yaml @@ -0,0 +1,18 @@ +# Copyright (C) 2024 Bang & Olufsen A/S, Denmark +# SPDX-License-Identifier: Apache-2.0 + +description: TI MSPM0 SPI controller + +compatible: "ti,mspm0-spi" + +include: [spi-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true 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..052ec7e0b4cec --- /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 diff --git a/modules/Kconfig b/modules/Kconfig index 94a3ccdf590a4..14fe21b26f72e 100644 --- a/modules/Kconfig +++ b/modules/Kconfig @@ -30,6 +30,7 @@ source "modules/Kconfig.picolibc" source "modules/Kconfig.nxp_s32" source "modules/Kconfig.silabs" source "modules/Kconfig.simplelink" +source "modules/Kconfig.mspm0" source "modules/Kconfig.sof" source "modules/Kconfig.stm32" source "modules/Kconfig.syst" 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..226f3bd626f61 --- /dev/null +++ b/soc/ti/mspm0/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +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..b816b16c38efa --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_SOC_MSPM0G350X) + zephyr_compile_definitions(-D__MSPM0G3507__) +endif() +zephyr_sources(soc.c) +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig new file mode 100644 index 0000000000000..9199f993b113e --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig @@ -0,0 +1,16 @@ +# 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_BIN + select BUILD_OUTPUT_HEX + select HAS_MSPM0_SDK + help + Enable support for TI MSPM0GXXXX. diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig new file mode 100644 index 0000000000000..1828440d8c0b7 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig @@ -0,0 +1,10 @@ +# TI MSPM0G3XXX + +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_MSPM0G1X0X_G3X0X + +rsource "Kconfig.defconfig.mspm0g*" + +endif # SOC_SERIES_MSPM0G1X0X_G3X0X diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig.mspm0g350x b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig.mspm0g350x new file mode 100644 index 0000000000000..2730885e0b22c --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.defconfig.mspm0g350x @@ -0,0 +1,17 @@ +# TI MSPM0G3507 SoC + +# Copyright (c) 2024 Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MSPM0G350X + +config SOC + default "mspm0g350X" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 32000000 + +config NUM_IRQS + default 32 + +endif # SOC_MSPM0G350X diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.soc b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.soc new file mode 100644 index 0000000000000..5d9ec199ea459 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/Kconfig.soc @@ -0,0 +1,33 @@ +# 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_MSPM0G350X + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G310X + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G150X + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_MSPM0G110X + bool + select SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC_SERIES + default "mspm0g1x0x_g3x0x" if SOC_SERIES_MSPM0G1X0X_G3X0X + +config SOC + default "mspm0g350x" if SOC_MSPM0G350X + default "mspm0g150x" if SOC_MSPM0G150X + default "mspm0g310x" if SOC_MSPM0G310X + default "mspm0g110x" if SOC_MSPM0G110X diff --git a/soc/ti/mspm0/mspm0g1x0x_g3x0x/linker.ld b/soc/ti/mspm0/mspm0g1x0x_g3x0x/linker.ld new file mode 100644 index 0000000000000..812d6f503317d --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/linker.ld @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * SPDX-License-Identifier: Apache-2.0 + * linker.ld - Linker command/script file + */ + +#include 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..e3e97f00103fa --- /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 __ZEPHYR_SOC_ARM_TI_MSPM0_M0G_PINCTRL_SOC_H__ +#define __ZEPHYR_SOC_ARM_TI_MSPM0_M0G_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_enable) << MSP_GPIO_HYSTERESIS_ENABLED) | \ + (DT_PROP(node_id, ti_invert_enable) << 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 /* __ZEPHYR_SOC_ARM_TI_MSPM0_M0G_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..f3b56a1bb2049 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static int ti_mspm0g_init(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); + + DL_SYSCTL_setSYSOSCFreq(DL_SYSCTL_SYSOSC_FREQ_BASE); + + /* Low Power Mode is configured to be SLEEP0 */ + DL_SYSCTL_setBORThreshold(DL_SYSCTL_BOR_THRESHOLD_LEVEL_0); + + return 0; +} + +SYS_INIT(ti_mspm0g_init, PRE_KERNEL_1, 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..cdc5b53af44d9 --- /dev/null +++ b/soc/ti/mspm0/mspm0g1x0x_g3x0x/soc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef soc_h +#define soc_h + +#define SYSCONFIG_WEAK __attribute__((weak)) + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* clang-format off */ + +#define POWER_STARTUP_DELAY (16) + +#define SOC_MSPM0_CPUCLK_FREQ_HZ MHZ(32) + +/* clang-format on */ + +void SYSCFG_DL_init(void); +void SYSCFG_DL_initPower(void); +void SYSCFG_DL_SYSCTL_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* soc_h */ diff --git a/soc/ti/mspm0/soc.yml b/soc/ti/mspm0/soc.yml new file mode 100644 index 0000000000000..d828daaeff87f --- /dev/null +++ b/soc/ti/mspm0/soc.yml @@ -0,0 +1,9 @@ +family: +- name: ti_mspm0 + series: + - name: mspm0gxxxx + socs: + - name: mspm0g350x + - name: mspm0g310x + - name: mspm0g150x + - name: mspm0g110x diff --git a/temp.stylefix b/temp.stylefix new file mode 100644 index 0000000000000..461a8e1aaf395 --- /dev/null +++ b/temp.stylefix @@ -0,0 +1,83 @@ +----------------------------------------------------------------------------- +Commit cdb5a294600a ("boards: deprecated: Update PHYTEC phyBOARD-Lyra AM62x") +----------------------------------------------------------------------------- +cdb5a294600aa5cbd088677832f18883d6e1d36d total: 0 errors, 0 warnings, 16 lines checked + +Commit cdb5a294600a ("boards: deprecated: Update PHYTEC phyBOARD-Lyra AM62x") has no obvious style problems and is ready for submission. +----------------------------------------------------------------------------- +Commit 91fdf590d23a ("MAINTAINERS: Add boards/phytec/phyboard_lyra to TI K3") +----------------------------------------------------------------------------- +91fdf590d23a6d342ce47cdf85fea7b8bce2572d total: 0 errors, 0 warnings, 8 lines checked + +Commit 91fdf590d23a ("MAINTAINERS: Add boards/phytec/phyboard_lyra to TI K3") has no obvious style problems and is ready for submission. +-------------------------------------------------------------------------------- +Commit b4eac67b8b2e ("Bluetooth: BAP: Shell: Add support for decoding LC3 data") +-------------------------------------------------------------------------------- +b4eac67b8b2eee5381d58671fddb8ae9bf2a3989 total: 0 errors, 0 warnings, 612 lines checked + +Commit b4eac67b8b2e ("Bluetooth: BAP: Shell: Add support for decoding LC3 data") has no obvious style problems and is ready for submission. +-------------------------------------------------------------------------------- +Commit 189541396c31 ("west: west.yml pointed to in-flight PR for MSPM0 support") +-------------------------------------------------------------------------------- +189541396c3105977a5fc1caa670f72a34205833 total: 0 errors, 0 warnings, 8 lines checked + +Commit 189541396c31 ("west: west.yml pointed to in-flight PR for MSPM0 support") has no obvious style problems and is ready for submission. +-------------------------------------------------- +Commit a957c92a5fba ("soc: added TI MSPM0 family") +-------------------------------------------------- +a957c92a5fba223a8c26586e346d09997fb292ea total: 0 errors, 0 warnings, 264 lines checked + +Commit a957c92a5fba ("soc: added TI MSPM0 family") has no obvious style problems and is ready for submission. +--------------------------------------------------------------- +Commit b1ee543f2e19 ("dts: add MSPM0 family to the devicetree") +--------------------------------------------------------------- +b1ee543f2e1949763e6b1966dba027a42f5867dc total: 0 errors, 0 warnings, 110 lines checked + +Commit b1ee543f2e19 ("dts: add MSPM0 family to the devicetree") has no obvious style problems and is ready for submission. +--------------------------------------------------------------- +Commit b1e6204db9b6 ("drivers: added pinctrl driver for MSPM0") +--------------------------------------------------------------- +b1e6204db9b6db0096930813346a6304cf612332 total: 0 errors, 0 warnings, 209 lines checked + +Commit b1e6204db9b6 ("drivers: added pinctrl driver for MSPM0") has no obvious style problems and is ready for submission. +------------------------------------------------------------------- +Commit 442d526cfe3b ("drivers: added gpio driver for MSPM0 family") +------------------------------------------------------------------- +442d526cfe3b699ce74d6efbea51c3991a12ae90 total: 0 errors, 0 warnings, 398 lines checked + +Commit 442d526cfe3b ("drivers: added gpio driver for MSPM0 family") has no obvious style problems and is ready for submission. +-------------------------------------------------------------- +Commit 2199c34e593b ("drivers: added serial driver for MSPM0") +-------------------------------------------------------------- +2199c34e593b308cb0fdf29ac1ea814267241127:330: ERROR:CODE_INDENT: code indent should use tabs where possible +#330: FILE: drivers/serial/uart_mspm0.c:263: ++ ^IMSP_UART_IRQ_REGISTER(index)^I\$ + +2199c34e593b308cb0fdf29ac1ea814267241127:330: WARNING:SPACE_BEFORE_TAB: please, no space before tabs +#330: FILE: drivers/serial/uart_mspm0.c:263: ++ ^IMSP_UART_IRQ_REGISTER(index)^I\$ + +2199c34e593b308cb0fdf29ac1ea814267241127:330: WARNING:LEADING_SPACE: please, no spaces at the start of a line +#330: FILE: drivers/serial/uart_mspm0.c:263: ++ ^IMSP_UART_IRQ_REGISTER(index)^I\$ + +2199c34e593b308cb0fdf29ac1ea814267241127 total: 1 errors, 2 warnings, 339 lines checked + +NOTE: For some of the reported defects, checkpatch may be able to + mechanically convert to the typical style using --fix or --fix-inplace. + +NOTE: Whitespace errors detected. + You may wish to use scripts/cleanpatch or scripts/cleanfile + +Commit 2199c34e593b ("drivers: added serial driver for MSPM0") has style problems, please review. +------------------------------------------------- +Commit 5c43afa78d9e ("boards: add lp_mspm0g3507") +------------------------------------------------- +5c43afa78d9e6e6086981ef887b656fb1daa2275 total: 0 errors, 0 warnings, 262 lines checked + +Commit 5c43afa78d9e ("boards: add lp_mspm0g3507") has no obvious style problems and is ready for submission. + +NOTE: Ignored message types: AVOID_EXTERNS BRACES C99_COMMENT_TOLERANCE COMPLEX_MACRO CONFIG_EXPERIMENTAL CONST_STRUCT DATE_TIME DT_SCHEMA_BINDING_PATCH DT_SPLIT_BINDING_PATCH ENOSYS EXPORT_SYMBOL FILE_PATH_CHANGES IS_ENABLED_CONFIG MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE NETWORKING_BLOCK_COMMENT_STYLE PREFER_KERNEL_TYPES PREFER_SECTION PRINTK_WITHOUT_KERN_LEVEL REPEATED_WORD SPDX_LICENSE_TAG SPLIT_STRING TRAILING_SEMICOLON UNDOCUMENTED_DT_STRING VOLATILE + +NOTE: If any of the errors are false positives, please report + them to the maintainers. diff --git a/west.yml b/west.yml index 4eee37fa81ac5..304b617a2c3e3 100644 --- a/west.yml +++ b/west.yml @@ -239,7 +239,7 @@ manifest: groups: - hal - name: hal_ti - revision: b85f86e51fc4d47c4c383d320d64d52d4d371ae4 + revision: pull/51/head path: modules/hal/ti groups: - hal