From 589e7233cd96d37dcffdd4baaaba04aca4c0e1db Mon Sep 17 00:00:00 2001 From: Girinandha Manivelpandiyan Date: Wed, 13 Aug 2025 17:46:08 +0530 Subject: [PATCH 1/3] dts: bindings: regulator: Add bindings for TI MSPM0 VREF module Add bindings for TI MSPM0 VREF module. Signed-off-by: Girinandha Manivelpandiyan --- dts/bindings/regulator/ti,mspm0-vref.yaml | 53 +++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 dts/bindings/regulator/ti,mspm0-vref.yaml diff --git a/dts/bindings/regulator/ti,mspm0-vref.yaml b/dts/bindings/regulator/ti,mspm0-vref.yaml new file mode 100644 index 0000000000000..a41aa1a75e45e --- /dev/null +++ b/dts/bindings/regulator/ti,mspm0-vref.yaml @@ -0,0 +1,53 @@ +# Copyright 2025 Linumiz GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +description: Texas Instruments MSPM0 Voltage Reference (VREF) Regulator + +compatible: "ti,mspm0-vref" + +include: + - name: regulator.yaml + - name: base.yaml + - name: pinctrl-device.yaml + +properties: + reg: + required: true + clocks: + required: true + regulator-uv: + type: int + required: true + enum: + - 1400000 + - 2500000 + description: | + Minimum supported output, usually 1400000 (1.4V) + Maximum supported output, usually 2500000 (2.5V) + ti,sample-hold-enable: + type: boolean + description: Enable sample & hold mode + ti,sample-cycles: + type: int + description: Number of sample cycles for sample & hold mode + default: 8 + pinctrl-0: + required: true + description: | + Gpio pin specification for VREF input/output pin ( PA23 ) + pinctrl-names: + required: true + ti,hold-cycles: + type: int + description: Number of hold cycles for sample & hold mode + default: 64 + ti,clk-div: + type: int + default: 1 + enum: + - 1 + - 2 + - 4 + - 6 + - 8 From 996a03bb20e9c246638c76e45ec75cad113454b2 Mon Sep 17 00:00:00 2001 From: Girinandha Manivelpandiyan Date: Wed, 13 Aug 2025 17:48:37 +0530 Subject: [PATCH 2/3] drivers: regulator: mspm0: Add supoort for TI MSPM0 VREF module TI MSPM0 VREF module is used by analog peripherals for reference voltage Add support for TI MSPM0 VREF module. Signed-off-by: Girinandha Manivelpandiyan --- drivers/regulator/CMakeLists.txt | 1 + drivers/regulator/Kconfig | 1 + drivers/regulator/Kconfig.mspm0 | 18 ++ drivers/regulator/regulator_mspm0_vref.c | 266 ++++++++++++++++++ .../zephyr/dt-bindings/regulator/mspm0_vref.h | 27 ++ modules/Kconfig.mspm0 | 3 + 6 files changed, 316 insertions(+) create mode 100644 drivers/regulator/Kconfig.mspm0 create mode 100644 drivers/regulator/regulator_mspm0_vref.c create mode 100644 include/zephyr/dt-bindings/regulator/mspm0_vref.h diff --git a/drivers/regulator/CMakeLists.txt b/drivers/regulator/CMakeLists.txt index 283fd976de735..18bbeca4bf463 100644 --- a/drivers/regulator/CMakeLists.txt +++ b/drivers/regulator/CMakeLists.txt @@ -16,6 +16,7 @@ zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM1100 regulator_npm1100.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM13XX regulator_npm13xx.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM2100 regulator_npm2100.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM6001 regulator_npm6001.c) +zephyr_library_sources_ifdef(CONFIG_REGULATOR_MSPM0_VREF regulator_mspm0_vref.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_PCA9420 regulator_pca9420.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_PF1550 regulator_pf1550.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_SHELL regulator_shell.c) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index ca2bf41ae895f..fc771395c1d73 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -34,6 +34,7 @@ source "drivers/regulator/Kconfig.fake" source "drivers/regulator/Kconfig.fixed" source "drivers/regulator/Kconfig.gpio" source "drivers/regulator/Kconfig.max20335" +source "drivers/regulator/Kconfig.mspm0" source "drivers/regulator/Kconfig.npm1100" source "drivers/regulator/Kconfig.npm13xx" source "drivers/regulator/Kconfig.npm2100" diff --git a/drivers/regulator/Kconfig.mspm0 b/drivers/regulator/Kconfig.mspm0 new file mode 100644 index 0000000000000..a26fc70a692e1 --- /dev/null +++ b/drivers/regulator/Kconfig.mspm0 @@ -0,0 +1,18 @@ +# Copyright (c) 2025, Linumiz GmbH +# SPDX-License-Identifier: Apache-2.0 + +config REGULATOR_MSPM0_VREF + bool "TI MSPM0 VREF peripheral driver" + depends on REGULATOR + depends on DT_HAS_TI_MSPM0_VREF_ENABLED + default y + select USE_MSPM0_DL_VREF + help + Enable the MSPM0 VREF driver + +config REGULATOR_MSPM0_VREF_INIT_PRIORITY + int "MSPM0 VREF peripheral driver init priority" + default 45 + depends on REGULATOR_MSPM0_VREF + help + Init priority for the MSPM0 VREF peripheral. diff --git a/drivers/regulator/regulator_mspm0_vref.c b/drivers/regulator/regulator_mspm0_vref.c new file mode 100644 index 0000000000000..34c4b8b48656c --- /dev/null +++ b/drivers/regulator/regulator_mspm0_vref.c @@ -0,0 +1,266 @@ +/* + * Copyright 2025 Linumiz GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_mspm0_vref + +#include +#include +#include +#include +#include +#include + +/* TI Driverlib includes */ +#include + +LOG_MODULE_REGISTER(vref, CONFIG_LOG_DEFAULT_LEVEL); + +#define VREF_1_4V 1400000 +#define VREF_2_5V 2500000 + +struct regulator_mspm0_vref_data { + struct regulator_common_data common; + DL_VREF_Config vref_cfg; +}; + +struct regulator_mspm0_vref_config { + struct regulator_common_config common; + const struct pinctrl_dev_config *vref_pin; + DL_VREF_ClockConfig vref_clock_cfg; + VREF_Regs *regs; +}; + +static int regulator_mspm0_vref_enable(const struct device *dev) +{ + const struct regulator_mspm0_vref_config *config = dev->config; + + DL_VREF_enableInternalRef(config->regs); + + return 0; +} + +static int regulator_mspm0_vref_disable(const struct device *dev) +{ + const struct regulator_mspm0_vref_config *config = dev->config; + + DL_VREF_disableInternalRef(config->regs); + + return 0; +} + +static int regulator_mspm0_vref_get_voltage(const struct device *dev, int32_t *volt_uv) +{ + const struct regulator_mspm0_vref_config *config = dev->config; + struct regulator_common_data *common = dev->data; + + if (volt_uv == NULL) { + return -EINVAL; + } + +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT + k_mutex_lock(&common->lock, K_FOREVER); +#endif + + if (config->regs->CTL0 & VREF_CTL0_BUFCONFIG_MASK) { + *volt_uv = VREF_1_4V; + } else { + *volt_uv = VREF_2_5V; + } + +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT + k_mutex_unlock(&common->lock); +#endif + + return 0; +} + +static int regulator_mspm0_vref_set_voltage(const struct device *dev, int32_t min_uv, + int32_t max_uv) +{ + const struct regulator_mspm0_vref_config *config = dev->config; + struct regulator_mspm0_vref_data *data = dev->data; + struct regulator_common_data *common = dev->data; + int32_t volt_set, volt_get; + int ret = 0; + + if (min_uv <= VREF_2_5V && max_uv >= VREF_2_5V) { + volt_set = VREF_2_5V; + } else if (min_uv <= VREF_1_4V && max_uv >= VREF_1_4V) { + volt_set = VREF_1_4V; + } else { + LOG_ERR("Invalid voltage range !!"); + return -EINVAL; + } + +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT + k_mutex_lock(&common->lock, K_FOREVER); +#endif + + if (common->refcnt != 0) { + volt_get = (config->regs->CTL0 & VREF_CTL0_BUFCONFIG_MASK) ? VREF_1_4V : VREF_2_5V; + + if (volt_set != volt_get) { + ret = -EBUSY; + goto out; + } + } else { + if (volt_set == VREF_2_5V) { + data->vref_cfg.bufConfig = DL_VREF_BUFCONFIG_OUTPUT_2_5V; + } else { + data->vref_cfg.bufConfig = DL_VREF_BUFCONFIG_OUTPUT_1_4V; + } + DL_VREF_configReference(config->regs, &data->vref_cfg); + } +out: + +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT + k_mutex_unlock(&common->lock); +#endif + + return ret; +} + +static int regulator_mspm0_vref_get_mode(const struct device *dev, regulator_mode_t *mode) +{ + const struct regulator_mspm0_vref_config *config = dev->config; + struct regulator_common_data *common = dev->data; + + if (mode == NULL) { + return -EINVAL; + } + +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT + k_mutex_lock(&common->lock, K_FOREVER); +#endif + + if (config->regs->CTL0 & VREF_CTL0_SHMODE_MASK) { + *mode = MSPM0_VREF_MODE_SHMODE; + } else { + *mode = MSPM0_VREF_MODE_NORMAL; + } + +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT + k_mutex_unlock(&common->lock); +#endif + + return 0; +} + +static int regulator_mspm0_vref_set_mode(const struct device *dev, regulator_mode_t mode) +{ + const struct regulator_mspm0_vref_config *config = dev->config; + struct regulator_mspm0_vref_data *data = dev->data; + struct regulator_common_data *common = dev->data; + regulator_mode_t mode_get; + int ret = 0; + +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT + k_mutex_lock(&common->lock, K_FOREVER); +#endif + + if (common->refcnt != 0) { + mode_get = (config->regs->CTL0 & VREF_CTL0_SHMODE_MASK) ? MSPM0_VREF_MODE_SHMODE + : MSPM0_VREF_MODE_NORMAL; + + if (mode_get != mode) { + ret = -EBUSY; + goto out; + } + } else { + switch (mode) { + case MSPM0_VREF_MODE_SHMODE: + data->vref_cfg.shModeEnable = DL_VREF_SHMODE_ENABLE; + break; + case MSPM0_VREF_MODE_NORMAL: + data->vref_cfg.shModeEnable = DL_VREF_SHMODE_DISABLE; + break; + default: + ret = -EINVAL; + goto out; + } + DL_VREF_configReference(config->regs, &data->vref_cfg); + } +out: + +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT + k_mutex_unlock(&common->lock); +#endif + + return ret; +} + +static int regulator_mspm0_vref_init(const struct device *dev) +{ + const struct regulator_mspm0_vref_config *config = dev->config; + struct regulator_mspm0_vref_data *data = dev->data; + int ret; + + regulator_common_data_init(dev); + + ret = pinctrl_apply_state(config->vref_pin, PINCTRL_STATE_DEFAULT); + if (ret) { + LOG_ERR("Pinctrl apply state Failed"); + return ret; + } + + /* Enable power */ + DL_VREF_enablePower(config->regs); + DL_VREF_configReference(config->regs, &data->vref_cfg); + DL_VREF_setClockConfig(config->regs, &config->vref_clock_cfg); + + ret = regulator_common_init(dev, false); + if (ret) { + LOG_ERR("Regulator common init Failed"); + return ret; + } + + return 0; +} + +static DEVICE_API(regulator, mspm0_vref_api) = { + .enable = regulator_mspm0_vref_enable, + .disable = regulator_mspm0_vref_disable, + .set_voltage = regulator_mspm0_vref_set_voltage, + .get_voltage = regulator_mspm0_vref_get_voltage, + .set_mode = regulator_mspm0_vref_set_mode, + .get_mode = regulator_mspm0_vref_get_mode, +}; + +#define VREF_CLOCK_DIVIDE_RATIO(n) CONCAT(DL_VREF_CLOCK_DIVIDE_, DT_INST_PROP(n, ti_clk_div)) + +#define REGULATOR_MSPM0_VREF_DEFINE(n) \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static struct regulator_mspm0_vref_data data_##n = { \ + .vref_cfg = { \ + .vrefEnable = DL_VREF_ENABLE_DISABLE, \ + .bufConfig = (DT_INST_PROP(n, regulator_uv) == VREF_1_4V \ + ? DL_VREF_BUFCONFIG_OUTPUT_1_4V \ + : DL_VREF_BUFCONFIG_OUTPUT_2_5V), \ + .shModeEnable = DT_INST_PROP(n, ti_sample_hold_enable) \ + ? DL_VREF_SHMODE_ENABLE : DL_VREF_SHMODE_DISABLE, \ + .shCycleCount = DT_INST_PROP(n, ti_sample_cycles), \ + .holdCycleCount = DT_INST_PROP(n, ti_hold_cycles), \ + }, \ + }; \ + \ + static const struct regulator_mspm0_vref_config config_##n = { \ + .common = REGULATOR_DT_INST_COMMON_CONFIG_INIT(n), \ + .vref_pin = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .regs = (VREF_Regs *)DT_INST_REG_ADDR(n), \ + .vref_clock_cfg = { \ + .clockSel = \ + MSPM0_CLOCK_PERIPH_REG_MASK(DT_INST_CLOCKS_CELL(n, clk)), \ + .divideRatio = VREF_CLOCK_DIVIDE_RATIO(n), \ + }, \ + }; \ + \ +DEVICE_DT_INST_DEFINE(n, regulator_mspm0_vref_init, NULL, &data_##n, \ + &config_##n, POST_KERNEL, \ + CONFIG_REGULATOR_MSPM0_VREF_INIT_PRIORITY, &mspm0_vref_api); + +DT_INST_FOREACH_STATUS_OKAY(REGULATOR_MSPM0_VREF_DEFINE) diff --git a/include/zephyr/dt-bindings/regulator/mspm0_vref.h b/include/zephyr/dt-bindings/regulator/mspm0_vref.h new file mode 100644 index 0000000000000..71128d5733b10 --- /dev/null +++ b/include/zephyr/dt-bindings/regulator/mspm0_vref.h @@ -0,0 +1,27 @@ +/* + * Copyright 2025 Linumiz GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_MSPM0_VREF_H +#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_MSPM0_VREF_H + +/** + * @defgroup regulator_mspm0_vref Devicetree helpers + * @ingroup regulator_interface + * @{ + */ + +/** + * @name MSPM0 VREF Regulator API Modes + * @{ + */ +#define MSPM0_VREF_MODE_NORMAL 0 +#define MSPM0_VREF_MODE_SHMODE 1 + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NXP_VREF_H */ diff --git a/modules/Kconfig.mspm0 b/modules/Kconfig.mspm0 index 7125ff4919672..f133acf74f2c0 100644 --- a/modules/Kconfig.mspm0 +++ b/modules/Kconfig.mspm0 @@ -14,3 +14,6 @@ config USE_MSPM0_DL_UART config USE_MSPM0_DL_TIMER bool + +config USE_MSPM0_DL_VREF + bool From 3a915e6fa8ec2b0494c663730e10f61701cef72b Mon Sep 17 00:00:00 2001 From: Girinandha Manivelpandiyan Date: Wed, 13 Aug 2025 17:45:01 +0530 Subject: [PATCH 3/3] dts: arm: ti: mspm0: Add VREF node for TI MSPM0 Add dts support for VREF Node for internal reference voltage. Signed-off-by: Girinandha Manivelpandiyan --- dts/arm/ti/mspm0/mspm0.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/dts/arm/ti/mspm0/mspm0.dtsi b/dts/arm/ti/mspm0/mspm0.dtsi index dd7f782050189..f8b9a4a034029 100644 --- a/dts/arm/ti/mspm0/mspm0.dtsi +++ b/dts/arm/ti/mspm0/mspm0.dtsi @@ -107,6 +107,20 @@ compatible = "serial-flash"; }; + vref0: vref@40030000 { + compatible = "ti,mspm0-vref"; + reg = <0x40030000 0x2000>; + clocks = <&ckm MSPM0_CLOCK_BUSCLK>; + ti,clk-div = < 0x1 >; + off-on-delay-us = <200>; + regulator-uv = <1400000>; + ti,sample-cycles = <10>; + ti,hold-cycles = <40>; + pinctrl-0 = <&analog_pa23>; + pinctrl-names = "default"; + status="disabled"; + }; + pinctrl: pin-controller@400a0000 { compatible = "ti,mspm0-pinctrl"; #address-cells = <1>;