diff --git a/boards/ti/lp_mspm33c321a/lp_mspm33c321a.dts b/boards/ti/lp_mspm33c321a/lp_mspm33c321a.dts index 2f2d00dcef24..9c36737a9499 100644 --- a/boards/ti/lp_mspm33c321a/lp_mspm33c321a.dts +++ b/boards/ti/lp_mspm33c321a/lp_mspm33c321a.dts @@ -53,3 +53,9 @@ clock-frequency = <32768>; ti,xtal-startup-delay-us = <640000>; }; + +&vref0 { + status = "okay"; + pinctrl-0 = <&analog_pa23>; + pinctrl-names = "default"; +}; diff --git a/drivers/regulator/Kconfig.mspm0 b/drivers/regulator/Kconfig.mspm0 index be97c7624bb4..51216a15a8e3 100644 --- a/drivers/regulator/Kconfig.mspm0 +++ b/drivers/regulator/Kconfig.mspm0 @@ -5,8 +5,8 @@ config REGULATOR_MSPM0_VREF bool "TI MSPM0 VREF peripheral driver" depends on REGULATOR depends on DT_HAS_TI_MSPM0_VREF_ENABLED + select PINCTRL default y - select USE_MSPM0_DL_VREF help Enable the MSPM0 VREF driver diff --git a/drivers/regulator/regulator_mspm0_vref.c b/drivers/regulator/regulator_mspm0_vref.c index 4e084066b3a1..5018d870de02 100644 --- a/drivers/regulator/regulator_mspm0_vref.c +++ b/drivers/regulator/regulator_mspm0_vref.c @@ -6,15 +6,12 @@ #define DT_DRV_COMPAT ti_mspm0_vref -#include #include #include #include #include #include - -/* TI Driverlib includes */ -#include +#include LOG_MODULE_REGISTER(vref, CONFIG_LOG_DEFAULT_LEVEL); @@ -22,28 +19,127 @@ LOG_MODULE_REGISTER(vref, CONFIG_LOG_DEFAULT_LEVEL); #define VREF_1_4V 1400000 #define VREF_2_5V 2500000 +struct regulator_mspm0_vref_gprcm { + volatile uint32_t pwren; /**< Power Enable register, offset: 0x00 */ + volatile uint32_t rstctl; /**< Reset Control register, offset: 0x04 */ + uint8_t reserved_1[0xC]; /**< Reserved, offset: 0x08 - 0x14 */ + volatile const uint32_t stat; /**< Status register, offset: 0x14 */ +}; + +struct regulator_mspm0_vref_regs { + uint8_t reserved_1[0x800]; /**< Reserved, offset: 0x000 - 0x800 */ + volatile struct regulator_mspm0_vref_gprcm gprcm; /**< Power/reset control, offset: 0x800 */ + uint8_t reserved_2[0x7E8]; /**< Reserved, offset: 0x818 - 0x1000 */ + volatile uint32_t clkdiv; /**< Clock Divider register, offset: 0x1000 */ + uint8_t reserved_3[0x4]; /**< Reserved, offset: 0x1004 - 0x1008 */ + volatile uint32_t clksel; /**< Clock Selection register, offset: 0x1008 */ + uint8_t reserved_4[0xF4]; /**< Reserved, offset: 0x100C - 0x1100 */ + volatile uint32_t ctl0; /**< Control 0 register, offset: 0x1100 */ + volatile uint32_t ctl1; /**< Control 1 register, offset: 0x1104 */ + volatile uint32_t ctl2; /**< Control 2 register, offset: 0x1108 */ + volatile uint32_t v2ien; /**< V2I Enable register, offset: 0x110C */ +}; + +/* pwren bits */ +#define VREF_PWREN_ENABLE BIT(0) +#define VREF_PWREN_KEY GENMASK(31, 24) +#define VREF_PWREN_KEY_UNLOCK 0x26U + +/* rstctl bits */ +#define VREF_RSTCTL_RESETASSERT BIT(0) +#define VREF_RSTCTL_RESETSTKYCLR BIT(1) +#define VREF_RSTCTL_KEY GENMASK(31, 24) +#define VREF_RSTCTL_KEY_UNLOCK 0xB1U + +/* stat bits */ +#define VREF_STAT_RESETSTKY BIT(16) + +/* clkdiv bits */ +#define VREF_CLKDIV_RATIO GENMASK(2, 0) +#define VREF_CLKDIV_RATIO_VAL(x) ((x) - 1) + +/* clksel bits */ +#define VREF_CLKSEL_LFCLK_SEL BIT(1) +#define VREF_CLKSEL_MFCLK_SEL BIT(2) +#define VREF_CLKSEL_BUSCLK_SEL BIT(3) + +/* ctl0 bits */ +#define VREF_CTL0_ENABLE BIT(0) +#define VREF_CTL0_COMP_VREF_ENABLE BIT(1) +#define VREF_CTL0_BUFCONFIG BIT(7) +#define VREF_CTL0_BUFCONFIG_2_5V 0U +#define VREF_CTL0_BUFCONFIG_1_4V VREF_CTL0_BUFCONFIG +#define VREF_CTL0_SHMODE BIT(8) + +/* ctl1 bits */ +#define VREF_CTL1_READY BIT(0) + +/* ctl2 bits */ +#define VREF_CTL2_SHCYCLE GENMASK(15, 0) +#define VREF_CTL2_HCYCLE GENMASK(31, 16) + +/* v2ien bits */ +#define VREF_V2IEN_V2I_EN BIT(0) + struct regulator_mspm0_vref_data { struct regulator_common_data common; - DL_VREF_Config vref_cfg; + uint32_t regulator_uv; + uint16_t sample_cycle_count; + bool v2i_enable; + uint16_t hold_cycle_count; + bool sh_mode_enable; }; 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; + struct regulator_mspm0_vref_regs *regs; + uint32_t clock_sel; + uint32_t clock_div; }; +static void regulator_mspm0_vref_configure(const struct regulator_mspm0_vref_config *config, + struct regulator_mspm0_vref_data *data) +{ + uint32_t buf_config = (data->regulator_uv == VREF_1_4V) ? VREF_CTL0_BUFCONFIG_1_4V + : VREF_CTL0_BUFCONFIG_2_5V; + + config->regs->ctl0 = buf_config | (data->sh_mode_enable ? VREF_CTL0_SHMODE : 0); + config->regs->ctl2 = + FIELD_PREP(VREF_CTL2_SHCYCLE, data->sample_cycle_count + data->hold_cycle_count) | + FIELD_PREP(VREF_CTL2_HCYCLE, data->hold_cycle_count); + config->regs->v2ien = data->v2i_enable ? VREF_V2IEN_V2I_EN : 0; +} + +static regulator_mode_t +regulator_mspm0_vref_mode_from_regs(const struct regulator_mspm0_vref_config *config) +{ + regulator_mode_t mode = MSPM0_VREF_MODE_NORMAL; + + if (config->regs->ctl0 & VREF_CTL0_SHMODE) { + mode |= MSPM0_VREF_MODE_SHMODE; + } + if (config->regs->v2ien & VREF_V2IEN_V2I_EN) { + mode |= MSPM0_VREF_MODE_V2I; + } + + return mode; +} + static int regulator_mspm0_vref_enable(const struct device *dev) { - DL_VREF_enableInternalRef(((const struct regulator_mspm0_vref_config *)dev->config)->regs); + const struct regulator_mspm0_vref_config *config = dev->config; + + config->regs->ctl0 |= VREF_CTL0_ENABLE; return 0; } static int regulator_mspm0_vref_disable(const struct device *dev) { - DL_VREF_disableInternalRef(((const struct regulator_mspm0_vref_config *)dev->config)->regs); + const struct regulator_mspm0_vref_config *config = dev->config; + + config->regs->ctl0 &= ~VREF_CTL0_ENABLE; return 0; } @@ -51,7 +147,9 @@ static int regulator_mspm0_vref_disable(const struct device *dev) static int regulator_mspm0_vref_get_voltage(const struct device *dev, int32_t *volt_uv) { const struct regulator_mspm0_vref_config *config = dev->config; +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT struct regulator_mspm0_vref_data *data = dev->data; +#endif if (volt_uv == NULL) { return -EINVAL; @@ -61,7 +159,7 @@ static int regulator_mspm0_vref_get_voltage(const struct device *dev, int32_t *v k_mutex_lock(&data->common.lock, K_FOREVER); #endif - if (config->regs->CTL0 & VREF_CTL0_BUFCONFIG_MASK) { + if (config->regs->ctl0 & VREF_CTL0_BUFCONFIG) { *volt_uv = VREF_1_4V; } else { *volt_uv = VREF_2_5V; @@ -96,18 +194,14 @@ static int regulator_mspm0_vref_set_voltage(const struct device *dev, int32_t mi #endif if (data->common.refcnt != 0) { - volt_get = (config->regs->CTL0 & VREF_CTL0_BUFCONFIG_MASK) ? VREF_1_4V : VREF_2_5V; + volt_get = (config->regs->ctl0 & VREF_CTL0_BUFCONFIG) ? 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); + data->regulator_uv = volt_set; + regulator_mspm0_vref_configure(config, data); } out: @@ -121,7 +215,9 @@ static int regulator_mspm0_vref_set_voltage(const struct device *dev, int32_t mi static int regulator_mspm0_vref_get_mode(const struct device *dev, regulator_mode_t *mode) { const struct regulator_mspm0_vref_config *config = dev->config; +#ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT struct regulator_mspm0_vref_data *data = dev->data; +#endif if (mode == NULL) { return -EINVAL; @@ -131,11 +227,7 @@ static int regulator_mspm0_vref_get_mode(const struct device *dev, regulator_mod k_mutex_lock(&data->common.lock, K_FOREVER); #endif - if (config->regs->CTL0 & VREF_CTL0_SHMODE_MASK) { - *mode = MSPM0_VREF_MODE_SHMODE; - } else { - *mode = MSPM0_VREF_MODE_NORMAL; - } + *mode = regulator_mspm0_vref_mode_from_regs(config); #ifdef CONFIG_REGULATOR_THREAD_SAFE_REFCNT k_mutex_unlock(&data->common.lock); @@ -155,26 +247,21 @@ static int regulator_mspm0_vref_set_mode(const struct device *dev, regulator_mod k_mutex_lock(&data->common.lock, K_FOREVER); #endif + if (mode & ~(MSPM0_VREF_MODE_SHMODE | MSPM0_VREF_MODE_V2I)) { + ret = -ENOTSUP; + goto out; + } + if (data->common.refcnt != 0) { - mode_get = (config->regs->CTL0 & VREF_CTL0_SHMODE_MASK) ? MSPM0_VREF_MODE_SHMODE - : MSPM0_VREF_MODE_NORMAL; + mode_get = regulator_mspm0_vref_mode_from_regs(config); 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); + data->sh_mode_enable = (mode & MSPM0_VREF_MODE_SHMODE) != 0; + data->v2i_enable = (mode & MSPM0_VREF_MODE_V2I) != 0; + regulator_mspm0_vref_configure(config, data); } out: @@ -200,10 +287,13 @@ static int regulator_mspm0_vref_init(const struct device *dev) } /* Enable power */ - DL_VREF_enablePower(config->regs); - delay_cycles(CONFIG_MSPM0_PERIPH_STARTUP_DELAY); - DL_VREF_configReference(config->regs, &data->vref_cfg); - DL_VREF_setClockConfig(config->regs, &config->vref_clock_cfg); + config->regs->gprcm.pwren = + FIELD_PREP(VREF_PWREN_KEY, VREF_PWREN_KEY_UNLOCK) | VREF_PWREN_ENABLE; + msp_delay_peripheral_startup(); + regulator_mspm0_vref_configure(config, data); + config->regs->clksel = config->clock_sel; + config->regs->clkdiv = + FIELD_PREP(VREF_CLKDIV_RATIO, VREF_CLKDIV_RATIO_VAL(config->clock_div)); ret = regulator_common_init(dev, false); if (ret) { @@ -223,34 +313,28 @@ static DEVICE_API(regulator, mspm0_vref_api) = { .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), \ - }, \ + .regulator_uv = DT_INST_PROP(n, regulator_uv), \ + .sh_mode_enable = DT_INST_PROP(n, ti_sample_hold_enable), \ + .sample_cycle_count = DT_INST_PROP(n, ti_sample_cycles), \ + .v2i_enable = DT_INST_PROP(n, ti_v2i_enable), \ + .hold_cycle_count = DT_INST_PROP(n, ti_hold_cycles), \ + .regulator_uv = DT_INST_PROP(n, regulator_uv), \ + .sh_mode_enable = DT_INST_PROP(n, ti_sample_hold_enable), \ + .sample_cycle_count = DT_INST_PROP(n, ti_sample_cycles), \ + .hold_cycle_count = 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), \ - }, \ + .regs = (struct regulator_mspm0_vref_regs *)DT_INST_REG_ADDR(n), \ + .clock_sel = MSPM0_CLOCK_PERIPH_REG_MASK(DT_INST_CLOCKS_CELL(n, clk)), \ + .clock_div = DT_INST_PROP(n, ti_clk_div), \ }; \ \ DEVICE_DT_INST_DEFINE(n, regulator_mspm0_vref_init, NULL, &data_##n, \ diff --git a/dts/arm/ti/mspm0/mspm0.dtsi b/dts/arm/ti/mspm0/mspm0.dtsi index 0163c8bc7022..d845f9e1eb93 100644 --- a/dts/arm/ti/mspm0/mspm0.dtsi +++ b/dts/arm/ti/mspm0/mspm0.dtsi @@ -7,6 +7,7 @@ #include #include +#include #include / { @@ -199,6 +200,8 @@ regulator-uv = <1400000>; ti,sample-cycles = <10>; ti,hold-cycles = <40>; + regulator-allowed-modes = , + ; status = "disabled"; }; diff --git a/dts/arm/ti/mspm33c/mspm33c.dtsi b/dts/arm/ti/mspm33c/mspm33c.dtsi index 81ab8f6b9891..e71065fc6a39 100644 --- a/dts/arm/ti/mspm33c/mspm33c.dtsi +++ b/dts/arm/ti/mspm33c/mspm33c.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include / { cpus { @@ -214,6 +215,22 @@ #dma-cells = <2>; status = "disabled"; }; + + vref0: vref@400e8000 { + compatible = "ti,mspm0-vref"; + reg = <0x400e8000 0x2000>; + clocks = <&ckm MSPM0_CLOCK_BUSCLK>; + ti,clk-div = <0x1>; + off-on-delay-us = <350>; + regulator-uv = <1400000>; + ti,sample-cycles = <10>; + ti,hold-cycles = <40>; + regulator-allowed-modes = , + , + , + ; + status = "disabled"; + }; }; }; diff --git a/dts/bindings/regulator/ti,mspm0-vref.yaml b/dts/bindings/regulator/ti,mspm0-vref.yaml index 000b0a65aca5..1c769e5d42bf 100644 --- a/dts/bindings/regulator/ti,mspm0-vref.yaml +++ b/dts/bindings/regulator/ti,mspm0-vref.yaml @@ -32,6 +32,10 @@ properties: type: boolean description: Enable sample & hold mode + ti,v2i-enable: + type: boolean + description: Enable voltage-to-current mode + ti,sample-cycles: type: int description: Number of sample cycles for sample & hold mode diff --git a/include/zephyr/dt-bindings/regulator/mspm0_vref.h b/include/zephyr/dt-bindings/regulator/mspm0_vref.h index 12e8c8cb6e9f..349d371be257 100644 --- a/include/zephyr/dt-bindings/regulator/mspm0_vref.h +++ b/include/zephyr/dt-bindings/regulator/mspm0_vref.h @@ -7,6 +7,8 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_MSPM0_VREF_H #define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_MSPM0_VREF_H +#include + /** * @file mspm0_vref.h * @brief MSPM0 VREF regulator devicetree helpers @@ -20,9 +22,13 @@ * @{ */ /** Normal operating mode */ -#define MSPM0_VREF_MODE_NORMAL 0 +#define MSPM0_VREF_MODE_NORMAL 0 /** Sample and hold mode */ -#define MSPM0_VREF_MODE_SHMODE 1 +#define MSPM0_VREF_MODE_SHMODE BIT(0) +/** Voltage-to-current buffer mode. */ +#define MSPM0_VREF_MODE_V2I BIT(1) +/** Sample and hold combined with voltage-to-current buffer mode */ +#define MSPM0_VREF_MODE_SHMODE_V2I (MSPM0_VREF_MODE_SHMODE | MSPM0_VREF_MODE_V2I) /** @} */ diff --git a/soc/ti/mspm/common/CMakeLists.txt b/soc/ti/mspm/common/CMakeLists.txt index 37c9b9d22640..b2dccf18da16 100644 --- a/soc/ti/mspm/common/CMakeLists.txt +++ b/soc/ti/mspm/common/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 -zephyr_sources_ifdef(CONFIG_HAS_MSPM0_SDK soc.c) +zephyr_sources(soc.c) zephyr_include_directories(.) zephyr_sources_ifdef(CONFIG_PM power.c) diff --git a/soc/ti/mspm/common/soc.c b/soc/ti/mspm/common/soc.c index 20c97ac52bbd..02893331eb4a 100644 --- a/soc/ti/mspm/common/soc.c +++ b/soc/ti/mspm/common/soc.c @@ -6,7 +6,10 @@ */ #include + +#ifdef CONFIG_HAS_MSPM0_SDK #include +#endif /* CONFIG_HAS_MSPM0_SDK */ #include @@ -19,8 +22,10 @@ void __noinline msp_delay_peripheral_startup(void) __asm__ volatile(NOP_N_TIMES(CONFIG_MSPM0_PERIPH_STARTUP_DELAY)); } +#ifdef CONFIG_HAS_MSPM0_SDK void soc_early_init_hook(void) { /* Low Power Mode is configured to be SLEEP0 */ DL_SYSCTL_setBORThreshold(DL_SYSCTL_BOR_THRESHOLD_LEVEL_0); } +#endif /* CONFIG_HAS_MSPM0_SDK */