[PATCH v3 7/9] regulator: mt6392: Add support for MT6392 regulator

Chen-Yu Tsai wenst at chromium.org
Wed Mar 18 22:04:12 PDT 2026


On Wed, Mar 18, 2026 at 2:46 AM Luca Leonardo Scorcia
<l.scorcia at gmail.com> wrote:
>
> From: Fabien Parent <parent.f at gmail.com>
>
> The MT6392 is a regulator found on boards based on the MediaTek
> MT8167, MT8516, and probably other SoCs. It is a so called PMIC and
> connects as a slave to a SoC using SPI, wrapped inside PWRAP.
>
> Signed-off-by: Fabien Parent <parent.f at gmail.com>
> Co-developed-by: Val Packett <val at packett.cool>
> Signed-off-by: Val Packett <val at packett.cool>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia at gmail.com>
> ---
>  drivers/regulator/Kconfig                  |   9 +
>  drivers/regulator/Makefile                 |   1 +
>  drivers/regulator/mt6392-regulator.c       | 487 +++++++++++++++++++++
>  include/linux/regulator/mt6392-regulator.h |  40 ++
>  4 files changed, 537 insertions(+)
>  create mode 100644 drivers/regulator/mt6392-regulator.c
>  create mode 100644 include/linux/regulator/mt6392-regulator.h
>
> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
> index d2335276cce5..66876d730807 100644
> --- a/drivers/regulator/Kconfig
> +++ b/drivers/regulator/Kconfig
> @@ -991,6 +991,15 @@ config REGULATOR_MT6380
>           This driver supports the control of different power rails of device
>           through regulator interface.
>
> +config REGULATOR_MT6392
> +       tristate "MediaTek MT6392 PMIC"
> +       depends on MFD_MT6397
> +       help
> +         Say y here to select this option to enable the power regulator of
> +         MediaTek MT6392 PMIC.
> +         This driver supports the control of different power rails of device
> +         through regulator interface.
> +
>  config REGULATOR_MT6397
>         tristate "MediaTek MT6397 PMIC"
>         depends on MFD_MT6397
> diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
> index 1beba1493241..db5145cfcf36 100644
> --- a/drivers/regulator/Makefile
> +++ b/drivers/regulator/Makefile
> @@ -117,6 +117,7 @@ obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6363) += mt6363-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6370) += mt6370-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
> +obj-$(CONFIG_REGULATOR_MT6392) += mt6392-regulator.o
>  obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
>  obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
>  obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o
> diff --git a/drivers/regulator/mt6392-regulator.c b/drivers/regulator/mt6392-regulator.c
> new file mode 100644
> index 000000000000..50cc0019f48a
> --- /dev/null
> +++ b/drivers/regulator/mt6392-regulator.c
> @@ -0,0 +1,487 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Copyright (c) 2020 MediaTek Inc.
> +// Copyright (c) 2020 BayLibre, SAS.
> +// Author: Chen Zhong <chen.zhong at mediatek.com>
> +// Author: Fabien Parent <fparent at baylibre.com>
> +//
> +// Based on mt6397-regulator.c
> +
> +#include <linux/module.h>
> +#include <linux/linear_range.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/mt6397/core.h>
> +#include <linux/mfd/mt6392/registers.h>
> +#include <linux/regulator/driver.h>
> +#include <linux/regulator/machine.h>
> +#include <linux/regulator/mt6392-regulator.h>
> +#include <linux/regulator/of_regulator.h>
> +#include <dt-bindings/regulator/mediatek,mt6392-regulator.h>
> +
> +/*
> + * MT6392 regulators' information
> + *
> + * @desc: standard fields of regulator description.
> + * @qi: Mask for query enable signal status of regulators
> + * @vselon_reg: Register sections for hardware control mode of bucks
> + * @vselctrl_reg: Register for controlling the buck control mode.
> + * @vselctrl_mask: Mask for query buck's voltage control mode.
> + */
> +struct mt6392_regulator_info {
> +       struct regulator_desc desc;
> +       u32 qi;
> +       u32 vselon_reg;
> +       u32 vselctrl_reg;
> +       u32 vselctrl_mask;
> +       u32 modeset_reg;
> +       u32 modeset_mask;
> +};
> +
> +#define MT6392_BUCK(match, vreg, min, max, step, volt_ranges, enreg,   \
> +               vosel, vosel_mask, voselon, vosel_ctrl,                 \
> +               _modeset_reg, _modeset_mask, rampdelay)         \
> +[MT6392_ID_##vreg] = {                                                 \
> +       .desc = {                                                       \
> +               .name = #vreg,                                          \
> +               .of_match = of_match_ptr(match),                        \
> +               .ops = &mt6392_volt_range_ops,                          \
> +               .type = REGULATOR_VOLTAGE,                              \
> +               .id = MT6392_ID_##vreg,                                 \
> +               .owner = THIS_MODULE,                                   \
> +               .n_voltages = ((max) - (min)) / (step) + 1,             \
> +               .linear_ranges = volt_ranges,                           \
> +               .n_linear_ranges = ARRAY_SIZE(volt_ranges),             \
> +               .vsel_reg = vosel,                                      \
> +               .vsel_mask = vosel_mask,                                \
> +               .enable_reg = enreg,                                    \
> +               .enable_mask = BIT(0),                                  \
> +               .ramp_delay = rampdelay,                                \

Please add the supply names.

> +       },                                                              \
> +       .qi = BIT(13),                                                  \
> +       .vselon_reg = voselon,                                          \
> +       .vselctrl_reg = vosel_ctrl,                                     \
> +       .vselctrl_mask = BIT(1),                                        \
> +       .modeset_reg = _modeset_reg,                                    \
> +       .modeset_mask = _modeset_mask,                                  \
> +}
> +
> +#define MT6392_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,   \
> +               vosel_mask, _modeset_reg, _modeset_mask, entime)        \
> +[MT6392_ID_##vreg] = {                                                 \
> +       .desc = {                                                       \
> +               .name = #vreg,                                          \
> +               .of_match = of_match_ptr(match),                        \
> +               .ops = &mt6392_volt_table_ops,                          \
> +               .type = REGULATOR_VOLTAGE,                              \
> +               .id = MT6392_ID_##vreg,                                 \
> +               .owner = THIS_MODULE,                                   \
> +               .n_voltages = ARRAY_SIZE(ldo_volt_table),               \
> +               .volt_table = ldo_volt_table,                           \
> +               .vsel_reg = vosel,                                      \
> +               .vsel_mask = vosel_mask,                                \
> +               .enable_reg = enreg,                                    \
> +               .enable_mask = BIT(enbit),                              \
> +               .enable_time = entime,                                  \
> +       },                                                              \
> +       .qi = BIT(15),                                                  \
> +       .modeset_reg = _modeset_reg,                                    \
> +       .modeset_mask = _modeset_mask,                                  \
> +}
> +
> +#define MT6392_LDO_LINEAR(match, vreg, min, max, step, volt_ranges,    \
> +               enreg, enbit, vosel, vosel_mask, _modeset_reg,          \
> +               _modeset_mask, entime)                                  \
> +[MT6392_ID_##vreg] = {                                                 \
> +       .desc = {                                                       \
> +               .name = #vreg,                                          \
> +               .of_match = of_match_ptr(match),                        \
> +               .ops = &mt6392_volt_ldo_range_ops,                      \
> +               .type = REGULATOR_VOLTAGE,                              \
> +               .id = MT6392_ID_##vreg,                                 \
> +               .owner = THIS_MODULE,                                   \
> +               .n_voltages = ((max) - (min)) / (step) + 1,             \
> +               .linear_ranges = volt_ranges,                           \
> +               .n_linear_ranges = ARRAY_SIZE(volt_ranges),             \
> +               .vsel_reg = vosel,                                      \
> +               .vsel_mask = vosel_mask,                                \
> +               .enable_reg = enreg,                                    \
> +               .enable_mask = BIT(enbit),                              \
> +               .enable_time = entime,                                  \
> +       },                                                              \
> +       .qi = BIT(15),                                                  \
> +       .modeset_reg = _modeset_reg,                                    \
> +       .modeset_mask = _modeset_mask,                                  \
> +}
> +
> +#define MT6392_REG_FIXED(match, vreg, enreg, enbit, volt,              \
> +               _modeset_reg, _modeset_mask, entime)                    \
> +[MT6392_ID_##vreg] = {                                                 \
> +       .desc = {                                                       \
> +               .name = #vreg,                                          \
> +               .of_match = of_match_ptr(match),                        \
> +               .ops = &mt6392_volt_fixed_ops,                          \
> +               .type = REGULATOR_VOLTAGE,                              \
> +               .id = MT6392_ID_##vreg,                                 \
> +               .owner = THIS_MODULE,                                   \
> +               .n_voltages = 1,                                        \
> +               .enable_reg = enreg,                                    \
> +               .enable_mask = BIT(enbit),                              \
> +               .enable_time = entime,                                  \
> +               .min_uV = volt,                                         \
> +       },                                                              \
> +       .qi = BIT(15),                                                  \
> +       .modeset_reg = _modeset_reg,                                    \
> +       .modeset_mask = _modeset_mask,                                  \
> +}
> +
> +#define MT6392_REG_FIXED_NO_MODE(match, vreg, enreg, enbit, volt,      \
> +       entime)                                                         \
> +[MT6392_ID_##vreg] = {                                                 \
> +       .desc = {                                                       \
> +               .name = #vreg,                                          \
> +               .of_match = of_match_ptr(match),                        \
> +               .ops = &mt6392_volt_fixed_no_mode_ops,                  \
> +               .type = REGULATOR_VOLTAGE,                              \
> +               .id = MT6392_ID_##vreg,                                 \
> +               .owner = THIS_MODULE,                                   \
> +               .n_voltages = 1,                                        \
> +               .enable_reg = enreg,                                    \
> +               .enable_mask = BIT(enbit),                              \
> +               .enable_time = entime,                                  \
> +               .min_uV = volt,                                         \
> +       },                                                              \
> +       .qi = BIT(15),                                                  \
> +}
> +
> +static const struct linear_range buck_volt_range1[] = {
> +       REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
> +};
> +
> +static const struct linear_range buck_volt_range2[] = {
> +       REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
> +};
> +
> +static const u32 ldo_volt_table1[] = {
> +       1800000, 1900000, 2000000, 2200000,
> +};
> +
> +static const struct linear_range ldo_volt_range2[] = {
> +       REGULATOR_LINEAR_RANGE(3300000, 0, 3, 100000),
> +};
> +
> +static const u32 ldo_volt_table3[] = {
> +       1800000, 3300000,
> +};
> +
> +static const u32 ldo_volt_table4[] = {
> +       3000000, 3300000,
> +};
> +
> +static const u32 ldo_volt_table5[] = {
> +       1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000, 3300000,
> +};
> +
> +static const u32 ldo_volt_table6[] = {
> +       1240000, 1390000,
> +};
> +
> +static const u32 ldo_volt_table7[] = {
> +       1200000, 1300000, 1500000, 1800000,
> +};
> +
> +static const u32 ldo_volt_table8[] = {
> +       1800000, 2000000,
> +};

If this PMIC is anything like the MT6358, then it has 0.01V fine
tuning for most if not all the LDOs. It is sometimes needed as
a rail may have a 0.04V boost that would otherwise be invisible
to the system. And then if you have something like 3.04V set in
the DT constraints, you end up with something the regulator driver
doesn't support, but the hardware does.

Please see how it's done in the MT6358 driver. I spent a lot of
time on that driver to make it actually support the full range
of voltages, and describing the supplies.


ChenYu



More information about the Linux-mediatek mailing list