diff --git a/drivers/regulator/CMakeLists.txt b/drivers/regulator/CMakeLists.txt index 170fff41e72..c05e2ddad9c 100644 --- a/drivers/regulator/CMakeLists.txt +++ b/drivers/regulator/CMakeLists.txt @@ -10,3 +10,4 @@ zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM1100 regulator_npm1100.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM6001 regulator_npm6001.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_PCA9420 regulator_pca9420.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_SHELL regulator_shell.c) +zephyr_library_sources_ifdef(CONFIG_REGULATOR_RPI_PICO regulator_rpi_pico.c) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index e0329db1b26..415fcfdfc4c 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -25,5 +25,6 @@ source "drivers/regulator/Kconfig.fixed" source "drivers/regulator/Kconfig.npm1100" source "drivers/regulator/Kconfig.npm6001" source "drivers/regulator/Kconfig.pca9420" +source "drivers/regulator/Kconfig.rpi_pico" endif # REGULATOR diff --git a/drivers/regulator/Kconfig.rpi_pico b/drivers/regulator/Kconfig.rpi_pico new file mode 100644 index 00000000000..fe97a524464 --- /dev/null +++ b/drivers/regulator/Kconfig.rpi_pico @@ -0,0 +1,19 @@ +# Copyright (c) 2023 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config REGULATOR_RPI_PICO + bool "RaspberryPi Pico regulator driver" + default y + depends on DT_HAS_RASPBERRYPI_CORE_SUPPLY_REGULATOR_ENABLED + help + Enable support for the RaspberryPi Pico regulator. + +if REGULATOR_RPI_PICO + +config REGULATOR_RPI_PICO_INIT_PRIORITY + int "RaspberryPi Pico regulator driver init priority" + default KERNEL_INIT_PRIORITY_DEVICE + help + Init priority for the RaspberryPi Pico regulator driver. + +endif diff --git a/drivers/regulator/regulator_rpi_pico.c b/drivers/regulator/regulator_rpi_pico.c new file mode 100644 index 00000000000..f2c0af1559e --- /dev/null +++ b/drivers/regulator/regulator_rpi_pico.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT raspberrypi_core_supply_regulator + +#include +#include +#include +#include +#include +#include +#include + +static const struct linear_range core_ranges[] = { + LINEAR_RANGE_INIT(800000u, 0u, 0u, 5u), + LINEAR_RANGE_INIT(850000u, 50000u, 6u, 15u), +}; + +static const size_t num_core_ranges = ARRAY_SIZE(core_ranges); + +struct regulator_rpi_pico_config { + struct regulator_common_config common; + vreg_and_chip_reset_hw_t * const reg; + const bool brown_out_detection; + const uint32_t brown_out_threshold; +}; + +struct regulator_rpi_pico_data { + struct regulator_common_data data; +}; + +/* + * APIs + */ + +static unsigned int regulator_rpi_pico_count_voltages(const struct device *dev) +{ + return linear_range_group_values_count(core_ranges, num_core_ranges); +} + +static int regulator_rpi_pico_list_voltage(const struct device *dev, unsigned int idx, + int32_t *volt_uv) +{ + return linear_range_group_get_value(core_ranges, num_core_ranges, idx, volt_uv); +} + +static int regulator_rpi_pico_set_voltage(const struct device *dev, int32_t min_uv, int32_t max_uv) +{ + const struct regulator_rpi_pico_config *config = dev->config; + uint16_t idx; + int ret; + + ret = linear_range_group_get_win_index(core_ranges, num_core_ranges, min_uv, max_uv, &idx); + if (ret < 0) { + return ret; + } + + config->reg->vreg = ((config->reg->vreg & ~VREG_AND_CHIP_RESET_VREG_VSEL_BITS) | + (idx << VREG_AND_CHIP_RESET_VREG_VSEL_LSB)); + + return 0; +} + +static int regulator_rpi_pico_get_voltage(const struct device *dev, int32_t *volt_uv) +{ + const struct regulator_rpi_pico_config *config = dev->config; + + return linear_range_group_get_value( + core_ranges, num_core_ranges, + ((config->reg->vreg & VREG_AND_CHIP_RESET_VREG_VSEL_BITS) >> + VREG_AND_CHIP_RESET_VREG_VSEL_LSB), + volt_uv); +} + +static int regulator_rpi_pico_enable(const struct device *dev) +{ + const struct regulator_rpi_pico_config *config = dev->config; + + config->reg->vreg |= BIT(VREG_AND_CHIP_RESET_VREG_EN_LSB); + + return 0; +} + +static int regulator_rpi_pico_disable(const struct device *dev) +{ + const struct regulator_rpi_pico_config *config = dev->config; + + config->reg->vreg &= ~BIT(VREG_AND_CHIP_RESET_VREG_EN_LSB); + + return 0; +} + +static int regulator_rpi_pico_set_mode(const struct device *dev, regulator_mode_t mode) +{ + const struct regulator_rpi_pico_config *config = dev->config; + + if (mode & REGULATOR_RPI_PICO_MODE_HI_Z) { + config->reg->vreg |= REGULATOR_RPI_PICO_MODE_HI_Z; + } else { + config->reg->vreg &= (~REGULATOR_RPI_PICO_MODE_HI_Z); + } + + return 0; +} + +static int regulator_rpi_pico_get_mode(const struct device *dev, regulator_mode_t *mode) +{ + const struct regulator_rpi_pico_config *config = dev->config; + + *mode = (config->reg->vreg & REGULATOR_RPI_PICO_MODE_HI_Z); + + return 0; +} + +static int regulator_rpi_pico_init(const struct device *dev) +{ + const struct regulator_rpi_pico_config *config = dev->config; + + if (config->brown_out_detection) { + config->reg->bod = + (BIT(VREG_AND_CHIP_RESET_BOD_EN_LSB) | + (config->brown_out_threshold << VREG_AND_CHIP_RESET_BOD_VSEL_LSB)); + } else { + config->reg->bod &= ~BIT(VREG_AND_CHIP_RESET_BOD_EN_LSB); + } + + regulator_common_data_init(dev); + + return regulator_common_init(dev, true); +} + +static const struct regulator_driver_api api = { + .enable = regulator_rpi_pico_enable, + .disable = regulator_rpi_pico_disable, + .count_voltages = regulator_rpi_pico_count_voltages, + .list_voltage = regulator_rpi_pico_list_voltage, + .set_voltage = regulator_rpi_pico_set_voltage, + .get_voltage = regulator_rpi_pico_get_voltage, + .set_mode = regulator_rpi_pico_set_mode, + .get_mode = regulator_rpi_pico_get_mode, +}; + +#define REGULATOR_RPI_PICO_DEFINE_ALL(inst) \ + static struct regulator_rpi_pico_data data_##inst; \ + \ + static const struct regulator_rpi_pico_config config_##inst = { \ + .common = REGULATOR_DT_COMMON_CONFIG_INIT(inst), \ + .reg = (vreg_and_chip_reset_hw_t * const)DT_INST_REG_ADDR(inst), \ + .brown_out_detection = DT_INST_PROP(inst, raspberrypi_brown_out_detection), \ + .brown_out_threshold = DT_INST_ENUM_IDX(inst, raspberrypi_brown_out_threshold), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, regulator_rpi_pico_init, NULL, &data_##inst, &config_##inst, \ + POST_KERNEL, CONFIG_REGULATOR_RPI_PICO_INIT_PRIORITY, &api); + +DT_INST_FOREACH_STATUS_OKAY(REGULATOR_RPI_PICO_DEFINE_ALL) diff --git a/dts/arm/rpi_pico/rp2040.dtsi b/dts/arm/rpi_pico/rp2040.dtsi index a5a6fe8d9e9..591041136b6 100644 --- a/dts/arm/rpi_pico/rp2040.dtsi +++ b/dts/arm/rpi_pico/rp2040.dtsi @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "rpi_pico_common.dtsi" @@ -184,6 +185,14 @@ status = "disabled"; #pwm-cells = <3>; }; + + vreg: vreg@40064000 { + compatible = "raspberrypi,core-supply-regulator"; + reg = <0x40064000 1>; + status = "okay"; + raspberrypi,brown-out-detection; + raspberrypi,brown-out-threshold = <860000>; + }; }; pinctrl: pin-controller { diff --git a/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml b/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml new file mode 100644 index 00000000000..2034ccd2c0f --- /dev/null +++ b/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml @@ -0,0 +1,48 @@ +# Copyright (c), 2023 TOKITA Hiroshi +# SPDX -License-Identifier: Apache-2.0 + +description: | + RaspberryPi Pico core supply regurator + +compatible: "raspberrypi,core-supply-regulator" + +include: + - name: base.yaml + - name: regulator.yaml + property-allowlist: + - regulator-always-on + - regulator-boot-on + - regulator-min-microvolt + - regulator-max-microvolt + - regulator-allowed-modes + - regulator-initial-mode + +properties: + raspberrypi,brown-out-detection: + type: boolean + description: + Enable brown-out detection + + raspberrypi,brown-out-threshold: + type: int + default: 860000 + enum: + - 473000 + - 516000 + - 559000 + - 602000 + - 645000 + - 688000 + - 731000 + - 774000 + - 817000 + - 860000 + - 903000 + - 946000 + - 989000 + - 1032000 + - 1075000 + - 1118000 + description: | + Reset if the core voltage drops below this threshold for a particular time + (determined by the 'brown-out detection assertion delay'). diff --git a/include/zephyr/dt-bindings/regulator/rpi_pico.h b/include/zephyr/dt-bindings/regulator/rpi_pico.h new file mode 100644 index 00000000000..55f24219f36 --- /dev/null +++ b/include/zephyr/dt-bindings/regulator/rpi_pico.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_RPI_PICO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_RPI_PICO_H_ + +#define REGULATOR_RPI_PICO_MODE_NORMAL 0x0 +#define REGULATOR_RPI_PICO_MODE_HI_Z 0x2 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_RPI_PICO_H_ */