* [PATCH v2 0/6] regulator: Add support for MediaTek MT6316/6363/6373 PMICs
@ 2025-06-24 7:35 AngeloGioacchino Del Regno
2025-06-24 7:35 ` [PATCH v2 1/6] dt-bindings: regulator: Document MediaTek MT6316 PMIC Regulators AngeloGioacchino Del Regno
` (5 more replies)
0 siblings, 6 replies; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-24 7:35 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Changes in v2:
- Fixed issues in mt6316-regulator.c and tested again
This series adds support for three new MediaTek PMICs: MT6316, MT6363
and MT6373 and their variants - used in board designs featuring the
MediaTek MT8196 Chromebook SoC, or the MT6991 Dimensity 9400 Smartphone
SoC.
AngeloGioacchino Del Regno (6):
dt-bindings: regulator: Document MediaTek MT6316 PMIC Regulators
regulator: Add support for MediaTek MT6316 SPMI PMIC Regulators
dt-bindings: regulator: Document MediaTek MT6363 PMIC Regulators
regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators
dt-bindings: regulator: Document MediaTek MT6373 PMIC Regulators
regulator: Add support for MediaTek MT6373 SPMI PMIC Regulators
.../regulator/mediatek,mt6316-regulator.yaml | 81 ++
.../regulator/mediatek,mt6363-regulator.yaml | 123 ++
.../regulator/mediatek,mt6373-regulator.yaml | 119 ++
drivers/regulator/Kconfig | 27 +
drivers/regulator/Makefile | 3 +
drivers/regulator/mt6316-regulator.c | 345 ++++++
drivers/regulator/mt6363-regulator.c | 1060 +++++++++++++++++
drivers/regulator/mt6373-regulator.c | 729 ++++++++++++
include/linux/regulator/mt6363-regulator.h | 326 +++++
include/linux/regulator/mt6373-regulator.h | 154 +++
10 files changed, 2967 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml
create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6373-regulator.yaml
create mode 100644 drivers/regulator/mt6316-regulator.c
create mode 100644 drivers/regulator/mt6363-regulator.c
create mode 100644 drivers/regulator/mt6373-regulator.c
create mode 100644 include/linux/regulator/mt6363-regulator.h
create mode 100644 include/linux/regulator/mt6373-regulator.h
--
2.49.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 1/6] dt-bindings: regulator: Document MediaTek MT6316 PMIC Regulators
2025-06-24 7:35 [PATCH v2 0/6] regulator: Add support for MediaTek MT6316/6363/6373 PMICs AngeloGioacchino Del Regno
@ 2025-06-24 7:35 ` AngeloGioacchino Del Regno
2025-06-27 8:16 ` Krzysztof Kozlowski
2025-06-24 7:35 ` [PATCH v2 2/6] regulator: Add support for MediaTek MT6316 SPMI " AngeloGioacchino Del Regno
` (4 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-24 7:35 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Add bindings for the regulators found in the MediaTek MT6316 PMIC,
usually found in board designs using the MT6991 Dimensity 9400 and
on MT8196 Kompanio SoC for Chromebooks.
This chip is fully controlled by SPMI and has multiple variants
providing different phase configurations.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
.../regulator/mediatek,mt6316-regulator.yaml | 81 +++++++++++++++++++
1 file changed, 81 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml
diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml
new file mode 100644
index 000000000000..019c3c36997c
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/mediatek,mt6316-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6316 SPMI PMIC Regulators
+
+maintainers:
+ - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+description: |
+ The MediaTek MT6316 PMIC is fully controlled by SPMI interface; it features
+ four step-down DC/DC (buck) converters and has multiple variants, providing
+ different phase configurations. In particular:
+ MT6316BP/VP: 2+2 Phase (buck 1+2, buck 3+4)
+ MT6316CP/HP/KP: 3+1 Phase (buck 1+2+4, buck 3)
+ MT6316DP/TP: 4+0 Phase (buck 1+2+3+4)
+
+properties:
+ compatible:
+ enum:
+ - mediatek,mt6316b-regulator
+ - mediatek,mt6316c-regulator
+ - mediatek,mt6316d-regulator
+
+ vbuck1234:
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+additionalProperties: false
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ const: mediatek,mt6316b-regulator
+ then:
+ patternProperties:
+ "^vbuck(12|34)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ - if:
+ properties:
+ compatible:
+ const: mediatek,mt6316c-regulator
+ then:
+ patternProperties:
+ "^vbuck(124|3)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ - if:
+ properties:
+ compatible:
+ const: mediatek,mt6316d-regulator
+ then:
+ properties:
+ vbuck1234: true
+ else:
+ properties:
+ vbuck1234: false
+
+examples:
+ - |
+ pmic {
+ regulators {
+ compatible = "mediatek,mt6316d-regulator";
+
+ vbuck1234 {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1277500>;
+ regulator-always-on;
+ };
+ };
+ };
+...
--
2.49.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 2/6] regulator: Add support for MediaTek MT6316 SPMI PMIC Regulators
2025-06-24 7:35 [PATCH v2 0/6] regulator: Add support for MediaTek MT6316/6363/6373 PMICs AngeloGioacchino Del Regno
2025-06-24 7:35 ` [PATCH v2 1/6] dt-bindings: regulator: Document MediaTek MT6316 PMIC Regulators AngeloGioacchino Del Regno
@ 2025-06-24 7:35 ` AngeloGioacchino Del Regno
2025-06-25 5:06 ` Chen-Yu Tsai
2025-06-24 7:35 ` [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 " AngeloGioacchino Del Regno
` (3 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-24 7:35 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Add a driver for the regulators found on all types of the MediaTek
MT6316 SPMI PMIC, fully controlled by SPMI interface and featuring
four step down DCDC (buck) converters.
In particular, this includes support for:
- MT6316(BP/VP): 2+2 Phase (Phase 1: buck1+2, Phase 2: buck3+4)
- MT6316(CP/HP/KP): 3+1 Phase (Phase 1: buck1+2+4, Phase 2: buck3)
- MT6316(DP/TP): 4+0 Phase (Single phase, buck1+2+3+4)
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6316-regulator.c | 345 +++++++++++++++++++++++++++
3 files changed, 355 insertions(+)
create mode 100644 drivers/regulator/mt6316-regulator.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6d8988387da4..bca2ebbd89b7 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -864,6 +864,15 @@ config REGULATOR_MT6315
This driver supports the control of different power rails of device
through regulator interface.
+config REGULATOR_MT6316
+ tristate "MT6316 SPMI PMIC regulator driver"
+ depends on SPMI || COMPILE_TEST
+ help
+ Say Y here to enable support for 2+2, 3+1 and 4 phase regulators
+ found in the MediaTek MT6316 BP, CP, DP, HP, VP and TP SPMI PMICs.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
config REGULATOR_MT6323
tristate "MediaTek MT6323 PMIC"
depends on MFD_MT6397
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index c0bc7a0f4e67..58643e35d2cc 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -103,6 +103,7 @@ obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o
obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o
+obj-$(CONFIG_REGULATOR_MT6315) += mt6316-regulator.o
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o
obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o
diff --git a/drivers/regulator/mt6316-regulator.c b/drivers/regulator/mt6316-regulator.c
new file mode 100644
index 000000000000..952852bbe923
--- /dev/null
+++ b/drivers/regulator/mt6316-regulator.c
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2024 MediaTek Inc.
+// Copyright (c) 2025 Collabora Ltd
+// AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/spmi.h>
+
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#define MT6316_BUCK_MODE_AUTO 0
+#define MT6316_BUCK_MODE_FORCE_PWM 1
+#define MT6316_BUCK_MODE_LP 2
+
+#define MT6316_CHIP_ID 0x20b
+#define MT6316_BUCK_TOP_CON0 0x1440
+#define EN_SET_OFFSET 0x1
+#define EN_CLR_OFFSET 0x2
+
+#define MT6316_BUCK_TOP_CON1 0x1443
+
+#define MT6316_BUCK_TOP_ELR0 0x1448
+#define MT6316_BUCK_TOP_ELR2 0x144a
+#define MT6316_BUCK_TOP_ELR4 0x144c
+#define MT6316_BUCK_TOP_ELR6 0x144e
+#define MT6316_VSEL_MASK GENMASK(8, 0)
+
+#define MT6316_VBUCK1_DBG 0x14a8
+#define MT6316_VBUCK2_DBG 0x1528
+#define MT6316_VBUCK3_DBG 0x15a8
+#define MT6316_VBUCK4_DBG 0x1628
+#define MT6316_BUCK_QI BIT(0)
+
+#define MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0 0x1688
+#define MT6316_BUCK_TOP_4PHASE_TOP_ELR_0 0x1690
+
+enum mt6316_type {
+ MT6316_TYPE_2PHASE,
+ MT6316_TYPE_3PHASE,
+ MT6316_TYPE_4PHASE
+};
+
+/**
+ * struct mt6316_regulator_info - MT6316 regulators information
+ * @desc: Regulator description structure
+ * @debug_reg: Debug register for regulator status
+ * @lp_mode_reg: Low Power mode register (normal/idle)
+ * @lp_mode_mask: Low Power mode regulator mask
+ * @modeset_reg: AUTO/PWM mode register
+ * @modeset_mask: AUTO/PWM regulator mask
+ */
+struct mt6316_regulator_info {
+ struct regulator_desc desc;
+ u16 debug_reg;
+ u16 lp_mode_reg;
+ u16 lp_mode_mask;
+ u16 modeset_reg;
+ u16 modeset_mask;
+};
+
+#define MT6316_BUCK(match, vreg_id, min, max, step, vs_reg) \
+{ \
+ .desc = { \
+ .name = match, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6316_vreg_setclr_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min) / step + 1, \
+ .min_uV = min, \
+ .uV_step = step, \
+ .enable_reg = MT6316_BUCK_TOP_CON0, \
+ .enable_mask = BIT(vreg_id - 1), \
+ .vsel_reg = vs_reg, \
+ .vsel_mask = MT6316_VSEL_MASK, \
+ .of_map_mode = mt6316_map_mode, \
+ }, \
+ .lp_mode_reg = MT6316_BUCK_TOP_CON1, \
+ .lp_mode_mask = BIT(vreg_id - 1), \
+ .modeset_reg = MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0, \
+ .modeset_mask = BIT(vreg_id - 1), \
+ .debug_reg = MT6316_VBUCK##vreg_id##_DBG, \
+}
+
+/* Values in some MT6316 registers are big endian, 9 bits long... */
+static inline u16 mt6316_be9_to_cpu(u16 val)
+{
+ return ((val >> 8) & BIT(0)) | ((val & GENMASK(7, 0)) << 1);
+}
+
+static inline u16 mt6316_cpu_to_be9(u16 val)
+{
+ return ((val & BIT(0)) << 8) | (val >> 1);
+}
+
+static unsigned int mt6316_map_mode(u32 mode)
+{
+ switch (mode) {
+ case MT6316_BUCK_MODE_AUTO:
+ return REGULATOR_MODE_NORMAL;
+ case MT6316_BUCK_MODE_FORCE_PWM:
+ return REGULATOR_MODE_FAST;
+ case MT6316_BUCK_MODE_LP:
+ return REGULATOR_MODE_IDLE;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+static int mt6316_vreg_enable_setclr(struct regulator_dev *rdev)
+{
+ return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_SET_OFFSET,
+ rdev->desc->enable_mask);
+}
+
+static int mt6316_vreg_disable_setclr(struct regulator_dev *rdev)
+{
+ return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_CLR_OFFSET,
+ rdev->desc->enable_mask);
+}
+
+static int mt6316_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector)
+{
+ u16 val = mt6316_cpu_to_be9(selector);
+
+ return regmap_bulk_write(rdev->regmap, rdev->desc->vsel_reg, &val, sizeof(val));
+}
+
+static int mt6316_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+ u16 val;
+ int ret;
+
+ ret = regmap_bulk_read(rdev->regmap, rdev->desc->vsel_reg, &val, sizeof(val));
+ if (ret)
+ return ret;
+
+ return mt6316_be9_to_cpu(val & rdev->desc->vsel_mask);
+}
+
+static int mt6316_regulator_get_status(struct regulator_dev *rdev)
+{
+ struct mt6316_regulator_info *info = rdev_get_drvdata(rdev);
+ u32 val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, info->debug_reg, &val);
+ if (ret)
+ return ret;
+
+ return val & MT6316_BUCK_QI ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
+}
+
+static unsigned int mt6316_regulator_get_mode(struct regulator_dev *rdev)
+{
+ struct mt6316_regulator_info *info = rdev_get_drvdata(rdev);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to get mode: %d\n", ret);
+ return ret;
+ }
+
+ if ((val & info->modeset_mask) == info->modeset_mask)
+ return REGULATOR_MODE_FAST;
+
+ ret = regmap_read(rdev->regmap, info->lp_mode_reg, &val);
+ val &= info->lp_mode_mask;
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to get lp mode: %d\n", ret);
+ return ret;
+ }
+
+ return val ? REGULATOR_MODE_IDLE : REGULATOR_MODE_NORMAL;
+}
+
+static int mt6316_regulator_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct mt6316_regulator_info *info = rdev_get_drvdata(rdev);
+ struct regmap *regmap = rdev->regmap;
+ int cur_mode, ret;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ ret = regmap_set_bits(regmap, info->modeset_reg, info->modeset_mask);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ cur_mode = mt6316_regulator_get_mode(rdev);
+ if (cur_mode < 0) {
+ ret = cur_mode;
+ break;
+ }
+
+ if (cur_mode == REGULATOR_MODE_FAST) {
+ ret = regmap_clear_bits(regmap, info->modeset_reg, info->modeset_mask);
+ break;
+ } else if (cur_mode == REGULATOR_MODE_IDLE) {
+ ret = regmap_clear_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
+ if (ret == 0)
+ usleep_range(100, 200);
+ } else {
+ ret = 0;
+ }
+ break;
+ case REGULATOR_MODE_IDLE:
+ ret = regmap_set_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to set mode %u: %d\n", mode, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct regulator_ops mt6316_vreg_setclr_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = mt6316_regulator_set_voltage_sel,
+ .get_voltage_sel = mt6316_regulator_get_voltage_sel,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = mt6316_vreg_enable_setclr,
+ .disable = mt6316_vreg_disable_setclr,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mt6316_regulator_get_status,
+ .set_mode = mt6316_regulator_set_mode,
+ .get_mode = mt6316_regulator_get_mode,
+};
+
+/* MT6316BP/VP - 2+2 phase buck */
+static struct mt6316_regulator_info mt6316bv_regulators[] = {
+ MT6316_BUCK("vbuck12", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
+ MT6316_BUCK("vbuck34", 3, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR4),
+};
+
+/* MT6316CP/HP/KP - 3+1 phase buck */
+static struct mt6316_regulator_info mt6316chk_regulators[] = {
+ MT6316_BUCK("vbuck124", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
+ MT6316_BUCK("vbuck3", 3, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR4),
+};
+
+/* MT6316DP/TP - 4 phase buck */
+static struct mt6316_regulator_info mt6316dt_regulators[] = {
+ MT6316_BUCK("vbuck1234", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
+};
+
+static const struct regmap_config mt6316_spmi_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = 0x1700,
+ .fast_io = true,
+};
+
+static int mt6316_regulator_probe(struct spmi_device *sdev)
+{
+ struct regulator_config config = {};
+ struct mt6316_regulator_info *info;
+ struct regulator_dev *rdev;
+ enum mt6316_type type;
+ int num_vregs, ret;
+ unsigned int i;
+ u32 chip_id;
+
+ config.regmap = devm_regmap_init_spmi_ext(sdev, &mt6316_spmi_regmap_config);
+ if (IS_ERR(config.regmap))
+ return PTR_ERR(config.regmap);
+
+ /*
+ * The first read is expected to fail: this PMIC needs to be woken up
+ * and that can be done with any activity over the SPMI bus.
+ */
+ regmap_read(config.regmap, MT6316_CHIP_ID, &chip_id);
+
+ /* The second read, instead, shall not fail! */
+ ret = regmap_read(config.regmap, MT6316_CHIP_ID, &chip_id);
+ if (ret) {
+ dev_err(&sdev->dev, "Cannot read Chip ID!\n");
+ return ret;
+ }
+ dev_dbg(&sdev->dev, "Chip ID: 0x%x\n", chip_id);
+
+ config.dev = &sdev->dev;
+
+ type = (uintptr_t)device_get_match_data(&sdev->dev);
+ switch (type) {
+ case MT6316_TYPE_2PHASE:
+ info = mt6316bv_regulators;
+ num_vregs = ARRAY_SIZE(mt6316bv_regulators);
+ break;
+ case MT6316_TYPE_3PHASE:
+ info = mt6316chk_regulators;
+ num_vregs = ARRAY_SIZE(mt6316chk_regulators);
+ break;
+ case MT6316_TYPE_4PHASE:
+ info = mt6316dt_regulators;
+ num_vregs = ARRAY_SIZE(mt6316dt_regulators);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_vregs; i++) {
+ config.driver_data = &info[i];
+
+ rdev = devm_regulator_register(&sdev->dev, &info[i].desc, &config);
+ if (IS_ERR(rdev))
+ return dev_err_probe(&sdev->dev, PTR_ERR(rdev),
+ "failed to register %s\n", info[i].desc.name);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mt6316_regulator_match[] = {
+ { .compatible = "mediatek,mt6316b-regulator", .data = (void *)MT6316_TYPE_2PHASE },
+ { .compatible = "mediatek,mt6316c-regulator", .data = (void *)MT6316_TYPE_3PHASE },
+ { .compatible = "mediatek,mt6316d-regulator", .data = (void *)MT6316_TYPE_4PHASE },
+ { /* sentinel */ }
+};
+
+static struct spmi_driver mt6316_regulator_driver = {
+ .driver = {
+ .name = "mt6316-regulator",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ .of_match_table = mt6316_regulator_match,
+ },
+ .probe = mt6316_regulator_probe,
+};
+module_spmi_driver(mt6316_regulator_driver);
+
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6316 PMIC");
+MODULE_LICENSE("GPL");
--
2.49.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 PMIC Regulators
2025-06-24 7:35 [PATCH v2 0/6] regulator: Add support for MediaTek MT6316/6363/6373 PMICs AngeloGioacchino Del Regno
2025-06-24 7:35 ` [PATCH v2 1/6] dt-bindings: regulator: Document MediaTek MT6316 PMIC Regulators AngeloGioacchino Del Regno
2025-06-24 7:35 ` [PATCH v2 2/6] regulator: Add support for MediaTek MT6316 SPMI " AngeloGioacchino Del Regno
@ 2025-06-24 7:35 ` AngeloGioacchino Del Regno
2025-06-27 8:18 ` Krzysztof Kozlowski
2025-06-24 7:35 ` [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI " AngeloGioacchino Del Regno
` (2 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-24 7:35 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Add bindings for the regulators found in the MediaTek MT6363 PMIC,
usually found in board designs using the MT6991 Dimensity 9400 and
on MT8196 Kompanio SoC for Chromebooks, along with the MT6316 and
MT6373 PMICs.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
.../regulator/mediatek,mt6363-regulator.yaml | 123 ++++++++++++++++++
1 file changed, 123 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
new file mode 100644
index 000000000000..f866c89c56f7
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/mediatek,mt6363-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6363 PMIC Regulators
+
+maintainers:
+ - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+description:
+ The MT6363 SPMI PMIC provides 10 BUCK and 26 LDO (Low Dropout) regulators
+ and can optionally provide overcurrent warnings with one ocp interrupt
+ for each voltage regulator.
+
+properties:
+ compatible:
+ const: mediatek,mt6363-regulator
+
+ interrupts:
+ description: Overcurrent warning interrupts
+ minItems: 1
+ maxItems: 36
+
+ interrupt-names:
+ description:
+ Names for the overcurrent interrupts are the same as the name
+ of a regulator (hence the same as each regulator's node name).
+ For example, the interrupt name for regulator vs2 will be "vs2".
+ minItems: 1
+ maxItems: 36
+
+ isink-load:
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ ldo-vemc:
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+patternProperties:
+ "^ldo-va(12-1|12-2|15)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^buck-vb[1-7]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^buck-sshub[124]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^ldo-v(aux|m|rfio|tref)18$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^ldo-vcn(13|15)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^ldo-vio(0p75|18)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^ldo-vram-(apu|cpub|cpum|cpul|digrf|mdfe|modem)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^ldo-vrf(0p9|12|13|18)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^ldo-vs[1-3]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^ldo-vufs(12|18)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ pmic {
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ regulators {
+ compatible = "mediatek,mt6363-regulator";
+ interrupts = <4 16 IRQ_TYPE_LEVEL_HIGH>, <4 17 IRQ_TYPE_LEVEL_HIGH>,
+ <4 18 IRQ_TYPE_LEVEL_HIGH>, <4 19 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "vcn15", "vcn13", "vrf09", "vrf12";
+
+ ldo-vio18 {
+ regulator-name = "pp1800-vio18-s3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allowed-modes = <0 2>;
+ regulator-allow-set-load;
+ };
+ };
+ };
+...
--
2.49.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators
2025-06-24 7:35 [PATCH v2 0/6] regulator: Add support for MediaTek MT6316/6363/6373 PMICs AngeloGioacchino Del Regno
` (2 preceding siblings ...)
2025-06-24 7:35 ` [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 " AngeloGioacchino Del Regno
@ 2025-06-24 7:35 ` AngeloGioacchino Del Regno
2025-06-27 19:42 ` Dan Carpenter
2025-07-06 6:22 ` kernel test robot
2025-06-24 7:35 ` [PATCH v2 5/6] dt-bindings: regulator: Document MediaTek MT6373 " AngeloGioacchino Del Regno
2025-06-24 7:35 ` [PATCH v2 6/6] regulator: Add support for MediaTek MT6373 SPMI " AngeloGioacchino Del Regno
5 siblings, 2 replies; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-24 7:35 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Add a driver for the regulators found on the MT6363 PMIC, fully
controlled by SPMI interface.
This PMIC regulates voltage with an input range of 2.6-5.0V, and
features 10 buck converters and 26 LDOs.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6363-regulator.c | 1060 ++++++++++++++++++++
include/linux/regulator/mt6363-regulator.h | 326 ++++++
4 files changed, 1396 insertions(+)
create mode 100644 drivers/regulator/mt6363-regulator.c
create mode 100644 include/linux/regulator/mt6363-regulator.h
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index bca2ebbd89b7..f2ab06538b8c 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -936,6 +936,15 @@ config REGULATOR_MT6360
2-channel buck with Thermal Shutdown and Overload Protection
6-channel High PSRR and Low Dropout LDO.
+config REGULATOR_MT6363
+ tristate "MT6363 SPMI PMIC regulator driver"
+ depends on SPMI || COMPILE_TEST
+ help
+ Say Y here to enable support for regulators found in the MediaTek
+ MT6363 SPMI PMIC.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
config REGULATOR_MT6370
tristate "MT6370 SubPMIC Regulator"
depends on MFD_MT6370
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 58643e35d2cc..9dd19f4227ea 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -111,6 +111,7 @@ obj-$(CONFIG_REGULATOR_MT6357) += mt6357-regulator.o
obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o
obj-$(CONFIG_REGULATOR_MT6359) += mt6359-regulator.o
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_MT6397) += mt6397-regulator.o
diff --git a/drivers/regulator/mt6363-regulator.c b/drivers/regulator/mt6363-regulator.c
new file mode 100644
index 000000000000..d594af411726
--- /dev/null
+++ b/drivers/regulator/mt6363-regulator.c
@@ -0,0 +1,1060 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2024 MediaTek Inc.
+// Copyright (c) 2025 Collabora Ltd
+// AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+#include <linux/delay.h>
+#include <linux/devm-helpers.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/mt6363-regulator.h>
+#include <linux/regulator/of_regulator.h>
+
+#define MT6363_REGULATOR_MODE_NORMAL 0
+#define MT6363_REGULATOR_MODE_FCCM 1
+#define MT6363_REGULATOR_MODE_LP 2
+#define MT6363_REGULATOR_MODE_ULP 3
+
+#define EN_SET_OFFSET 0x1
+#define EN_CLR_OFFSET 0x2
+#define OP_CFG_OFFSET 0x5
+
+#define NORMAL_OP_CFG 0x10
+#define NORMAL_OP_EN 0x800000
+
+#define OC_IRQ_ENABLE_DELAY_MS 10
+
+/* Unlock keys for TMA and BUCK_TOP */
+#define MT6363_TMA_UNLOCK_VALUE 0x9c9c
+#define MT6363_BUCK_TOP_UNLOCK_VALUE 0x5543
+
+#define MT6363_RG_BUCK_EFUSE_RSV1 0x1447
+#define MT6363_RG_BUCK_EFUSE_RSV1_MASK GENMASK(7, 4)
+
+enum {
+ MT6363_ID_VS2,
+ MT6363_ID_VBUCK1,
+ MT6363_ID_VBUCK2,
+ MT6363_ID_VBUCK3,
+ MT6363_ID_VBUCK4,
+ MT6363_ID_VBUCK5,
+ MT6363_ID_VBUCK6,
+ MT6363_ID_VBUCK7,
+ MT6363_ID_VS1,
+ MT6363_ID_VS3,
+ MT6363_ID_VBUCK1_SSHUB,
+ MT6363_ID_VBUCK2_SSHUB,
+ MT6363_ID_VBUCK4_SSHUB,
+ MT6363_ID_VSRAM_DIGRF,
+ MT6363_ID_VSRAM_MDFE,
+ MT6363_ID_VSRAM_MODEM,
+ MT6363_ID_VSRAM_CPUB,
+ MT6363_ID_VSRAM_CPUM,
+ MT6363_ID_VSRAM_CPUL,
+ MT6363_ID_VSRAM_APU,
+ MT6363_ID_VEMC,
+ MT6363_ID_VCN13,
+ MT6363_ID_VTREF18,
+ MT6363_ID_VAUX18,
+ MT6363_ID_VCN15,
+ MT6363_ID_VUFS18,
+ MT6363_ID_VIO18,
+ MT6363_ID_VM18,
+ MT6363_ID_VA15,
+ MT6363_ID_VRF18,
+ MT6363_ID_VRFIO18,
+ MT6363_ID_VIO075,
+ MT6363_ID_VUFS12,
+ MT6363_ID_VA12_1,
+ MT6363_ID_VA12_2,
+ MT6363_ID_VRF12,
+ MT6363_ID_VRF13,
+ MT6363_ID_VRF09,
+ MT6363_ID_ISINK_LOAD
+};
+
+/**
+ * struct mt6363_regulator_info - MT6363 regulators information
+ * @desc: Regulator description structure
+ * @lp_mode_reg: Low Power mode register (normal/idle)
+ * @lp_mode_mask: Low Power mode regulator mask
+ * @hw_lp_mode_reg: Hardware voted Low Power mode register (normal/idle)
+ * @hw_lp_mode_mask: Hardware voted Low Power mode regulator mask
+ * @modeset_reg: AUTO/PWM mode register
+ * @modeset_mask: AUTO/PWM regulator mask
+ * @vocal_reg: Voltage Output Calibration register
+ * @vocal_mask: Voltage Output Calibration regulator mask
+ * @lp_imax_uA: Maximum load current (microamps), for Low Power mode only
+ * @op_en_reg: Operation mode enablement register
+ * @orig_op_en: Backup of a regulator's operation mode enablement register
+ * @orig_op_cfg: Backup of a regulator's operation mode configuration register
+ * @oc_work: Delayed work for enabling overcurrent IRQ
+ * @irq: Interrupt for overcurrent event
+ */
+struct mt6363_regulator_info {
+ struct regulator_desc desc;
+ u16 lp_mode_reg;
+ u16 lp_mode_mask;
+ u16 hw_lp_mode_reg;
+ u16 hw_lp_mode_mask;
+ u16 modeset_reg;
+ u16 modeset_mask;
+ u16 vocal_reg;
+ u16 vocal_mask;
+ int lp_imax_uA;
+ u16 op_en_reg;
+ u32 orig_op_en;
+ u8 orig_op_cfg;
+ struct delayed_work oc_work;
+ int irq;
+};
+
+#define MT6363_BUCK(match, vreg, min, max, step, en_reg, en_bit, vs_reg,\
+ vs_mask, lp_reg, lp_bit, mset_reg, mset_bit)\
+[MT6363_ID_##vreg] = { \
+ .desc = { \
+ .name = match, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6363_vreg_setclr_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6363_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min) / step + 1, \
+ .min_uV = min, \
+ .uV_step = step, \
+ .enable_reg = en_reg, \
+ .enable_mask = BIT(en_bit), \
+ .vsel_reg = vs_reg, \
+ .vsel_mask = vs_mask, \
+ .of_map_mode = mt6363_map_mode, \
+ }, \
+ .lp_mode_reg = lp_reg, \
+ .lp_mode_mask = BIT(lp_bit), \
+ .hw_lp_mode_reg = MT6363_BUCK_##vreg##_HW_LP_MODE, \
+ .hw_lp_mode_mask = 0xc, \
+ .modeset_reg = mset_reg, \
+ .modeset_mask = BIT(mset_bit), \
+ .lp_imax_uA = 100000, \
+ .op_en_reg = MT6363_BUCK_##vreg##_OP_EN_0, \
+}
+
+#define MT6363_SSHUB(match, vreg, min, max, step, en_reg, \
+ vs_reg, vs_mask) \
+[MT6363_ID_##vreg] = { \
+ .desc = { \
+ .name = match, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6363_sshub_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6363_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min) / step + 1, \
+ .min_uV = min, \
+ .uV_step = step, \
+ .enable_reg = en_reg, \
+ .enable_mask = BIT(0), \
+ .vsel_reg = vs_reg, \
+ .vsel_mask = vs_mask, \
+ .of_map_mode = mt6363_map_mode, \
+ }, \
+}
+
+#define MT6363_LDO_LINEAR_OPS(match, vreg, vops, min, max, step, \
+ en_reg, en_bit, vs_reg, vs_mask, \
+ lp_reg, lp_bit) \
+[MT6363_ID_##vreg] = { \
+ .desc = { \
+ .name = match, \
+ .of_match = of_match_ptr(match), \
+ .ops = &vops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6363_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min) / step + 1, \
+ .min_uV = min, \
+ .uV_step = step, \
+ .enable_reg = en_reg, \
+ .enable_mask = BIT(en_bit), \
+ .vsel_reg = vs_reg, \
+ .vsel_mask = vs_mask, \
+ .of_map_mode = mt6363_map_mode, \
+ }, \
+ .lp_mode_reg = lp_reg, \
+ .lp_mode_mask = BIT(lp_bit), \
+ .hw_lp_mode_reg = MT6363_LDO_##vreg##_HW_LP_MODE, \
+ .hw_lp_mode_mask = 0x4, \
+}
+
+#define MT6363_LDO_L_SC(match, vreg, min, max, step, en_reg, en_bit, \
+ vs_reg, vs_mask, lp_reg, lp_bit) \
+ MT6363_LDO_LINEAR_OPS(match, vreg, mt6363_vreg_setclr_ops, \
+ min, max, step, en_reg, en_bit, \
+ vs_reg, vs_mask, lp_reg, lp_bit)
+
+#define MT6363_LDO_L(match, vreg, min, max, step, en_reg, en_bit, \
+ vs_reg, vs_mask, lp_reg, lp_bit) \
+ MT6363_LDO_LINEAR_OPS(match, vreg, mt6363_ldo_linear_ops, \
+ min, max, step, en_reg, en_bit, \
+ vs_reg, vs_mask, lp_reg, lp_bit)
+
+#define MT6363_LDO_VT_OPS(match, vreg, vops, vtable, en_reg, en_bit, \
+ vs_reg, vs_mask, cal_reg, cal_mask, \
+ lp_reg, lp_bit) \
+[MT6363_ID_##vreg] = { \
+ .desc = { \
+ .name = match, \
+ .of_match = of_match_ptr(match), \
+ .ops = &vops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6363_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .volt_table = vtable, \
+ .n_voltages = ARRAY_SIZE(vtable), \
+ .enable_reg = en_reg, \
+ .enable_mask = BIT(en_bit), \
+ .vsel_reg = vs_reg, \
+ .vsel_mask = vs_mask, \
+ .of_map_mode = mt6363_map_mode, \
+ }, \
+ .vocal_reg = cal_reg, \
+ .vocal_mask = cal_mask, \
+ .lp_mode_reg = lp_reg, \
+ .lp_mode_mask = BIT(lp_bit), \
+ .hw_lp_mode_reg = MT6363_LDO_##vreg##_HW_LP_MODE, \
+ .hw_lp_mode_mask = 0x4, \
+ .lp_imax_uA = 10000, \
+ .op_en_reg = MT6363_LDO_##vreg##_OP_EN0, \
+}
+
+#define MT6363_LDO_VT(match, vreg, vtable, en_reg, en_bit, vsel_reg, \
+ vs_mask, cal_reg, cal_mask, lp_reg, lp_bit) \
+ MT6363_LDO_VT_OPS(match, vreg, mt6363_ldo_vtable_ops, vtable, \
+ en_reg, en_bit, vsel_reg, vs_mask, \
+ cal_reg, cal_mask, lp_reg, lp_bit)
+
+static const unsigned int ldo_vemc_volt_table[] = {
+ 1200000, 1300000, 1500000, 1700000, 1800000, 2000000, 2500000, 2600000,
+ 2700000, 2800000, 2900000, 3000000, 3100000, 3300000, 3400000, 3500000,
+};
+
+static const unsigned int ldo_volt_table1[] = {
+ 900000, 1000000, 1100000, 1200000, 1300000, 1700000, 1800000, 1810000,
+};
+
+static const unsigned int ldo_volt_table2[] = {
+ 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+ 2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
+};
+
+static const unsigned int ldo_volt_table3[] = {
+ 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000,
+ 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000,
+};
+
+static const unsigned int ldo_volt_table4[] = {
+ 550000, 600000, 650000, 700000, 750000, 800000, 900000, 950000,
+ 1000000, 1050000, 1100000, 1150000, 1700000, 1750000, 1800000, 1850000,
+};
+
+static const unsigned int ldo_volt_table5[] = {
+ 600000, 650000, 700000, 750000, 800000,
+};
+
+static int mt6363_vreg_enable_setclr(struct regulator_dev *rdev)
+{
+ return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_SET_OFFSET,
+ rdev->desc->enable_mask);
+}
+
+static int mt6363_vreg_disable_setclr(struct regulator_dev *rdev)
+{
+ return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_CLR_OFFSET,
+ rdev->desc->enable_mask);
+}
+
+static inline unsigned int mt6363_map_mode(unsigned int mode)
+{
+ switch (mode) {
+ case MT6363_REGULATOR_MODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ case MT6363_REGULATOR_MODE_FCCM:
+ return REGULATOR_MODE_FAST;
+ case MT6363_REGULATOR_MODE_LP:
+ return REGULATOR_MODE_IDLE;
+ case MT6363_REGULATOR_MODE_ULP:
+ return REGULATOR_MODE_STANDBY;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+static unsigned int mt6363_regulator_get_mode(struct regulator_dev *rdev)
+{
+ struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to get mt6363 mode: %d\n", ret);
+ return ret;
+ }
+
+ if (val & info->modeset_mask)
+ return REGULATOR_MODE_FAST;
+
+ if (info->hw_lp_mode_reg) {
+ ret = regmap_read(rdev->regmap, info->hw_lp_mode_reg, &val);
+ val &= info->hw_lp_mode_mask;
+ } else {
+ ret = regmap_read(rdev->regmap, info->lp_mode_reg, &val);
+ val &= info->lp_mode_mask;
+ }
+
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to get lp mode: %d\n", ret);
+ return ret;
+ }
+
+ if (val)
+ return REGULATOR_MODE_IDLE;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int mt6363_buck_unlock(struct regmap *map, bool unlock)
+{
+ u16 buf = unlock ? MT6363_BUCK_TOP_UNLOCK_VALUE : 0;
+
+ return regmap_bulk_write(map, MT6363_BUCK_TOP_KEY_PROT_LO, &buf, sizeof(buf));
+}
+
+static int mt6363_regulator_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
+ struct regmap *regmap;
+ int cur_mode, ret;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ ret = mt6363_buck_unlock(regmap, true);
+ if (ret)
+ break;
+
+ ret = regmap_set_bits(regmap, info->modeset_reg, info->modeset_mask);
+
+ mt6363_buck_unlock(regmap, false);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ cur_mode = mt6363_regulator_get_mode(rdev);
+ if (cur_mode < 0) {
+ ret = cur_mode;
+ break;
+ }
+
+ if (cur_mode == REGULATOR_MODE_FAST) {
+ ret = mt6363_buck_unlock(regmap, true);
+ if (ret)
+ break;
+
+ ret = regmap_clear_bits(regmap, info->modeset_reg, info->modeset_mask);
+
+ mt6363_buck_unlock(regmap, false);
+ break;
+ } else if (cur_mode == REGULATOR_MODE_IDLE) {
+ ret = regmap_clear_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
+ if (ret == 0)
+ usleep_range(100, 200);
+ }
+ break;
+ case REGULATOR_MODE_IDLE:
+ ret = regmap_set_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to set mode %u: %d\n", mode, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt6363_regulator_set_load(struct regulator_dev *rdev, int load_uA)
+{
+ struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
+ unsigned int opmode_cfg, opmode_en;
+ int i, ret;
+
+ if (!info->lp_imax_uA)
+ return -EINVAL;
+
+ if (load_uA >= info->lp_imax_uA) {
+ ret = mt6363_regulator_set_mode(rdev, REGULATOR_MODE_NORMAL);
+ if (ret)
+ return ret;
+
+ opmode_cfg = NORMAL_OP_CFG;
+ opmode_en = NORMAL_OP_EN;
+ } else {
+ opmode_cfg = info->orig_op_cfg;
+ opmode_en = info->orig_op_en;
+ }
+
+ ret = regmap_write(rdev->regmap, info->op_en_reg + OP_CFG_OFFSET, opmode_cfg);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < 3; i++) {
+ ret = regmap_write(rdev->regmap, info->op_en_reg + i,
+ (opmode_en >> (i * 8)) & GENMASK(7, 0));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt6363_vemc_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+ const u16 tma_unlock_key = MT6363_TMA_UNLOCK_VALUE;
+ struct regmap *regmap = rdev->regmap;
+ unsigned int val;
+ u16 mask;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, MT6363_TOP_TRAP, &val);
+ if (ret)
+ return ret;
+
+ if (val > 1)
+ return -EINVAL;
+
+ /* Unlock TMA for writing */
+ ret = regmap_bulk_write(rdev->regmap, MT6363_TOP_TMA_KEY_L,
+ &tma_unlock_key, sizeof(tma_unlock_key));
+ if (ret)
+ return ret;
+
+ /* If HW trapping value is 1, use VEMC_VOSEL_1 instead of VEMC_VOSEL_0 */
+ if (val == 1) {
+ mask = MT6363_RG_VEMC_VOSEL_1_MASK;
+ sel = FIELD_PREP(MT6363_RG_VEMC_VOSEL_1_MASK, sel);
+ } else {
+ mask = rdev->desc->vsel_mask;
+ }
+
+ /* Function must return the result of this write operation */
+ ret = regmap_update_bits(regmap, rdev->desc->vsel_reg, mask, sel);
+
+ /* Unconditionally re-lock TMA */
+ val = 0;
+ regmap_bulk_write(rdev->regmap, MT6363_TOP_TMA_KEY_L, &val, 2);
+
+ return ret;
+}
+
+static int mt6363_vemc_get_voltage_sel(struct regulator_dev *rdev)
+{
+ unsigned int sel, trap;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &sel);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(rdev->regmap, MT6363_TOP_TRAP, &trap);
+ if (ret)
+ return ret;
+
+ /* If HW trapping value is 1, use VEMC_VOSEL_1 instead of VEMC_VOSEL_0 */
+ if (trap > 1)
+ return -EINVAL;
+ else if (trap == 1)
+ ret = FIELD_GET(MT6363_RG_VEMC_VOSEL_1_MASK, sel);
+ else
+ ret = sel & rdev->desc->vsel_mask;
+
+ return ret;
+}
+
+static int mt6363_va15_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+ struct regmap *regmap = rdev->regmap;
+ int ret;
+
+ ret = mt6363_buck_unlock(regmap, true);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(regmap, rdev->desc->vsel_reg, rdev->desc->vsel_mask, sel);
+ if (ret)
+ goto va15_unlock;
+
+ ret = regmap_update_bits(regmap, MT6363_RG_BUCK_EFUSE_RSV1,
+ MT6363_RG_BUCK_EFUSE_RSV1_MASK, sel);
+ if (ret)
+ goto va15_unlock;
+
+va15_unlock:
+ mt6363_buck_unlock(rdev->regmap, false);
+ return ret;
+}
+
+static const struct regulator_ops mt6363_vreg_setclr_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = mt6363_vreg_enable_setclr,
+ .disable = mt6363_vreg_disable_setclr,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6363_regulator_set_mode,
+ .get_mode = mt6363_regulator_get_mode,
+ .set_load = mt6363_regulator_set_load,
+};
+
+/* SSHUB LDO doesn't support mode and load settings */
+static const struct regulator_ops mt6363_sshub_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_ops mt6363_ldo_linear_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6363_regulator_set_mode,
+ .get_mode = mt6363_regulator_get_mode,
+};
+
+static const struct regulator_ops mt6363_ldo_vtable_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6363_regulator_set_mode,
+ .get_mode = mt6363_regulator_get_mode,
+ .set_load = mt6363_regulator_set_load,
+};
+
+static const struct regulator_ops mt6363_ldo_vemc_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = mt6363_vemc_set_voltage_sel,
+ .get_voltage_sel = mt6363_vemc_get_voltage_sel,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6363_regulator_set_mode,
+ .get_mode = mt6363_regulator_get_mode,
+ .set_load = mt6363_regulator_set_load,
+};
+
+static const struct regulator_ops mt6363_ldo_va15_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = mt6363_va15_set_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6363_regulator_set_mode,
+ .get_mode = mt6363_regulator_get_mode,
+ .set_load = mt6363_regulator_set_load,
+};
+
+static int mt6363_isink_load_enable(struct regulator_dev *rdev)
+{
+ int ret;
+
+ ret = regmap_set_bits(rdev->regmap, MT6363_ISINK_EN_CTRL0,
+ MT6363_ISINK_CTRL0_MASK);
+ if (ret)
+ return ret;
+
+ return regmap_set_bits(rdev->regmap, MT6363_ISINK_EN_CTRL1,
+ MT6363_ISINK_CTRL1_MASK);
+}
+
+static int mt6363_isink_load_disable(struct regulator_dev *rdev)
+{
+ int ret;
+
+ ret = regmap_clear_bits(rdev->regmap, MT6363_ISINK_EN_CTRL1, MT6363_ISINK_CTRL1_MASK);
+ if (ret)
+ return ret;
+
+ return regmap_clear_bits(rdev->regmap, MT6363_ISINK_EN_CTRL0, MT6363_ISINK_CTRL0_MASK);
+}
+
+static int mt6363_isink_load_is_enabled(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, MT6363_ISINK_EN_CTRL1, &val);
+ if (ret)
+ return ret;
+
+ return (val & MT6363_ISINK_CTRL1_MASK) == MT6363_ISINK_CTRL1_MASK;
+}
+
+static const struct regulator_ops mt6363_isink_load_ops = {
+ .enable = mt6363_isink_load_enable,
+ .disable = mt6363_isink_load_disable,
+ .is_enabled = mt6363_isink_load_is_enabled,
+};
+
+/* The array is indexed by id(MT6363_ID_XXX) */
+static struct mt6363_regulator_info mt6363_regulators[] = {
+ MT6363_BUCK("buck-vs2", VS2, 0, 1600000, 12500,
+ MT6363_RG_BUCK0_EN_ADDR,
+ MT6363_RG_BUCK_VS2_EN_BIT,
+ MT6363_RG_BUCK_VS2_VOSEL_ADDR,
+ MT6363_RG_BUCK_VS2_VOSEL_MASK,
+ MT6363_RG_BUCK0_LP_ADDR,
+ MT6363_RG_BUCK_VS2_LP_BIT,
+ MT6363_RG_BUCK0_FCCM_ADDR,
+ MT6363_RG_VS2_FCCM_BIT),
+ MT6363_BUCK("buck-vb1", VBUCK1, 0, 1193750, 6250,
+ MT6363_RG_BUCK0_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK1_EN_BIT,
+ MT6363_RG_BUCK_VBUCK1_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK1_VOSEL_MASK,
+ MT6363_RG_BUCK0_LP_ADDR,
+ MT6363_RG_BUCK_VBUCK1_LP_BIT,
+ MT6363_RG_BUCK0_FCCM_ADDR,
+ MT6363_RG_VBUCK1_FCCM_BIT),
+ MT6363_BUCK("buck-vb2", VBUCK2, 0, 1193750, 6250,
+ MT6363_RG_BUCK0_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK2_EN_BIT,
+ MT6363_RG_BUCK_VBUCK2_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK2_VOSEL_MASK,
+ MT6363_RG_BUCK0_LP_ADDR,
+ MT6363_RG_BUCK_VBUCK2_LP_BIT,
+ MT6363_RG_BUCK0_FCCM_ADDR,
+ MT6363_RG_VBUCK2_FCCM_BIT),
+ MT6363_BUCK("buck-vb3", VBUCK3, 0, 1193750, 6250,
+ MT6363_RG_BUCK0_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK3_EN_BIT,
+ MT6363_RG_BUCK_VBUCK3_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK3_VOSEL_MASK,
+ MT6363_RG_BUCK0_LP_ADDR,
+ MT6363_RG_BUCK_VBUCK3_LP_BIT,
+ MT6363_RG_BUCK0_FCCM_ADDR,
+ MT6363_RG_VBUCK3_FCCM_BIT),
+ MT6363_BUCK("buck-vb4", VBUCK4, 0, 1193750, 6250,
+ MT6363_RG_BUCK0_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK4_EN_BIT,
+ MT6363_RG_BUCK_VBUCK4_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK4_VOSEL_MASK,
+ MT6363_RG_BUCK0_LP_ADDR,
+ MT6363_RG_BUCK_VBUCK4_LP_BIT,
+ MT6363_RG_BUCK0_1_FCCM_ADDR,
+ MT6363_RG_VBUCK4_FCCM_BIT),
+ MT6363_BUCK("buck-vb5", VBUCK5, 0, 1193750, 6250,
+ MT6363_RG_BUCK0_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK5_EN_BIT,
+ MT6363_RG_BUCK_VBUCK5_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK5_VOSEL_MASK,
+ MT6363_RG_BUCK0_LP_ADDR,
+ MT6363_RG_BUCK_VBUCK5_LP_BIT,
+ MT6363_RG_BUCK0_1_FCCM_ADDR,
+ MT6363_RG_VBUCK5_FCCM_BIT),
+ MT6363_BUCK("buck-vb6", VBUCK6, 0, 1193750, 6250,
+ MT6363_RG_BUCK0_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK6_EN_BIT,
+ MT6363_RG_BUCK_VBUCK6_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK6_VOSEL_MASK,
+ MT6363_RG_BUCK0_LP_ADDR,
+ MT6363_RG_BUCK_VBUCK6_LP_BIT,
+ MT6363_RG_BUCK0_1_FCCM_ADDR,
+ MT6363_RG_VBUCK6_FCCM_BIT),
+ MT6363_BUCK("buck-vb7", VBUCK7, 0, 1193750, 6250,
+ MT6363_RG_BUCK0_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK7_EN_BIT,
+ MT6363_RG_BUCK_VBUCK7_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK7_VOSEL_MASK,
+ MT6363_RG_BUCK0_LP_ADDR,
+ MT6363_RG_BUCK_VBUCK7_LP_BIT,
+ MT6363_RG_BUCK0_1_FCCM_ADDR,
+ MT6363_RG_VBUCK7_FCCM_BIT),
+ MT6363_BUCK("buck-vs1", VS1, 0, 2200000, 12500,
+ MT6363_RG_BUCK1_EN_ADDR,
+ MT6363_RG_BUCK_VS1_EN_BIT,
+ MT6363_RG_BUCK_VS1_VOSEL_ADDR,
+ MT6363_RG_BUCK_VS1_VOSEL_MASK,
+ MT6363_RG_BUCK1_LP_ADDR,
+ MT6363_RG_BUCK_VS1_LP_BIT,
+ MT6363_RG_VS1_FCCM_ADDR,
+ MT6363_RG_VS1_FCCM_BIT),
+ MT6363_BUCK("buck-vs3", VS3, 0, 1193750, 6250,
+ MT6363_RG_BUCK1_EN_ADDR,
+ MT6363_RG_BUCK_VS3_EN_BIT,
+ MT6363_RG_BUCK_VS3_VOSEL_ADDR,
+ MT6363_RG_BUCK_VS3_VOSEL_MASK,
+ MT6363_RG_BUCK1_LP_ADDR,
+ MT6363_RG_BUCK_VS3_LP_BIT,
+ MT6363_RG_VS3_FCCM_ADDR,
+ MT6363_RG_VS3_FCCM_BIT),
+ MT6363_SSHUB("buck-sshub1", VBUCK1_SSHUB, 0, 1193750, 6250,
+ MT6363_RG_BUCK_VBUCK1_SSHUB_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK1_SSHUB_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK1_SSHUB_VOSEL_MASK),
+ MT6363_SSHUB("buck-sshub2", VBUCK2_SSHUB, 0, 1193750, 6250,
+ MT6363_RG_BUCK_VBUCK2_SSHUB_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK2_SSHUB_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK2_SSHUB_VOSEL_MASK),
+ MT6363_SSHUB("buck-sshub4", VBUCK4_SSHUB, 0, 1193750, 6250,
+ MT6363_RG_BUCK_VBUCK4_SSHUB_EN_ADDR,
+ MT6363_RG_BUCK_VBUCK4_SSHUB_VOSEL_ADDR,
+ MT6363_RG_BUCK_VBUCK4_SSHUB_VOSEL_MASK),
+ MT6363_LDO_L_SC("ldo-vsram-digrf", VSRAM_DIGRF, 400000, 1193750, 6250,
+ MT6363_RG_BUCK1_EN_ADDR,
+ MT6363_RG_LDO_VSRAM_DIGRF_EN_BIT,
+ MT6363_RG_LDO_VSRAM_DIGRF_VOSEL_ADDR,
+ MT6363_RG_LDO_VSRAM_DIGRF_VOSEL_MASK,
+ MT6363_RG_BUCK1_LP_ADDR,
+ MT6363_RG_LDO_VSRAM_DIGRF_LP_BIT),
+ MT6363_LDO_L_SC("ldo-vsram-mdfe", VSRAM_MDFE, 400000, 1193750, 6250,
+ MT6363_RG_BUCK1_EN_ADDR,
+ MT6363_RG_LDO_VSRAM_MDFE_EN_BIT,
+ MT6363_RG_LDO_VSRAM_MDFE_VOSEL_ADDR,
+ MT6363_RG_LDO_VSRAM_MDFE_VOSEL_MASK,
+ MT6363_RG_BUCK1_LP_ADDR,
+ MT6363_RG_LDO_VSRAM_MDFE_LP_BIT),
+ MT6363_LDO_L_SC("ldo-vsram-modem", VSRAM_MODEM, 400000, 1193750, 6250,
+ MT6363_RG_BUCK1_EN_ADDR,
+ MT6363_RG_LDO_VSRAM_MODEM_EN_BIT,
+ MT6363_RG_LDO_VSRAM_MODEM_VOSEL_ADDR,
+ MT6363_RG_LDO_VSRAM_MODEM_VOSEL_MASK,
+ MT6363_RG_BUCK1_LP_ADDR,
+ MT6363_RG_LDO_VSRAM_MODEM_LP_BIT),
+ MT6363_LDO_L("ldo-vsram-cpub", VSRAM_CPUB, 400000, 1193750, 6250,
+ MT6363_RG_LDO_VSRAM_CPUB_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUB_EN_BIT,
+ MT6363_RG_LDO_VSRAM_CPUB_VOSEL_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUB_VOSEL_MASK,
+ MT6363_RG_LDO_VSRAM_CPUB_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUB_LP_BIT),
+ MT6363_LDO_L("ldo-vsram-cpum", VSRAM_CPUM, 400000, 1193750, 6250,
+ MT6363_RG_LDO_VSRAM_CPUM_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUM_EN_BIT,
+ MT6363_RG_LDO_VSRAM_CPUM_VOSEL_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUM_VOSEL_MASK,
+ MT6363_RG_LDO_VSRAM_CPUM_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUM_LP_BIT),
+ MT6363_LDO_L("ldo-vsram-cpul", VSRAM_CPUL, 400000, 1193750, 6250,
+ MT6363_RG_LDO_VSRAM_CPUL_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUL_EN_BIT,
+ MT6363_RG_LDO_VSRAM_CPUL_VOSEL_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUL_VOSEL_MASK,
+ MT6363_RG_LDO_VSRAM_CPUL_ADDR,
+ MT6363_RG_LDO_VSRAM_CPUL_LP_BIT),
+ MT6363_LDO_L("ldo-vsram-apu", VSRAM_APU, 400000, 1193750, 6250,
+ MT6363_RG_LDO_VSRAM_APU_ADDR,
+ MT6363_RG_LDO_VSRAM_APU_EN_BIT,
+ MT6363_RG_LDO_VSRAM_APU_VOSEL_ADDR,
+ MT6363_RG_LDO_VSRAM_APU_VOSEL_MASK,
+ MT6363_RG_LDO_VSRAM_APU_ADDR,
+ MT6363_RG_LDO_VSRAM_APU_LP_BIT),
+ MT6363_LDO_VT_OPS("ldo-vemc", VEMC, mt6363_ldo_vemc_ops, ldo_vemc_volt_table,
+ MT6363_RG_LDO_VEMC_ADDR, MT6363_RG_LDO_VEMC_EN_BIT,
+ MT6363_RG_VEMC_VOSEL_0_ADDR,
+ MT6363_RG_VEMC_VOSEL_0_MASK,
+ MT6363_RG_VEMC_VOCAL_0_ADDR,
+ MT6363_RG_VEMC_VOCAL_0_MASK,
+ MT6363_RG_LDO_VEMC_ADDR,
+ MT6363_RG_LDO_VEMC_LP_BIT),
+ MT6363_LDO_VT("ldo-vcn13", VCN13, ldo_volt_table1,
+ MT6363_RG_LDO_VCN13_ADDR, MT6363_RG_LDO_VCN13_EN_BIT,
+ MT6363_RG_VCN13_VOSEL_ADDR,
+ MT6363_RG_VCN13_VOSEL_MASK,
+ MT6363_RG_VCN13_VOCAL_ADDR,
+ MT6363_RG_VCN13_VOCAL_MASK,
+ MT6363_RG_LDO_VCN13_ADDR,
+ MT6363_RG_LDO_VCN13_LP_BIT),
+ MT6363_LDO_VT("ldo-vtref18", VTREF18, ldo_volt_table2,
+ MT6363_RG_LDO_VTREF18_ADDR, MT6363_RG_LDO_VTREF18_EN_BIT,
+ MT6363_RG_VTREF18_VOSEL_ADDR,
+ MT6363_RG_VTREF18_VOSEL_MASK,
+ MT6363_RG_VTREF18_VOCAL_ADDR,
+ MT6363_RG_VTREF18_VOCAL_MASK,
+ MT6363_RG_LDO_VTREF18_ADDR,
+ MT6363_RG_LDO_VTREF18_LP_BIT),
+ MT6363_LDO_VT("ldo-vaux18", VAUX18, ldo_volt_table2,
+ MT6363_RG_LDO_VAUX18_ADDR, MT6363_RG_LDO_VAUX18_EN_BIT,
+ MT6363_RG_VAUX18_VOSEL_ADDR,
+ MT6363_RG_VAUX18_VOSEL_MASK,
+ MT6363_RG_VAUX18_VOCAL_ADDR,
+ MT6363_RG_VAUX18_VOCAL_MASK,
+ MT6363_RG_LDO_VAUX18_ADDR,
+ MT6363_RG_LDO_VAUX18_LP_BIT),
+ MT6363_LDO_VT("ldo-vcn15", VCN15, ldo_volt_table3,
+ MT6363_RG_LDO_VCN15_ADDR, MT6363_RG_LDO_VCN15_EN_BIT,
+ MT6363_RG_VCN15_VOSEL_ADDR,
+ MT6363_RG_VCN15_VOSEL_MASK,
+ MT6363_RG_VCN15_VOCAL_ADDR,
+ MT6363_RG_VCN15_VOCAL_MASK,
+ MT6363_RG_LDO_VCN15_ADDR,
+ MT6363_RG_LDO_VCN15_LP_BIT),
+ MT6363_LDO_VT("ldo-vufs18", VUFS18, ldo_volt_table3,
+ MT6363_RG_LDO_VUFS18_ADDR, MT6363_RG_LDO_VUFS18_EN_BIT,
+ MT6363_RG_VUFS18_VOSEL_ADDR,
+ MT6363_RG_VUFS18_VOSEL_MASK,
+ MT6363_RG_VUFS18_VOCAL_ADDR,
+ MT6363_RG_VUFS18_VOCAL_MASK,
+ MT6363_RG_LDO_VUFS18_ADDR,
+ MT6363_RG_LDO_VUFS18_LP_BIT),
+ MT6363_LDO_VT("ldo-vio18", VIO18, ldo_volt_table3,
+ MT6363_RG_LDO_VIO18_ADDR, MT6363_RG_LDO_VIO18_EN_BIT,
+ MT6363_RG_VIO18_VOSEL_ADDR,
+ MT6363_RG_VIO18_VOSEL_MASK,
+ MT6363_RG_VIO18_VOCAL_ADDR,
+ MT6363_RG_VIO18_VOCAL_MASK,
+ MT6363_RG_LDO_VIO18_ADDR,
+ MT6363_RG_LDO_VIO18_LP_BIT),
+ MT6363_LDO_VT("ldo-vm18", VM18, ldo_volt_table4,
+ MT6363_RG_LDO_VM18_ADDR, MT6363_RG_LDO_VM18_EN_BIT,
+ MT6363_RG_VM18_VOSEL_ADDR,
+ MT6363_RG_VM18_VOSEL_MASK,
+ MT6363_RG_VM18_VOCAL_ADDR,
+ MT6363_RG_VM18_VOCAL_MASK,
+ MT6363_RG_LDO_VM18_ADDR,
+ MT6363_RG_LDO_VM18_LP_BIT),
+ MT6363_LDO_VT_OPS("ldo-va15", VA15, mt6363_ldo_va15_ops, ldo_volt_table3,
+ MT6363_RG_LDO_VA15_ADDR, MT6363_RG_LDO_VA15_EN_BIT,
+ MT6363_RG_VA15_VOSEL_ADDR,
+ MT6363_RG_VA15_VOSEL_MASK,
+ MT6363_RG_VA15_VOCAL_ADDR,
+ MT6363_RG_VA15_VOCAL_MASK,
+ MT6363_RG_LDO_VA15_ADDR,
+ MT6363_RG_LDO_VA15_LP_BIT),
+ MT6363_LDO_VT("ldo-vrf18", VRF18, ldo_volt_table3,
+ MT6363_RG_LDO_VRF18_ADDR, MT6363_RG_LDO_VRF18_EN_BIT,
+ MT6363_RG_VRF18_VOSEL_ADDR,
+ MT6363_RG_VRF18_VOSEL_MASK,
+ MT6363_RG_VRF18_VOCAL_ADDR,
+ MT6363_RG_VRF18_VOCAL_MASK,
+ MT6363_RG_LDO_VRF18_ADDR,
+ MT6363_RG_LDO_VRF18_LP_BIT),
+ MT6363_LDO_VT("ldo-vrf-io18", VRFIO18, ldo_volt_table3,
+ MT6363_RG_LDO_VRFIO18_ADDR, MT6363_RG_LDO_VRFIO18_EN_BIT,
+ MT6363_RG_VRFIO18_VOSEL_ADDR,
+ MT6363_RG_VRFIO18_VOSEL_MASK,
+ MT6363_RG_VRFIO18_VOCAL_ADDR,
+ MT6363_RG_VRFIO18_VOCAL_MASK,
+ MT6363_RG_LDO_VRFIO18_ADDR,
+ MT6363_RG_LDO_VRFIO18_LP_BIT),
+ MT6363_LDO_VT("ldo-vio0p75", VIO075, ldo_volt_table5,
+ MT6363_RG_LDO_VIO075_ADDR, MT6363_RG_LDO_VIO075_EN_BIT,
+ MT6363_RG_VIO075_VOCFG_ADDR,
+ MT6363_RG_VIO075_VOSEL_MASK,
+ MT6363_RG_VIO075_VOCFG_ADDR,
+ MT6363_RG_VIO075_VOCAL_MASK,
+ MT6363_RG_LDO_VIO075_ADDR,
+ MT6363_RG_LDO_VIO075_LP_BIT),
+ MT6363_LDO_VT("ldo-vufs12", VUFS12, ldo_volt_table4,
+ MT6363_RG_LDO_VUFS12_ADDR, MT6363_RG_LDO_VUFS12_EN_BIT,
+ MT6363_RG_VUFS12_VOSEL_ADDR,
+ MT6363_RG_VUFS12_VOSEL_MASK,
+ MT6363_RG_VUFS12_VOCAL_ADDR,
+ MT6363_RG_VUFS12_VOCAL_MASK,
+ MT6363_RG_LDO_VUFS12_ADDR,
+ MT6363_RG_LDO_VUFS12_LP_BIT),
+ MT6363_LDO_VT("ldo-va12-1", VA12_1, ldo_volt_table3,
+ MT6363_RG_LDO_VA12_1_ADDR, MT6363_RG_LDO_VA12_1_EN_BIT,
+ MT6363_RG_VA12_1_VOSEL_ADDR,
+ MT6363_RG_VA12_1_VOSEL_MASK,
+ MT6363_RG_VA12_1_VOCAL_ADDR,
+ MT6363_RG_VA12_1_VOCAL_MASK,
+ MT6363_RG_LDO_VA12_1_ADDR,
+ MT6363_RG_LDO_VA12_1_LP_BIT),
+ MT6363_LDO_VT("ldo-va12-2", VA12_2, ldo_volt_table3,
+ MT6363_RG_LDO_VA12_2_ADDR, MT6363_RG_LDO_VA12_2_EN_BIT,
+ MT6363_RG_VA12_2_VOSEL_ADDR,
+ MT6363_RG_VA12_2_VOSEL_MASK,
+ MT6363_RG_VA12_2_VOCAL_ADDR,
+ MT6363_RG_VA12_2_VOCAL_MASK,
+ MT6363_RG_LDO_VA12_2_ADDR,
+ MT6363_RG_LDO_VA12_2_LP_BIT),
+ MT6363_LDO_VT("ldo-vrf12", VRF12, ldo_volt_table3,
+ MT6363_RG_LDO_VRF12_ADDR, MT6363_RG_LDO_VRF12_EN_BIT,
+ MT6363_RG_VRF12_VOSEL_ADDR,
+ MT6363_RG_VRF12_VOSEL_MASK,
+ MT6363_RG_VRF12_VOCAL_ADDR,
+ MT6363_RG_VRF12_VOCAL_MASK,
+ MT6363_RG_LDO_VRF12_ADDR,
+ MT6363_RG_LDO_VRF12_LP_BIT),
+ MT6363_LDO_VT("ldo-vrf13", VRF13, ldo_volt_table1,
+ MT6363_RG_LDO_VRF13_ADDR, MT6363_RG_LDO_VRF13_EN_BIT,
+ MT6363_RG_VRF13_VOSEL_ADDR,
+ MT6363_RG_VRF13_VOSEL_MASK,
+ MT6363_RG_VRF13_VOCAL_ADDR,
+ MT6363_RG_VRF13_VOCAL_MASK,
+ MT6363_RG_LDO_VRF13_ADDR,
+ MT6363_RG_LDO_VRF13_LP_BIT),
+ MT6363_LDO_VT("ldo-vrf0p9", VRF09, ldo_volt_table1,
+ MT6363_RG_LDO_VRF09_ADDR, MT6363_RG_LDO_VRF09_EN_BIT,
+ MT6363_RG_VRF09_VOSEL_ADDR,
+ MT6363_RG_VRF09_VOSEL_MASK,
+ MT6363_RG_VRF09_VOCAL_ADDR,
+ MT6363_RG_VRF09_VOCAL_MASK,
+ MT6363_RG_LDO_VRF09_ADDR,
+ MT6363_RG_LDO_VRF09_LP_BIT),
+ [MT6363_ID_ISINK_LOAD] = {
+ .desc = {
+ .name = "ISINK_LOAD",
+ .of_match = of_match_ptr("isink-load"),
+ .id = MT6363_ID_ISINK_LOAD,
+ .type = REGULATOR_CURRENT,
+ .ops = &mt6363_isink_load_ops,
+ .owner = THIS_MODULE,
+ },
+ }
+};
+
+static void mt6363_oc_irq_enable_work(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct mt6363_regulator_info *info =
+ container_of(dwork, struct mt6363_regulator_info, oc_work);
+
+ enable_irq(info->irq);
+}
+
+static irqreturn_t mt6363_oc_isr(int irq, void *data)
+{
+ struct regulator_dev *rdev = (struct regulator_dev *)data;
+ struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
+
+ disable_irq_nosync(info->irq);
+
+ if (regulator_is_enabled_regmap(rdev))
+ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+ schedule_delayed_work(&info->oc_work, msecs_to_jiffies(OC_IRQ_ENABLE_DELAY_MS));
+
+ return IRQ_HANDLED;
+}
+
+static int mt6363_backup_op_setting(struct regmap *map, struct mt6363_regulator_info *info)
+{
+ unsigned int i, val;
+ int ret;
+
+ ret = regmap_read(map, info->op_en_reg + OP_CFG_OFFSET, &val);
+ if (ret)
+ return ret;
+
+ info->orig_op_cfg = val;
+
+ for (i = 0; i < 3; i++) {
+ ret = regmap_read(map, info->op_en_reg + i, &val);
+ if (ret)
+ return ret;
+
+ info->orig_op_en |= val << (i * 8);
+ }
+
+ return 0;
+}
+
+static int mt6363_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = {};
+ struct mt6363_regulator_info *info;
+ struct regulator_dev *rdev;
+ int i, ret;
+
+ config.regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!config.regmap)
+ return dev_err_probe(&pdev->dev, -ENODEV, "Cannot get regmap\n");
+
+ config.dev = &pdev->dev;
+
+ for (i = 0; i < ARRAY_SIZE(mt6363_regulators); i++) {
+ info = &mt6363_regulators[i];
+ info->irq = platform_get_irq_byname_optional(pdev, info->desc.name);
+
+ config.driver_data = info;
+ rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
+ if (IS_ERR(rdev))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rdev),
+ "failed to register %s\n", info->desc.name);
+
+ if (info->lp_imax_uA) {
+ ret = mt6363_backup_op_setting(config.regmap, info);
+ if (ret) {
+ dev_warn(&pdev->dev, "failed to backup op_setting for %s\n",
+ info->desc.name);
+ info->lp_imax_uA = 0;
+ }
+ }
+
+ if (info->irq <= 0)
+ continue;
+ ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
+ mt6363_oc_isr, IRQF_ONESHOT,
+ info->desc.name, rdev);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to request overcurrent IRQ for %s\n",
+ info->desc.name);
+
+ INIT_DELAYED_WORK(&info->oc_work, mt6363_oc_irq_enable_work);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mt6363_regulator_match[] = {
+ { .compatible = "mediatek,mt6363-regulator" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver mt6363_regulator_driver = {
+ .driver = {
+ .name = "mt6363-regulator",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ .of_match_table = mt6363_regulator_match,
+ },
+ .probe = mt6363_regulator_probe,
+};
+module_platform_driver(mt6363_regulator_driver);
+
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6363 PMIC");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/regulator/mt6363-regulator.h b/include/linux/regulator/mt6363-regulator.h
new file mode 100644
index 000000000000..e2580bcd4d73
--- /dev/null
+++ b/include/linux/regulator/mt6363-regulator.h
@@ -0,0 +1,326 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ * Copyright (c) 2025 Collabora Ltd
+ */
+
+#include <linux/bits.h>
+
+#ifndef __LINUX_REGULATOR_MT6363_H
+#define __LINUX_REGULATOR_MT6363_H
+
+/* Register */
+#define MT6363_TOP_TRAP 0x36
+#define MT6363_TOP_TMA_KEY_L 0x39e
+#define MT6363_RG_BUCK0_EN_ADDR 0x240
+#define MT6363_RG_BUCK_VS2_EN_BIT 0
+#define MT6363_RG_BUCK_VBUCK1_EN_BIT 1
+#define MT6363_RG_BUCK_VBUCK2_EN_BIT 2
+#define MT6363_RG_BUCK_VBUCK3_EN_BIT 3
+#define MT6363_RG_BUCK_VBUCK4_EN_BIT 4
+#define MT6363_RG_BUCK_VBUCK5_EN_BIT 5
+#define MT6363_RG_BUCK_VBUCK6_EN_BIT 6
+#define MT6363_RG_BUCK_VBUCK7_EN_BIT 7
+#define MT6363_RG_BUCK1_EN_ADDR 0x243
+#define MT6363_RG_BUCK_VS1_EN_BIT 0
+#define MT6363_RG_BUCK_VS3_EN_BIT 1
+#define MT6363_RG_LDO_VSRAM_DIGRF_EN_BIT 4
+#define MT6363_RG_LDO_VSRAM_MDFE_EN_BIT 5
+#define MT6363_RG_LDO_VSRAM_MODEM_EN_BIT 6
+#define MT6363_RG_BUCK0_LP_ADDR 0x246
+#define MT6363_RG_BUCK_VS2_LP_BIT 0
+#define MT6363_RG_BUCK_VBUCK1_LP_BIT 1
+#define MT6363_RG_BUCK_VBUCK2_LP_BIT 2
+#define MT6363_RG_BUCK_VBUCK3_LP_BIT 3
+#define MT6363_RG_BUCK_VBUCK4_LP_BIT 4
+#define MT6363_RG_BUCK_VBUCK5_LP_BIT 5
+#define MT6363_RG_BUCK_VBUCK6_LP_BIT 6
+#define MT6363_RG_BUCK_VBUCK7_LP_BIT 7
+#define MT6363_RG_BUCK1_LP_ADDR 0x249
+#define MT6363_RG_BUCK_VS1_LP_BIT 0
+#define MT6363_RG_BUCK_VS3_LP_BIT 1
+#define MT6363_RG_LDO_VSRAM_DIGRF_LP_BIT 4
+#define MT6363_RG_LDO_VSRAM_MDFE_LP_BIT 5
+#define MT6363_RG_LDO_VSRAM_MODEM_LP_BIT 6
+#define MT6363_RG_BUCK_VS2_VOSEL_ADDR 0x24c
+#define MT6363_RG_BUCK_VS2_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VBUCK1_VOSEL_ADDR 0x24d
+#define MT6363_RG_BUCK_VBUCK1_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VBUCK2_VOSEL_ADDR 0x24e
+#define MT6363_RG_BUCK_VBUCK2_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VBUCK3_VOSEL_ADDR 0x24f
+#define MT6363_RG_BUCK_VBUCK3_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VBUCK4_VOSEL_ADDR 0x250
+#define MT6363_RG_BUCK_VBUCK4_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VBUCK5_VOSEL_ADDR 0x251
+#define MT6363_RG_BUCK_VBUCK5_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VBUCK6_VOSEL_ADDR 0x252
+#define MT6363_RG_BUCK_VBUCK6_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VBUCK7_VOSEL_ADDR 0x253
+#define MT6363_RG_BUCK_VBUCK7_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VS1_VOSEL_ADDR 0x254
+#define MT6363_RG_BUCK_VS1_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_BUCK_VS3_VOSEL_ADDR 0x255
+#define MT6363_RG_BUCK_VS3_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_RG_LDO_VSRAM_DIGRF_VOSEL_ADDR 0x258
+#define MT6363_RG_LDO_VSRAM_DIGRF_VOSEL_MASK GENMASK(6, 0)
+#define MT6363_RG_LDO_VSRAM_MDFE_VOSEL_ADDR 0x259
+#define MT6363_RG_LDO_VSRAM_MDFE_VOSEL_MASK GENMASK(6, 0)
+#define MT6363_RG_LDO_VSRAM_MODEM_VOSEL_ADDR 0x25a
+#define MT6363_RG_LDO_VSRAM_MODEM_VOSEL_MASK GENMASK(6, 0)
+#define MT6363_BUCK_TOP_KEY_PROT_LO 0x142a
+#define MT6363_BUCK_VS2_WDTDBG_VOSEL_ADDR 0x142c
+#define MT6363_BUCK_VBUCK1_WDTDBG_VOSEL_ADDR 0x142d
+#define MT6363_BUCK_VBUCK2_WDTDBG_VOSEL_ADDR 0x142e
+#define MT6363_BUCK_VBUCK3_WDTDBG_VOSEL_ADDR 0x142f
+#define MT6363_BUCK_VBUCK4_WDTDBG_VOSEL_ADDR 0x1430
+#define MT6363_BUCK_VBUCK5_WDTDBG_VOSEL_ADDR 0x1431
+#define MT6363_BUCK_VBUCK6_WDTDBG_VOSEL_ADDR 0x1432
+#define MT6363_BUCK_VBUCK7_WDTDBG_VOSEL_ADDR 0x1433
+#define MT6363_BUCK_VS1_WDTDBG_VOSEL_ADDR 0x1434
+#define MT6363_BUCK_VS3_WDTDBG_VOSEL_ADDR 0x1435
+#define MT6363_BUCK_VS2_OP_EN_0 0x148d
+#define MT6363_BUCK_VS2_HW_LP_MODE 0x1498
+#define MT6363_BUCK_VBUCK1_OP_EN_0 0x150d
+#define MT6363_BUCK_VBUCK1_HW_LP_MODE 0x1518
+#define MT6363_RG_BUCK_VBUCK1_SSHUB_EN_ADDR 0x151a
+#define MT6363_RG_BUCK_VBUCK1_SSHUB_VOSEL_ADDR 0x151b
+#define MT6363_RG_BUCK_VBUCK1_SSHUB_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_BUCK_VBUCK2_OP_EN_0 0x158d
+#define MT6363_BUCK_VBUCK2_HW_LP_MODE 0x1598
+#define MT6363_RG_BUCK_VBUCK2_SSHUB_EN_ADDR 0x159a
+#define MT6363_RG_BUCK_VBUCK2_SSHUB_VOSEL_ADDR 0x159b
+#define MT6363_RG_BUCK_VBUCK2_SSHUB_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_BUCK_VBUCK3_OP_EN_0 0x160d
+#define MT6363_BUCK_VBUCK3_HW_LP_MODE 0x1618
+#define MT6363_BUCK_VBUCK4_OP_EN_0 0x168d
+#define MT6363_BUCK_VBUCK4_HW_LP_MODE 0x1698
+#define MT6363_RG_BUCK_VBUCK4_SSHUB_EN_ADDR 0x169a
+#define MT6363_RG_BUCK_VBUCK4_SSHUB_VOSEL_ADDR 0x169b
+#define MT6363_RG_BUCK_VBUCK4_SSHUB_VOSEL_MASK GENMASK(7, 0)
+#define MT6363_BUCK_VBUCK5_OP_EN_0 0x170d
+#define MT6363_BUCK_VBUCK5_HW_LP_MODE 0x1718
+#define MT6363_BUCK_VBUCK6_OP_EN_0 0x178d
+#define MT6363_BUCK_VBUCK6_HW_LP_MODE 0x1798
+#define MT6363_BUCK_VBUCK7_OP_EN_0 0x180d
+#define MT6363_BUCK_VBUCK7_HW_LP_MODE 0x1818
+#define MT6363_BUCK_VS1_OP_EN_0 0x188d
+#define MT6363_BUCK_VS1_HW_LP_MODE 0x1898
+#define MT6363_BUCK_VS3_OP_EN_0 0x190d
+#define MT6363_BUCK_VS3_HW_LP_MODE 0x1918
+#define MT6363_RG_VS1_FCCM_ADDR 0x1994
+#define MT6363_RG_VS1_FCCM_BIT 0
+#define MT6363_RG_VS3_FCCM_ADDR 0x19a3
+#define MT6363_RG_VS3_FCCM_BIT 0
+#define MT6363_RG_BUCK0_FCCM_ADDR 0x1a32
+#define MT6363_RG_VBUCK1_FCCM_BIT 0
+#define MT6363_RG_VBUCK2_FCCM_BIT 1
+#define MT6363_RG_VBUCK3_FCCM_BIT 2
+#define MT6363_RG_VS2_FCCM_BIT 3
+#define MT6363_RG_BUCK0_1_FCCM_ADDR 0x1ab2
+#define MT6363_RG_VBUCK4_FCCM_BIT 0
+#define MT6363_RG_VBUCK5_FCCM_BIT 1
+#define MT6363_RG_VBUCK6_FCCM_BIT 2
+#define MT6363_RG_VBUCK7_FCCM_BIT 3
+#define MT6363_RG_VCN13_VOSEL_ADDR 0x1b3f
+#define MT6363_RG_VCN13_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VEMC_VOSEL_0_ADDR 0x1b40
+#define MT6363_RG_VEMC_VOSEL_0_MASK GENMASK(3, 0)
+#define MT6363_RG_VEMC_VOSEL_1_MASK GENMASK(7, 4)
+#define MT6363_RG_LDO_VSRAM_CPUB_VOSEL_ADDR 0x1b44
+#define MT6363_RG_LDO_VSRAM_CPUB_VOSEL_MASK GENMASK(6, 0)
+#define MT6363_RG_LDO_VSRAM_CPUM_VOSEL_ADDR 0x1b45
+#define MT6363_RG_LDO_VSRAM_CPUM_VOSEL_MASK GENMASK(6, 0)
+#define MT6363_RG_LDO_VSRAM_CPUL_VOSEL_ADDR 0x1b46
+#define MT6363_RG_LDO_VSRAM_CPUL_VOSEL_MASK GENMASK(6, 0)
+#define MT6363_RG_LDO_VSRAM_APU_VOSEL_ADDR 0x1b47
+#define MT6363_RG_LDO_VSRAM_APU_VOSEL_MASK GENMASK(6, 0)
+#define MT6363_RG_VEMC_VOCAL_0_ADDR 0x1b4b
+#define MT6363_RG_VEMC_VOCAL_0_MASK GENMASK(3, 0)
+#define MT6363_RG_LDO_VCN15_ADDR 0x1b87
+#define MT6363_RG_LDO_VCN15_EN_BIT 0
+#define MT6363_RG_LDO_VCN15_LP_BIT 1
+#define MT6363_LDO_VCN15_HW_LP_MODE 0x1b8b
+#define MT6363_LDO_VCN15_OP_EN0 0x1b8c
+#define MT6363_RG_LDO_VRF09_ADDR 0x1b95
+#define MT6363_RG_LDO_VRF09_EN_BIT 0
+#define MT6363_RG_LDO_VRF09_LP_BIT 1
+#define MT6363_LDO_VRF09_HW_LP_MODE 0x1b99
+#define MT6363_LDO_VRF09_OP_EN0 0x1b9a
+#define MT6363_RG_LDO_VRF12_ADDR 0x1ba3
+#define MT6363_RG_LDO_VRF12_EN_BIT 0
+#define MT6363_RG_LDO_VRF12_LP_BIT 1
+#define MT6363_LDO_VRF12_HW_LP_MODE 0x1ba7
+#define MT6363_LDO_VRF12_OP_EN0 0x1ba8
+#define MT6363_RG_LDO_VRF13_ADDR 0x1bb1
+#define MT6363_RG_LDO_VRF13_EN_BIT 0
+#define MT6363_RG_LDO_VRF13_LP_BIT 1
+#define MT6363_LDO_VRF13_HW_LP_MODE 0x1bb5
+#define MT6363_LDO_VRF13_OP_EN0 0x1bb6
+#define MT6363_RG_LDO_VRF18_ADDR 0x1bbf
+#define MT6363_RG_LDO_VRF18_EN_BIT 0
+#define MT6363_RG_LDO_VRF18_LP_BIT 1
+#define MT6363_LDO_VRF18_HW_LP_MODE 0x1bc3
+#define MT6363_LDO_VRF18_OP_EN0 0x1bc4
+#define MT6363_RG_LDO_VRFIO18_ADDR 0x1bcd
+#define MT6363_RG_LDO_VRFIO18_EN_BIT 0
+#define MT6363_RG_LDO_VRFIO18_LP_BIT 1
+#define MT6363_LDO_VRFIO18_HW_LP_MODE 0x1bd1
+#define MT6363_LDO_VRFIO18_OP_EN0 0x1bd2
+#define MT6363_RG_LDO_VTREF18_ADDR 0x1c07
+#define MT6363_RG_LDO_VTREF18_EN_BIT 0
+#define MT6363_RG_LDO_VTREF18_LP_BIT 1
+#define MT6363_LDO_VTREF18_HW_LP_MODE 0x1c0b
+#define MT6363_LDO_VTREF18_OP_EN0 0x1c0c
+#define MT6363_RG_LDO_VAUX18_ADDR 0x1c15
+#define MT6363_RG_LDO_VAUX18_EN_BIT 0
+#define MT6363_RG_LDO_VAUX18_LP_BIT 1
+#define MT6363_LDO_VAUX18_HW_LP_MODE 0x1c19
+#define MT6363_LDO_VAUX18_OP_EN0 0x1c1a
+#define MT6363_RG_LDO_VEMC_ADDR 0x1c23
+#define MT6363_RG_LDO_VEMC_EN_BIT 0
+#define MT6363_RG_LDO_VEMC_LP_BIT 1
+#define MT6363_LDO_VEMC_HW_LP_MODE 0x1c27
+#define MT6363_LDO_VEMC_OP_EN0 0x1c28
+#define MT6363_RG_LDO_VUFS12_ADDR 0x1c31
+#define MT6363_RG_LDO_VUFS12_EN_BIT 0
+#define MT6363_RG_LDO_VUFS12_LP_BIT 1
+#define MT6363_LDO_VUFS12_HW_LP_MODE 0x1c35
+#define MT6363_LDO_VUFS12_OP_EN0 0x1c36
+#define MT6363_RG_LDO_VUFS18_ADDR 0x1c3f
+#define MT6363_RG_LDO_VUFS18_EN_BIT 0
+#define MT6363_RG_LDO_VUFS18_LP_BIT 1
+#define MT6363_LDO_VUFS18_HW_LP_MODE 0x1c43
+#define MT6363_LDO_VUFS18_OP_EN0 0x1c44
+#define MT6363_RG_LDO_VIO18_ADDR 0x1c4d
+#define MT6363_RG_LDO_VIO18_EN_BIT 0
+#define MT6363_RG_LDO_VIO18_LP_BIT 1
+#define MT6363_LDO_VIO18_HW_LP_MODE 0x1c51
+#define MT6363_LDO_VIO18_OP_EN0 0x1c52
+#define MT6363_RG_LDO_VIO075_ADDR 0x1c87
+#define MT6363_RG_LDO_VIO075_EN_BIT 0
+#define MT6363_RG_LDO_VIO075_LP_BIT 1
+#define MT6363_LDO_VIO075_HW_LP_MODE 0x1c8b
+#define MT6363_LDO_VIO075_OP_EN0 0x1c8c
+#define MT6363_RG_LDO_VA12_1_ADDR 0x1c95
+#define MT6363_RG_LDO_VA12_1_EN_BIT 0
+#define MT6363_RG_LDO_VA12_1_LP_BIT 1
+#define MT6363_LDO_VA12_1_HW_LP_MODE 0x1c99
+#define MT6363_LDO_VA12_1_OP_EN0 0x1c9a
+#define MT6363_RG_LDO_VA12_2_ADDR 0x1ca3
+#define MT6363_RG_LDO_VA12_2_EN_BIT 0
+#define MT6363_RG_LDO_VA12_2_LP_BIT 1
+#define MT6363_LDO_VA12_2_HW_LP_MODE 0x1ca7
+#define MT6363_LDO_VA12_2_OP_EN0 0x1ca8
+#define MT6363_RG_LDO_VA15_ADDR 0x1cb1
+#define MT6363_RG_LDO_VA15_EN_BIT 0
+#define MT6363_RG_LDO_VA15_LP_BIT 1
+#define MT6363_LDO_VA15_HW_LP_MODE 0x1cb5
+#define MT6363_LDO_VA15_OP_EN0 0x1cb6
+#define MT6363_RG_LDO_VM18_ADDR 0x1cbf
+#define MT6363_RG_LDO_VM18_EN_BIT 0
+#define MT6363_RG_LDO_VM18_LP_BIT 1
+#define MT6363_LDO_VM18_HW_LP_MODE 0x1cc3
+#define MT6363_LDO_VM18_OP_EN0 0x1cc4
+#define MT6363_RG_LDO_VCN13_ADDR 0x1d07
+#define MT6363_RG_LDO_VCN13_EN_BIT 0
+#define MT6363_RG_LDO_VCN13_LP_BIT 1
+#define MT6363_LDO_VCN13_HW_LP_MODE 0x1d0b
+#define MT6363_LDO_VCN13_OP_EN0 0x1d14
+#define MT6363_LDO_VSRAM_DIGRF_HW_LP_MODE 0x1d21
+#define MT6363_LDO_VSRAM_DIGRF_OP_EN0 0x1d2a
+#define MT6363_LDO_VSRAM_MDFE_HW_LP_MODE 0x1d8b
+#define MT6363_LDO_VSRAM_MDFE_OP_EN0 0x1d94
+#define MT6363_LDO_VSRAM_MODEM_HW_LP_MODE 0x1da6
+#define MT6363_LDO_VSRAM_MODEM_OP_EN0 0x1daf
+#define MT6363_RG_LDO_VSRAM_CPUB_ADDR 0x1e07
+#define MT6363_RG_LDO_VSRAM_CPUB_EN_BIT 0
+#define MT6363_RG_LDO_VSRAM_CPUB_LP_BIT 1
+#define MT6363_LDO_VSRAM_CPUB_HW_LP_MODE 0x1e0b
+#define MT6363_LDO_VSRAM_CPUB_OP_EN0 0x1e14
+#define MT6363_RG_LDO_VSRAM_CPUM_ADDR 0x1e1d
+#define MT6363_RG_LDO_VSRAM_CPUM_EN_BIT 0
+#define MT6363_RG_LDO_VSRAM_CPUM_LP_BIT 1
+#define MT6363_LDO_VSRAM_CPUM_HW_LP_MODE 0x1e21
+#define MT6363_LDO_VSRAM_CPUM_OP_EN0 0x1e2a
+#define MT6363_RG_LDO_VSRAM_CPUL_ADDR 0x1e87
+#define MT6363_RG_LDO_VSRAM_CPUL_EN_BIT 0
+#define MT6363_RG_LDO_VSRAM_CPUL_LP_BIT 1
+#define MT6363_LDO_VSRAM_CPUL_HW_LP_MODE 0x1e8b
+#define MT6363_LDO_VSRAM_CPUL_OP_EN0 0x1e94
+#define MT6363_RG_LDO_VSRAM_APU_ADDR 0x1e9d
+#define MT6363_RG_LDO_VSRAM_APU_EN_BIT 0
+#define MT6363_RG_LDO_VSRAM_APU_LP_BIT 1
+#define MT6363_LDO_VSRAM_APU_HW_LP_MODE 0x1ea1
+#define MT6363_LDO_VSRAM_APU_OP_EN0 0x1eaa
+#define MT6363_RG_VTREF18_VOCAL_ADDR 0x1f08
+#define MT6363_RG_VTREF18_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VTREF18_VOSEL_ADDR 0x1f09
+#define MT6363_RG_VTREF18_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VAUX18_VOCAL_ADDR 0x1f0c
+#define MT6363_RG_VAUX18_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VAUX18_VOSEL_ADDR 0x1f0d
+#define MT6363_RG_VAUX18_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VCN15_VOCAL_ADDR 0x1f13
+#define MT6363_RG_VCN15_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VCN15_VOSEL_ADDR 0x1f14
+#define MT6363_RG_VCN15_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VUFS18_VOCAL_ADDR 0x1f17
+#define MT6363_RG_VUFS18_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VUFS18_VOSEL_ADDR 0x1f18
+#define MT6363_RG_VUFS18_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VIO18_VOCAL_ADDR 0x1f1b
+#define MT6363_RG_VIO18_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VIO18_VOSEL_ADDR 0x1f1c
+#define MT6363_RG_VIO18_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VM18_VOCAL_ADDR 0x1f1f
+#define MT6363_RG_VM18_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VM18_VOSEL_ADDR 0x1f20
+#define MT6363_RG_VM18_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VA15_VOCAL_ADDR 0x1f23
+#define MT6363_RG_VA15_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VA15_VOSEL_ADDR 0x1f24
+#define MT6363_RG_VA15_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRF18_VOCAL_ADDR 0x1f27
+#define MT6363_RG_VRF18_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRF18_VOSEL_ADDR 0x1f28
+#define MT6363_RG_VRF18_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRFIO18_VOCAL_ADDR 0x1f2b
+#define MT6363_RG_VRFIO18_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRFIO18_VOSEL_ADDR 0x1f2c
+#define MT6363_RG_VRFIO18_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VIO075_VOCFG_ADDR 0x1f31
+#define MT6363_RG_VIO075_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VIO075_VOSEL_MASK GENMASK(6, 4)
+#define MT6363_RG_VCN13_VOCAL_ADDR 0x1f88
+#define MT6363_RG_VCN13_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VUFS12_VOCAL_ADDR 0x1f91
+#define MT6363_RG_VUFS12_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VUFS12_VOSEL_ADDR 0x1f92
+#define MT6363_RG_VUFS12_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VA12_1_VOCAL_ADDR 0x1f95
+#define MT6363_RG_VA12_1_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VA12_1_VOSEL_ADDR 0x1f96
+#define MT6363_RG_VA12_1_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VA12_2_VOCAL_ADDR 0x1f99
+#define MT6363_RG_VA12_2_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VA12_2_VOSEL_ADDR 0x1f9a
+#define MT6363_RG_VA12_2_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRF12_VOCAL_ADDR 0x1f9d
+#define MT6363_RG_VRF12_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRF12_VOSEL_ADDR 0x1f9e
+#define MT6363_RG_VRF12_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRF13_VOCAL_ADDR 0x1fa1
+#define MT6363_RG_VRF13_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRF13_VOSEL_ADDR 0x1fa2
+#define MT6363_RG_VRF13_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRF09_VOCAL_ADDR 0x1fa8
+#define MT6363_RG_VRF09_VOCAL_MASK GENMASK(3, 0)
+#define MT6363_RG_VRF09_VOSEL_ADDR 0x1fa9
+#define MT6363_RG_VRF09_VOSEL_MASK GENMASK(3, 0)
+#define MT6363_ISINK_EN_CTRL0 0x220b
+#define MT6363_ISINK_CTRL0_MASK GENMASK(7, 0)
+#define MT6363_ISINK_EN_CTRL1 0x220c
+#define MT6363_ISINK_CTRL1_MASK GENMASK(7, 4)
+
+#endif /* __LINUX_REGULATOR_MT6363_H */
--
2.49.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 5/6] dt-bindings: regulator: Document MediaTek MT6373 PMIC Regulators
2025-06-24 7:35 [PATCH v2 0/6] regulator: Add support for MediaTek MT6316/6363/6373 PMICs AngeloGioacchino Del Regno
` (3 preceding siblings ...)
2025-06-24 7:35 ` [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI " AngeloGioacchino Del Regno
@ 2025-06-24 7:35 ` AngeloGioacchino Del Regno
2025-06-27 8:21 ` Krzysztof Kozlowski
2025-06-24 7:35 ` [PATCH v2 6/6] regulator: Add support for MediaTek MT6373 SPMI " AngeloGioacchino Del Regno
5 siblings, 1 reply; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-24 7:35 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Add bindings for the regulators found in the MediaTek MT6363 PMIC,
usually found in board designs using the MT6991 Dimensity 9400 and
on MT8196 Kompanio SoC for Chromebooks, along with the MT6316 and
MT6363 PMICs.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
.../regulator/mediatek,mt6373-regulator.yaml | 119 ++++++++++++++++++
1 file changed, 119 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6373-regulator.yaml
diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6373-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6373-regulator.yaml
new file mode 100644
index 000000000000..08deb1258b98
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6373-regulator.yaml
@@ -0,0 +1,119 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/mediatek,mt6373-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6373 PMIC Regulators
+
+maintainers:
+ - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+description:
+ The MT6363 SPMI PMIC provides 10 BUCK and 25 LDO (Low Dropout) regulators
+ and can optionally provide overcurrent warnings with one ocp interrupt
+ for each voltage regulator.
+
+properties:
+ compatible:
+ const: mediatek,mt6373-regulator
+
+ interrupts:
+ description: Overcurrent warning interrupts
+ minItems: 1
+ maxItems: 35
+
+ interrupt-names:
+ description:
+ Names for the overcurrent interrupts are the same as the name
+ of a regulator (hence the same as each regulator's node name).
+ For example, the interrupt name for regulator vs2 will be "vs2".
+ minItems: 1
+ maxItems: 35
+
+patternProperties:
+ "^v(ant|aud|aux)18$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^vbuck[12356789]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^vbuck4(-ufs)?$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^vcn33-[123]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^v(f|t)p":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^v(cn18io|efuse|ibr|io28|sram-digrf-aif|usb)":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^vmc(h)?$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^vmch-(eint-low|eint-high)?$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^vrf(09|12|13|18|io18)-aif$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^vsim[12]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ pmic {
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ regulators {
+ compatible = "mediatek,mt6373-regulator";
+ interrupts = <5 17 IRQ_TYPE_LEVEL_HIGH>, <5 18 IRQ_TYPE_LEVEL_HIGH>,
+ <5 19 IRQ_TYPE_LEVEL_HIGH>, <5 20 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "vusb", "vaux18", "vrf13-aif", "vrf18-aif";
+
+ vaux18 {
+ regulator-name = "avss18-auxadc-mt6373";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allowed-modes = <0 1 2>;
+ };
+
+ vmc {
+ regulator-name = "pp1800-2900-vmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-allowed-modes = <0 2>;
+ };
+ };
+ };
+...
--
2.49.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 6/6] regulator: Add support for MediaTek MT6373 SPMI PMIC Regulators
2025-06-24 7:35 [PATCH v2 0/6] regulator: Add support for MediaTek MT6316/6363/6373 PMICs AngeloGioacchino Del Regno
` (4 preceding siblings ...)
2025-06-24 7:35 ` [PATCH v2 5/6] dt-bindings: regulator: Document MediaTek MT6373 " AngeloGioacchino Del Regno
@ 2025-06-24 7:35 ` AngeloGioacchino Del Regno
5 siblings, 0 replies; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-24 7:35 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Add a driver for the regulators found on the MediaTek MT6373 PMIC,
fully controlled by SPMI interface.
Similarly to MT6363, this PMIC regulates voltage with input range
of 2.6-5.0V, and features 10 buck converters and 25 LDOs.
This PMIC is usually found on board designs using the MT6991 or
MT8196 SoC, in combination with the MT6363 PMIC.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6373-regulator.c | 729 +++++++++++++++++++++
include/linux/regulator/mt6373-regulator.h | 154 +++++
4 files changed, 893 insertions(+)
create mode 100644 drivers/regulator/mt6373-regulator.c
create mode 100644 include/linux/regulator/mt6373-regulator.h
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index f2ab06538b8c..1b80cee7cfa1 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -953,6 +953,15 @@ config REGULATOR_MT6370
This driver supports the control for DisplayBias voltages and one
general purpose LDO which is commonly used to drive the vibrator.
+config REGULATOR_MT6373
+ tristate "MT6373 SPMI PMIC regulator driver"
+ depends on SPMI || COMPILE_TEST
+ help
+ Say Y here to enable support for buck and LDO regulators found in
+ the MediaTek MT6373 SPMI PMIC and its variants.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
config REGULATOR_MT6380
tristate "MediaTek MT6380 PMIC"
depends on MTK_PMIC_WRAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 9dd19f4227ea..f75abb140d8d 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_REGULATOR_MT6359) += mt6359-regulator.o
obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
obj-$(CONFIG_REGULATOR_MT6363) += mt6363-regulator.o
obj-$(CONFIG_REGULATOR_MT6370) += mt6370-regulator.o
+obj-$(CONFIG_REGULATOR_MT6373) += mt6373-regulator.o
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
diff --git a/drivers/regulator/mt6373-regulator.c b/drivers/regulator/mt6373-regulator.c
new file mode 100644
index 000000000000..e4a68d5d02a4
--- /dev/null
+++ b/drivers/regulator/mt6373-regulator.c
@@ -0,0 +1,729 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2024 MediaTek Inc.
+// Copyright (c) 2025 Collabora Ltd
+// AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/devm-helpers.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/mt6373-regulator.h>
+#include <linux/regulator/of_regulator.h>
+
+#define MT6373_REGULATOR_MODE_NORMAL 0
+#define MT6373_REGULATOR_MODE_FCCM 1
+#define MT6373_REGULATOR_MODE_LP 2
+#define MT6373_REGULATOR_MODE_ULP 3
+
+#define EN_SET_OFFSET 0x1
+#define EN_CLR_OFFSET 0x2
+
+#define MT6373_RG_RSV_SWREG_H 0xa09
+#define MT6373_PLG_CFG_ELR1 0x3ab
+#define MT6373_ELR_MASK 0xc
+
+#define OC_IRQ_ENABLE_DELAY_MS 10
+
+/* Unlock key for mode setting */
+#define MT6373_BUCK_TOP_UNLOCK_VALUE 0x5543
+
+enum {
+ MT6373_ID_VBUCK0,
+ MT6373_ID_VBUCK1,
+ MT6373_ID_VBUCK2,
+ MT6373_ID_VBUCK3,
+ MT6373_ID_VBUCK4,
+ MT6373_ID_VBUCK4_UFS,
+ MT6373_ID_VBUCK5,
+ MT6373_ID_VBUCK6,
+ MT6373_ID_VBUCK7,
+ MT6373_ID_VBUCK8,
+ MT6373_ID_VBUCK9,
+ MT6373_ID_VUSB,
+ MT6373_ID_VAUX18,
+ MT6373_ID_VRF13_AIF,
+ MT6373_ID_VRF18_AIF,
+ MT6373_ID_VRFIO18_AIF,
+ MT6373_ID_VRF09_AIF,
+ MT6373_ID_VRF12_AIF,
+ MT6373_ID_VANT18,
+ MT6373_ID_VSRAM_DIGRF_AIF,
+ MT6373_ID_VIBR,
+ MT6373_ID_VIO28,
+ MT6373_ID_VFP,
+ MT6373_ID_VTP,
+ MT6373_ID_VMCH,
+ MT6373_ID_VMC,
+ MT6373_ID_VAUD18,
+ MT6373_ID_VCN33_1,
+ MT6373_ID_VCN33_2,
+ MT6373_ID_VCN33_3,
+ MT6373_ID_VCN18IO,
+ MT6373_ID_VEFUSE,
+ MT6373_ID_VMCH_EINT_HIGH,
+ MT6373_ID_VMCH_EINT_LOW
+};
+
+/**
+ * struct mt6373_regulator_info - MT6373 regulators information
+ * @desc: Regulator description structure
+ * @lp_mode_reg: Low Power mode register (normal/idle)
+ * @lp_mode_mask: Low Power mode regulator mask
+ * @modeset_reg: AUTO/PWM mode register
+ * @modeset_mask: AUTO/PWM regulator mask
+ * @vocal_reg: Voltage Output Calibration register
+ * @vocal_mask: Voltage Output Calibration regulator mask
+ * @oc_work: Delayed work for enabling overcurrent IRQ
+ * @irq: Interrupt for overcurrent event
+ */
+struct mt6373_regulator_info {
+ struct regulator_desc desc;
+ u16 lp_mode_reg;
+ u16 lp_mode_mask;
+ u16 modeset_reg;
+ u16 modeset_mask;
+ u16 vocal_reg;
+ u16 vocal_mask;
+ struct delayed_work oc_work;
+ int irq;
+};
+
+#define MT6373_BUCK(match, vreg, min, max, step, en_reg, en_bit, vs_reg,\
+ vs_mask, lp_reg, lp_bit, mset_reg, mset_bit) \
+[MT6373_ID_##vreg] = { \
+ .desc = { \
+ .name = match, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6373_vreg_setclr_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6373_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min) / step + 1, \
+ .min_uV = min, \
+ .uV_step = step, \
+ .enable_reg = en_reg, \
+ .enable_mask = BIT(en_bit), \
+ .vsel_reg = vs_reg, \
+ .vsel_mask = vs_mask, \
+ .of_map_mode = mt6373_map_mode, \
+ }, \
+ .lp_mode_reg = lp_reg, \
+ .lp_mode_mask = BIT(lp_bit), \
+ .modeset_reg = mset_reg, \
+ .modeset_mask = BIT(mset_bit), \
+}
+
+#define MT6373_LDO_L(match, vreg, min, max, step, en_reg, vs_reg, \
+ vs_mask) \
+[MT6373_ID_##vreg] = { \
+ .desc = { \
+ .name = match, \
+ .of_match = of_match_ptr(match), \
+ .ops = &mt6373_ldo_linear_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6373_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min) / step + 1, \
+ .min_uV = min, \
+ .uV_step = step, \
+ .enable_reg = en_reg, \
+ .enable_mask = BIT(0), \
+ .vsel_reg = vs_reg, \
+ .vsel_mask = vs_mask, \
+ .of_map_mode = mt6373_map_mode, \
+ }, \
+ .lp_mode_reg = en_reg, \
+ .lp_mode_mask = BIT(1), \
+}
+
+#define MT6373_LDO_VT_OPS(match, vreg, vops, vtable, en_reg, vs_reg, \
+ cal_reg) \
+[MT6373_ID_##vreg] = { \
+ .desc = { \
+ .name = match, \
+ .of_match = of_match_ptr(match), \
+ .ops = &vops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6373_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .volt_table = vtable, \
+ .n_voltages = ARRAY_SIZE(vtable), \
+ .enable_reg = en_reg, \
+ .enable_mask = BIT(0), \
+ .vsel_reg = vs_reg, \
+ .vsel_mask = MT6373_PMIC_RG_LDO_VT_VOCALSEL_MASK, \
+ .of_map_mode = mt6373_map_mode, \
+ }, \
+ .vocal_reg = cal_reg, \
+ .vocal_mask = MT6373_PMIC_RG_LDO_VT_VOCALSEL_MASK, \
+ .lp_mode_reg = en_reg, \
+ .lp_mode_mask = BIT(1), \
+}
+
+#define MT6373_LDO_VT(match, vreg, vtable, en_reg, vsel_reg, cal_reg) \
+ MT6373_LDO_VT_OPS(match, vreg, mt6373_ldo_vtable_ops, vtable, \
+ en_reg, vsel_reg, cal_reg)
+
+static const unsigned int ldo_volt_table1[] = {
+ 1200000, 1300000, 1500000, 1700000, 1800000, 2000000, 2100000, 2200000,
+ 2700000, 2800000, 2900000, 3000000, 3100000, 3300000, 3400000, 3500000,
+};
+
+static const unsigned int ldo_volt_table2[] = {
+ 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+ 2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
+};
+
+static const unsigned int ldo_volt_table3[] = {
+ 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000,
+ 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000,
+};
+
+static const unsigned int ldo_volt_table4[] = {
+ 1200000, 1300000, 1500000, 1700000, 1800000, 2000000, 2500000, 2600000,
+ 2700000, 2800000, 2900000, 3000000, 3100000, 3300000, 3400000, 3500000,
+};
+
+static const unsigned int ldo_volt_table5[] = {
+ 900000, 1000000, 1100000, 1200000, 1300000, 1700000, 1800000, 1810000,
+};
+
+static int mt6373_vreg_enable_setclr(struct regulator_dev *rdev)
+{
+ return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_SET_OFFSET,
+ rdev->desc->enable_mask);
+}
+
+static int mt6373_vreg_disable_setclr(struct regulator_dev *rdev)
+{
+ return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_CLR_OFFSET,
+ rdev->desc->enable_mask);
+}
+
+static inline unsigned int mt6373_map_mode(unsigned int mode)
+{
+ switch (mode) {
+ case MT6373_REGULATOR_MODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ case MT6373_REGULATOR_MODE_FCCM:
+ return REGULATOR_MODE_FAST;
+ case MT6373_REGULATOR_MODE_LP:
+ return REGULATOR_MODE_IDLE;
+ case MT6373_REGULATOR_MODE_ULP:
+ return REGULATOR_MODE_STANDBY;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+static int mt6373_vmch_eint_enable(struct regulator_dev *rdev)
+{
+ const struct regulator_desc *rdesc = rdev->desc;
+ unsigned int val;
+ int ret;
+
+ if (rdesc->id == MT6373_ID_VMCH_EINT_HIGH)
+ val = MT6373_PMIC_RG_LDO_VMCH_EINT_POL_BIT;
+ else
+ val = 0;
+
+ ret = regmap_update_bits(rdev->regmap, MT6373_LDO_VMCH_EINT,
+ MT6373_PMIC_RG_LDO_VMCH_EINT_POL_BIT, val);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(rdev->regmap, MT6373_PMIC_RG_LDO_VMCH_ADDR,
+ rdesc->enable_mask);
+ if (ret)
+ return ret;
+
+ return regmap_set_bits(rdev->regmap, rdesc->enable_reg, rdesc->enable_mask);
+}
+
+static int mt6373_vmch_eint_disable(struct regulator_dev *rdev)
+{
+ const struct regulator_desc *rdesc = rdev->desc;
+ int ret;
+
+ ret = regmap_clear_bits(rdev->regmap, MT6373_PMIC_RG_LDO_VMCH_ADDR,
+ rdesc->enable_mask);
+ if (ret)
+ return ret;
+
+ /* Wait for VMCH discharging */
+ usleep_range(1500, 1600);
+
+ return regmap_clear_bits(rdev->regmap, rdesc->enable_reg, rdesc->enable_mask);
+}
+
+static unsigned int mt6373_regulator_get_mode(struct regulator_dev *rdev)
+{
+ struct mt6373_regulator_info *info = rdev_get_drvdata(rdev);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to get mt6373 mode: %d\n", ret);
+ return ret;
+ }
+
+ if (val & info->modeset_mask)
+ return REGULATOR_MODE_FAST;
+
+ ret = regmap_read(rdev->regmap, info->lp_mode_reg, &val);
+ val &= info->lp_mode_mask;
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to get lp mode: %d\n", ret);
+ return ret;
+ }
+
+ if (val)
+ return REGULATOR_MODE_IDLE;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int mt6373_buck_unlock(struct regmap *map, bool unlock)
+{
+ u16 buf = unlock ? MT6373_BUCK_TOP_UNLOCK_VALUE : 0;
+
+ return regmap_bulk_write(map, MT6373_BUCK_TOP_KEY_PROT_LO, &buf, sizeof(buf));
+}
+
+static int mt6373_regulator_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct mt6373_regulator_info *info = rdev_get_drvdata(rdev);
+ struct regmap *regmap;
+ int cur_mode, ret;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ ret = mt6373_buck_unlock(regmap, true);
+ if (ret)
+ break;
+
+ ret = regmap_set_bits(regmap, info->modeset_reg, info->modeset_mask);
+
+ mt6373_buck_unlock(regmap, false);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ cur_mode = mt6373_regulator_get_mode(rdev);
+ if (cur_mode < 0) {
+ ret = cur_mode;
+ break;
+ }
+
+ if (cur_mode == REGULATOR_MODE_FAST) {
+ ret = mt6373_buck_unlock(regmap, true);
+ if (ret)
+ break;
+
+ ret = regmap_clear_bits(regmap, info->modeset_reg, info->modeset_mask);
+
+ mt6373_buck_unlock(regmap, false);
+ break;
+ } else if (cur_mode == REGULATOR_MODE_IDLE) {
+ ret = regmap_clear_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
+ if (ret == 0)
+ usleep_range(100, 200);
+ }
+ break;
+ case REGULATOR_MODE_IDLE:
+ ret = regmap_set_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret) {
+ dev_err(&rdev->dev, "Failed to set mode %u: %d\n", mode, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct regulator_ops mt6373_vreg_setclr_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = mt6373_vreg_enable_setclr,
+ .disable = mt6373_vreg_disable_setclr,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6373_regulator_set_mode,
+ .get_mode = mt6373_regulator_get_mode,
+};
+
+static const struct regulator_ops mt6373_ldo_linear_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6373_regulator_set_mode,
+ .get_mode = mt6373_regulator_get_mode,
+};
+
+static const struct regulator_ops mt6373_ldo_vtable_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6373_regulator_set_mode,
+ .get_mode = mt6373_regulator_get_mode,
+};
+
+static const struct regulator_ops mt6373_vmch_eint_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = mt6373_vmch_eint_enable,
+ .disable = mt6373_vmch_eint_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mt6373_regulator_set_mode,
+ .get_mode = mt6373_regulator_get_mode,
+};
+
+/* The array is indexed by id(MT6373_ID_XXX) */
+static struct mt6373_regulator_info mt6373_regulators[] = {
+ MT6373_BUCK("vbuck0", VBUCK0, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK0_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK0_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK0_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK0_FCCM_BIT),
+ MT6373_BUCK("vbuck1", VBUCK1, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK1_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK1_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK1_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK1_FCCM_BIT),
+ MT6373_BUCK("vbuck2", VBUCK2, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK2_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK2_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK2_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK2_FCCM_BIT),
+ MT6373_BUCK("vbuck3", VBUCK3, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK3_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK3_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK3_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK3_FCCM_BIT),
+ MT6373_BUCK("vbuck4", VBUCK4, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK4_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK4_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK4_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK4_FCCM_BIT),
+ MT6373_BUCK("vbuck4-ufs", VBUCK4_UFS, 0, 2650125, 13875,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK4_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK4_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK4_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_1_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK4_FCCM_BIT),
+ MT6373_BUCK("vbuck5", VBUCK5, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK5_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK5_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK5_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_1_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK5_FCCM_BIT),
+ MT6373_BUCK("vbuck6", VBUCK6, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK6_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK6_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK6_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_1_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK6_FCCM_BIT),
+ MT6373_BUCK("vbuck7", VBUCK7, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK0_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK7_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK7_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK0_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK7_LP_BIT,
+ MT6373_PMIC_RG_BUCK0_1_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK7_FCCM_BIT),
+ MT6373_BUCK("vbuck8", VBUCK8, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK1_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK8_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK8_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK1_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK8_LP_BIT,
+ MT6373_PMIC_RG_BUCK1_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK8_FCCM_BIT),
+ MT6373_BUCK("vbuck9", VBUCK9, 0, 1193750, 6250,
+ MT6373_PMIC_RG_BUCK1_EN_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK9_EN_BIT,
+ MT6373_PMIC_RG_BUCK_VBUCK9_VOSEL_ADDR,
+ MT6373_PMIC_RG_BUCK_VOSEL_MASK,
+ MT6373_PMIC_RG_BUCK1_LP_ADDR,
+ MT6373_PMIC_RG_BUCK_VBUCK9_LP_BIT,
+ MT6373_PMIC_RG_BUCK1_FCCM_ADDR,
+ MT6373_PMIC_RG_VBUCK9_FCCM_BIT),
+ MT6373_LDO_L("vsram-digrf-aif", VSRAM_DIGRF_AIF, 400000, 1193750, 6250,
+ MT6373_PMIC_RG_LDO_VSRAM_DIGRF_AIF_ADDR,
+ MT6373_PMIC_RG_LDO_VSRAM_DIGRF_AIF_VOSEL_ADDR,
+ MT6373_PMIC_RG_LDO_VSRAM_DIGRF_AIF_VOSEL_MASK),
+ MT6373_LDO_VT("vusb", VUSB, ldo_volt_table1,
+ MT6373_PMIC_RG_LDO_VUSB_ADDR,
+ MT6373_PMIC_RG_VUSB_VOSEL_ADDR,
+ MT6373_PMIC_RG_VUSB_VOCAL_ADDR),
+ MT6373_LDO_VT("vaux18", VAUX18, ldo_volt_table2,
+ MT6373_PMIC_RG_LDO_VAUX18_ADDR,
+ MT6373_PMIC_RG_VAUX18_VOSEL_ADDR,
+ MT6373_PMIC_RG_VAUX18_VOCAL_ADDR),
+ MT6373_LDO_VT("vrf13-aif", VRF13_AIF, ldo_volt_table3,
+ MT6373_PMIC_RG_LDO_VRF13_AIF_ADDR,
+ MT6373_PMIC_RG_VRF13_AIF_VOSEL_ADDR,
+ MT6373_PMIC_RG_VRF13_AIF_VOCAL_ADDR),
+ MT6373_LDO_VT("vrf18-aif", VRF18_AIF, ldo_volt_table3,
+ MT6373_PMIC_RG_LDO_VRF18_AIF_ADDR,
+ MT6373_PMIC_RG_VRF18_AIF_VOSEL_ADDR,
+ MT6373_PMIC_RG_VRF18_AIF_VOCAL_ADDR),
+ MT6373_LDO_VT("vrfio18-aif", VRFIO18_AIF, ldo_volt_table3,
+ MT6373_PMIC_RG_LDO_VRFIO18_AIF_ADDR,
+ MT6373_PMIC_RG_VRFIO18_AIF_VOSEL_ADDR,
+ MT6373_PMIC_RG_VRFIO18_AIF_VOCAL_ADDR),
+ MT6373_LDO_VT("vrf09-aif", VRF09_AIF, ldo_volt_table3,
+ MT6373_PMIC_RG_LDO_VRF09_AIF_ADDR,
+ MT6373_PMIC_RG_VRF09_AIF_VOSEL_ADDR,
+ MT6373_PMIC_RG_VRF09_AIF_VOCAL_ADDR),
+ MT6373_LDO_VT("vrf12-aif", VRF12_AIF, ldo_volt_table5,
+ MT6373_PMIC_RG_LDO_VRF12_AIF_ADDR,
+ MT6373_PMIC_RG_VRF12_AIF_VOSEL_ADDR,
+ MT6373_PMIC_RG_VRF12_AIF_VOCAL_ADDR),
+ MT6373_LDO_VT("vant18", VANT18, ldo_volt_table3,
+ MT6373_PMIC_RG_LDO_VANT18_ADDR,
+ MT6373_PMIC_RG_VANT18_VOSEL_ADDR,
+ MT6373_PMIC_RG_VANT18_VOCAL_ADDR),
+ MT6373_LDO_VT("vibr", VIBR, ldo_volt_table1,
+ MT6373_PMIC_RG_LDO_VIBR_ADDR,
+ MT6373_PMIC_RG_VIBR_VOSEL_ADDR,
+ MT6373_PMIC_RG_VIBR_VOCAL_ADDR),
+ MT6373_LDO_VT("vio28", VIO28, ldo_volt_table1,
+ MT6373_PMIC_RG_LDO_VIO28_ADDR,
+ MT6373_PMIC_RG_VIO28_VOSEL_ADDR,
+ MT6373_PMIC_RG_VIO28_VOCAL_ADDR),
+ MT6373_LDO_VT("vfp", VFP, ldo_volt_table1,
+ MT6373_PMIC_RG_LDO_VFP_ADDR,
+ MT6373_PMIC_RG_VFP_VOSEL_ADDR,
+ MT6373_PMIC_RG_VFP_VOCAL_ADDR),
+ MT6373_LDO_VT("vtp", VTP, ldo_volt_table1,
+ MT6373_PMIC_RG_LDO_VTP_ADDR,
+ MT6373_PMIC_RG_VTP_VOSEL_ADDR,
+ MT6373_PMIC_RG_VTP_VOCAL_ADDR),
+ MT6373_LDO_VT("vmch", VMCH, ldo_volt_table4,
+ MT6373_PMIC_RG_LDO_VMCH_ADDR,
+ MT6373_PMIC_RG_VMCH_VOSEL_ADDR,
+ MT6373_PMIC_RG_VMCH_VOCAL_ADDR),
+ MT6373_LDO_VT("vmc", VMC, ldo_volt_table1,
+ MT6373_PMIC_RG_LDO_VMC_ADDR,
+ MT6373_PMIC_RG_VMC_VOSEL_ADDR,
+ MT6373_PMIC_RG_VMC_VOCAL_ADDR),
+ MT6373_LDO_VT("vaud18", VAUD18, ldo_volt_table3,
+ MT6373_PMIC_RG_LDO_VAUD18_ADDR,
+ MT6373_PMIC_RG_VAUD18_VOSEL_ADDR,
+ MT6373_PMIC_RG_VAUD18_VOCAL_ADDR),
+ MT6373_LDO_VT("vcn33-1", VCN33_1, ldo_volt_table4,
+ MT6373_PMIC_RG_LDO_VCN33_1_ADDR,
+ MT6373_PMIC_RG_VCN33_1_VOSEL_ADDR,
+ MT6373_PMIC_RG_VCN33_1_VOCAL_ADDR),
+ MT6373_LDO_VT("vcn33-2", VCN33_2, ldo_volt_table4,
+ MT6373_PMIC_RG_LDO_VCN33_2_ADDR,
+ MT6373_PMIC_RG_VCN33_2_VOSEL_ADDR,
+ MT6373_PMIC_RG_VCN33_2_VOCAL_ADDR),
+ MT6373_LDO_VT("vcn33-3", VCN33_3, ldo_volt_table4,
+ MT6373_PMIC_RG_LDO_VCN33_3_ADDR,
+ MT6373_PMIC_RG_VCN33_3_VOSEL_ADDR,
+ MT6373_PMIC_RG_VCN33_3_VOCAL_ADDR),
+ MT6373_LDO_VT("vcn18io", VCN18IO, ldo_volt_table3,
+ MT6373_PMIC_RG_LDO_VCN18IO_ADDR,
+ MT6373_PMIC_RG_VCN18IO_VOSEL_ADDR,
+ MT6373_PMIC_RG_VCN18IO_VOCAL_ADDR),
+ MT6373_LDO_VT("vefuse", VEFUSE, ldo_volt_table1,
+ MT6373_PMIC_RG_LDO_VEFUSE_ADDR,
+ MT6373_PMIC_RG_VEFUSE_VOSEL_ADDR,
+ MT6373_PMIC_RG_VEFUSE_VOCAL_ADDR),
+ MT6373_LDO_VT_OPS("vmch-eint-high", VMCH_EINT_HIGH,
+ mt6373_vmch_eint_ops, ldo_volt_table4,
+ MT6373_LDO_VMCH_EINT,
+ MT6373_PMIC_RG_VMCH_VOSEL_ADDR,
+ MT6373_PMIC_RG_VMC_VOCAL_ADDR),
+ MT6373_LDO_VT_OPS("vmch-eint-low", VMCH_EINT_LOW,
+ mt6373_vmch_eint_ops, ldo_volt_table4,
+ MT6373_LDO_VMCH_EINT,
+ MT6373_PMIC_RG_VMCH_VOSEL_ADDR,
+ MT6373_PMIC_RG_VMC_VOCAL_ADDR),
+};
+
+static void mt6373_oc_irq_enable_work(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct mt6373_regulator_info *info =
+ container_of(dwork, struct mt6373_regulator_info, oc_work);
+
+ enable_irq(info->irq);
+}
+
+static irqreturn_t mt6373_oc_isr(int irq, void *data)
+{
+ struct regulator_dev *rdev = (struct regulator_dev *)data;
+ struct mt6373_regulator_info *info = rdev_get_drvdata(rdev);
+
+ disable_irq_nosync(info->irq);
+
+ if (regulator_is_enabled_regmap(rdev))
+ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+ schedule_delayed_work(&info->oc_work, msecs_to_jiffies(OC_IRQ_ENABLE_DELAY_MS));
+
+ return IRQ_HANDLED;
+}
+
+static int mt6373_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = {};
+ struct mt6373_regulator_info *info;
+ struct regulator_dev *rdev;
+ bool is_vbuck4_hw_ctrl;
+ bool is_cw_variant;
+ int i, ret;
+ u32 val;
+
+ config.regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!config.regmap)
+ return dev_err_probe(&pdev->dev, -ENODEV, "Cannot get regmap\n");
+
+ config.dev = &pdev->dev;
+
+ /* Read PMIC variant information */
+ ret = regmap_read(config.regmap, MT6373_PLG_CFG_ELR1, &val);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Cannot read ID register\n");
+
+ val = FIELD_GET(MT6373_ELR_VARIANT_MASK, val);
+ is_cw_variant = (val == MT6373_ELR_VARIANT_MT6373CW);
+
+ /* Read Reserved-SW information */
+ ret = regmap_read(config.regmap, MT6373_RG_RSV_SWREG_H, &val);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Cannot read RSV_SW register\n");
+
+ is_vbuck4_hw_ctrl = val & MT6373_RG_RSV_SWREG_VBUCK4_HW_CTRL;
+
+ for (i = 0; i < ARRAY_SIZE(mt6373_regulators); i++) {
+ info = &mt6373_regulators[i];
+
+ /* MT6373CW does not have a VBUCK4_UFS regulator */
+ if (is_cw_variant && info->desc.id == MT6373_ID_VBUCK4_UFS)
+ continue;
+
+ /* VBUCK4 vreg software control is not allowed if in hw_ctrl mode */
+ if (is_vbuck4_hw_ctrl && info->desc.id == MT6373_ID_VBUCK4)
+ continue;
+
+ info->irq = platform_get_irq_byname_optional(pdev, info->desc.name);
+
+ config.driver_data = info;
+ rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
+ if (IS_ERR(rdev))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rdev),
+ "failed to register %s\n", info->desc.name);
+
+ if (info->irq <= 0)
+ continue;
+ ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
+ mt6373_oc_isr, IRQF_ONESHOT,
+ info->desc.name, rdev);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to request overcurrent IRQ for %s\n",
+ info->desc.name);
+
+ INIT_DELAYED_WORK(&info->oc_work, mt6373_oc_irq_enable_work);
+ }
+
+ return 0;
+}
+
+static void mt6373_regulator_shutdown(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!regmap) {
+ dev_err(&pdev->dev, "Cannot get regmap for shutdown!\n");
+ return;
+ }
+
+ regmap_write(regmap, MT6373_TOP_CFG_ELR5, MT6373_TOP_CFG_ELR5_SHUTDOWN);
+}
+
+static const struct of_device_id mt6373_regulator_match[] = {
+ { .compatible = "mediatek,mt6373-regulator" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver mt6373_regulator_driver = {
+ .driver = {
+ .name = "mt6373-regulator",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ .of_match_table = mt6373_regulator_match,
+ },
+ .probe = mt6373_regulator_probe,
+ .shutdown = mt6373_regulator_shutdown
+};
+module_platform_driver(mt6373_regulator_driver);
+
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_DESCRIPTION("MediaTek MT6373 PMIC Regulator Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/regulator/mt6373-regulator.h b/include/linux/regulator/mt6373-regulator.h
new file mode 100644
index 000000000000..b1cdee3df54f
--- /dev/null
+++ b/include/linux/regulator/mt6373-regulator.h
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 MediaTek Inc.
+ * Copyright (c) 2025 Collabora Ltd
+ */
+
+#include <linux/bits.h>
+
+#ifndef __LINUX_REGULATOR_MT6373_H
+#define __LINUX_REGULATOR_MT6373_H
+
+/* Register */
+#define MT6373_BUCK_TOP_KEY_PROT_LO 0x142a
+#define MT6373_TOP_CFG_ELR5 0x147
+#define MT6373_TOP_CFG_ELR5_SHUTDOWN BIT(0)
+
+#define MT6373_PMIC_RG_BUCK0_EN_ADDR 0x240
+#define MT6373_PMIC_RG_BUCK_VBUCK0_EN_BIT 0
+#define MT6373_PMIC_RG_BUCK_VBUCK1_EN_BIT 1
+#define MT6373_PMIC_RG_BUCK_VBUCK2_EN_BIT 2
+#define MT6373_PMIC_RG_BUCK_VBUCK3_EN_BIT 3
+#define MT6373_PMIC_RG_BUCK_VBUCK4_EN_BIT 4
+#define MT6373_PMIC_RG_BUCK_VBUCK5_EN_BIT 5
+#define MT6373_PMIC_RG_BUCK_VBUCK6_EN_BIT 6
+#define MT6373_PMIC_RG_BUCK_VBUCK7_EN_BIT 7
+
+#define MT6373_PMIC_RG_BUCK1_EN_ADDR 0x243
+#define MT6373_PMIC_RG_BUCK_VBUCK8_EN_BIT 0
+#define MT6373_PMIC_RG_BUCK_VBUCK9_EN_BIT 1
+
+#define MT6373_PMIC_RG_BUCK0_LP_ADDR 0x246
+#define MT6373_PMIC_RG_BUCK_VBUCK0_LP_BIT 0
+#define MT6373_PMIC_RG_BUCK_VBUCK1_LP_BIT 1
+#define MT6373_PMIC_RG_BUCK_VBUCK2_LP_BIT 2
+#define MT6373_PMIC_RG_BUCK_VBUCK3_LP_BIT 3
+#define MT6373_PMIC_RG_BUCK_VBUCK4_LP_BIT 4
+#define MT6373_PMIC_RG_BUCK_VBUCK5_LP_BIT 5
+#define MT6373_PMIC_RG_BUCK_VBUCK6_LP_BIT 6
+#define MT6373_PMIC_RG_BUCK_VBUCK7_LP_BIT 7
+
+#define MT6373_PMIC_RG_BUCK1_LP_ADDR 0x249
+#define MT6373_PMIC_RG_BUCK_VBUCK8_LP_BIT 0
+#define MT6373_PMIC_RG_BUCK_VBUCK9_LP_BIT 1
+
+#define MT6373_PMIC_RG_BUCK_VBUCK0_VOSEL_ADDR 0x24c
+#define MT6373_PMIC_RG_BUCK_VBUCK1_VOSEL_ADDR 0x24d
+#define MT6373_PMIC_RG_BUCK_VBUCK2_VOSEL_ADDR 0x24e
+#define MT6373_PMIC_RG_BUCK_VBUCK3_VOSEL_ADDR 0x24f
+#define MT6373_PMIC_RG_BUCK_VBUCK4_VOSEL_ADDR 0x250
+#define MT6373_PMIC_RG_BUCK_VBUCK5_VOSEL_ADDR 0x251
+#define MT6373_PMIC_RG_BUCK_VBUCK6_VOSEL_ADDR 0x252
+#define MT6373_PMIC_RG_BUCK_VBUCK7_VOSEL_ADDR 0x253
+#define MT6373_PMIC_RG_BUCK_VBUCK8_VOSEL_ADDR 0x254
+#define MT6373_PMIC_RG_BUCK_VBUCK9_VOSEL_ADDR 0x255
+#define MT6373_PMIC_RG_BUCK_VOSEL_MASK GENMASK(8, 0)
+
+#define MT6373_PLG_CFG_ELR1 0x3ab
+#define MT6373_ELR_VARIANT_MASK GENMASK(3, 2)
+#define MT6373_ELR_VARIANT_MT6373CW 1
+#define MT6373_RG_RSV_SWREG_H 0xa09
+#define MT6373_RG_RSV_SWREG_VBUCK4_HW_CTRL BIT(0)
+
+#define MT6373_PMIC_RG_BUCK1_FCCM_ADDR 0x199d
+#define MT6373_PMIC_RG_VBUCK8_FCCM_BIT 6
+#define MT6373_PMIC_RG_VBUCK9_FCCM_BIT 7
+
+#define MT6373_PMIC_RG_BUCK0_FCCM_ADDR 0x1a32
+#define MT6373_PMIC_RG_VBUCK0_FCCM_BIT 0
+#define MT6373_PMIC_RG_VBUCK1_FCCM_BIT 1
+#define MT6373_PMIC_RG_VBUCK2_FCCM_BIT 2
+#define MT6373_PMIC_RG_VBUCK3_FCCM_BIT 3
+
+#define MT6373_PMIC_RG_BUCK0_1_FCCM_ADDR 0x1ab2
+#define MT6373_PMIC_RG_VBUCK4_FCCM_BIT 0
+#define MT6373_PMIC_RG_VBUCK5_FCCM_BIT 1
+#define MT6373_PMIC_RG_VBUCK6_FCCM_BIT 2
+#define MT6373_PMIC_RG_VBUCK7_FCCM_BIT 3
+
+#define MT6373_PMIC_RG_LDO_VSRAM_DIGRF_AIF_VOSEL_ADDR 0x1b39
+#define MT6373_PMIC_RG_LDO_VSRAM_DIGRF_AIF_VOSEL_MASK GENMASK(6, 0)
+
+#define MT6373_PMIC_RG_LDO_VAUD18_ADDR 0x1b87
+#define MT6373_PMIC_RG_LDO_VUSB_ADDR 0x1b95
+#define MT6373_PMIC_RG_LDO_VAUX18_ADDR 0x1ba3
+#define MT6373_PMIC_RG_LDO_VRF13_AIF_ADDR 0x1bb1
+#define MT6373_PMIC_RG_LDO_VRF18_AIF_ADDR 0x1bbf
+#define MT6373_PMIC_RG_LDO_VRFIO18_AIF_ADDR 0x1bcd
+#define MT6373_PMIC_RG_LDO_VCN33_1_ADDR 0x1c07
+#define MT6373_PMIC_RG_LDO_VCN33_2_ADDR 0x1c15
+#define MT6373_PMIC_RG_LDO_VCN33_3_ADDR 0x1c23
+#define MT6373_PMIC_RG_LDO_VCN18IO_ADDR 0x1c31
+#define MT6373_PMIC_RG_LDO_VRF09_AIF_ADDR 0x1c3f
+#define MT6373_PMIC_RG_LDO_VRF12_AIF_ADDR 0x1c4d
+#define MT6373_PMIC_RG_LDO_VANT18_ADDR 0x1c87
+#define MT6373_PMIC_RG_LDO_VEFUSE_ADDR 0x1ca3
+#define MT6373_PMIC_RG_LDO_VMCH_ADDR 0x1cb1
+#define MT6373_LDO_VMCH_EINT 0x1cbf
+#define MT6373_PMIC_RG_LDO_VMCH_EINT_POL_BIT BIT(2)
+#define MT6373_PMIC_RG_LDO_VMC_ADDR 0x1cc0
+#define MT6373_PMIC_RG_LDO_VIBR_ADDR 0x1cce
+#define MT6373_PMIC_RG_LDO_VIO28_ADDR 0x1d07
+#define MT6373_PMIC_RG_LDO_VFP_ADDR 0x1d15
+#define MT6373_PMIC_RG_LDO_VTP_ADDR 0x1d23
+#define MT6373_PMIC_RG_LDO_VSIM1_ADDR 0x1d31
+#define MT6373_PMIC_RG_LDO_VSIM2_ADDR 0x1d40
+#define MT6373_PMIC_RG_LDO_VSIM2_LP_ADDR 0x1d40
+#define MT6373_PMIC_RG_LDO_VSRAM_DIGRF_AIF_ADDR 0x1d87
+#define MT6373_PMIC_RG_VAUX18_VOCAL_ADDR 0x1e08
+#define MT6373_PMIC_RG_VAUX18_VOSEL_ADDR 0x1e09
+#define MT6373_PMIC_RG_VUSB_VOCAL_ADDR 0x1e0c
+#define MT6373_PMIC_RG_VUSB_VOSEL_ADDR 0x1e0d
+#define MT6373_PMIC_RG_VCN33_1_VOCAL_ADDR 0x1e10
+#define MT6373_PMIC_RG_VCN33_1_VOSEL_ADDR 0x1e11
+#define MT6373_PMIC_RG_VCN33_2_VOCAL_ADDR 0x1e14
+#define MT6373_PMIC_RG_VCN33_2_VOSEL_ADDR 0x1e15
+#define MT6373_PMIC_RG_VCN33_3_VOCAL_ADDR 0x1e18
+#define MT6373_PMIC_RG_VCN33_3_VOSEL_ADDR 0x1e19
+#define MT6373_PMIC_RG_VMCH_VOCAL_ADDR 0x1e1c
+#define MT6373_PMIC_RG_VMCH_VOSEL_ADDR 0x1e1d
+#define MT6373_PMIC_RG_VEFUSE_VOCAL_ADDR 0x1e20
+#define MT6373_PMIC_RG_VEFUSE_VOSEL_ADDR 0x1e21
+#define MT6373_PMIC_RG_VMC_VOCAL_ADDR 0x1e24
+#define MT6373_PMIC_RG_VMC_VOSEL_ADDR 0x1e25
+#define MT6373_PMIC_RG_VIBR_VOCAL_ADDR 0x1e28
+#define MT6373_PMIC_RG_VIBR_VOSEL_ADDR 0x1e29
+#define MT6373_PMIC_RG_VIO28_VOCAL_ADDR 0x1e2c
+#define MT6373_PMIC_RG_VIO28_VOSEL_ADDR 0x1e2d
+#define MT6373_PMIC_RG_VFP_VOCAL_ADDR 0x1e30
+#define MT6373_PMIC_RG_VFP_VOSEL_ADDR 0x1e31
+#define MT6373_PMIC_RG_VTP_VOCAL_ADDR 0x1e34
+#define MT6373_PMIC_RG_VTP_VOSEL_ADDR 0x1e35
+#define MT6373_PMIC_RG_VSIM1_VOCAL_ADDR 0x1e38
+#define MT6373_PMIC_RG_VSIM1_VOSEL_ADDR 0x1e39
+#define MT6373_PMIC_RG_VSIM2_VOCAL_ADDR 0x1e3c
+#define MT6373_PMIC_RG_VSIM2_VOSEL_ADDR 0x1e3d
+#define MT6373_PMIC_RG_VAUD18_VOCAL_ADDR 0x1e88
+#define MT6373_PMIC_RG_VAUD18_VOSEL_ADDR 0x1e89
+#define MT6373_PMIC_RG_VRF18_AIF_VOCAL_ADDR 0x1e8c
+#define MT6373_PMIC_RG_VRF18_AIF_VOSEL_ADDR 0x1e8d
+#define MT6373_PMIC_RG_VCN18IO_VOCAL_ADDR 0x1e90
+#define MT6373_PMIC_RG_VCN18IO_VOSEL_ADDR 0x1e91
+#define MT6373_PMIC_RG_VRFIO18_AIF_VOCAL_ADDR 0x1e94
+#define MT6373_PMIC_RG_VRFIO18_AIF_VOSEL_ADDR 0x1e95
+#define MT6373_PMIC_RG_VANT18_VOCAL_ADDR 0x1e98
+#define MT6373_PMIC_RG_VANT18_VOSEL_ADDR 0x1e99
+#define MT6373_PMIC_RG_VRF13_AIF_VOCAL_ADDR 0x1f08
+#define MT6373_PMIC_RG_VRF13_AIF_VOSEL_ADDR 0x1f09
+#define MT6373_PMIC_RG_VRF12_AIF_VOCAL_ADDR 0x1f0c
+#define MT6373_PMIC_RG_VRF12_AIF_VOSEL_ADDR 0x1f0d
+#define MT6373_PMIC_RG_VRF09_AIF_VOCAL_ADDR 0x1f88
+#define MT6373_PMIC_RG_VRF09_AIF_VOSEL_ADDR 0x1f89
+#define MT6373_PMIC_RG_LDO_VT_VOCALSEL_MASK GENMASK(7, 0)
+
+#endif /* __LINUX_REGULATOR_MT6363_H */
--
2.49.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v2 2/6] regulator: Add support for MediaTek MT6316 SPMI PMIC Regulators
2025-06-24 7:35 ` [PATCH v2 2/6] regulator: Add support for MediaTek MT6316 SPMI " AngeloGioacchino Del Regno
@ 2025-06-25 5:06 ` Chen-Yu Tsai
2025-06-25 8:43 ` AngeloGioacchino Del Regno
0 siblings, 1 reply; 17+ messages in thread
From: Chen-Yu Tsai @ 2025-06-25 5:06 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: broonie, lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
kernel
Hi,
On Tue, Jun 24, 2025 at 3:46 PM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Add a driver for the regulators found on all types of the MediaTek
> MT6316 SPMI PMIC, fully controlled by SPMI interface and featuring
> four step down DCDC (buck) converters.
>
> In particular, this includes support for:
> - MT6316(BP/VP): 2+2 Phase (Phase 1: buck1+2, Phase 2: buck3+4)
> - MT6316(CP/HP/KP): 3+1 Phase (Phase 1: buck1+2+4, Phase 2: buck3)
> - MT6316(DP/TP): 4+0 Phase (Single phase, buck1+2+3+4)
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
> drivers/regulator/Kconfig | 9 +
> drivers/regulator/Makefile | 1 +
> drivers/regulator/mt6316-regulator.c | 345 +++++++++++++++++++++++++++
> 3 files changed, 355 insertions(+)
> create mode 100644 drivers/regulator/mt6316-regulator.c
>
> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
> index 6d8988387da4..bca2ebbd89b7 100644
> --- a/drivers/regulator/Kconfig
> +++ b/drivers/regulator/Kconfig
> @@ -864,6 +864,15 @@ config REGULATOR_MT6315
> This driver supports the control of different power rails of device
> through regulator interface.
>
> +config REGULATOR_MT6316
> + tristate "MT6316 SPMI PMIC regulator driver"
> + depends on SPMI || COMPILE_TEST
> + help
> + Say Y here to enable support for 2+2, 3+1 and 4 phase regulators
> + found in the MediaTek MT6316 BP, CP, DP, HP, VP and TP SPMI PMICs.
> + This driver supports the control of different power rails of device
> + through regulator interface.
> +
> config REGULATOR_MT6323
> tristate "MediaTek MT6323 PMIC"
> depends on MFD_MT6397
> diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
> index c0bc7a0f4e67..58643e35d2cc 100644
> --- a/drivers/regulator/Makefile
> +++ b/drivers/regulator/Makefile
> @@ -103,6 +103,7 @@ obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o
> obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
> obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
> obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o
> +obj-$(CONFIG_REGULATOR_MT6315) += mt6316-regulator.o
> obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
> obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o
> obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o
> diff --git a/drivers/regulator/mt6316-regulator.c b/drivers/regulator/mt6316-regulator.c
> new file mode 100644
> index 000000000000..952852bbe923
> --- /dev/null
> +++ b/drivers/regulator/mt6316-regulator.c
> @@ -0,0 +1,345 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Copyright (c) 2024 MediaTek Inc.
> +// Copyright (c) 2025 Collabora Ltd
> +// AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> +
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/regmap.h>
> +#include <linux/spmi.h>
> +
> +#include <linux/regulator/driver.h>
> +#include <linux/regulator/machine.h>
> +#include <linux/regulator/of_regulator.h>
> +
> +#define MT6316_BUCK_MODE_AUTO 0
> +#define MT6316_BUCK_MODE_FORCE_PWM 1
> +#define MT6316_BUCK_MODE_LP 2
> +
> +#define MT6316_CHIP_ID 0x20b
> +#define MT6316_BUCK_TOP_CON0 0x1440
> +#define EN_SET_OFFSET 0x1
> +#define EN_CLR_OFFSET 0x2
> +
> +#define MT6316_BUCK_TOP_CON1 0x1443
> +
> +#define MT6316_BUCK_TOP_ELR0 0x1448
> +#define MT6316_BUCK_TOP_ELR2 0x144a
> +#define MT6316_BUCK_TOP_ELR4 0x144c
> +#define MT6316_BUCK_TOP_ELR6 0x144e
> +#define MT6316_VSEL_MASK GENMASK(8, 0)
> +
> +#define MT6316_VBUCK1_DBG 0x14a8
> +#define MT6316_VBUCK2_DBG 0x1528
> +#define MT6316_VBUCK3_DBG 0x15a8
> +#define MT6316_VBUCK4_DBG 0x1628
> +#define MT6316_BUCK_QI BIT(0)
> +
> +#define MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0 0x1688
> +#define MT6316_BUCK_TOP_4PHASE_TOP_ELR_0 0x1690
> +
> +enum mt6316_type {
> + MT6316_TYPE_2PHASE,
> + MT6316_TYPE_3PHASE,
> + MT6316_TYPE_4PHASE
> +};
> +
> +/**
> + * struct mt6316_regulator_info - MT6316 regulators information
> + * @desc: Regulator description structure
> + * @debug_reg: Debug register for regulator status
> + * @lp_mode_reg: Low Power mode register (normal/idle)
> + * @lp_mode_mask: Low Power mode regulator mask
> + * @modeset_reg: AUTO/PWM mode register
> + * @modeset_mask: AUTO/PWM regulator mask
> + */
> +struct mt6316_regulator_info {
> + struct regulator_desc desc;
> + u16 debug_reg;
> + u16 lp_mode_reg;
> + u16 lp_mode_mask;
> + u16 modeset_reg;
> + u16 modeset_mask;
> +};
> +
> +#define MT6316_BUCK(match, vreg_id, min, max, step, vs_reg) \
> +{ \
> + .desc = { \
> + .name = match, \
> + .of_match = of_match_ptr(match), \
> + .ops = &mt6316_vreg_setclr_ops, \
> + .type = REGULATOR_VOLTAGE, \
> + .owner = THIS_MODULE, \
> + .n_voltages = (max - min) / step + 1, \
> + .min_uV = min, \
> + .uV_step = step, \
> + .enable_reg = MT6316_BUCK_TOP_CON0, \
> + .enable_mask = BIT(vreg_id - 1), \
> + .vsel_reg = vs_reg, \
> + .vsel_mask = MT6316_VSEL_MASK, \
> + .of_map_mode = mt6316_map_mode, \
> + }, \
> + .lp_mode_reg = MT6316_BUCK_TOP_CON1, \
> + .lp_mode_mask = BIT(vreg_id - 1), \
> + .modeset_reg = MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0, \
> + .modeset_mask = BIT(vreg_id - 1), \
> + .debug_reg = MT6316_VBUCK##vreg_id##_DBG, \
> +}
[...]
> +
> +/* MT6316BP/VP - 2+2 phase buck */
> +static struct mt6316_regulator_info mt6316bv_regulators[] = {
> + MT6316_BUCK("vbuck12", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
> + MT6316_BUCK("vbuck34", 3, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR4),
^
While this is technically correct as the selector does start from 0,
I don't think the regulator can actually go down to 0V. In the past
for the MT6311 / MT6315, MediaTek always added a standard minimum
voltage in the device tree.
I believe a combination of setting .linear_min_sel and adjusting min_uV
and n_voltages is the correct solution.
> +};
> +
> +/* MT6316CP/HP/KP - 3+1 phase buck */
> +static struct mt6316_regulator_info mt6316chk_regulators[] = {
> + MT6316_BUCK("vbuck124", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
> + MT6316_BUCK("vbuck3", 3, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR4),
> +};
> +
> +/* MT6316DP/TP - 4 phase buck */
> +static struct mt6316_regulator_info mt6316dt_regulators[] = {
> + MT6316_BUCK("vbuck1234", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
> +};
> +
> +static const struct regmap_config mt6316_spmi_regmap_config = {
> + .reg_bits = 16,
> + .val_bits = 8,
> + .max_register = 0x1700,
> + .fast_io = true,
> +};
> +
> +static int mt6316_regulator_probe(struct spmi_device *sdev)
> +{
> + struct regulator_config config = {};
> + struct mt6316_regulator_info *info;
> + struct regulator_dev *rdev;
> + enum mt6316_type type;
> + int num_vregs, ret;
> + unsigned int i;
> + u32 chip_id;
> +
> + config.regmap = devm_regmap_init_spmi_ext(sdev, &mt6316_spmi_regmap_config);
> + if (IS_ERR(config.regmap))
> + return PTR_ERR(config.regmap);
> +
> + /*
> + * The first read is expected to fail: this PMIC needs to be woken up
> + * and that can be done with any activity over the SPMI bus.
> + */
> + regmap_read(config.regmap, MT6316_CHIP_ID, &chip_id);
> +
> + /* The second read, instead, shall not fail! */
> + ret = regmap_read(config.regmap, MT6316_CHIP_ID, &chip_id);
> + if (ret) {
> + dev_err(&sdev->dev, "Cannot read Chip ID!\n");
> + return ret;
> + }
> + dev_dbg(&sdev->dev, "Chip ID: 0x%x\n", chip_id);
> +
> + config.dev = &sdev->dev;
> +
> + type = (uintptr_t)device_get_match_data(&sdev->dev);
> + switch (type) {
> + case MT6316_TYPE_2PHASE:
Instead of being tied to the compatible string / PMIC variant,
I wonder if this is something that can be read back from the
PMIC. You wouldn't need so many variant compatible strings if
that's the case.
FWIW we do that for some of the X-Powers AXP PMICs.
ChenYu
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 2/6] regulator: Add support for MediaTek MT6316 SPMI PMIC Regulators
2025-06-25 5:06 ` Chen-Yu Tsai
@ 2025-06-25 8:43 ` AngeloGioacchino Del Regno
0 siblings, 0 replies; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-25 8:43 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: broonie, lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
kernel
Il 25/06/25 07:06, Chen-Yu Tsai ha scritto:
> Hi,
>
> On Tue, Jun 24, 2025 at 3:46 PM AngeloGioacchino Del Regno
> <angelogioacchino.delregno@collabora.com> wrote:
>>
>> Add a driver for the regulators found on all types of the MediaTek
>> MT6316 SPMI PMIC, fully controlled by SPMI interface and featuring
>> four step down DCDC (buck) converters.
>>
>> In particular, this includes support for:
>> - MT6316(BP/VP): 2+2 Phase (Phase 1: buck1+2, Phase 2: buck3+4)
>> - MT6316(CP/HP/KP): 3+1 Phase (Phase 1: buck1+2+4, Phase 2: buck3)
>> - MT6316(DP/TP): 4+0 Phase (Single phase, buck1+2+3+4)
>>
>> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> ---
>> drivers/regulator/Kconfig | 9 +
>> drivers/regulator/Makefile | 1 +
>> drivers/regulator/mt6316-regulator.c | 345 +++++++++++++++++++++++++++
>> 3 files changed, 355 insertions(+)
>> create mode 100644 drivers/regulator/mt6316-regulator.c
>>
>> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
>> index 6d8988387da4..bca2ebbd89b7 100644
>> --- a/drivers/regulator/Kconfig
>> +++ b/drivers/regulator/Kconfig
>> @@ -864,6 +864,15 @@ config REGULATOR_MT6315
>> This driver supports the control of different power rails of device
>> through regulator interface.
>>
>> +config REGULATOR_MT6316
>> + tristate "MT6316 SPMI PMIC regulator driver"
>> + depends on SPMI || COMPILE_TEST
>> + help
>> + Say Y here to enable support for 2+2, 3+1 and 4 phase regulators
>> + found in the MediaTek MT6316 BP, CP, DP, HP, VP and TP SPMI PMICs.
>> + This driver supports the control of different power rails of device
>> + through regulator interface.
>> +
>> config REGULATOR_MT6323
>> tristate "MediaTek MT6323 PMIC"
>> depends on MFD_MT6397
>> diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
>> index c0bc7a0f4e67..58643e35d2cc 100644
>> --- a/drivers/regulator/Makefile
>> +++ b/drivers/regulator/Makefile
>> @@ -103,6 +103,7 @@ obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o
>> obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
>> obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
>> obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o
>> +obj-$(CONFIG_REGULATOR_MT6315) += mt6316-regulator.o
>> obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
>> obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o
>> obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o
>> diff --git a/drivers/regulator/mt6316-regulator.c b/drivers/regulator/mt6316-regulator.c
>> new file mode 100644
>> index 000000000000..952852bbe923
>> --- /dev/null
>> +++ b/drivers/regulator/mt6316-regulator.c
>> @@ -0,0 +1,345 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +//
>> +// Copyright (c) 2024 MediaTek Inc.
>> +// Copyright (c) 2025 Collabora Ltd
>> +// AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> +
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/regmap.h>
>> +#include <linux/spmi.h>
>> +
>> +#include <linux/regulator/driver.h>
>> +#include <linux/regulator/machine.h>
>> +#include <linux/regulator/of_regulator.h>
>> +
>> +#define MT6316_BUCK_MODE_AUTO 0
>> +#define MT6316_BUCK_MODE_FORCE_PWM 1
>> +#define MT6316_BUCK_MODE_LP 2
>> +
>> +#define MT6316_CHIP_ID 0x20b
>> +#define MT6316_BUCK_TOP_CON0 0x1440
>> +#define EN_SET_OFFSET 0x1
>> +#define EN_CLR_OFFSET 0x2
>> +
>> +#define MT6316_BUCK_TOP_CON1 0x1443
>> +
>> +#define MT6316_BUCK_TOP_ELR0 0x1448
>> +#define MT6316_BUCK_TOP_ELR2 0x144a
>> +#define MT6316_BUCK_TOP_ELR4 0x144c
>> +#define MT6316_BUCK_TOP_ELR6 0x144e
>> +#define MT6316_VSEL_MASK GENMASK(8, 0)
>> +
>> +#define MT6316_VBUCK1_DBG 0x14a8
>> +#define MT6316_VBUCK2_DBG 0x1528
>> +#define MT6316_VBUCK3_DBG 0x15a8
>> +#define MT6316_VBUCK4_DBG 0x1628
>> +#define MT6316_BUCK_QI BIT(0)
>> +
>> +#define MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0 0x1688
>> +#define MT6316_BUCK_TOP_4PHASE_TOP_ELR_0 0x1690
>> +
>> +enum mt6316_type {
>> + MT6316_TYPE_2PHASE,
>> + MT6316_TYPE_3PHASE,
>> + MT6316_TYPE_4PHASE
>> +};
>> +
>> +/**
>> + * struct mt6316_regulator_info - MT6316 regulators information
>> + * @desc: Regulator description structure
>> + * @debug_reg: Debug register for regulator status
>> + * @lp_mode_reg: Low Power mode register (normal/idle)
>> + * @lp_mode_mask: Low Power mode regulator mask
>> + * @modeset_reg: AUTO/PWM mode register
>> + * @modeset_mask: AUTO/PWM regulator mask
>> + */
>> +struct mt6316_regulator_info {
>> + struct regulator_desc desc;
>> + u16 debug_reg;
>> + u16 lp_mode_reg;
>> + u16 lp_mode_mask;
>> + u16 modeset_reg;
>> + u16 modeset_mask;
>> +};
>> +
>> +#define MT6316_BUCK(match, vreg_id, min, max, step, vs_reg) \
>> +{ \
>> + .desc = { \
>> + .name = match, \
>> + .of_match = of_match_ptr(match), \
>> + .ops = &mt6316_vreg_setclr_ops, \
>> + .type = REGULATOR_VOLTAGE, \
>> + .owner = THIS_MODULE, \
>> + .n_voltages = (max - min) / step + 1, \
>> + .min_uV = min, \
>> + .uV_step = step, \
>> + .enable_reg = MT6316_BUCK_TOP_CON0, \
>> + .enable_mask = BIT(vreg_id - 1), \
>> + .vsel_reg = vs_reg, \
>> + .vsel_mask = MT6316_VSEL_MASK, \
>> + .of_map_mode = mt6316_map_mode, \
>> + }, \
>> + .lp_mode_reg = MT6316_BUCK_TOP_CON1, \
>> + .lp_mode_mask = BIT(vreg_id - 1), \
>> + .modeset_reg = MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0, \
>> + .modeset_mask = BIT(vreg_id - 1), \
>> + .debug_reg = MT6316_VBUCK##vreg_id##_DBG, \
>> +}
>
> [...]
>
>> +
>> +/* MT6316BP/VP - 2+2 phase buck */
>> +static struct mt6316_regulator_info mt6316bv_regulators[] = {
>> + MT6316_BUCK("vbuck12", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
>> + MT6316_BUCK("vbuck34", 3, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR4),
>
> ^
> While this is technically correct as the selector does start from 0,
> I don't think the regulator can actually go down to 0V. In the past
> for the MT6311 / MT6315, MediaTek always added a standard minimum
> voltage in the device tree.
I believe the same, but I've done it as per what the datasheet says... so if
a zero selector is valid, the driver shall be able to set a zero selector.
The datasheet is not clear about the behavior of setting 0V - as in, if the
buck gets its VIN and outputs nothing, or if it is the same as powering it off,
as much as not being clear about some of the electrical characteristics.
For me, there's no way to test what the 0V setting electrically does exactly,
I was only able to test that when setting that selector to zero, the platform
gets severely undervolted and crashes - but that undervolt crash happens at a
broad (substantially low) voltages range - so this particular zero setting was
.. again.. impossible to test.
>
> I believe a combination of setting .linear_min_sel and adjusting min_uV
> and n_voltages is the correct solution.
>
Could be, but again - if the datasheet says that this is a supported setting,
we should declare it as a supported setting.
Unless the datasheet is wrong (which is not impossible tbh) - but then what
can you do if that's the case, apart from grabbing (very) expensive equipment,
and go through that rabbit hole like that? :-(
>> +};
>> +
>> +/* MT6316CP/HP/KP - 3+1 phase buck */
>> +static struct mt6316_regulator_info mt6316chk_regulators[] = {
>> + MT6316_BUCK("vbuck124", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
>> + MT6316_BUCK("vbuck3", 3, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR4),
>> +};
>> +
>> +/* MT6316DP/TP - 4 phase buck */
>> +static struct mt6316_regulator_info mt6316dt_regulators[] = {
>> + MT6316_BUCK("vbuck1234", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
>> +};
>> +
>> +static const struct regmap_config mt6316_spmi_regmap_config = {
>> + .reg_bits = 16,
>> + .val_bits = 8,
>> + .max_register = 0x1700,
>> + .fast_io = true,
>> +};
>> +
>> +static int mt6316_regulator_probe(struct spmi_device *sdev)
>> +{
>> + struct regulator_config config = {};
>> + struct mt6316_regulator_info *info;
>> + struct regulator_dev *rdev;
>> + enum mt6316_type type;
>> + int num_vregs, ret;
>> + unsigned int i;
>> + u32 chip_id;
>> +
>> + config.regmap = devm_regmap_init_spmi_ext(sdev, &mt6316_spmi_regmap_config);
>> + if (IS_ERR(config.regmap))
>> + return PTR_ERR(config.regmap);
>> +
>> + /*
>> + * The first read is expected to fail: this PMIC needs to be woken up
>> + * and that can be done with any activity over the SPMI bus.
>> + */
>> + regmap_read(config.regmap, MT6316_CHIP_ID, &chip_id);
>> +
>> + /* The second read, instead, shall not fail! */
>> + ret = regmap_read(config.regmap, MT6316_CHIP_ID, &chip_id);
>> + if (ret) {
>> + dev_err(&sdev->dev, "Cannot read Chip ID!\n");
>> + return ret;
>> + }
>> + dev_dbg(&sdev->dev, "Chip ID: 0x%x\n", chip_id);
>> +
>> + config.dev = &sdev->dev;
>> +
>> + type = (uintptr_t)device_get_match_data(&sdev->dev);
>> + switch (type) {
>> + case MT6316_TYPE_2PHASE:
>
> Instead of being tied to the compatible string / PMIC variant,
> I wonder if this is something that can be read back from the
> PMIC. You wouldn't need so many variant compatible strings if
> that's the case.
We think alike - always loved that.
The answer is simple (and sad): the datasheet doesn't contain this information...
and more...: some of what you see in this driver (and the other two) is done with
a combination of cross-checking between various downstream kernels and some risky
tinkering.
Cheers,
Angelo
>
> FWIW we do that for some of the X-Powers AXP PMICs.
>
>
> ChenYu
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: regulator: Document MediaTek MT6316 PMIC Regulators
2025-06-24 7:35 ` [PATCH v2 1/6] dt-bindings: regulator: Document MediaTek MT6316 PMIC Regulators AngeloGioacchino Del Regno
@ 2025-06-27 8:16 ` Krzysztof Kozlowski
0 siblings, 0 replies; 17+ messages in thread
From: Krzysztof Kozlowski @ 2025-06-27 8:16 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: broonie, lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
kernel
On Tue, Jun 24, 2025 at 09:35:43AM +0200, AngeloGioacchino Del Regno wrote:
> Add bindings for the regulators found in the MediaTek MT6316 PMIC,
> usually found in board designs using the MT6991 Dimensity 9400 and
> on MT8196 Kompanio SoC for Chromebooks.
>
> This chip is fully controlled by SPMI and has multiple variants
> providing different phase configurations.
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
> .../regulator/mediatek,mt6316-regulator.yaml | 81 +++++++++++++++++++
> 1 file changed, 81 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml
>
> diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml
> new file mode 100644
> index 000000000000..019c3c36997c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6316-regulator.yaml
> @@ -0,0 +1,81 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/regulator/mediatek,mt6316-regulator.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek MT6316 SPMI PMIC Regulators
> +
> +maintainers:
> + - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> +
> +description: |
> + The MediaTek MT6316 PMIC is fully controlled by SPMI interface; it features
> + four step-down DC/DC (buck) converters and has multiple variants, providing
> + different phase configurations. In particular:
> + MT6316BP/VP: 2+2 Phase (buck 1+2, buck 3+4)
> + MT6316CP/HP/KP: 3+1 Phase (buck 1+2+4, buck 3)
> + MT6316DP/TP: 4+0 Phase (buck 1+2+3+4)
> +
> +properties:
> + compatible:
> + enum:
> + - mediatek,mt6316b-regulator
> + - mediatek,mt6316c-regulator
> + - mediatek,mt6316d-regulator
> +
> + vbuck1234:
> + type: object
> + $ref: regulator.yaml#
> + unevaluatedProperties: false
> +
Here you define all regulators
> +additionalProperties: false
This goes to the end.
> +
> +allOf:
> + - if:
> + properties:
> + compatible:
> + const: mediatek,mt6316b-regulator
> + then:
> + patternProperties:
> + "^vbuck(12|34)$":
Every device has different regulators, so there is little benefit in
keeping this in one schema file.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 PMIC Regulators
2025-06-24 7:35 ` [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 " AngeloGioacchino Del Regno
@ 2025-06-27 8:18 ` Krzysztof Kozlowski
2025-06-30 3:25 ` Chen-Yu Tsai
0 siblings, 1 reply; 17+ messages in thread
From: Krzysztof Kozlowski @ 2025-06-27 8:18 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: broonie, lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
kernel
On Tue, Jun 24, 2025 at 09:35:45AM +0200, AngeloGioacchino Del Regno wrote:
> Add bindings for the regulators found in the MediaTek MT6363 PMIC,
> usually found in board designs using the MT6991 Dimensity 9400 and
> on MT8196 Kompanio SoC for Chromebooks, along with the MT6316 and
> MT6373 PMICs.
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
> .../regulator/mediatek,mt6363-regulator.yaml | 123 ++++++++++++++++++
> 1 file changed, 123 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
>
> diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
> new file mode 100644
> index 000000000000..f866c89c56f7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
> @@ -0,0 +1,123 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/regulator/mediatek,mt6363-regulator.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek MT6363 PMIC Regulators
> +
> +maintainers:
> + - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> +
> +description:
> + The MT6363 SPMI PMIC provides 10 BUCK and 26 LDO (Low Dropout) regulators
> + and can optionally provide overcurrent warnings with one ocp interrupt
> + for each voltage regulator.
> +
> +properties:
> + compatible:
> + const: mediatek,mt6363-regulator
> +
> + interrupts:
> + description: Overcurrent warning interrupts
Are you sure interrupts are physically not connected?
> + minItems: 1
> + maxItems: 36
> +
> + interrupt-names:
> + description:
> + Names for the overcurrent interrupts are the same as the name
> + of a regulator (hence the same as each regulator's node name).
> + For example, the interrupt name for regulator vs2 will be "vs2".
You need to define the items or pattern if this is really flexible in
the hardware (not drivers).
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 5/6] dt-bindings: regulator: Document MediaTek MT6373 PMIC Regulators
2025-06-24 7:35 ` [PATCH v2 5/6] dt-bindings: regulator: Document MediaTek MT6373 " AngeloGioacchino Del Regno
@ 2025-06-27 8:21 ` Krzysztof Kozlowski
0 siblings, 0 replies; 17+ messages in thread
From: Krzysztof Kozlowski @ 2025-06-27 8:21 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: broonie, lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
kernel
On Tue, Jun 24, 2025 at 09:35:47AM +0200, AngeloGioacchino Del Regno wrote:
> +properties:
> + compatible:
> + const: mediatek,mt6373-regulator
Where is mediatek,mt6373? Nothing in cover letter explains that, but I
expect parent device schema to $ref this one or (better) mention
compatibles for child.
> +
> + interrupts:
> + description: Overcurrent warning interrupts
> + minItems: 1
> + maxItems: 35
> +
> + interrupt-names:
> + description:
> + Names for the overcurrent interrupts are the same as the name
> + of a regulator (hence the same as each regulator's node name).
> + For example, the interrupt name for regulator vs2 will be "vs2".
> + minItems: 1
> + maxItems: 35
> +
> +patternProperties:
> + "^v(ant|aud|aux)18$":
> + type: object
> + $ref: regulator.yaml#
> + unevaluatedProperties: false
You need to document what modes mean in schema with constraints and in
text with their actual meaning (see regulator.yaml).
Also: Other comments from previous patch are applicable.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators
2025-06-24 7:35 ` [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI " AngeloGioacchino Del Regno
@ 2025-06-27 19:42 ` Dan Carpenter
2025-07-06 6:22 ` kernel test robot
1 sibling, 0 replies; 17+ messages in thread
From: Dan Carpenter @ 2025-06-27 19:42 UTC (permalink / raw)
To: oe-kbuild, AngeloGioacchino Del Regno, broonie
Cc: lkp, oe-kbuild-all, lgirdwood, robh, krzk+dt, conor+dt,
matthias.bgg, angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Hi AngeloGioacchino,
kernel test robot noticed the following build warnings:
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/AngeloGioacchino-Del-Regno/dt-bindings-regulator-Document-MediaTek-MT6316-PMIC-Regulators/20250624-154048
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
patch link: https://lore.kernel.org/r/20250624073548.29732-5-angelogioacchino.delregno%40collabora.com
patch subject: [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators
config: x86_64-randconfig-161-20250627 (https://download.01.org/0day-ci/archive/20250628/202506280258.somyWWgp-lkp@intel.com/config)
compiler: clang version 20.1.7 (https://github.com/llvm/llvm-project 6146a88f60492b520a36f8f8f3231e15f3cc6082)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202506280258.somyWWgp-lkp@intel.com/
New smatch warnings:
drivers/regulator/mt6363-regulator.c:351 mt6363_regulator_set_mode() error: uninitialized symbol 'regmap'.
drivers/regulator/mt6363-regulator.c:388 mt6363_regulator_set_mode() error: uninitialized symbol 'ret'.
vim +/regmap +351 drivers/regulator/mt6363-regulator.c
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 342 static int mt6363_regulator_set_mode(struct regulator_dev *rdev,
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 343 unsigned int mode)
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 344 {
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 345 struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 346 struct regmap *regmap;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 347 int cur_mode, ret;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 348
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 349 switch (mode) {
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 350 case REGULATOR_MODE_FAST:
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 @351 ret = mt6363_buck_unlock(regmap, true);
^^^^^
Uninitialized.
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 352 if (ret)
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 353 break;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 354
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 355 ret = regmap_set_bits(regmap, info->modeset_reg, info->modeset_mask);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 356
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 357 mt6363_buck_unlock(regmap, false);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 358 break;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 359 case REGULATOR_MODE_NORMAL:
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 360 cur_mode = mt6363_regulator_get_mode(rdev);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 361 if (cur_mode < 0) {
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 362 ret = cur_mode;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 363 break;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 364 }
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 365
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 366 if (cur_mode == REGULATOR_MODE_FAST) {
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 367 ret = mt6363_buck_unlock(regmap, true);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 368 if (ret)
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 369 break;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 370
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 371 ret = regmap_clear_bits(regmap, info->modeset_reg, info->modeset_mask);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 372
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 373 mt6363_buck_unlock(regmap, false);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 374 break;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 375 } else if (cur_mode == REGULATOR_MODE_IDLE) {
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 376 ret = regmap_clear_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 377 if (ret == 0)
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 378 usleep_range(100, 200);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 379 }
ret not initialized on else path.
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 380 break;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 381 case REGULATOR_MODE_IDLE:
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 382 ret = regmap_set_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 383 break;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 384 default:
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 385 ret = -EINVAL;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 386 }
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 387
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 @388 if (ret) {
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 389 dev_err(&rdev->dev, "Failed to set mode %u: %d\n", mode, ret);
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 390 return ret;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 391 }
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 392
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 393 return 0;
5dae648aed0eaf AngeloGioacchino Del Regno 2025-06-24 394 }
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 PMIC Regulators
2025-06-27 8:18 ` Krzysztof Kozlowski
@ 2025-06-30 3:25 ` Chen-Yu Tsai
2025-06-30 7:52 ` AngeloGioacchino Del Regno
0 siblings, 1 reply; 17+ messages in thread
From: Chen-Yu Tsai @ 2025-06-30 3:25 UTC (permalink / raw)
To: Krzysztof Kozlowski, AngeloGioacchino Del Regno
Cc: broonie, lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
kernel
On Fri, Jun 27, 2025 at 4:24 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Tue, Jun 24, 2025 at 09:35:45AM +0200, AngeloGioacchino Del Regno wrote:
> > Add bindings for the regulators found in the MediaTek MT6363 PMIC,
> > usually found in board designs using the MT6991 Dimensity 9400 and
> > on MT8196 Kompanio SoC for Chromebooks, along with the MT6316 and
> > MT6373 PMICs.
> >
> > Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> > ---
> > .../regulator/mediatek,mt6363-regulator.yaml | 123 ++++++++++++++++++
> > 1 file changed, 123 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
> > new file mode 100644
> > index 000000000000..f866c89c56f7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
> > @@ -0,0 +1,123 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/regulator/mediatek,mt6363-regulator.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: MediaTek MT6363 PMIC Regulators
> > +
> > +maintainers:
> > + - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> > +
> > +description:
> > + The MT6363 SPMI PMIC provides 10 BUCK and 26 LDO (Low Dropout) regulators
> > + and can optionally provide overcurrent warnings with one ocp interrupt
> > + for each voltage regulator.
> > +
> > +properties:
> > + compatible:
> > + const: mediatek,mt6363-regulator
> > +
> > + interrupts:
> > + description: Overcurrent warning interrupts
>
> Are you sure interrupts are physically not connected?
Side note:
I wonder if we really need to describe _all_ the interrupts here.
Looking at the PMIC as a whole, the interrupt tree is something like
SoC <- SPMI inband IRQ - PMIC top level IRQ block <- sub-function IRQ blocks:
- BUCK (buck regulator over current)
- LDO (LDO regulator over current)
- PSC (key press / system low voltage)
- MISC (protected registers accessed / SPMI stuff)
And some other blocks that may apply to other MediaTek PMICs:
- HK (some threshold triggered interrupt)
- BM (battery management related)
The thing I'm trying to get to is that all these interrupt vectors are
internal to the whole PMIC. Do we really need to spell them out in the
device tree? The top level compatible should already imply how all the
internals are wired up.
ChenYu
> > + minItems: 1
> > + maxItems: 36
> > +
> > + interrupt-names:
> > + description:
> > + Names for the overcurrent interrupts are the same as the name
> > + of a regulator (hence the same as each regulator's node name).
> > + For example, the interrupt name for regulator vs2 will be "vs2".
>
> You need to define the items or pattern if this is really flexible in
> the hardware (not drivers).
>
> Best regards,
> Krzysztof
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 PMIC Regulators
2025-06-30 3:25 ` Chen-Yu Tsai
@ 2025-06-30 7:52 ` AngeloGioacchino Del Regno
2025-06-30 8:34 ` Chen-Yu Tsai
0 siblings, 1 reply; 17+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-06-30 7:52 UTC (permalink / raw)
To: Chen-Yu Tsai, Krzysztof Kozlowski
Cc: broonie, lgirdwood, robh, krzk+dt, conor+dt, matthias.bgg,
linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
kernel
Il 30/06/25 05:25, Chen-Yu Tsai ha scritto:
> On Fri, Jun 27, 2025 at 4:24 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>
>> On Tue, Jun 24, 2025 at 09:35:45AM +0200, AngeloGioacchino Del Regno wrote:
>>> Add bindings for the regulators found in the MediaTek MT6363 PMIC,
>>> usually found in board designs using the MT6991 Dimensity 9400 and
>>> on MT8196 Kompanio SoC for Chromebooks, along with the MT6316 and
>>> MT6373 PMICs.
>>>
>>> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>>> ---
>>> .../regulator/mediatek,mt6363-regulator.yaml | 123 ++++++++++++++++++
>>> 1 file changed, 123 insertions(+)
>>> create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
>>> new file mode 100644
>>> index 000000000000..f866c89c56f7
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
>>> @@ -0,0 +1,123 @@
>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/regulator/mediatek,mt6363-regulator.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: MediaTek MT6363 PMIC Regulators
>>> +
>>> +maintainers:
>>> + - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>>> +
>>> +description:
>>> + The MT6363 SPMI PMIC provides 10 BUCK and 26 LDO (Low Dropout) regulators
>>> + and can optionally provide overcurrent warnings with one ocp interrupt
>>> + for each voltage regulator.
>>> +
>>> +properties:
>>> + compatible:
>>> + const: mediatek,mt6363-regulator
>>> +
>>> + interrupts:
>>> + description: Overcurrent warning interrupts
>>
>> Are you sure interrupts are physically not connected?
Yes, I'm sure, they are not.
>
> Side note:
>
> I wonder if we really need to describe _all_ the interrupts here.
>
> Looking at the PMIC as a whole, the interrupt tree is something like
>
> SoC <- SPMI inband IRQ - PMIC top level IRQ block <- sub-function IRQ blocks:
>
> - BUCK (buck regulator over current)
> - LDO (LDO regulator over current)
> - PSC (key press / system low voltage)
> - MISC (protected registers accessed / SPMI stuff)
>
> And some other blocks that may apply to other MediaTek PMICs:
>
> - HK (some threshold triggered interrupt)
> - BM (battery management related)
>
> The thing I'm trying to get to is that all these interrupt vectors are
> internal to the whole PMIC. Do we really need to spell them out in the
> device tree? The top level compatible should already imply how all the
> internals are wired up.
>
Chen-Yu:
Yes, we do: not all boards need overcurrent protection on all of the rails, but
especially, in the past I have seen (multiple times) board designs (not MediaTek,
but that doesn't mean anything) that will trigger the overcurrent protection due
to a high inrush upon rail enablement - in these cases, the ocp would have to be
either ignored completely or reset and read after a while.
Not only that: since not all rails are actually used, due to EMI (and other issues
which usually mean suboptimally built boards) some of those may randomly trigger
OCP, and that's another case in which that should be ignored.
So... yes, we want to define the overcurrent interrupts in the devicetree.
>
> ChenYu
>
>>> + minItems: 1
>>> + maxItems: 36
>>> +
>>> + interrupt-names:
>>> + description:
>>> + Names for the overcurrent interrupts are the same as the name
>>> + of a regulator (hence the same as each regulator's node name).
>>> + For example, the interrupt name for regulator vs2 will be "vs2".
>>
>> You need to define the items or pattern if this is really flexible in
>> the hardware (not drivers).
krzk:
It's flexible in the hardware... but how do I define a pattern here?
I avoided to define the items because you can miss some; I mean....
You may have, on one board:
"vs1", "vsram", "someother", "another"
on another: "vsram", "another"
...and another: "vs1", "another"
(etc etc)
Is there any way to allow missing items in between?
Because then there's 36 possible items, so there are more than 100 possible
combinations (keeping the order, but missing something in between..!).
Cheers,
Angelo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 PMIC Regulators
2025-06-30 7:52 ` AngeloGioacchino Del Regno
@ 2025-06-30 8:34 ` Chen-Yu Tsai
0 siblings, 0 replies; 17+ messages in thread
From: Chen-Yu Tsai @ 2025-06-30 8:34 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: Krzysztof Kozlowski, broonie, lgirdwood, robh, krzk+dt, conor+dt,
matthias.bgg, linux-kernel, devicetree, linux-arm-kernel,
linux-mediatek, kernel
Hi,
On Mon, Jun 30, 2025 at 3:52 PM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Il 30/06/25 05:25, Chen-Yu Tsai ha scritto:
> > On Fri, Jun 27, 2025 at 4:24 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
> >>
> >> On Tue, Jun 24, 2025 at 09:35:45AM +0200, AngeloGioacchino Del Regno wrote:
> >>> Add bindings for the regulators found in the MediaTek MT6363 PMIC,
> >>> usually found in board designs using the MT6991 Dimensity 9400 and
> >>> on MT8196 Kompanio SoC for Chromebooks, along with the MT6316 and
> >>> MT6373 PMICs.
> >>>
> >>> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> >>> ---
> >>> .../regulator/mediatek,mt6363-regulator.yaml | 123 ++++++++++++++++++
> >>> 1 file changed, 123 insertions(+)
> >>> create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
> >>> new file mode 100644
> >>> index 000000000000..f866c89c56f7
> >>> --- /dev/null
> >>> +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6363-regulator.yaml
> >>> @@ -0,0 +1,123 @@
> >>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> >>> +%YAML 1.2
> >>> +---
> >>> +$id: http://devicetree.org/schemas/regulator/mediatek,mt6363-regulator.yaml#
> >>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> >>> +
> >>> +title: MediaTek MT6363 PMIC Regulators
> >>> +
> >>> +maintainers:
> >>> + - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> >>> +
> >>> +description:
> >>> + The MT6363 SPMI PMIC provides 10 BUCK and 26 LDO (Low Dropout) regulators
> >>> + and can optionally provide overcurrent warnings with one ocp interrupt
> >>> + for each voltage regulator.
> >>> +
> >>> +properties:
> >>> + compatible:
> >>> + const: mediatek,mt6363-regulator
> >>> +
> >>> + interrupts:
> >>> + description: Overcurrent warning interrupts
> >>
> >> Are you sure interrupts are physically not connected?
>
> Yes, I'm sure, they are not.
>
> >
> > Side note:
> >
> > I wonder if we really need to describe _all_ the interrupts here.
> >
> > Looking at the PMIC as a whole, the interrupt tree is something like
> >
> > SoC <- SPMI inband IRQ - PMIC top level IRQ block <- sub-function IRQ blocks:
> >
> > - BUCK (buck regulator over current)
> > - LDO (LDO regulator over current)
> > - PSC (key press / system low voltage)
> > - MISC (protected registers accessed / SPMI stuff)
> >
> > And some other blocks that may apply to other MediaTek PMICs:
> >
> > - HK (some threshold triggered interrupt)
> > - BM (battery management related)
> >
> > The thing I'm trying to get to is that all these interrupt vectors are
> > internal to the whole PMIC. Do we really need to spell them out in the
> > device tree? The top level compatible should already imply how all the
> > internals are wired up.
> >
>
> Chen-Yu:
>
> Yes, we do: not all boards need overcurrent protection on all of the rails, but
> especially, in the past I have seen (multiple times) board designs (not MediaTek,
> but that doesn't mean anything) that will trigger the overcurrent protection due
> to a high inrush upon rail enablement - in these cases, the ocp would have to be
> either ignored completely or reset and read after a while.
>
> Not only that: since not all rails are actually used, due to EMI (and other issues
> which usually mean suboptimally built boards) some of those may randomly trigger
> OCP, and that's another case in which that should be ignored.
>
> So... yes, we want to define the overcurrent interrupts in the devicetree.
I understand the use case, but I think that's kind of giving the interrupts
property a second meaning.
Instead, if you look at the common regulator bindings, there is a
"regulator-over-current-protection" which signals that over current
protection should be enabled for a given regulator. Perhaps you could
use that? I think this common property also implies that over current
protection has to be explicitly enabled.
> >
> > ChenYu
> >
> >>> + minItems: 1
> >>> + maxItems: 36
> >>> +
> >>> + interrupt-names:
> >>> + description:
> >>> + Names for the overcurrent interrupts are the same as the name
> >>> + of a regulator (hence the same as each regulator's node name).
> >>> + For example, the interrupt name for regulator vs2 will be "vs2".
> >>
> >> You need to define the items or pattern if this is really flexible in
> >> the hardware (not drivers).
>
> krzk:
>
> It's flexible in the hardware... but how do I define a pattern here?
> I avoided to define the items because you can miss some; I mean....
>
> You may have, on one board:
> "vs1", "vsram", "someother", "another"
>
> on another: "vsram", "another"
>
> ...and another: "vs1", "another"
>
> (etc etc)
>
> Is there any way to allow missing items in between?
> Because then there's 36 possible items, so there are more than 100 possible
> combinations (keeping the order, but missing something in between..!).
I recently saw in the net/snps,dwmac.yaml binding the following:
clock-names:
minItems: 1
maxItems: 10
additionalItems: true
contains:
enum:
- stmmaceth
- pclk
- ptp_ref
I suppose you could adapt this pattern, list all the possibilities, and
set additionalItems to false. I don't think it can pick out duplicates
though.
ChenYu
> Cheers,
> Angelo
>
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators
2025-06-24 7:35 ` [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI " AngeloGioacchino Del Regno
2025-06-27 19:42 ` Dan Carpenter
@ 2025-07-06 6:22 ` kernel test robot
1 sibling, 0 replies; 17+ messages in thread
From: kernel test robot @ 2025-07-06 6:22 UTC (permalink / raw)
To: AngeloGioacchino Del Regno, broonie
Cc: llvm, oe-kbuild-all, lgirdwood, robh, krzk+dt, conor+dt,
matthias.bgg, angelogioacchino.delregno, linux-kernel, devicetree,
linux-arm-kernel, linux-mediatek, kernel
Hi AngeloGioacchino,
kernel test robot noticed the following build errors:
[auto build test ERROR on broonie-regulator/for-next]
[also build test ERROR on linus/master v6.16-rc4 next-20250704]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/AngeloGioacchino-Del-Regno/dt-bindings-regulator-Document-MediaTek-MT6316-PMIC-Regulators/20250624-154048
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
patch link: https://lore.kernel.org/r/20250624073548.29732-5-angelogioacchino.delregno%40collabora.com
patch subject: [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators
config: hexagon-allmodconfig (https://download.01.org/0day-ci/archive/20250706/202507061437.VKBqvJPn-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250706/202507061437.VKBqvJPn-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507061437.VKBqvJPn-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/regulator/mt6363-regulator.c:375:14: warning: variable 'ret' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
375 | } else if (cur_mode == REGULATOR_MODE_IDLE) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/regulator/mt6363-regulator.c:388:6: note: uninitialized use occurs here
388 | if (ret) {
| ^~~
drivers/regulator/mt6363-regulator.c:375:10: note: remove the 'if' if its condition is always true
375 | } else if (cur_mode == REGULATOR_MODE_IDLE) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/regulator/mt6363-regulator.c:347:19: note: initialize the variable 'ret' to silence this warning
347 | int cur_mode, ret;
| ^
| = 0
drivers/regulator/mt6363-regulator.c:351:28: warning: variable 'regmap' is uninitialized when used here [-Wuninitialized]
351 | ret = mt6363_buck_unlock(regmap, true);
| ^~~~~~
drivers/regulator/mt6363-regulator.c:346:23: note: initialize the variable 'regmap' to silence this warning
346 | struct regmap *regmap;
| ^
| = NULL
>> drivers/regulator/mt6363-regulator.c:455:9: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
455 | sel = FIELD_PREP(MT6363_RG_VEMC_VOSEL_1_MASK, sel);
| ^
>> drivers/regulator/mt6363-regulator.c:487:9: error: call to undeclared function 'FIELD_GET'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
487 | ret = FIELD_GET(MT6363_RG_VEMC_VOSEL_1_MASK, sel);
| ^
2 warnings and 2 errors generated.
vim +/FIELD_PREP +455 drivers/regulator/mt6363-regulator.c
430
431 static int mt6363_vemc_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
432 {
433 const u16 tma_unlock_key = MT6363_TMA_UNLOCK_VALUE;
434 struct regmap *regmap = rdev->regmap;
435 unsigned int val;
436 u16 mask;
437 int ret;
438
439 ret = regmap_read(rdev->regmap, MT6363_TOP_TRAP, &val);
440 if (ret)
441 return ret;
442
443 if (val > 1)
444 return -EINVAL;
445
446 /* Unlock TMA for writing */
447 ret = regmap_bulk_write(rdev->regmap, MT6363_TOP_TMA_KEY_L,
448 &tma_unlock_key, sizeof(tma_unlock_key));
449 if (ret)
450 return ret;
451
452 /* If HW trapping value is 1, use VEMC_VOSEL_1 instead of VEMC_VOSEL_0 */
453 if (val == 1) {
454 mask = MT6363_RG_VEMC_VOSEL_1_MASK;
> 455 sel = FIELD_PREP(MT6363_RG_VEMC_VOSEL_1_MASK, sel);
456 } else {
457 mask = rdev->desc->vsel_mask;
458 }
459
460 /* Function must return the result of this write operation */
461 ret = regmap_update_bits(regmap, rdev->desc->vsel_reg, mask, sel);
462
463 /* Unconditionally re-lock TMA */
464 val = 0;
465 regmap_bulk_write(rdev->regmap, MT6363_TOP_TMA_KEY_L, &val, 2);
466
467 return ret;
468 }
469
470 static int mt6363_vemc_get_voltage_sel(struct regulator_dev *rdev)
471 {
472 unsigned int sel, trap;
473 int ret;
474
475 ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &sel);
476 if (ret)
477 return ret;
478
479 ret = regmap_read(rdev->regmap, MT6363_TOP_TRAP, &trap);
480 if (ret)
481 return ret;
482
483 /* If HW trapping value is 1, use VEMC_VOSEL_1 instead of VEMC_VOSEL_0 */
484 if (trap > 1)
485 return -EINVAL;
486 else if (trap == 1)
> 487 ret = FIELD_GET(MT6363_RG_VEMC_VOSEL_1_MASK, sel);
488 else
489 ret = sel & rdev->desc->vsel_mask;
490
491 return ret;
492 }
493
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2025-07-06 6:22 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-24 7:35 [PATCH v2 0/6] regulator: Add support for MediaTek MT6316/6363/6373 PMICs AngeloGioacchino Del Regno
2025-06-24 7:35 ` [PATCH v2 1/6] dt-bindings: regulator: Document MediaTek MT6316 PMIC Regulators AngeloGioacchino Del Regno
2025-06-27 8:16 ` Krzysztof Kozlowski
2025-06-24 7:35 ` [PATCH v2 2/6] regulator: Add support for MediaTek MT6316 SPMI " AngeloGioacchino Del Regno
2025-06-25 5:06 ` Chen-Yu Tsai
2025-06-25 8:43 ` AngeloGioacchino Del Regno
2025-06-24 7:35 ` [PATCH v2 3/6] dt-bindings: regulator: Document MediaTek MT6363 " AngeloGioacchino Del Regno
2025-06-27 8:18 ` Krzysztof Kozlowski
2025-06-30 3:25 ` Chen-Yu Tsai
2025-06-30 7:52 ` AngeloGioacchino Del Regno
2025-06-30 8:34 ` Chen-Yu Tsai
2025-06-24 7:35 ` [PATCH v2 4/6] regulator: Add support for MediaTek MT6363 SPMI " AngeloGioacchino Del Regno
2025-06-27 19:42 ` Dan Carpenter
2025-07-06 6:22 ` kernel test robot
2025-06-24 7:35 ` [PATCH v2 5/6] dt-bindings: regulator: Document MediaTek MT6373 " AngeloGioacchino Del Regno
2025-06-27 8:21 ` Krzysztof Kozlowski
2025-06-24 7:35 ` [PATCH v2 6/6] regulator: Add support for MediaTek MT6373 SPMI " AngeloGioacchino Del Regno
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).