* [PATCH v4 6/6] regulator: mt6359: Add proper ldo_vcn33_[12] regulators
From: Chen-Yu Tsai @ 2026-05-14 9:15 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-arm-kernel, linux-mediatek, devicetree
In-Reply-To: <20260514091520.2718987-1-wenst@chromium.org>
The ldo_vcn33_[12]_wifi and ldo_vcn33_[12]_bt are just two regulator
outputs instead of four. The wifi and bt parts refer to separate enable
bits that are OR-ed together to affect the actual regulator output. The
separate bits allow the wifi and bt stacks to enable their power without
coordination between them. These have been deprecated in favor of proper
nodes matching the output.
Add proper ldo_vcn33_[12] regulators to replace the existing ones. The
enable status is synced to just one of the two enable bits, and the
other is forced off. This makes the handling in other bits simpler.
The existing *_(bt|wifi) regulators are converted to no-op regulators
that are fed from their new respective ldo_vcn33_[12] regulator. This
allows existing device trees to continue to work.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Changes since v3:
- Fixed index off-by-one in error message in mt6359_sync_vcn33_setting()
(Sashiko)
- Added check of return value from mt6359_sync_vcn33_setting() (Sashiko)
Changes since v1:
- Instead of dropping one regulator from each output, add a new one for
each output; the existing *_(bt|wifi) ones are then supplied from the
new one
---
drivers/regulator/mt6359-regulator.c | 184 +++++++++++++++++----
include/linux/regulator/mt6359-regulator.h | 10 +-
2 files changed, 159 insertions(+), 35 deletions(-)
diff --git a/drivers/regulator/mt6359-regulator.c b/drivers/regulator/mt6359-regulator.c
index 46cafe93b24e..af0e0339fbdd 100644
--- a/drivers/regulator/mt6359-regulator.c
+++ b/drivers/regulator/mt6359-regulator.c
@@ -166,6 +166,20 @@ struct mt6359_regulator_info {
.qi = BIT(0), \
}
+#define MT6359_LDO_NOOP(match, _name, supply) \
+[MT6359_ID_##_name] = { \
+ .desc = { \
+ .name = #_name, \
+ .supply_name = supply, \
+ .of_match = of_match_ptr(match), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .ops = &mt6359_noop_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MT6359_ID_##_name, \
+ .owner = THIS_MODULE, \
+ }, \
+}
+
static const unsigned int vsim1_voltages[] = {
0, 0, 0, 1700000, 1800000, 0, 0, 0, 2700000, 0, 0, 3000000, 3100000,
};
@@ -475,6 +489,9 @@ static const struct regulator_ops mt6359p_vemc_ops = {
.get_status = mt6359_get_status,
};
+/* Used for backward-compatible placeholder regulators */
+static const struct regulator_ops mt6359_noop_ops = {};
+
/* The array is indexed by id(MT6359_ID_XXX) */
static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_BUCK("buck_vs1", VS1, "vsys-vs1", 800000, 2200000, 12500,
@@ -596,18 +613,12 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_DA_VCN13_B_EN_ADDR, MT6359_RG_VCN13_VOSEL_ADDR,
MT6359_RG_VCN13_VOSEL_MASK << MT6359_RG_VCN13_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vcn33_1_bt", VCN33_1_BT, "vsys-ldo1", vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_1", VCN33_1, "vsys-ldo1", vcn33_voltages,
MT6359_RG_LDO_VCN33_1_EN_0_ADDR,
MT6359_RG_LDO_VCN33_1_EN_0_SHIFT,
MT6359_DA_VCN33_1_B_EN_ADDR, MT6359_RG_VCN33_1_VOSEL_ADDR,
MT6359_RG_VCN33_1_VOSEL_MASK <<
MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_vcn33_1_wifi", VCN33_1_WIFI, "vsys-ldo1", vcn33_voltages,
- MT6359_RG_LDO_VCN33_1_EN_1_ADDR,
- MT6359_RG_LDO_VCN33_1_EN_1_SHIFT,
- MT6359_DA_VCN33_1_B_EN_ADDR, MT6359_RG_VCN33_1_VOSEL_ADDR,
- MT6359_RG_VCN33_1_VOSEL_MASK <<
- MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
MT6359_REG_FIXED("ldo_vaux18", VAUX18, "vsys-ldo2", MT6359_RG_LDO_VAUX18_EN_ADDR,
MT6359_DA_VAUX18_B_EN_ADDR, 1800000),
MT6359_LDO_LINEAR("ldo_vsram_others", VSRAM_OTHERS, "vs2-ldo1", 500000, 1293750,
@@ -644,18 +655,12 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_DA_VEMC_B_EN_ADDR, MT6359_RG_VEMC_VOSEL_ADDR,
MT6359_RG_VEMC_VOSEL_MASK << MT6359_RG_VEMC_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vcn33_2_bt", VCN33_2_BT, "vsys-ldo1", vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_2", VCN33_2, "vsys-ldo1", vcn33_voltages,
MT6359_RG_LDO_VCN33_2_EN_0_ADDR,
MT6359_RG_LDO_VCN33_2_EN_0_SHIFT,
MT6359_DA_VCN33_2_B_EN_ADDR, MT6359_RG_VCN33_2_VOSEL_ADDR,
MT6359_RG_VCN33_2_VOSEL_MASK <<
MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_vcn33_2_wifi", VCN33_2_WIFI, "vsys-ldo1", vcn33_voltages,
- MT6359_RG_LDO_VCN33_2_EN_1_ADDR,
- MT6359_RG_LDO_VCN33_2_EN_1_SHIFT,
- MT6359_DA_VCN33_2_B_EN_ADDR, MT6359_RG_VCN33_2_VOSEL_ADDR,
- MT6359_RG_VCN33_2_VOSEL_MASK <<
- MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
MT6359_LDO("ldo_va12", VA12, "vs2-ldo2", va12_voltages,
MT6359_RG_LDO_VA12_EN_ADDR, MT6359_RG_LDO_VA12_EN_SHIFT,
MT6359_DA_VA12_B_EN_ADDR, MT6359_RG_VA12_VOSEL_ADDR,
@@ -711,6 +716,11 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_SHIFT),
+ /* Placeholders for DT backward compatibility */
+ MT6359_LDO_NOOP("ldo_vcn33_1_bt", VCN33_1_BT, "LDO_VCN33_1"),
+ MT6359_LDO_NOOP("ldo_vcn33_1_wifi", VCN33_1_WIFI, "LDO_VCN33_1"),
+ MT6359_LDO_NOOP("ldo_vcn33_2_bt", VCN33_2_BT, "LDO_VCN33_2"),
+ MT6359_LDO_NOOP("ldo_vcn33_2_wifi", VCN33_2_WIFI, "LDO_VCN33_2"),
};
static const struct mt6359_regulator_info mt6359p_regulators[] = {
@@ -835,18 +845,12 @@ static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359P_DA_VCN13_B_EN_ADDR, MT6359P_RG_VCN13_VOSEL_ADDR,
MT6359_RG_VCN13_VOSEL_MASK << MT6359_RG_VCN13_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vcn33_1_bt", VCN33_1_BT, "vsys-ldo1", vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_1", VCN33_1, "vsys-ldo1", vcn33_voltages,
MT6359P_RG_LDO_VCN33_1_EN_0_ADDR,
MT6359_RG_LDO_VCN33_1_EN_0_SHIFT,
MT6359P_DA_VCN33_1_B_EN_ADDR, MT6359P_RG_VCN33_1_VOSEL_ADDR,
MT6359_RG_VCN33_1_VOSEL_MASK <<
MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_vcn33_1_wifi", VCN33_1_WIFI, "vsys-ldo1", vcn33_voltages,
- MT6359P_RG_LDO_VCN33_1_EN_1_ADDR,
- MT6359P_RG_LDO_VCN33_1_EN_1_SHIFT,
- MT6359P_DA_VCN33_1_B_EN_ADDR, MT6359P_RG_VCN33_1_VOSEL_ADDR,
- MT6359_RG_VCN33_1_VOSEL_MASK <<
- MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
MT6359_REG_FIXED("ldo_vaux18", VAUX18, "vsys-ldo2", MT6359P_RG_LDO_VAUX18_EN_ADDR,
MT6359P_DA_VAUX18_B_EN_ADDR, 1800000),
MT6359_LDO_LINEAR("ldo_vsram_others", VSRAM_OTHERS, "vs2-ldo1", 500000, 1293750,
@@ -885,18 +889,12 @@ static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359P_RG_LDO_VEMC_VOSEL_0_ADDR,
MT6359P_RG_LDO_VEMC_VOSEL_0_MASK <<
MT6359P_RG_LDO_VEMC_VOSEL_0_SHIFT),
- MT6359_LDO("ldo_vcn33_2_bt", VCN33_2_BT, "vsys-ldo1", vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_2", VCN33_2, "vsys-ldo1", vcn33_voltages,
MT6359P_RG_LDO_VCN33_2_EN_0_ADDR,
MT6359P_RG_LDO_VCN33_2_EN_0_SHIFT,
MT6359P_DA_VCN33_2_B_EN_ADDR, MT6359P_RG_VCN33_2_VOSEL_ADDR,
MT6359_RG_VCN33_2_VOSEL_MASK <<
MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_vcn33_2_wifi", VCN33_2_WIFI, "vsys-ldo1", vcn33_voltages,
- MT6359P_RG_LDO_VCN33_2_EN_1_ADDR,
- MT6359_RG_LDO_VCN33_2_EN_1_SHIFT,
- MT6359P_DA_VCN33_2_B_EN_ADDR, MT6359P_RG_VCN33_2_VOSEL_ADDR,
- MT6359_RG_VCN33_2_VOSEL_MASK <<
- MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
MT6359_LDO("ldo_va12", VA12, "vs2-ldo2", va12_voltages,
MT6359P_RG_LDO_VA12_EN_ADDR, MT6359P_RG_LDO_VA12_EN_SHIFT,
MT6359P_DA_VA12_B_EN_ADDR, MT6359P_RG_VA12_VOSEL_ADDR,
@@ -951,27 +949,119 @@ static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359P_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_SHIFT),
+ /* Placeholders for DT backward compatibility */
+ MT6359_LDO_NOOP("ldo_vcn33_1_bt", VCN33_1_BT, "LDO_VCN33_1"),
+ MT6359_LDO_NOOP("ldo_vcn33_1_wifi", VCN33_1_WIFI, "LDO_VCN33_1"),
+ MT6359_LDO_NOOP("ldo_vcn33_2_bt", VCN33_2_BT, "LDO_VCN33_2"),
+ MT6359_LDO_NOOP("ldo_vcn33_2_wifi", VCN33_2_WIFI, "LDO_VCN33_2"),
+};
+
+struct mt6359_vcn33_regs {
+ u32 wifi_en_reg;
+ u32 wifi_en_mask;
+ u32 bt_en_reg;
+ u32 bt_en_mask;
+};
+
+static const struct mt6359_vcn33_regs vcn33_regs[][2] = {
+ { /* MT6359 */
+ {
+ .wifi_en_reg = MT6359_RG_LDO_VCN33_1_EN_1_ADDR,
+ .wifi_en_mask = BIT(MT6359_RG_LDO_VCN33_1_EN_1_SHIFT),
+ .bt_en_reg = MT6359_RG_LDO_VCN33_1_EN_0_ADDR,
+ .bt_en_mask = BIT(MT6359_RG_LDO_VCN33_1_EN_0_SHIFT),
+ }, {
+ .wifi_en_reg = MT6359_RG_LDO_VCN33_2_EN_1_ADDR,
+ .wifi_en_mask = BIT(MT6359_RG_LDO_VCN33_2_EN_1_SHIFT),
+ .bt_en_reg = MT6359_RG_LDO_VCN33_2_EN_0_ADDR,
+ .bt_en_mask = BIT(MT6359_RG_LDO_VCN33_2_EN_0_SHIFT),
+ }
+ }, { /* MT6359P */
+ {
+ .wifi_en_reg = MT6359P_RG_LDO_VCN33_1_EN_1_ADDR,
+ .wifi_en_mask = BIT(MT6359P_RG_LDO_VCN33_1_EN_1_SHIFT),
+ .bt_en_reg = MT6359P_RG_LDO_VCN33_1_EN_0_ADDR,
+ .bt_en_mask = BIT(MT6359_RG_LDO_VCN33_1_EN_0_SHIFT),
+ }, {
+ .wifi_en_reg = MT6359P_RG_LDO_VCN33_2_EN_1_ADDR,
+ .wifi_en_mask = BIT(MT6359_RG_LDO_VCN33_2_EN_1_SHIFT),
+ .bt_en_reg = MT6359P_RG_LDO_VCN33_2_EN_0_ADDR,
+ .bt_en_mask = BIT(MT6359P_RG_LDO_VCN33_2_EN_0_SHIFT),
+ }
+ }
};
+static int mt6359_sync_vcn33_setting(struct device *dev, unsigned int idx)
+{
+ struct mt6397_chip *mt6397 = dev_get_drvdata(dev->parent);
+ unsigned int val;
+ int ret;
+
+ /*
+ * VCN33_[12]_WIFI and VCN33_[12]_BT are two separate enable bits for
+ * the same regulator. They share the same voltage setting and output
+ * pin. Instead of having two potentially conflicting regulators, just
+ * have one regulator. Sync the two enable bits and only use one in
+ * the regulator device.
+ */
+ for (unsigned int i = 0; i < ARRAY_SIZE(vcn33_regs[0]); i++) {
+ u32 bt_en_mask = vcn33_regs[idx][i].bt_en_mask;
+ u32 wifi_en_mask = vcn33_regs[idx][i].wifi_en_mask;
+
+ ret = regmap_read(mt6397->regmap, vcn33_regs[idx][i].wifi_en_reg, &val);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read VCN33_%u_WIFI setting\n",
+ i + 1);
+
+ if (!(val & wifi_en_mask))
+ continue;
+
+ /* Sync VCN33_[12]_WIFI enable status to VCN33_[12]_BT */
+ ret = regmap_update_bits(mt6397->regmap, vcn33_regs[idx][i].bt_en_reg,
+ bt_en_mask, bt_en_mask);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to sync VCN33_%u_WIFI setting to VCN33_%u_BT\n",
+ i + 1, i + 1);
+
+ /* Disable VCN33_[12]_WIFI */
+ ret = regmap_update_bits(mt6397->regmap, vcn33_regs[idx][i].wifi_en_reg,
+ wifi_en_mask, 0);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to disable VCN33_%u_WIFI\n", i + 1);
+ }
+
+ return 0;
+}
+
static int mt6359_regulator_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = {};
struct regulator_dev *rdev;
const struct mt6359_regulator_info *mt6359_info;
- const char *vio18_name;
+ const char *vio18_name, *vcn33_1_name, *vcn33_2_name;
int i, hw_ver, ret;
ret = regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver);
if (ret)
return ret;
- if (hw_ver >= MT6359P_CHIP_VER)
+ if (hw_ver >= MT6359P_CHIP_VER) {
mt6359_info = mt6359p_regulators;
- else
+ ret = mt6359_sync_vcn33_setting(&pdev->dev, 1);
+ if (ret)
+ return ret;
+ } else {
mt6359_info = mt6359_regulators;
+ ret = mt6359_sync_vcn33_setting(&pdev->dev, 0);
+ if (ret)
+ return ret;
+ }
vio18_name = mt6359_info[MT6359_ID_VIO18].desc.name;
+ vcn33_1_name = mt6359_info[MT6359_ID_VCN33_1].desc.name;
+ vcn33_2_name = mt6359_info[MT6359_ID_VCN33_2].desc.name;
config.dev = mt6397->dev;
config.regmap = mt6397->regmap;
@@ -993,6 +1083,30 @@ static int mt6359_regulator_probe(struct platform_device *pdev)
desc = _desc;
}
+ /* Use vcn33_1's actual name as supply_name for vcn33_1_(bt|wifi) */
+ if ((i == MT6359_ID_VCN33_1_BT || i == MT6359_ID_VCN33_1_WIFI) &&
+ strcmp(desc->supply_name, vcn33_1_name) != 0) {
+ _desc = devm_kzalloc(&pdev->dev, sizeof(*_desc), GFP_KERNEL);
+ if (!_desc)
+ return -ENOMEM;
+
+ memcpy(_desc, desc, sizeof(*_desc));
+ _desc->supply_name = vcn33_1_name;
+ desc = _desc;
+ }
+
+ /* Use vcn33_2's actual name as supply_name for vcn33_2_(bt|wifi) */
+ if ((i == MT6359_ID_VCN33_2_BT || i == MT6359_ID_VCN33_2_WIFI) &&
+ strcmp(desc->supply_name, vcn33_2_name) != 0) {
+ _desc = devm_kzalloc(&pdev->dev, sizeof(*_desc), GFP_KERNEL);
+ if (!_desc)
+ return -ENOMEM;
+
+ memcpy(_desc, desc, sizeof(*_desc));
+ _desc->supply_name = vcn33_2_name;
+ desc = _desc;
+ }
+
rdev = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s\n", mt6359_info->desc.name);
@@ -1002,6 +1116,14 @@ static int mt6359_regulator_probe(struct platform_device *pdev)
/* Save vio18 name for vbbck */
if (i == MT6359_ID_VIO18)
vio18_name = rdev_get_name(rdev);
+
+ /* Save vcn33_1 name for vbbck */
+ if (i == MT6359_ID_VCN33_1)
+ vcn33_1_name = rdev_get_name(rdev);
+
+ /* Save vcn33_2 name for vbbck */
+ if (i == MT6359_ID_VCN33_2)
+ vcn33_2_name = rdev_get_name(rdev);
}
return 0;
diff --git a/include/linux/regulator/mt6359-regulator.h b/include/linux/regulator/mt6359-regulator.h
index 6d6e5a58f482..ce2cd0fc9d95 100644
--- a/include/linux/regulator/mt6359-regulator.h
+++ b/include/linux/regulator/mt6359-regulator.h
@@ -29,8 +29,7 @@ enum {
MT6359_ID_VCN18,
MT6359_ID_VFE28,
MT6359_ID_VCN13,
- MT6359_ID_VCN33_1_BT,
- MT6359_ID_VCN33_1_WIFI,
+ MT6359_ID_VCN33_1,
MT6359_ID_VAUX18,
MT6359_ID_VSRAM_OTHERS,
MT6359_ID_VEFUSE,
@@ -39,8 +38,7 @@ enum {
MT6359_ID_VBIF28,
MT6359_ID_VIO28,
MT6359_ID_VEMC,
- MT6359_ID_VCN33_2_BT,
- MT6359_ID_VCN33_2_WIFI,
+ MT6359_ID_VCN33_2,
MT6359_ID_VA12,
MT6359_ID_VA09,
MT6359_ID_VRF18,
@@ -51,6 +49,10 @@ enum {
MT6359_ID_VSRAM_PROC1,
MT6359_ID_VSIM2,
MT6359_ID_VSRAM_OTHERS_SSHUB,
+ MT6359_ID_VCN33_1_BT,
+ MT6359_ID_VCN33_1_WIFI,
+ MT6359_ID_VCN33_2_BT,
+ MT6359_ID_VCN33_2_WIFI,
MT6359_ID_RG_MAX,
};
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH v4 5/6] regulator: mt6359: Add regulator supply names
From: Chen-Yu Tsai @ 2026-05-14 9:15 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-arm-kernel, linux-mediatek, devicetree
In-Reply-To: <20260514091520.2718987-1-wenst@chromium.org>
The MT6359 regulator DT binding defines the supply names for the PMIC.
Add support for them by adding .supply_name field settings for each
regulator. The buck regulators each have their own supply. The name
of the supply is related to the name of the buck regulator. The LDOs
have shared supplies.
Add the supply name to the declaration of each regulator. At the moment
they are declared explicitly, but the buck regulator macro can be made
to derive both the match string and supply name from the base name once
the *_sshub regulators are figured out and removed. For context, the
*_sshub regulators are not separate regulators, but separate settings
for the same name regulators without the "_sshub" suffix.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Changes since v3:
- Changed vbbck's supply name to 'VIO18' to match vio18's default name
(Sashiko)
Changes since v1:
- Handle vbbck's supply internally
---
drivers/regulator/mt6359-regulator.c | 220 +++++++++++++++------------
1 file changed, 125 insertions(+), 95 deletions(-)
diff --git a/drivers/regulator/mt6359-regulator.c b/drivers/regulator/mt6359-regulator.c
index bcf9a476a34e..46cafe93b24e 100644
--- a/drivers/regulator/mt6359-regulator.c
+++ b/drivers/regulator/mt6359-regulator.c
@@ -38,7 +38,7 @@ struct mt6359_regulator_info {
u32 lp_mode_mask;
};
-#define MT6359_BUCK(match, _name, min, max, step, \
+#define MT6359_BUCK(match, _name, supply, min, max, step, \
_enable_reg, _status_reg, \
_vsel_reg, _vsel_mask, \
_lp_mode_reg, _lp_mode_shift, \
@@ -46,6 +46,7 @@ struct mt6359_regulator_info {
[MT6359_ID_##_name] = { \
.desc = { \
.name = #_name, \
+ .supply_name = supply, \
.of_match = of_match_ptr(match), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &mt6359_volt_linear_ops, \
@@ -69,11 +70,12 @@ struct mt6359_regulator_info {
.modeset_mask = BIT(_modeset_shift), \
}
-#define MT6359_LDO_LINEAR(match, _name, min, max, step, \
+#define MT6359_LDO_LINEAR(match, _name, supply, min, max, step, \
_enable_reg, _status_reg, _vsel_reg, _vsel_mask) \
[MT6359_ID_##_name] = { \
.desc = { \
.name = #_name, \
+ .supply_name = supply, \
.of_match = of_match_ptr(match), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &mt6359_volt_linear_ops, \
@@ -92,12 +94,13 @@ struct mt6359_regulator_info {
.qi = BIT(0), \
}
-#define MT6359_LDO(match, _name, _volt_table, \
+#define MT6359_LDO(match, _name, supply, _volt_table, \
_enable_reg, _enable_mask, _status_reg, \
_vsel_reg, _vsel_mask, _en_delay) \
[MT6359_ID_##_name] = { \
.desc = { \
.name = #_name, \
+ .supply_name = supply, \
.of_match = of_match_ptr(match), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &mt6359_volt_table_ops, \
@@ -116,11 +119,13 @@ struct mt6359_regulator_info {
.qi = BIT(0), \
}
-#define MT6359_REG_FIXED(match, _name, _enable_reg, \
- _status_reg, _fixed_volt) \
+#define MT6359_REG_FIXED(match, _name, supply, \
+ _enable_reg, _status_reg, \
+ _fixed_volt) \
[MT6359_ID_##_name] = { \
.desc = { \
.name = #_name, \
+ .supply_name = supply, \
.of_match = of_match_ptr(match), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &mt6359_volt_fixed_ops, \
@@ -136,12 +141,14 @@ struct mt6359_regulator_info {
.qi = BIT(0), \
}
-#define MT6359P_LDO1(match, _name, _ops, _volt_table, \
- _enable_reg, _enable_mask, _status_reg, \
- _vsel_reg, _vsel_mask) \
+#define MT6359P_LDO1(match, _name, supply, _ops, \
+ _volt_table, _enable_reg, \
+ _enable_mask, _status_reg, \
+ _vsel_reg, _vsel_mask) \
[MT6359_ID_##_name] = { \
.desc = { \
.name = #_name, \
+ .supply_name = supply, \
.of_match = of_match_ptr(match), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &_ops, \
@@ -470,14 +477,14 @@ static const struct regulator_ops mt6359p_vemc_ops = {
/* The array is indexed by id(MT6359_ID_XXX) */
static const struct mt6359_regulator_info mt6359_regulators[] = {
- MT6359_BUCK("buck_vs1", VS1, 800000, 2200000, 12500,
+ MT6359_BUCK("buck_vs1", VS1, "vsys-vs1", 800000, 2200000, 12500,
MT6359_RG_BUCK_VS1_EN_ADDR,
MT6359_DA_VS1_EN_ADDR, MT6359_RG_BUCK_VS1_VOSEL_ADDR,
MT6359_RG_BUCK_VS1_VOSEL_MASK <<
MT6359_RG_BUCK_VS1_VOSEL_SHIFT,
MT6359_RG_BUCK_VS1_LP_ADDR, MT6359_RG_BUCK_VS1_LP_SHIFT,
MT6359_RG_VS1_FPWM_ADDR, MT6359_RG_VS1_FPWM_SHIFT),
- MT6359_BUCK("buck_vgpu11", VGPU11, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vgpu11", VGPU11, "vsys-vgpu11", 400000, 1193750, 6250,
MT6359_RG_BUCK_VGPU11_EN_ADDR,
MT6359_DA_VGPU11_EN_ADDR, MT6359_RG_BUCK_VGPU11_VOSEL_ADDR,
MT6359_RG_BUCK_VGPU11_VOSEL_MASK <<
@@ -485,7 +492,7 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_RG_BUCK_VGPU11_LP_ADDR,
MT6359_RG_BUCK_VGPU11_LP_SHIFT,
MT6359_RG_VGPU11_FCCM_ADDR, MT6359_RG_VGPU11_FCCM_SHIFT),
- MT6359_BUCK("buck_vmodem", VMODEM, 400000, 1100000, 6250,
+ MT6359_BUCK("buck_vmodem", VMODEM, "vsys-vmodem", 400000, 1100000, 6250,
MT6359_RG_BUCK_VMODEM_EN_ADDR,
MT6359_DA_VMODEM_EN_ADDR, MT6359_RG_BUCK_VMODEM_VOSEL_ADDR,
MT6359_RG_BUCK_VMODEM_VOSEL_MASK <<
@@ -493,35 +500,35 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_RG_BUCK_VMODEM_LP_ADDR,
MT6359_RG_BUCK_VMODEM_LP_SHIFT,
MT6359_RG_VMODEM_FCCM_ADDR, MT6359_RG_VMODEM_FCCM_SHIFT),
- MT6359_BUCK("buck_vpu", VPU, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vpu", VPU, "vsys-vpu", 400000, 1193750, 6250,
MT6359_RG_BUCK_VPU_EN_ADDR,
MT6359_DA_VPU_EN_ADDR, MT6359_RG_BUCK_VPU_VOSEL_ADDR,
MT6359_RG_BUCK_VPU_VOSEL_MASK <<
MT6359_RG_BUCK_VPU_VOSEL_SHIFT,
MT6359_RG_BUCK_VPU_LP_ADDR, MT6359_RG_BUCK_VPU_LP_SHIFT,
MT6359_RG_VPU_FCCM_ADDR, MT6359_RG_VPU_FCCM_SHIFT),
- MT6359_BUCK("buck_vcore", VCORE, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vcore", VCORE, "vsys-vcore", 400000, 1193750, 6250,
MT6359_RG_BUCK_VCORE_EN_ADDR,
MT6359_DA_VCORE_EN_ADDR, MT6359_RG_BUCK_VCORE_VOSEL_ADDR,
MT6359_RG_BUCK_VCORE_VOSEL_MASK <<
MT6359_RG_BUCK_VCORE_VOSEL_SHIFT,
MT6359_RG_BUCK_VCORE_LP_ADDR, MT6359_RG_BUCK_VCORE_LP_SHIFT,
MT6359_RG_VCORE_FCCM_ADDR, MT6359_RG_VCORE_FCCM_SHIFT),
- MT6359_BUCK("buck_vs2", VS2, 800000, 1600000, 12500,
+ MT6359_BUCK("buck_vs2", VS2, "vsys-vs2", 800000, 1600000, 12500,
MT6359_RG_BUCK_VS2_EN_ADDR,
MT6359_DA_VS2_EN_ADDR, MT6359_RG_BUCK_VS2_VOSEL_ADDR,
MT6359_RG_BUCK_VS2_VOSEL_MASK <<
MT6359_RG_BUCK_VS2_VOSEL_SHIFT,
MT6359_RG_BUCK_VS2_LP_ADDR, MT6359_RG_BUCK_VS2_LP_SHIFT,
MT6359_RG_VS2_FPWM_ADDR, MT6359_RG_VS2_FPWM_SHIFT),
- MT6359_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
+ MT6359_BUCK("buck_vpa", VPA, "vsys-vpa", 500000, 3650000, 50000,
MT6359_RG_BUCK_VPA_EN_ADDR,
MT6359_DA_VPA_EN_ADDR, MT6359_RG_BUCK_VPA_VOSEL_ADDR,
MT6359_RG_BUCK_VPA_VOSEL_MASK <<
MT6359_RG_BUCK_VPA_VOSEL_SHIFT,
MT6359_RG_BUCK_VPA_LP_ADDR, MT6359_RG_BUCK_VPA_LP_SHIFT,
MT6359_RG_VPA_MODESET_ADDR, MT6359_RG_VPA_MODESET_SHIFT),
- MT6359_BUCK("buck_vproc2", VPROC2, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vproc2", VPROC2, "vsys-vproc2", 400000, 1193750, 6250,
MT6359_RG_BUCK_VPROC2_EN_ADDR,
MT6359_DA_VPROC2_EN_ADDR, MT6359_RG_BUCK_VPROC2_VOSEL_ADDR,
MT6359_RG_BUCK_VPROC2_VOSEL_MASK <<
@@ -529,7 +536,7 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_RG_BUCK_VPROC2_LP_ADDR,
MT6359_RG_BUCK_VPROC2_LP_SHIFT,
MT6359_RG_VPROC2_FCCM_ADDR, MT6359_RG_VPROC2_FCCM_SHIFT),
- MT6359_BUCK("buck_vproc1", VPROC1, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vproc1", VPROC1, "vsys-vproc1", 400000, 1193750, 6250,
MT6359_RG_BUCK_VPROC1_EN_ADDR,
MT6359_DA_VPROC1_EN_ADDR, MT6359_RG_BUCK_VPROC1_VOSEL_ADDR,
MT6359_RG_BUCK_VPROC1_VOSEL_MASK <<
@@ -537,7 +544,7 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_RG_BUCK_VPROC1_LP_ADDR,
MT6359_RG_BUCK_VPROC1_LP_SHIFT,
MT6359_RG_VPROC1_FCCM_ADDR, MT6359_RG_VPROC1_FCCM_SHIFT),
- MT6359_BUCK("buck_vcore_sshub", VCORE_SSHUB, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vcore_sshub", VCORE_SSHUB, "vsys-vcore", 400000, 1193750, 6250,
MT6359_RG_BUCK_VCORE_SSHUB_EN_ADDR,
MT6359_DA_VCORE_EN_ADDR,
MT6359_RG_BUCK_VCORE_SSHUB_VOSEL_ADDR,
@@ -545,158 +552,159 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_RG_BUCK_VCORE_SSHUB_VOSEL_SHIFT,
MT6359_RG_BUCK_VCORE_LP_ADDR, MT6359_RG_BUCK_VCORE_LP_SHIFT,
MT6359_RG_VCORE_FCCM_ADDR, MT6359_RG_VCORE_FCCM_SHIFT),
- MT6359_REG_FIXED("ldo_vaud18", VAUD18, MT6359_RG_LDO_VAUD18_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vaud18", VAUD18, "vs1-ldo1", MT6359_RG_LDO_VAUD18_EN_ADDR,
MT6359_DA_VAUD18_B_EN_ADDR, 1800000),
- MT6359_LDO("ldo_vsim1", VSIM1, vsim1_voltages,
+ MT6359_LDO("ldo_vsim1", VSIM1, "vsys-ldo2", vsim1_voltages,
MT6359_RG_LDO_VSIM1_EN_ADDR, MT6359_RG_LDO_VSIM1_EN_SHIFT,
MT6359_DA_VSIM1_B_EN_ADDR, MT6359_RG_VSIM1_VOSEL_ADDR,
MT6359_RG_VSIM1_VOSEL_MASK << MT6359_RG_VSIM1_VOSEL_SHIFT,
480),
- MT6359_LDO("ldo_vibr", VIBR, vibr_voltages,
+ MT6359_LDO("ldo_vibr", VIBR, "vsys-ldo1", vibr_voltages,
MT6359_RG_LDO_VIBR_EN_ADDR, MT6359_RG_LDO_VIBR_EN_SHIFT,
MT6359_DA_VIBR_B_EN_ADDR, MT6359_RG_VIBR_VOSEL_ADDR,
MT6359_RG_VIBR_VOSEL_MASK << MT6359_RG_VIBR_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vrf12", VRF12, vrf12_voltages,
+ MT6359_LDO("ldo_vrf12", VRF12, "vs2-ldo2", vrf12_voltages,
MT6359_RG_LDO_VRF12_EN_ADDR, MT6359_RG_LDO_VRF12_EN_SHIFT,
MT6359_DA_VRF12_B_EN_ADDR, MT6359_RG_VRF12_VOSEL_ADDR,
MT6359_RG_VRF12_VOSEL_MASK << MT6359_RG_VRF12_VOSEL_SHIFT,
120),
- MT6359_REG_FIXED("ldo_vusb", VUSB, MT6359_RG_LDO_VUSB_EN_0_ADDR,
+ MT6359_REG_FIXED("ldo_vusb", VUSB, "vsys-ldo2", MT6359_RG_LDO_VUSB_EN_0_ADDR,
MT6359_DA_VUSB_B_EN_ADDR, 3000000),
- MT6359_LDO_LINEAR("ldo_vsram_proc2", VSRAM_PROC2, 500000, 1293750, 6250,
+ MT6359_LDO_LINEAR("ldo_vsram_proc2", VSRAM_PROC2, "vs2-ldo1", 500000, 1293750, 6250,
MT6359_RG_LDO_VSRAM_PROC2_EN_ADDR,
MT6359_DA_VSRAM_PROC2_B_EN_ADDR,
MT6359_RG_LDO_VSRAM_PROC2_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_PROC2_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_PROC2_VOSEL_SHIFT),
- MT6359_LDO("ldo_vio18", VIO18, volt18_voltages,
+ MT6359_LDO("ldo_vio18", VIO18, "vs1-ldo2", volt18_voltages,
MT6359_RG_LDO_VIO18_EN_ADDR, MT6359_RG_LDO_VIO18_EN_SHIFT,
MT6359_DA_VIO18_B_EN_ADDR, MT6359_RG_VIO18_VOSEL_ADDR,
MT6359_RG_VIO18_VOSEL_MASK << MT6359_RG_VIO18_VOSEL_SHIFT,
960),
- MT6359_LDO("ldo_vcamio", VCAMIO, volt18_voltages,
+ MT6359_LDO("ldo_vcamio", VCAMIO, "vs1-ldo1", volt18_voltages,
MT6359_RG_LDO_VCAMIO_EN_ADDR, MT6359_RG_LDO_VCAMIO_EN_SHIFT,
MT6359_DA_VCAMIO_B_EN_ADDR, MT6359_RG_VCAMIO_VOSEL_ADDR,
MT6359_RG_VCAMIO_VOSEL_MASK << MT6359_RG_VCAMIO_VOSEL_SHIFT,
1290),
- MT6359_REG_FIXED("ldo_vcn18", VCN18, MT6359_RG_LDO_VCN18_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vcn18", VCN18, "vs1-ldo2", MT6359_RG_LDO_VCN18_EN_ADDR,
MT6359_DA_VCN18_B_EN_ADDR, 1800000),
- MT6359_REG_FIXED("ldo_vfe28", VFE28, MT6359_RG_LDO_VFE28_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vfe28", VFE28, "vsys-ldo1", MT6359_RG_LDO_VFE28_EN_ADDR,
MT6359_DA_VFE28_B_EN_ADDR, 2800000),
- MT6359_LDO("ldo_vcn13", VCN13, vcn13_voltages,
+ MT6359_LDO("ldo_vcn13", VCN13, "vs2-ldo2", vcn13_voltages,
MT6359_RG_LDO_VCN13_EN_ADDR, MT6359_RG_LDO_VCN13_EN_SHIFT,
MT6359_DA_VCN13_B_EN_ADDR, MT6359_RG_VCN13_VOSEL_ADDR,
MT6359_RG_VCN13_VOSEL_MASK << MT6359_RG_VCN13_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vcn33_1_bt", VCN33_1_BT, vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_1_bt", VCN33_1_BT, "vsys-ldo1", vcn33_voltages,
MT6359_RG_LDO_VCN33_1_EN_0_ADDR,
MT6359_RG_LDO_VCN33_1_EN_0_SHIFT,
MT6359_DA_VCN33_1_B_EN_ADDR, MT6359_RG_VCN33_1_VOSEL_ADDR,
MT6359_RG_VCN33_1_VOSEL_MASK <<
MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_vcn33_1_wifi", VCN33_1_WIFI, vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_1_wifi", VCN33_1_WIFI, "vsys-ldo1", vcn33_voltages,
MT6359_RG_LDO_VCN33_1_EN_1_ADDR,
MT6359_RG_LDO_VCN33_1_EN_1_SHIFT,
MT6359_DA_VCN33_1_B_EN_ADDR, MT6359_RG_VCN33_1_VOSEL_ADDR,
MT6359_RG_VCN33_1_VOSEL_MASK <<
MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
- MT6359_REG_FIXED("ldo_vaux18", VAUX18, MT6359_RG_LDO_VAUX18_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vaux18", VAUX18, "vsys-ldo2", MT6359_RG_LDO_VAUX18_EN_ADDR,
MT6359_DA_VAUX18_B_EN_ADDR, 1800000),
- MT6359_LDO_LINEAR("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750,
+ MT6359_LDO_LINEAR("ldo_vsram_others", VSRAM_OTHERS, "vs2-ldo1", 500000, 1293750,
6250,
MT6359_RG_LDO_VSRAM_OTHERS_EN_ADDR,
MT6359_DA_VSRAM_OTHERS_B_EN_ADDR,
MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_SHIFT),
- MT6359_LDO("ldo_vefuse", VEFUSE, vefuse_voltages,
+ MT6359_LDO("ldo_vefuse", VEFUSE, "vs1-ldo2", vefuse_voltages,
MT6359_RG_LDO_VEFUSE_EN_ADDR, MT6359_RG_LDO_VEFUSE_EN_SHIFT,
MT6359_DA_VEFUSE_B_EN_ADDR, MT6359_RG_VEFUSE_VOSEL_ADDR,
MT6359_RG_VEFUSE_VOSEL_MASK << MT6359_RG_VEFUSE_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vxo22", VXO22, vxo22_voltages,
+ MT6359_LDO("ldo_vxo22", VXO22, "vsys-ldo2", vxo22_voltages,
MT6359_RG_LDO_VXO22_EN_ADDR, MT6359_RG_LDO_VXO22_EN_SHIFT,
MT6359_DA_VXO22_B_EN_ADDR, MT6359_RG_VXO22_VOSEL_ADDR,
MT6359_RG_VXO22_VOSEL_MASK << MT6359_RG_VXO22_VOSEL_SHIFT,
120),
- MT6359_LDO("ldo_vrfck", VRFCK, vrfck_voltages,
+ MT6359_LDO("ldo_vrfck", VRFCK, "vsys-ldo2", vrfck_voltages,
MT6359_RG_LDO_VRFCK_EN_ADDR, MT6359_RG_LDO_VRFCK_EN_SHIFT,
MT6359_DA_VRFCK_B_EN_ADDR, MT6359_RG_VRFCK_VOSEL_ADDR,
MT6359_RG_VRFCK_VOSEL_MASK << MT6359_RG_VRFCK_VOSEL_SHIFT,
480),
- MT6359_REG_FIXED("ldo_vbif28", VBIF28, MT6359_RG_LDO_VBIF28_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vbif28", VBIF28, "vsys-ldo2", MT6359_RG_LDO_VBIF28_EN_ADDR,
MT6359_DA_VBIF28_B_EN_ADDR, 2800000),
- MT6359_LDO("ldo_vio28", VIO28, vio28_voltages,
+ MT6359_LDO("ldo_vio28", VIO28, "vsys-ldo2", vio28_voltages,
MT6359_RG_LDO_VIO28_EN_ADDR, MT6359_RG_LDO_VIO28_EN_SHIFT,
MT6359_DA_VIO28_B_EN_ADDR, MT6359_RG_VIO28_VOSEL_ADDR,
MT6359_RG_VIO28_VOSEL_MASK << MT6359_RG_VIO28_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vemc", VEMC, vemc_voltages,
+ MT6359_LDO("ldo_vemc", VEMC, "vsys-ldo2", vemc_voltages,
MT6359_RG_LDO_VEMC_EN_ADDR, MT6359_RG_LDO_VEMC_EN_SHIFT,
MT6359_DA_VEMC_B_EN_ADDR, MT6359_RG_VEMC_VOSEL_ADDR,
MT6359_RG_VEMC_VOSEL_MASK << MT6359_RG_VEMC_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vcn33_2_bt", VCN33_2_BT, vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_2_bt", VCN33_2_BT, "vsys-ldo1", vcn33_voltages,
MT6359_RG_LDO_VCN33_2_EN_0_ADDR,
MT6359_RG_LDO_VCN33_2_EN_0_SHIFT,
MT6359_DA_VCN33_2_B_EN_ADDR, MT6359_RG_VCN33_2_VOSEL_ADDR,
MT6359_RG_VCN33_2_VOSEL_MASK <<
MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_vcn33_2_wifi", VCN33_2_WIFI, vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_2_wifi", VCN33_2_WIFI, "vsys-ldo1", vcn33_voltages,
MT6359_RG_LDO_VCN33_2_EN_1_ADDR,
MT6359_RG_LDO_VCN33_2_EN_1_SHIFT,
MT6359_DA_VCN33_2_B_EN_ADDR, MT6359_RG_VCN33_2_VOSEL_ADDR,
MT6359_RG_VCN33_2_VOSEL_MASK <<
MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_va12", VA12, va12_voltages,
+ MT6359_LDO("ldo_va12", VA12, "vs2-ldo2", va12_voltages,
MT6359_RG_LDO_VA12_EN_ADDR, MT6359_RG_LDO_VA12_EN_SHIFT,
MT6359_DA_VA12_B_EN_ADDR, MT6359_RG_VA12_VOSEL_ADDR,
MT6359_RG_VA12_VOSEL_MASK << MT6359_RG_VA12_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_va09", VA09, va09_voltages,
+ MT6359_LDO("ldo_va09", VA09, "vs2-ldo2", va09_voltages,
MT6359_RG_LDO_VA09_EN_ADDR, MT6359_RG_LDO_VA09_EN_SHIFT,
MT6359_DA_VA09_B_EN_ADDR, MT6359_RG_VA09_VOSEL_ADDR,
MT6359_RG_VA09_VOSEL_MASK << MT6359_RG_VA09_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vrf18", VRF18, vrf18_voltages,
+ MT6359_LDO("ldo_vrf18", VRF18, "vs1-ldo2", vrf18_voltages,
MT6359_RG_LDO_VRF18_EN_ADDR, MT6359_RG_LDO_VRF18_EN_SHIFT,
MT6359_DA_VRF18_B_EN_ADDR, MT6359_RG_VRF18_VOSEL_ADDR,
MT6359_RG_VRF18_VOSEL_MASK << MT6359_RG_VRF18_VOSEL_SHIFT,
120),
- MT6359_LDO_LINEAR("ldo_vsram_md", VSRAM_MD, 500000, 1100000, 6250,
+ MT6359_LDO_LINEAR("ldo_vsram_md", VSRAM_MD, "vs2-ldo1", 500000, 1100000, 6250,
MT6359_RG_LDO_VSRAM_MD_EN_ADDR,
MT6359_DA_VSRAM_MD_B_EN_ADDR,
MT6359_RG_LDO_VSRAM_MD_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_MD_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_MD_VOSEL_SHIFT),
- MT6359_LDO("ldo_vufs", VUFS, volt18_voltages,
+ MT6359_LDO("ldo_vufs", VUFS, "vs1-ldo1", volt18_voltages,
MT6359_RG_LDO_VUFS_EN_ADDR, MT6359_RG_LDO_VUFS_EN_SHIFT,
MT6359_DA_VUFS_B_EN_ADDR, MT6359_RG_VUFS_VOSEL_ADDR,
MT6359_RG_VUFS_VOSEL_MASK << MT6359_RG_VUFS_VOSEL_SHIFT,
1920),
- MT6359_LDO("ldo_vm18", VM18, volt18_voltages,
+ MT6359_LDO("ldo_vm18", VM18, "vs1-ldo1", volt18_voltages,
MT6359_RG_LDO_VM18_EN_ADDR, MT6359_RG_LDO_VM18_EN_SHIFT,
MT6359_DA_VM18_B_EN_ADDR, MT6359_RG_VM18_VOSEL_ADDR,
MT6359_RG_VM18_VOSEL_MASK << MT6359_RG_VM18_VOSEL_SHIFT,
1920),
- MT6359_LDO("ldo_vbbck", VBBCK, vbbck_voltages,
+ /* vbbck is fed from vio18 internally. */
+ MT6359_LDO("ldo_vbbck", VBBCK, "VIO18", vbbck_voltages,
MT6359_RG_LDO_VBBCK_EN_ADDR, MT6359_RG_LDO_VBBCK_EN_SHIFT,
MT6359_DA_VBBCK_B_EN_ADDR, MT6359_RG_VBBCK_VOSEL_ADDR,
MT6359_RG_VBBCK_VOSEL_MASK << MT6359_RG_VBBCK_VOSEL_SHIFT,
240),
- MT6359_LDO_LINEAR("ldo_vsram_proc1", VSRAM_PROC1, 500000, 1293750, 6250,
+ MT6359_LDO_LINEAR("ldo_vsram_proc1", VSRAM_PROC1, "vs2-ldo1", 500000, 1293750, 6250,
MT6359_RG_LDO_VSRAM_PROC1_EN_ADDR,
MT6359_DA_VSRAM_PROC1_B_EN_ADDR,
MT6359_RG_LDO_VSRAM_PROC1_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_PROC1_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_PROC1_VOSEL_SHIFT),
- MT6359_LDO("ldo_vsim2", VSIM2, vsim2_voltages,
+ MT6359_LDO("ldo_vsim2", VSIM2, "vsys-ldo2", vsim2_voltages,
MT6359_RG_LDO_VSIM2_EN_ADDR, MT6359_RG_LDO_VSIM2_EN_SHIFT,
MT6359_DA_VSIM2_B_EN_ADDR, MT6359_RG_VSIM2_VOSEL_ADDR,
MT6359_RG_VSIM2_VOSEL_MASK << MT6359_RG_VSIM2_VOSEL_SHIFT,
480),
- MT6359_LDO_LINEAR("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB,
+ MT6359_LDO_LINEAR("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, "vs2-ldo1",
500000, 1293750, 6250,
MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_EN_ADDR,
MT6359_DA_VSRAM_OTHERS_B_EN_ADDR,
@@ -706,14 +714,14 @@ static const struct mt6359_regulator_info mt6359_regulators[] = {
};
static const struct mt6359_regulator_info mt6359p_regulators[] = {
- MT6359_BUCK("buck_vs1", VS1, 800000, 2200000, 12500,
+ MT6359_BUCK("buck_vs1", VS1, "vsys-vs1", 800000, 2200000, 12500,
MT6359_RG_BUCK_VS1_EN_ADDR,
MT6359_DA_VS1_EN_ADDR, MT6359_RG_BUCK_VS1_VOSEL_ADDR,
MT6359_RG_BUCK_VS1_VOSEL_MASK <<
MT6359_RG_BUCK_VS1_VOSEL_SHIFT,
MT6359_RG_BUCK_VS1_LP_ADDR, MT6359_RG_BUCK_VS1_LP_SHIFT,
MT6359_RG_VS1_FPWM_ADDR, MT6359_RG_VS1_FPWM_SHIFT),
- MT6359_BUCK("buck_vgpu11", VGPU11, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vgpu11", VGPU11, "vsys-vgpu11", 400000, 1193750, 6250,
MT6359_RG_BUCK_VGPU11_EN_ADDR,
MT6359_DA_VGPU11_EN_ADDR, MT6359P_RG_BUCK_VGPU11_VOSEL_ADDR,
MT6359_RG_BUCK_VGPU11_VOSEL_MASK <<
@@ -721,7 +729,7 @@ static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359_RG_BUCK_VGPU11_LP_ADDR,
MT6359_RG_BUCK_VGPU11_LP_SHIFT,
MT6359_RG_VGPU11_FCCM_ADDR, MT6359_RG_VGPU11_FCCM_SHIFT),
- MT6359_BUCK("buck_vmodem", VMODEM, 400000, 1100000, 6250,
+ MT6359_BUCK("buck_vmodem", VMODEM, "vsys-vmodem", 400000, 1100000, 6250,
MT6359_RG_BUCK_VMODEM_EN_ADDR,
MT6359_DA_VMODEM_EN_ADDR, MT6359_RG_BUCK_VMODEM_VOSEL_ADDR,
MT6359_RG_BUCK_VMODEM_VOSEL_MASK <<
@@ -729,35 +737,35 @@ static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359_RG_BUCK_VMODEM_LP_ADDR,
MT6359_RG_BUCK_VMODEM_LP_SHIFT,
MT6359_RG_VMODEM_FCCM_ADDR, MT6359_RG_VMODEM_FCCM_SHIFT),
- MT6359_BUCK("buck_vpu", VPU, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vpu", VPU, "vsys-vpu", 400000, 1193750, 6250,
MT6359_RG_BUCK_VPU_EN_ADDR,
MT6359_DA_VPU_EN_ADDR, MT6359_RG_BUCK_VPU_VOSEL_ADDR,
MT6359_RG_BUCK_VPU_VOSEL_MASK <<
MT6359_RG_BUCK_VPU_VOSEL_SHIFT,
MT6359_RG_BUCK_VPU_LP_ADDR, MT6359_RG_BUCK_VPU_LP_SHIFT,
MT6359_RG_VPU_FCCM_ADDR, MT6359_RG_VPU_FCCM_SHIFT),
- MT6359_BUCK("buck_vcore", VCORE, 506250, 1300000, 6250,
+ MT6359_BUCK("buck_vcore", VCORE, "vsys-vcore", 506250, 1300000, 6250,
MT6359_RG_BUCK_VCORE_EN_ADDR,
MT6359_DA_VCORE_EN_ADDR, MT6359P_RG_BUCK_VCORE_VOSEL_ADDR,
MT6359_RG_BUCK_VCORE_VOSEL_MASK <<
MT6359_RG_BUCK_VCORE_VOSEL_SHIFT,
MT6359_RG_BUCK_VCORE_LP_ADDR, MT6359_RG_BUCK_VCORE_LP_SHIFT,
MT6359_RG_VCORE_FCCM_ADDR, MT6359_RG_VCORE_FCCM_SHIFT),
- MT6359_BUCK("buck_vs2", VS2, 800000, 1600000, 12500,
+ MT6359_BUCK("buck_vs2", VS2, "vsys-vs2", 800000, 1600000, 12500,
MT6359_RG_BUCK_VS2_EN_ADDR,
MT6359_DA_VS2_EN_ADDR, MT6359_RG_BUCK_VS2_VOSEL_ADDR,
MT6359_RG_BUCK_VS2_VOSEL_MASK <<
MT6359_RG_BUCK_VS2_VOSEL_SHIFT,
MT6359_RG_BUCK_VS2_LP_ADDR, MT6359_RG_BUCK_VS2_LP_SHIFT,
MT6359_RG_VS2_FPWM_ADDR, MT6359_RG_VS2_FPWM_SHIFT),
- MT6359_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
+ MT6359_BUCK("buck_vpa", VPA, "vsys-vpa", 500000, 3650000, 50000,
MT6359_RG_BUCK_VPA_EN_ADDR,
MT6359_DA_VPA_EN_ADDR, MT6359_RG_BUCK_VPA_VOSEL_ADDR,
MT6359_RG_BUCK_VPA_VOSEL_MASK <<
MT6359_RG_BUCK_VPA_VOSEL_SHIFT,
MT6359_RG_BUCK_VPA_LP_ADDR, MT6359_RG_BUCK_VPA_LP_SHIFT,
MT6359_RG_VPA_MODESET_ADDR, MT6359_RG_VPA_MODESET_SHIFT),
- MT6359_BUCK("buck_vproc2", VPROC2, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vproc2", VPROC2, "vsys-vproc2", 400000, 1193750, 6250,
MT6359_RG_BUCK_VPROC2_EN_ADDR,
MT6359_DA_VPROC2_EN_ADDR, MT6359_RG_BUCK_VPROC2_VOSEL_ADDR,
MT6359_RG_BUCK_VPROC2_VOSEL_MASK <<
@@ -765,7 +773,7 @@ static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359_RG_BUCK_VPROC2_LP_ADDR,
MT6359_RG_BUCK_VPROC2_LP_SHIFT,
MT6359_RG_VPROC2_FCCM_ADDR, MT6359_RG_VPROC2_FCCM_SHIFT),
- MT6359_BUCK("buck_vproc1", VPROC1, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vproc1", VPROC1, "vsys-vproc1", 400000, 1193750, 6250,
MT6359_RG_BUCK_VPROC1_EN_ADDR,
MT6359_DA_VPROC1_EN_ADDR, MT6359_RG_BUCK_VPROC1_VOSEL_ADDR,
MT6359_RG_BUCK_VPROC1_VOSEL_MASK <<
@@ -773,7 +781,7 @@ static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359_RG_BUCK_VPROC1_LP_ADDR,
MT6359_RG_BUCK_VPROC1_LP_SHIFT,
MT6359_RG_VPROC1_FCCM_ADDR, MT6359_RG_VPROC1_FCCM_SHIFT),
- MT6359_BUCK("buck_vgpu11_sshub", VGPU11_SSHUB, 400000, 1193750, 6250,
+ MT6359_BUCK("buck_vgpu11_sshub", VGPU11_SSHUB, "vsys-vgpu11", 400000, 1193750, 6250,
MT6359P_RG_BUCK_VGPU11_SSHUB_EN_ADDR,
MT6359_DA_VGPU11_EN_ADDR,
MT6359P_RG_BUCK_VGPU11_SSHUB_VOSEL_ADDR,
@@ -782,161 +790,161 @@ static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359_RG_BUCK_VGPU11_LP_ADDR,
MT6359_RG_BUCK_VGPU11_LP_SHIFT,
MT6359_RG_VGPU11_FCCM_ADDR, MT6359_RG_VGPU11_FCCM_SHIFT),
- MT6359_REG_FIXED("ldo_vaud18", VAUD18, MT6359P_RG_LDO_VAUD18_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vaud18", VAUD18, "vs1-ldo1", MT6359P_RG_LDO_VAUD18_EN_ADDR,
MT6359P_DA_VAUD18_B_EN_ADDR, 1800000),
- MT6359_LDO("ldo_vsim1", VSIM1, vsim1_voltages,
+ MT6359_LDO("ldo_vsim1", VSIM1, "vsys-ldo2", vsim1_voltages,
MT6359P_RG_LDO_VSIM1_EN_ADDR, MT6359P_RG_LDO_VSIM1_EN_SHIFT,
MT6359P_DA_VSIM1_B_EN_ADDR, MT6359P_RG_VSIM1_VOSEL_ADDR,
MT6359_RG_VSIM1_VOSEL_MASK << MT6359_RG_VSIM1_VOSEL_SHIFT,
480),
- MT6359_LDO("ldo_vibr", VIBR, vibr_voltages,
+ MT6359_LDO("ldo_vibr", VIBR, "vsys-ldo1", vibr_voltages,
MT6359P_RG_LDO_VIBR_EN_ADDR, MT6359P_RG_LDO_VIBR_EN_SHIFT,
MT6359P_DA_VIBR_B_EN_ADDR, MT6359P_RG_VIBR_VOSEL_ADDR,
MT6359_RG_VIBR_VOSEL_MASK << MT6359_RG_VIBR_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vrf12", VRF12, vrf12_voltages,
+ MT6359_LDO("ldo_vrf12", VRF12, "vs2-ldo2", vrf12_voltages,
MT6359P_RG_LDO_VRF12_EN_ADDR, MT6359P_RG_LDO_VRF12_EN_SHIFT,
MT6359P_DA_VRF12_B_EN_ADDR, MT6359P_RG_VRF12_VOSEL_ADDR,
MT6359_RG_VRF12_VOSEL_MASK << MT6359_RG_VRF12_VOSEL_SHIFT,
480),
- MT6359_REG_FIXED("ldo_vusb", VUSB, MT6359P_RG_LDO_VUSB_EN_0_ADDR,
+ MT6359_REG_FIXED("ldo_vusb", VUSB, "vsys-ldo2", MT6359P_RG_LDO_VUSB_EN_0_ADDR,
MT6359P_DA_VUSB_B_EN_ADDR, 3000000),
- MT6359_LDO_LINEAR("ldo_vsram_proc2", VSRAM_PROC2, 500000, 1293750, 6250,
+ MT6359_LDO_LINEAR("ldo_vsram_proc2", VSRAM_PROC2, "vs2-ldo1", 500000, 1293750, 6250,
MT6359P_RG_LDO_VSRAM_PROC2_EN_ADDR,
MT6359P_DA_VSRAM_PROC2_B_EN_ADDR,
MT6359P_RG_LDO_VSRAM_PROC2_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_PROC2_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_PROC2_VOSEL_SHIFT),
- MT6359_LDO("ldo_vio18", VIO18, volt18_voltages,
+ MT6359_LDO("ldo_vio18", VIO18, "vs1-ldo2", volt18_voltages,
MT6359P_RG_LDO_VIO18_EN_ADDR, MT6359P_RG_LDO_VIO18_EN_SHIFT,
MT6359P_DA_VIO18_B_EN_ADDR, MT6359P_RG_VIO18_VOSEL_ADDR,
MT6359_RG_VIO18_VOSEL_MASK << MT6359_RG_VIO18_VOSEL_SHIFT,
960),
- MT6359_LDO("ldo_vcamio", VCAMIO, volt18_voltages,
+ MT6359_LDO("ldo_vcamio", VCAMIO, "vs1-ldo1", volt18_voltages,
MT6359P_RG_LDO_VCAMIO_EN_ADDR,
MT6359P_RG_LDO_VCAMIO_EN_SHIFT,
MT6359P_DA_VCAMIO_B_EN_ADDR, MT6359P_RG_VCAMIO_VOSEL_ADDR,
MT6359_RG_VCAMIO_VOSEL_MASK << MT6359_RG_VCAMIO_VOSEL_SHIFT,
1290),
- MT6359_REG_FIXED("ldo_vcn18", VCN18, MT6359P_RG_LDO_VCN18_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vcn18", VCN18, "vs1-ldo2", MT6359P_RG_LDO_VCN18_EN_ADDR,
MT6359P_DA_VCN18_B_EN_ADDR, 1800000),
- MT6359_REG_FIXED("ldo_vfe28", VFE28, MT6359P_RG_LDO_VFE28_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vfe28", VFE28, "vsys-ldo1", MT6359P_RG_LDO_VFE28_EN_ADDR,
MT6359P_DA_VFE28_B_EN_ADDR, 2800000),
- MT6359_LDO("ldo_vcn13", VCN13, vcn13_voltages,
+ MT6359_LDO("ldo_vcn13", VCN13, "vs2-ldo2", vcn13_voltages,
MT6359P_RG_LDO_VCN13_EN_ADDR, MT6359P_RG_LDO_VCN13_EN_SHIFT,
MT6359P_DA_VCN13_B_EN_ADDR, MT6359P_RG_VCN13_VOSEL_ADDR,
MT6359_RG_VCN13_VOSEL_MASK << MT6359_RG_VCN13_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vcn33_1_bt", VCN33_1_BT, vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_1_bt", VCN33_1_BT, "vsys-ldo1", vcn33_voltages,
MT6359P_RG_LDO_VCN33_1_EN_0_ADDR,
MT6359_RG_LDO_VCN33_1_EN_0_SHIFT,
MT6359P_DA_VCN33_1_B_EN_ADDR, MT6359P_RG_VCN33_1_VOSEL_ADDR,
MT6359_RG_VCN33_1_VOSEL_MASK <<
MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_vcn33_1_wifi", VCN33_1_WIFI, vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_1_wifi", VCN33_1_WIFI, "vsys-ldo1", vcn33_voltages,
MT6359P_RG_LDO_VCN33_1_EN_1_ADDR,
MT6359P_RG_LDO_VCN33_1_EN_1_SHIFT,
MT6359P_DA_VCN33_1_B_EN_ADDR, MT6359P_RG_VCN33_1_VOSEL_ADDR,
MT6359_RG_VCN33_1_VOSEL_MASK <<
MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
- MT6359_REG_FIXED("ldo_vaux18", VAUX18, MT6359P_RG_LDO_VAUX18_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vaux18", VAUX18, "vsys-ldo2", MT6359P_RG_LDO_VAUX18_EN_ADDR,
MT6359P_DA_VAUX18_B_EN_ADDR, 1800000),
- MT6359_LDO_LINEAR("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750,
+ MT6359_LDO_LINEAR("ldo_vsram_others", VSRAM_OTHERS, "vs2-ldo1", 500000, 1293750,
6250,
MT6359P_RG_LDO_VSRAM_OTHERS_EN_ADDR,
MT6359P_DA_VSRAM_OTHERS_B_EN_ADDR,
MT6359P_RG_LDO_VSRAM_OTHERS_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_SHIFT),
- MT6359_LDO("ldo_vefuse", VEFUSE, vefuse_voltages,
+ MT6359_LDO("ldo_vefuse", VEFUSE, "vs1-ldo2", vefuse_voltages,
MT6359P_RG_LDO_VEFUSE_EN_ADDR,
MT6359P_RG_LDO_VEFUSE_EN_SHIFT,
MT6359P_DA_VEFUSE_B_EN_ADDR, MT6359P_RG_VEFUSE_VOSEL_ADDR,
MT6359_RG_VEFUSE_VOSEL_MASK << MT6359_RG_VEFUSE_VOSEL_SHIFT,
240),
- MT6359_LDO("ldo_vxo22", VXO22, vxo22_voltages,
+ MT6359_LDO("ldo_vxo22", VXO22, "vsys-ldo2", vxo22_voltages,
MT6359P_RG_LDO_VXO22_EN_ADDR, MT6359P_RG_LDO_VXO22_EN_SHIFT,
MT6359P_DA_VXO22_B_EN_ADDR, MT6359P_RG_VXO22_VOSEL_ADDR,
MT6359_RG_VXO22_VOSEL_MASK << MT6359_RG_VXO22_VOSEL_SHIFT,
480),
- MT6359_LDO("ldo_vrfck_1", VRFCK, vrfck_voltages_1,
+ MT6359_LDO("ldo_vrfck_1", VRFCK, "vsys-ldo2", vrfck_voltages_1,
MT6359P_RG_LDO_VRFCK_EN_ADDR, MT6359P_RG_LDO_VRFCK_EN_SHIFT,
MT6359P_DA_VRFCK_B_EN_ADDR, MT6359P_RG_VRFCK_VOSEL_ADDR,
MT6359_RG_VRFCK_VOSEL_MASK << MT6359_RG_VRFCK_VOSEL_SHIFT,
480),
- MT6359_REG_FIXED("ldo_vbif28", VBIF28, MT6359P_RG_LDO_VBIF28_EN_ADDR,
+ MT6359_REG_FIXED("ldo_vbif28", VBIF28, "vsys-ldo2", MT6359P_RG_LDO_VBIF28_EN_ADDR,
MT6359P_DA_VBIF28_B_EN_ADDR, 2800000),
- MT6359_LDO("ldo_vio28", VIO28, vio28_voltages,
+ MT6359_LDO("ldo_vio28", VIO28, "vsys-ldo2", vio28_voltages,
MT6359P_RG_LDO_VIO28_EN_ADDR, MT6359P_RG_LDO_VIO28_EN_SHIFT,
MT6359P_DA_VIO28_B_EN_ADDR, MT6359P_RG_VIO28_VOSEL_ADDR,
MT6359_RG_VIO28_VOSEL_MASK << MT6359_RG_VIO28_VOSEL_SHIFT,
1920),
- MT6359P_LDO1("ldo_vemc_1", VEMC, mt6359p_vemc_ops, vemc_voltages_1,
+ MT6359P_LDO1("ldo_vemc_1", VEMC, "vsys-ldo2", mt6359p_vemc_ops, vemc_voltages_1,
MT6359P_RG_LDO_VEMC_EN_ADDR, MT6359P_RG_LDO_VEMC_EN_SHIFT,
MT6359P_DA_VEMC_B_EN_ADDR,
MT6359P_RG_LDO_VEMC_VOSEL_0_ADDR,
MT6359P_RG_LDO_VEMC_VOSEL_0_MASK <<
MT6359P_RG_LDO_VEMC_VOSEL_0_SHIFT),
- MT6359_LDO("ldo_vcn33_2_bt", VCN33_2_BT, vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_2_bt", VCN33_2_BT, "vsys-ldo1", vcn33_voltages,
MT6359P_RG_LDO_VCN33_2_EN_0_ADDR,
MT6359P_RG_LDO_VCN33_2_EN_0_SHIFT,
MT6359P_DA_VCN33_2_B_EN_ADDR, MT6359P_RG_VCN33_2_VOSEL_ADDR,
MT6359_RG_VCN33_2_VOSEL_MASK <<
MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_vcn33_2_wifi", VCN33_2_WIFI, vcn33_voltages,
+ MT6359_LDO("ldo_vcn33_2_wifi", VCN33_2_WIFI, "vsys-ldo1", vcn33_voltages,
MT6359P_RG_LDO_VCN33_2_EN_1_ADDR,
MT6359_RG_LDO_VCN33_2_EN_1_SHIFT,
MT6359P_DA_VCN33_2_B_EN_ADDR, MT6359P_RG_VCN33_2_VOSEL_ADDR,
MT6359_RG_VCN33_2_VOSEL_MASK <<
MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
- MT6359_LDO("ldo_va12", VA12, va12_voltages,
+ MT6359_LDO("ldo_va12", VA12, "vs2-ldo2", va12_voltages,
MT6359P_RG_LDO_VA12_EN_ADDR, MT6359P_RG_LDO_VA12_EN_SHIFT,
MT6359P_DA_VA12_B_EN_ADDR, MT6359P_RG_VA12_VOSEL_ADDR,
MT6359_RG_VA12_VOSEL_MASK << MT6359_RG_VA12_VOSEL_SHIFT,
960),
- MT6359_LDO("ldo_va09", VA09, va09_voltages,
+ MT6359_LDO("ldo_va09", VA09, "vs2-ldo2", va09_voltages,
MT6359P_RG_LDO_VA09_EN_ADDR, MT6359P_RG_LDO_VA09_EN_SHIFT,
MT6359P_DA_VA09_B_EN_ADDR, MT6359P_RG_VA09_VOSEL_ADDR,
MT6359_RG_VA09_VOSEL_MASK << MT6359_RG_VA09_VOSEL_SHIFT,
960),
- MT6359_LDO("ldo_vrf18", VRF18, vrf18_voltages,
+ MT6359_LDO("ldo_vrf18", VRF18, "vs1-ldo2", vrf18_voltages,
MT6359P_RG_LDO_VRF18_EN_ADDR, MT6359P_RG_LDO_VRF18_EN_SHIFT,
MT6359P_DA_VRF18_B_EN_ADDR, MT6359P_RG_VRF18_VOSEL_ADDR,
MT6359_RG_VRF18_VOSEL_MASK << MT6359_RG_VRF18_VOSEL_SHIFT,
240),
- MT6359_LDO_LINEAR("ldo_vsram_md", VSRAM_MD, 500000, 1293750, 6250,
+ MT6359_LDO_LINEAR("ldo_vsram_md", VSRAM_MD, "vs2-ldo1", 500000, 1293750, 6250,
MT6359P_RG_LDO_VSRAM_MD_EN_ADDR,
MT6359P_DA_VSRAM_MD_B_EN_ADDR,
MT6359P_RG_LDO_VSRAM_MD_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_MD_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_MD_VOSEL_SHIFT),
- MT6359_LDO("ldo_vufs", VUFS, volt18_voltages,
+ MT6359_LDO("ldo_vufs", VUFS, "vs1-ldo1", volt18_voltages,
MT6359P_RG_LDO_VUFS_EN_ADDR, MT6359P_RG_LDO_VUFS_EN_SHIFT,
MT6359P_DA_VUFS_B_EN_ADDR, MT6359P_RG_VUFS_VOSEL_ADDR,
MT6359_RG_VUFS_VOSEL_MASK << MT6359_RG_VUFS_VOSEL_SHIFT,
1920),
- MT6359_LDO("ldo_vm18", VM18, volt18_voltages,
+ MT6359_LDO("ldo_vm18", VM18, "vs1-ldo1", volt18_voltages,
MT6359P_RG_LDO_VM18_EN_ADDR, MT6359P_RG_LDO_VM18_EN_SHIFT,
MT6359P_DA_VM18_B_EN_ADDR, MT6359P_RG_VM18_VOSEL_ADDR,
MT6359_RG_VM18_VOSEL_MASK << MT6359_RG_VM18_VOSEL_SHIFT,
1920),
- MT6359_LDO("ldo_vbbck", VBBCK, vbbck_voltages,
+ MT6359_LDO("ldo_vbbck", VBBCK, "LDO_VIO18", vbbck_voltages,
MT6359P_RG_LDO_VBBCK_EN_ADDR, MT6359P_RG_LDO_VBBCK_EN_SHIFT,
MT6359P_DA_VBBCK_B_EN_ADDR, MT6359P_RG_VBBCK_VOSEL_ADDR,
MT6359P_RG_VBBCK_VOSEL_MASK << MT6359P_RG_VBBCK_VOSEL_SHIFT,
480),
- MT6359_LDO_LINEAR("ldo_vsram_proc1", VSRAM_PROC1, 500000, 1293750, 6250,
+ MT6359_LDO_LINEAR("ldo_vsram_proc1", VSRAM_PROC1, "vs2-ldo1", 500000, 1293750, 6250,
MT6359P_RG_LDO_VSRAM_PROC1_EN_ADDR,
MT6359P_DA_VSRAM_PROC1_B_EN_ADDR,
MT6359P_RG_LDO_VSRAM_PROC1_VOSEL_ADDR,
MT6359_RG_LDO_VSRAM_PROC1_VOSEL_MASK <<
MT6359_RG_LDO_VSRAM_PROC1_VOSEL_SHIFT),
- MT6359_LDO("ldo_vsim2", VSIM2, vsim2_voltages,
+ MT6359_LDO("ldo_vsim2", VSIM2, "vsys-ldo2", vsim2_voltages,
MT6359P_RG_LDO_VSIM2_EN_ADDR, MT6359P_RG_LDO_VSIM2_EN_SHIFT,
MT6359P_DA_VSIM2_B_EN_ADDR, MT6359P_RG_VSIM2_VOSEL_ADDR,
MT6359_RG_VSIM2_VOSEL_MASK << MT6359_RG_VSIM2_VOSEL_SHIFT,
480),
- MT6359_LDO_LINEAR("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB,
+ MT6359_LDO_LINEAR("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, "vs2-ldo1",
500000, 1293750, 6250,
MT6359P_RG_LDO_VSRAM_OTHERS_SSHUB_EN_ADDR,
MT6359P_DA_VSRAM_OTHERS_B_EN_ADDR,
@@ -951,6 +959,7 @@ static int mt6359_regulator_probe(struct platform_device *pdev)
struct regulator_config config = {};
struct regulator_dev *rdev;
const struct mt6359_regulator_info *mt6359_info;
+ const char *vio18_name;
int i, hw_ver, ret;
ret = regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver);
@@ -962,16 +971,37 @@ static int mt6359_regulator_probe(struct platform_device *pdev)
else
mt6359_info = mt6359_regulators;
+ vio18_name = mt6359_info[MT6359_ID_VIO18].desc.name;
+
config.dev = mt6397->dev;
config.regmap = mt6397->regmap;
for (i = 0; i < MT6359_MAX_REGULATOR; i++, mt6359_info++) {
+ const struct regulator_desc *desc = &mt6359_info->desc;
+ struct regulator_desc *_desc;
+
/* drop const here, but all uses in the driver are const */
config.driver_data = (void *)mt6359_info;
- rdev = devm_regulator_register(&pdev->dev, &mt6359_info->desc, &config);
+
+ /* Use vio18's actual name as supply_name for vbbck */
+ if (i == MT6359_ID_VBBCK && strcmp(desc->supply_name, vio18_name) != 0) {
+ _desc = devm_kzalloc(&pdev->dev, sizeof(*_desc), GFP_KERNEL);
+ if (!_desc)
+ return -ENOMEM;
+
+ memcpy(_desc, desc, sizeof(*_desc));
+ _desc->supply_name = vio18_name;
+ desc = _desc;
+ }
+
+ rdev = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s\n", mt6359_info->desc.name);
return PTR_ERR(rdev);
}
+
+ /* Save vio18 name for vbbck */
+ if (i == MT6359_ID_VIO18)
+ vio18_name = rdev_get_name(rdev);
}
return 0;
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH v4 4/6] regulator: mt6359: const-ify regulator descriptions
From: Chen-Yu Tsai @ 2026-05-14 9:15 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-arm-kernel, linux-mediatek, devicetree
In-Reply-To: <20260514091520.2718987-1-wenst@chromium.org>
The regulator descriptions and extended descriptions don't change at
runtime. The only reason they are not const is that the regulator
driver data is non-const.
Const-ify the descriptions and all references to them. For the driver
data, explicitly cast it to non-const void *.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/regulator/mt6359-regulator.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/regulator/mt6359-regulator.c b/drivers/regulator/mt6359-regulator.c
index c8a788858824..bcf9a476a34e 100644
--- a/drivers/regulator/mt6359-regulator.c
+++ b/drivers/regulator/mt6359-regulator.c
@@ -251,7 +251,7 @@ static int mt6359_get_status(struct regulator_dev *rdev)
{
int ret;
u32 regval;
- struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
+ const struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
ret = regmap_read(rdev->regmap, info->status_reg, ®val);
if (ret != 0) {
@@ -267,7 +267,7 @@ static int mt6359_get_status(struct regulator_dev *rdev)
static unsigned int mt6359_regulator_get_mode(struct regulator_dev *rdev)
{
- struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
+ const struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
int ret, regval;
ret = regmap_read(rdev->regmap, info->modeset_reg, ®val);
@@ -299,7 +299,7 @@ static unsigned int mt6359_regulator_get_mode(struct regulator_dev *rdev)
static int mt6359_regulator_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
- struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
+ const struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
int ret = 0, val;
int curr_mode;
@@ -354,7 +354,7 @@ static int mt6359_regulator_set_mode(struct regulator_dev *rdev,
static int mt6359p_vemc_set_voltage_sel(struct regulator_dev *rdev,
u32 sel)
{
- struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
+ const struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
int ret;
u32 val = 0;
@@ -393,7 +393,7 @@ static int mt6359p_vemc_set_voltage_sel(struct regulator_dev *rdev,
static int mt6359p_vemc_get_voltage_sel(struct regulator_dev *rdev)
{
- struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
+ const struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
int ret;
u32 val = 0;
@@ -469,7 +469,7 @@ static const struct regulator_ops mt6359p_vemc_ops = {
};
/* The array is indexed by id(MT6359_ID_XXX) */
-static struct mt6359_regulator_info mt6359_regulators[] = {
+static const struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_BUCK("buck_vs1", VS1, 800000, 2200000, 12500,
MT6359_RG_BUCK_VS1_EN_ADDR,
MT6359_DA_VS1_EN_ADDR, MT6359_RG_BUCK_VS1_VOSEL_ADDR,
@@ -705,7 +705,7 @@ static struct mt6359_regulator_info mt6359_regulators[] = {
MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_SHIFT),
};
-static struct mt6359_regulator_info mt6359p_regulators[] = {
+static const struct mt6359_regulator_info mt6359p_regulators[] = {
MT6359_BUCK("buck_vs1", VS1, 800000, 2200000, 12500,
MT6359_RG_BUCK_VS1_EN_ADDR,
MT6359_DA_VS1_EN_ADDR, MT6359_RG_BUCK_VS1_VOSEL_ADDR,
@@ -950,7 +950,7 @@ static int mt6359_regulator_probe(struct platform_device *pdev)
struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = {};
struct regulator_dev *rdev;
- struct mt6359_regulator_info *mt6359_info;
+ const struct mt6359_regulator_info *mt6359_info;
int i, hw_ver, ret;
ret = regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver);
@@ -965,7 +965,8 @@ static int mt6359_regulator_probe(struct platform_device *pdev)
config.dev = mt6397->dev;
config.regmap = mt6397->regmap;
for (i = 0; i < MT6359_MAX_REGULATOR; i++, mt6359_info++) {
- config.driver_data = mt6359_info;
+ /* drop const here, but all uses in the driver are const */
+ config.driver_data = (void *)mt6359_info;
rdev = devm_regulator_register(&pdev->dev, &mt6359_info->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s\n", mt6359_info->desc.name);
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH v4 3/6] regulator: dt-bindings: mt6359: Deprecate bogus vcn33_[12]_* split regulators
From: Chen-Yu Tsai @ 2026-05-14 9:15 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-arm-kernel, linux-mediatek, devicetree,
Krzysztof Kozlowski
In-Reply-To: <20260514091520.2718987-1-wenst@chromium.org>
vcn33_[12]_bt and vcn33_[12]_wifi refer to the same output. There are
two enable bits in the registers so that BT and WiFi drivers can toggle
them separately without any coordination. If either bit is set, then the
regulator output is enabled.
Deprecate the existing regulators, and add proper regulators matching
the outputs: vcn33_1 and vcn33_2.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
Changes since v3:
- Added ending match to regex for deprecated vcn33_[12]_(bt|wifi) (Sashiko)
- Updated example to use proper vcn33_[12] nodes (Sashiko)
---
.../bindings/regulator/mt6359-regulator.yaml | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml b/Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml
index ac925334ae83..e3c20412c8a7 100644
--- a/Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml
@@ -30,7 +30,7 @@ patternProperties:
$ref: regulator.yaml#
unevaluatedProperties: false
- "^ldo_vcn(18|13|33_1_bt|13_1_wifi|33_2_bt|33_2_wifi)$":
+ "^ldo_vcn(18|13|33_[12])$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
@@ -55,6 +55,15 @@ patternProperties:
$ref: regulator.yaml#
unevaluatedProperties: false
+ "^ldo_vcn33_[12]_(bt|wifi)$":
+ type: object
+ $ref: regulator.yaml#
+ description:
+ vcn33_[12]_(bt|wifi) are incorrect representations.
+ Use vcn33_[12] instead.
+ deprecated: true
+ unevaluatedProperties: false
+
additionalProperties: false
examples:
@@ -203,13 +212,8 @@ examples:
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1300000>;
};
- mt6359_vcn33_1_bt_ldo_reg: ldo_vcn33_1_bt {
- regulator-name = "vcn33_1_bt";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <3500000>;
- };
- mt6359_vcn33_1_wifi_ldo_reg: ldo_vcn33_1_wifi {
- regulator-name = "vcn33_1_wifi";
+ mt6359_vcn33_1_bt_ldo_reg: ldo_vcn33_1 {
+ regulator-name = "vcn33_1";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <3500000>;
};
@@ -270,13 +274,8 @@ examples:
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <3300000>;
};
- mt6359_vcn33_2_bt_ldo_reg: ldo_vcn33_2_bt {
- regulator-name = "vcn33_2_bt";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <3500000>;
- };
- mt6359_vcn33_2_wifi_ldo_reg: ldo_vcn33_2_wifi {
- regulator-name = "vcn33_2_wifi";
+ mt6359_vcn33_2_bt_ldo_reg: ldo_vcn33_2 {
+ regulator-name = "vcn33_2";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <3500000>;
};
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH v4 2/6] regulator: dt-bindings: mt6359: Drop regulator-name pattern restrictions
From: Chen-Yu Tsai @ 2026-05-14 9:15 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-arm-kernel, linux-mediatek, devicetree,
Krzysztof Kozlowski
In-Reply-To: <20260514091520.2718987-1-wenst@chromium.org>
The name of the regulator should match what the board design specifies
for the power rail. There should be no limitations on what the name can
be, and they definitely don't always follow the PMIC's own names.
Drop the restrictions on regulator-name.
Fixes: 8771456635d5 ("dt-bindings: regulator: Add document for MT6359 regulator")
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
.../bindings/regulator/mt6359-regulator.yaml | 43 -------------------
1 file changed, 43 deletions(-)
diff --git a/Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml b/Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml
index fe4ac9350ba0..ac925334ae83 100644
--- a/Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml
@@ -18,84 +18,41 @@ patternProperties:
"^buck_v(s1|gpu11|modem|pu|core|s2|pa|proc2|proc1|core_sshub)$":
type: object
$ref: regulator.yaml#
-
- properties:
- regulator-name:
- pattern: "^v(s1|gpu11|modem|pu|core|s2|pa|proc2|proc1|core_sshub)$"
-
unevaluatedProperties: false
"^ldo_v(ibr|rf12|usb|camio|efuse|xo22)$":
type: object
$ref: regulator.yaml#
-
- properties:
- regulator-name:
- pattern: "^v(ibr|rf12|usb|camio|efuse|xo22)$"
-
unevaluatedProperties: false
"^ldo_v(rfck|emc|a12|a09|ufs|bbck)$":
type: object
$ref: regulator.yaml#
-
- properties:
- regulator-name:
- pattern: "^v(rfck|emc|a12|a09|ufs|bbck)$"
-
unevaluatedProperties: false
"^ldo_vcn(18|13|33_1_bt|13_1_wifi|33_2_bt|33_2_wifi)$":
type: object
$ref: regulator.yaml#
-
- properties:
- regulator-name:
- pattern: "^vcn(18|13|33_1_bt|13_1_wifi|33_2_bt|33_2_wifi)$"
-
unevaluatedProperties: false
"^ldo_vsram_(proc2|others|md|proc1|others_sshub)$":
type: object
$ref: regulator.yaml#
-
- properties:
- regulator-name:
- pattern: "^vsram_(proc2|others|md|proc1|others_sshub)$"
-
unevaluatedProperties: false
"^ldo_v(fe|bif|io)28$":
type: object
$ref: regulator.yaml#
-
- properties:
- regulator-name:
- pattern: "^v(fe|bif|io)28$"
-
unevaluatedProperties: false
"^ldo_v(aud|io|aux|rf|m)18$":
type: object
$ref: regulator.yaml#
-
- properties:
- regulator-name:
- pattern: "^v(aud|io|aux|rf|m)18$"
-
unevaluatedProperties: false
"^ldo_vsim[12]$":
type: object
$ref: regulator.yaml#
-
- properties:
- regulator-name:
- pattern: "^vsim[12]$"
-
- required:
- - regulator-name
-
unevaluatedProperties: false
additionalProperties: false
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH v4 1/6] mfd: dt-bindings: mt6397: Add regulator supplies
From: Chen-Yu Tsai @ 2026-05-14 9:15 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-arm-kernel, linux-mediatek, devicetree,
Krzysztof Kozlowski
In-Reply-To: <20260514091520.2718987-1-wenst@chromium.org>
On the MT6397 family each buck regulator has a separate supply. LDOs are
split into various groups with independent supplies. There is also a
supply for the regulator control logic.
Add descriptions for all of the supplies for the MT6359.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
Lee, request from Mark:
Lee, this seems like mostly a regulator series - OK for me to apply this
patch and send you a tag for it?
Changes since v3:
- Dropped duplicate 'va09' from 'vsys-ldo2-supply' (Sashiko)
Changes since v2:
- Fix vsys-vsmps-supply property name
Changes since v1:
- Use regular expression to describe vcn33_* names
- Moved regulator supplies to top level PMIC node
- Moved changes to mfd binding
---
.../bindings/mfd/mediatek,mt6397.yaml | 50 +++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
index 05c121b0cb3d..ecdc77fafaf4 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -225,12 +225,62 @@ properties:
description:
Pin controller
+ vsys-smps-supply:
+ description: Supply for regulator control logic
+
+patternProperties:
+ "^vsys-v[a-z]+[0-9]*-supply$":
+ description: Supplies for PMIC buck regulators
+ "^vs(ys|[12])-ldo[1-9]-supply$":
+ description: Supplies for PMIC LDO regulators
+
required:
- compatible
- regulators
additionalProperties: false
+allOf:
+ - if:
+ properties:
+ "compatible":
+ contains:
+ const: mediatek,mt6359
+ then:
+ properties:
+ vsys-ldo1-supply:
+ description: Supply for LDOs vcn33_[12], vio28, vfe28, vibr
+ vsys-ldo2-supply:
+ description: Supply for LDOs vaux18, vbif28, vxo22, vrfck, vrfck_1,
+ vemc, vsim1, vsim2, vusb
+ vsys-vcore-supply:
+ description: Supply for buck regulator vcore
+ vsys-vgpu11-supply:
+ description: Supply for buck regulator vgpu11
+ vsys-vmodem-supply:
+ description: Supply for buck regulator vmodem
+ vsys-vpa-supply:
+ description: Supply for buck regulator vpa
+ vsys-vproc1-supply:
+ description: Supply for buck regulator vproc1
+ vsys-vproc2-supply:
+ description: Supply for buck regulator vproc2
+ vsys-vpu-supply:
+ description: Supply for buck regulator vpu
+ vsys-vs1-supply:
+ description: Supply for buck regulator vs1
+ vsys-vs2-supply:
+ description: Supply for buck regulator vs2
+ vs1-ldo1-supply:
+ description: Supply for LDOs vaud18, vcamio, vm18, vufs
+ vs1-ldo2-supply:
+ description: Supply for LDOs vcn18, vefuse, vio18, vrf18
+ vs2-ldo1-supply:
+ description:
+ Supply for LDOs vsram_proc1, vsram_proc2, vsram_others, vsram_md
+ vs2-ldo2-supply:
+ description: Supply for LDOs va09, va12, vcn13, vrf12
+
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH v4 0/6] regulator: mt6359: cleanup and add supplies
From: Chen-Yu Tsai @ 2026-05-14 9:15 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-arm-kernel, linux-mediatek, devicetree
Hi,
This is v4 of my "MT6359 PMIC cleanup and add supplies" series. This
version addresses review comments from Sashiko.
Changes since v3:
- Dropped duplicate 'va09' regulator from 'vsys-ldo2-supply'
- Added ending match to regex for deprecated vcn33_[12]_(bt|wifi) nodes
- Updated regulator DT example to use proper vcn33_[12] nodes
- Changed vbbck's supply name to 'VIO18' to match vio18 regulator's
default name
- Fixed index off-by-one in error message in mt6359_sync_vcn33_setting()
- Added check of return value from mt6359_sync_vcn33_setting()
- Link to v3:
https://lore.kernel.org/all/20260512085358.1693208-1-wenst@chromium.org/
Changes since v2:
- Fixed vsys-smps-supply property name (from "vspms-supply")
- Collected reviewed-by on patch 3
- Included Lee in recipients (sorry about that)
- Link to v2:
https://lore.kernel.org/all/20260429074113.3720271-1-wenst@chromium.org/
Changes since v1:
- Moved regulator supply properties up to the PMIC mfd node
- This requires moving the properties to the mfd bindings
- deprecated vcn33_[12]_(bt|wifi) regulators and added vcn33_[12]
- model the deprecated ones as downstream to the new ones
(vcn33_[12] -> vcn33_[12]_(bt|wifi)
- Handle internal supply of vbbck directly in the driver, instead of
specifying it in the binding
- Added patch to constify data structures in the regulator driver
- Link to v1:
https://lore.kernel.org/all/20260320072440.2403318-1-wenst@chromium.org/
This series is part of a broader collection of regulator related
cleanups for MediaTek Chromebooks. This one covers the MT6359 PMIC.
The MT6359 PMIC is similar to the MT6358 and MT6366 PMICs. I've done
cleanups for those in the past.
Patch 1 adds the names of the power supply inputs to the binding.
Patch 2 drops the restrictions on the regulator-name property from the
binding. The name of the supply rail ideally should match the design
schematics, not the PMIC's output name. The DT should be free to set
whatever name it needs.
Patch 3 deprecates the vcn33_[12]_(bt|wifi) regulators, and adds new
proper vcn33_[12] regulators. The two *real* VCN33 regulator outputs
each have two enable bits that are OR-ed together to control the
output. This allowed WiFi and BT stacks to separately control power
output without coordination.
Patch 4 constifies the data structures used throughout the regulator
driver. While not directly related, it touches the same context and
it is easier to include it in the series.
Patch 5 adds the supply names from the DT binding change in patch 2
to the regulator descriptions in the driver. This patch has a whole
bunch of checkpatch.pl warnings, but I wonder if it's because the
context size for checking complex macros is not large enough.
Patch 6 implements the changes of the DT binding change in patch 3.
One part not yet covered in this series is the removal of the *_sshub
regulators. These are not actual regulators, but a set of separate
configurations to be used by the low power sensor hub or embedded
controller. How these combine with the standard set of configurations
set by the main processor is TBD.
Device tree changes will be sent separately. The goal is to get the
regulator tree as complete as possible. This includes adding supply
names to other regulator DT bindings, and adding all the supply links
to the existing DTs.
Please have a look.
Thanks
ChenYu
Chen-Yu Tsai (6):
mfd: dt-bindings: mt6397: Add regulator supplies
regulator: dt-bindings: mt6359: Drop regulator-name pattern
restrictions
regulator: dt-bindings: mt6359: Deprecate bogus vcn33_[12]_* split
regulators
regulator: mt6359: const-ify regulator descriptions
regulator: mt6359: Add regulator supply names
regulator: mt6359: Add proper ldo_vcn33_[12] regulators
.../bindings/mfd/mediatek,mt6397.yaml | 50 +++
.../bindings/regulator/mt6359-regulator.yaml | 70 +--
drivers/regulator/mt6359-regulator.c | 405 ++++++++++++------
include/linux/regulator/mt6359-regulator.h | 10 +-
4 files changed, 348 insertions(+), 187 deletions(-)
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply
* [PATCH v1] ufs: core: decouple CQE processing from spinlock critical section
From: peter.wang @ 2026-05-14 8:26 UTC (permalink / raw)
To: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb
Cc: wsd_upstream, linux-mediatek, peter.wang, chun-hung.wu,
alice.chao, cc.chou, chaotian.jing, tun-yu.yu, eddie.huang,
naomi.chu, ed.tsai, bvanassche, quic_cang, quic_asutoshd,
light.hsieh
From: Peter Wang <peter.wang@mediatek.com>
Currently, ufshcd_mcq_process_cqe() is called while holding the CQ
spinlock, which can lead to unnecessary lock contention since CQE
processing may involve time-consuming operations like completing I/O
requests and invoking callbacks.
Refactor the CQE processing flow to separate the lock-protected queue
head/tail slot updates from the actual CQE processing:
1. Add a new 'cqe_last_addr' field to 'ufs_hw_queue' to cache the
address of the last CQE entry, precomputed during memory allocation
in ufshcd_mcq_memory_alloc(). This avoids repeated recalculation
during the hot path.
2. Introduce ufshcd_mcq_inc_cqe_addr() helper in ufshcd-priv.h to
increment a CQE pointer with wraparound, using 'cqe_last_addr' for
boundary checking.
3. Refactor ufshcd_mcq_process_cqe() to accept a 'struct cq_entry *'
directly instead of deriving it from the hardware queue, decoupling
it from queue state.
4. In both ufshcd_mcq_compl_all_cqes_lock() and
ufshcd_mcq_poll_cqe_lock(), snapshot the starting CQE pointer before
advancing the head slot under the spinlock, then process the collected
CQEs after releasing the lock using the new helper.
This reduces the time spent holding the CQ spinlock to only the
minimal queue slot management operations, improving concurrency and
reducing latency under heavy I/O workloads.
Signed-off-by: Peter Wang <peter.wang@mediatek.com>
---
drivers/ufs/core/ufs-mcq.c | 23 ++++++++++++++++++-----
drivers/ufs/core/ufshcd-priv.h | 20 ++++++++++++++++++++
include/ufs/ufshcd.h | 1 +
3 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index c1b1d67a1ddc..74a6595f9bda 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -248,6 +248,7 @@ int ufshcd_mcq_memory_alloc(struct ufs_hba *hba)
dev_err(hba->dev, "CQE allocation failed\n");
return -ENOMEM;
}
+ hwq->cqe_last_addr = hwq->cqe_base_addr + hwq->max_entries - 1;
}
return 0;
@@ -307,10 +308,8 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba, struct cq_entry *cqe)
}
static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
- struct ufs_hw_queue *hwq)
+ struct cq_entry *cqe)
{
- struct cq_entry *cqe = ufshcd_mcq_cur_cqe(hwq);
-
if (cqe->command_desc_base_addr) {
int tag = ufshcd_mcq_get_tag(hba, cqe);
@@ -335,10 +334,12 @@ void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba,
{
unsigned long flags;
u32 entries = hwq->max_entries;
+ struct cq_entry *cqe;
+ int i;
spin_lock_irqsave(&hwq->cq_lock, flags);
+ cqe = ufshcd_mcq_cur_cqe(hwq);
while (entries > 0) {
- ufshcd_mcq_process_cqe(hba, hwq);
ufshcd_mcq_inc_cq_head_slot(hwq);
entries--;
}
@@ -346,6 +347,11 @@ void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba,
ufshcd_mcq_update_cq_tail_slot(hwq);
hwq->cq_head_slot = hwq->cq_tail_slot;
spin_unlock_irqrestore(&hwq->cq_lock, flags);
+
+ for (i = 0; i < hwq->max_entries; i++) {
+ ufshcd_mcq_process_cqe(hba, cqe);
+ cqe = ufshcd_mcq_inc_cqe_addr(hwq, cqe);
+ }
}
unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
@@ -353,11 +359,13 @@ unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
{
unsigned long completed_reqs = 0;
unsigned long flags;
+ struct cq_entry *cqe;
+ int i;
spin_lock_irqsave(&hwq->cq_lock, flags);
+ cqe = ufshcd_mcq_cur_cqe(hwq);
ufshcd_mcq_update_cq_tail_slot(hwq);
while (!ufshcd_mcq_is_cq_empty(hwq)) {
- ufshcd_mcq_process_cqe(hba, hwq);
ufshcd_mcq_inc_cq_head_slot(hwq);
completed_reqs++;
}
@@ -366,6 +374,11 @@ unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
ufshcd_mcq_update_cq_head(hwq);
spin_unlock_irqrestore(&hwq->cq_lock, flags);
+ for (i = 0; i < completed_reqs; i++) {
+ ufshcd_mcq_process_cqe(hba, cqe);
+ cqe = ufshcd_mcq_inc_cqe_addr(hwq, cqe);
+ }
+
return completed_reqs;
}
EXPORT_SYMBOL_GPL(ufshcd_mcq_poll_cqe_lock);
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index 0a72148cb053..6d4d3e726a9a 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -440,6 +440,26 @@ static inline struct scsi_cmnd *ufshcd_tag_to_cmd(struct ufs_hba *hba, u32 tag)
return blk_mq_rq_to_pdu(rq);
}
+/**
+ * ufshcd_mcq_inc_cqe_addr - increment CQE pointer with wraparound
+ * @hwq: pointer to the hardware queue
+ * @cqe: current CQE pointer to increment
+ *
+ * Increments the CQE pointer to the next entry. If the pointer
+ * exceeds the last entry, it wraps around to the base address.
+ *
+ * Returns: pointer to the next cq_entry
+ */
+static inline struct cq_entry *ufshcd_mcq_inc_cqe_addr(struct ufs_hw_queue *q,
+ struct cq_entry *cqe)
+{
+ cqe++;
+ if (cqe > q->cqe_last_addr)
+ cqe = q->cqe_base_addr;
+
+ return cqe;
+}
+
static inline void ufshcd_inc_sq_tail(struct ufs_hw_queue *q)
__must_hold(&q->sq_lock)
{
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index cfbc75d8df83..1becb38e215e 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -1291,6 +1291,7 @@ struct ufs_hw_queue {
struct utp_transfer_req_desc *sqe_base_addr;
dma_addr_t sqe_dma_addr;
struct cq_entry *cqe_base_addr;
+ struct cq_entry *cqe_last_addr;
dma_addr_t cqe_dma_addr;
u32 max_entries;
u32 id;
--
2.45.2
^ permalink raw reply related
* Re: [PATCH] dt-bindings: PCI: mediatek-gen3: Allow memory-region for restricted DMA buffer
From: Chen-Yu Tsai @ 2026-05-14 8:12 UTC (permalink / raw)
To: Rob Herring
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Ryder Lee,
Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Bjorn Helgaas, Krzysztof Kozlowski,
Conor Dooley, devicetree, linux-pci, linux-mediatek, linux-kernel
In-Reply-To: <20260513231550.GA2280946-robh@kernel.org>
On Thu, May 14, 2026 at 7:15 AM Rob Herring <robh@kernel.org> wrote:
>
> On Fri, May 08, 2026 at 02:36:32PM +0800, Chen-Yu Tsai wrote:
> > On some SoCs without an IOMMU behind the PCIe controller, the PCIe
> > controller memory access could be limited to a small region by the
> > firmware configuring a memory protection unit. This memory region
> > must be assigned to the PCIe controller so that the OS knows to
> > use that region. Otherwise PCIe devices would not work properly.
> >
>
> What you are describing is dma-ranges. Why not use that?
Answer from yesterday:
I didn't know about it. I was just moving the property from the WiFi
controller node down to the PCIe controller in the other DT patch [1].
Answer from today:
Also, it doesn't work. See my reply to Mani.
ChenYu
> > Allow the memory-region property with one item pointing to a
> > restricted DMA buffer.
> >
> > Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
> > ---
> > This patch compliments another patch that moved the memory-region from
> > the PCIe device to the PCIe controller [1].
> >
> > [1] https://lore.kernel.org/all/20260430120725.241779-1-wenst@chromium.org/
> >
> > Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml | 4 ++++
> > 1 file changed, 4 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
> > index 4db700fc36ba..4a9e41d01628 100644
> > --- a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
> > +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
> > @@ -115,6 +115,10 @@ properties:
> > power-domains:
> > maxItems: 1
> >
> > + memory-region:
> > + maxItems: 1
> > + description: phandle to restricted DMA buffer
> > +
> > mediatek,pbus-csr:
> > $ref: /schemas/types.yaml#/definitions/phandle-array
> > items:
> > --
> > 2.54.0.563.g4f69b47b94-goog
> >
^ permalink raw reply
* Re: [PATCH] dt-bindings: PCI: mediatek-gen3: Allow memory-region for restricted DMA buffer
From: Chen-Yu Tsai @ 2026-05-14 7:54 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Ryder Lee,
Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
Bjorn Helgaas, Krzysztof Kozlowski, Conor Dooley, devicetree,
linux-pci, linux-mediatek, linux-kernel
In-Reply-To: <locoul5wdzuvvmm7mqpuntjqu4o75gmyd5npgfqrw3zuwsrse6@dhrjggs4cihh>
On Thu, May 14, 2026 at 1:23 PM Manivannan Sadhasivam <mani@kernel.org> wrote:
>
> On Fri, May 08, 2026 at 02:36:32PM +0800, Chen-Yu Tsai wrote:
> > On some SoCs without an IOMMU behind the PCIe controller, the PCIe
> > controller memory access could be limited to a small region by the
> > firmware configuring a memory protection unit. This memory region
> > must be assigned to the PCIe controller so that the OS knows to
> > use that region. Otherwise PCIe devices would not work properly.
> >
>
> So this means, the PCIe devices can only access a specific carveout memory
> configured by MPU for DMA? If so, you should use 'dma-ranges' as suggested by
> Rob.
>
> 'memory-region' also serves the purpose, but for PCI, we have the dedicated
> 'dma-ranges' property.
I think I need some sort of guide on writing the 'dma-ranges' property,
because it is not working for me.
I'm adding
dma-ranges = <0x42000000 0 0x00000000 0 0xc0000000 0 0x4000000>;
to the PCIe controller node, and dropping the memory-region. The WiFi
driver subsequently fails to allocate buffers:
rtw88_8822ce 0000:01:00.0: enabling device (0000 -> 0003)
rtw88_8822ce 0000:01:00.0: failed to allocate tx ring
This is dma_alloc_coherent() failing.
rtw88_8822ce 0000:01:00.0: Firmware version 9.9.15, H2C version 15
rtw88_8822ce 0000:01:00.0: failed to allocate pci resources
rtw88_8822ce 0000:01:00.0: WOW Firmware version 9.9.4, H2C version 15
rtw88_8822ce 0000:01:00.0: failed to setup pci resources
rtw88_8822ce 0000:01:00.0: probe with driver rtw88_8822ce failed
with error -12
Also, using memory-region seems more straight-forward: I have a region of
memory dedicated to the PCIe controller. I describe the memory region,
and assign it to the PCIe controller.
Thanks
ChenYu
^ permalink raw reply
* Re: [PATCH] arm64: dts: mediatek: mt7981b: Add PMU
From: Peter Collingbourne @ 2026-05-14 6:45 UTC (permalink / raw)
To: Sjoerd Simons
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <6dbefb2c80964c0394771ae11fd0f9e05486db29.camel@collabora.com>
On Mon, May 4, 2026 at 11:49 PM Sjoerd Simons <sjoerd@collabora.com> wrote:
>
> On Sat, 2026-05-02 at 00:49 -0700, Peter Collingbourne wrote:
> > The interrupt number was taken from a downstream DTS of the similar MT7987
> > [1] and verified on my OpenWrt One.
> >
> > Signed-off-by: Peter Collingbourne <peter@pcc.me.uk>
> > Link: [1]
> > https://github.com/openwrt/openwrt/blob/e4b3d5c799aef3be20b7f6079e8e5a14b215c116/target/linux/mediatek/dts/mt7987.dtsi#L246
> > ---
> > arch/arm64/boot/dts/mediatek/mt7981b.dtsi | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
> > b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
> > index 4084f4dfa3e5..3c6fbb6c5333 100644
> > --- a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
> > +++ b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
> > @@ -38,6 +38,12 @@ oscillator-40m {
> > #clock-cells = <0>;
> > };
> >
> > + pmu {
> > + compatible = "arm,cortex-a53-pmu";
> > + interrupt-parent = <&gic>;
>
> The parent node already specifies the interrupt-parent, so this is redundant.
>
> > + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
> > + };
> > +
>
> Otherwise looks good
Thanks, sent v2 with removed interrupt-parent.
Peter
^ permalink raw reply
* [PATCH v2] arm64: dts: mediatek: mt7981b: Add PMU
From: Peter Collingbourne @ 2026-05-14 6:44 UTC (permalink / raw)
To: Sjoerd Simons
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, Peter Collingbourne
The interrupt number was taken from a downstream DTS of the similar MT7987
[1] and verified on my OpenWrt One.
Signed-off-by: Peter Collingbourne <peter@pcc.me.uk>
Link: [1] https://github.com/openwrt/openwrt/blob/e4b3d5c799aef3be20b7f6079e8e5a14b215c116/target/linux/mediatek/dts/mt7987.dtsi#L246
---
v2:
* Remove interrupt-parent
arch/arm64/boot/dts/mediatek/mt7981b.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
index 1bbe219380f9..ba6720031908 100644
--- a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
@@ -38,6 +38,11 @@ oscillator-40m {
#clock-cells = <0>;
};
+ pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
psci {
compatible = "arm,psci-1.0";
method = "smc";
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v1 2/2] ASoC: Use named initializers for arrays of i2c_device_data
From: Krzysztof Kozlowski @ 2026-05-14 5:59 UTC (permalink / raw)
To: Uwe Kleine-König (The Capable Hub), Liam Girdwood,
Mark Brown
Cc: David Rhodes, Richard Fitzgerald, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Lars-Peter Clausen,
Nuno Sá, Martin Povišer, Support Opensource, Nick Li,
M R Swami Reddy, Vishwas A Deshpande, Peter Rosin,
Matthias Brugger, AngeloGioacchino Del Regno, Oder Chiou,
Fabio Estevam, Kiseok Jo, Kevin Cernekee, Steven Eckhoff,
Kuninori Morimoto, Charles Keepax, Thorsten Blum, Chris Morgan,
Dan Carpenter, Marco Crivellari, Weidong Wang, Aaron Kling,
Teguh Sobirin, Luca Weiss, Bharadwaj Raju, Hsieh Hung-En,
Binbin Zhou, Shimrra Shai, Zhang Yi, Srinivas Kandagatla,
Qasim Ijaz, Sharique Mohammad, Chen Ni, Neo Chang,
Cezary Rojewski, Cristian Ciocaltea, Kees Cook, Qianfeng Rong,
Tim Bird, Bram Vlerick, Peter Korsgaard, Linus Walleij,
Wenyuan Li, Bartosz Golaszewski, Shengjiu Wang,
Sebastian Krzyszkowiak, Xichao Zhao, linux-sound, patches,
linux-kernel, asahi, linux-arm-kernel, linux-mediatek,
Markus Schneider-Pargmann
In-Reply-To: <65f6da30-eb20-4020-b13a-ac7d4c823dfc@kernel.org>
On 13/05/2026 21:00, Krzysztof Kozlowski wrote:
> On 13/05/2026 19:23, Uwe Kleine-König (The Capable Hub) wrote:
>> MODULE_DEVICE_TABLE(i2c, adau1372_i2c_ids);
>> diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
>> index 16b9b2658341..5dd961b233ce 100644
>> --- a/sound/soc/codecs/adau1373.c
>> +++ b/sound/soc/codecs/adau1373.c
>> @@ -1599,7 +1599,7 @@ static int adau1373_i2c_probe(struct i2c_client *client)
>> }
>>
>> static const struct i2c_device_id adau1373_i2c_id[] = {
>> - { "adau1373" },
>> + { .name = "adau1373" },
>> { }
>> };
>
> This is inconsistent with most (or all?) of other xx_device_id table
> usages and, IIUC, is not even necessary to achieve your goal (which
> itself is good).
After talking on IRC, I see that actually many of platform_device_id use
named initializers for '.name' and PCI uses macro for that, thus my
"consistency" concern is not really valid. Especially that if you change
i2c and spi tables, the named initializers might be more frequent...
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH] dt-bindings: PCI: mediatek-gen3: Allow memory-region for restricted DMA buffer
From: Manivannan Sadhasivam @ 2026-05-14 5:23 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Ryder Lee,
Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
Bjorn Helgaas, Krzysztof Kozlowski, Conor Dooley, devicetree,
linux-pci, linux-mediatek, linux-kernel
In-Reply-To: <20260508063633.3894348-1-wenst@chromium.org>
On Fri, May 08, 2026 at 02:36:32PM +0800, Chen-Yu Tsai wrote:
> On some SoCs without an IOMMU behind the PCIe controller, the PCIe
> controller memory access could be limited to a small region by the
> firmware configuring a memory protection unit. This memory region
> must be assigned to the PCIe controller so that the OS knows to
> use that region. Otherwise PCIe devices would not work properly.
>
So this means, the PCIe devices can only access a specific carveout memory
configured by MPU for DMA? If so, you should use 'dma-ranges' as suggested by
Rob.
'memory-region' also serves the purpose, but for PCI, we have the dedicated
'dma-ranges' property.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [net-next v8 2/3] net: ethernet: mtk_eth_soc: Add RSS support
From: Jakub Kicinski @ 2026-05-14 1:56 UTC (permalink / raw)
To: Frank Wunderlich
Cc: Mason Chang, AngeloGioacchino Del Regno, netdev, Russell King,
linux-kernel, Andrew Lunn, Eric Dumazet, linux-mediatek,
Daniel Golle, Matthias Brugger, Paolo Abeni, Lorenzo Bianconi,
David S. Miller, linux-arm-kernel, Felix Fietkau
In-Reply-To: <20260509190938.169290-3-linux@fw-web.de>
On Sat, 9 May 2026 21:09:31 +0200 Frank Wunderlich wrote:
> From: Mason Chang <mason-cw.chang@mediatek.com>
>
> Add support for Receive Side Scaling.
>
> We can adjust SMP affinity with the following command:
> echo [CPU bitmap num] > /proc/irq/[virtual IRQ ID]/smp_affinity,
> with interrupts evenly assigned to 4 CPUs, we were able to measure
> an RX throughput of 7.3Gbps using iperf3 on the MT7988. Further
> optimizations will be carried out in the future.
Would be great to split this up a little more for ease of review.
> +static int mtk_rss_init(struct mtk_eth *eth)
> +{
> + const struct mtk_soc_data *soc = eth->soc;
> + const struct mtk_reg_map *reg_map = eth->soc->reg_map;
> + struct mtk_rss_params *rss_params = ð->rss_params;
reverse xmas tree should be followed, please fix everywhere in this
submission
> + u32 val;
> + int i;
> +
> + netdev_rss_key_fill(rss_params->hash_key, MTK_RSS_HASH_KEYSIZE);
> +
> + for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
> + rss_params->indirection_table[i] = ethtool_rxfh_indir_default(i, eth->soc->rss_num);
> +
> + if (soc->rx.desc_size == sizeof(struct mtk_rx_dma)) {
> + /* Set RSS rings to PSE modes */
> + for (i = 1; i <= MTK_HW_LRO_RING_NUM(eth); i++) {
> + val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
> + val |= MTK_RING_PSE_MODE;
> + mtk_w32(eth, val, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
> + }
> +
> + /* Enable non-lro multiple rx */
> + val = mtk_r32(eth, reg_map->pdma.lro_ctrl_dw0);
> + val |= MTK_NON_LRO_MULTI_EN;
> + mtk_w32(eth, val, reg_map->pdma.lro_ctrl_dw0);
> +
> + /* Enable RSS dly int supoort */
> + val |= MTK_LRO_DLY_INT_EN;
> + mtk_w32(eth, val, reg_map->pdma.lro_ctrl_dw0);
> + }
> +
> + /* Hash Type */
> + val = mtk_r32(eth, reg_map->pdma.rss_glo_cfg);
> + val |= MTK_RSS_IPV4_STATIC_HASH;
> + val |= MTK_RSS_IPV6_STATIC_HASH;
> + mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
> +
> + /* Hash Key */
> + for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++)
> + mtk_w32(eth, rss_params->hash_key[i], MTK_RSS_HASH_KEY_DW(reg_map, i));
> +
> + /* Select the size of indirection table */
> + for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++)
> + mtk_w32(eth, mtk_rss_indr_table(rss_params, i),
> + MTK_RSS_INDR_TABLE_DW(reg_map, i));
> +
> + /* Pause */
> + val |= MTK_RSS_CFG_REQ;
> + mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
> +
> + /* Enable RSS */
> + val |= MTK_RSS_EN;
> + mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
> +
> + /* Release pause */
> + val &= ~(MTK_RSS_CFG_REQ);
> + mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
> +
> + /* Set perRSS GRP INT */
> + mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(1)),
> + MTK_RX_DONE_INT(eth, MTK_RSS_RING(1)), reg_map->pdma.int_grp);
> + mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(2)),
> + MTK_RX_DONE_INT(eth, MTK_RSS_RING(2)), reg_map->pdma.int_grp + 0x4);
> + mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(3)),
> + MTK_RX_DONE_INT(eth, MTK_RSS_RING(3)), reg_map->pdma.int_grp3);
> +
> + return 0;
> +}
> +/* struct mtk_rss_params - This is the structure holding parameters
> + * for the RSS ring
> + * @hash_key The element is used to record the
> + * secret key for the RSS ring
> + * indirection_table The element is used to record the
> + * indirection table for the RSS ring
> + */
Quite odd looking comment. Having the right side aligned like that
makes it header to correlate where doc for fields start.
And there's @ missing for indirection_table.
^ permalink raw reply
* Re: [net-next v8 3/3] net: ethernet: mtk_eth_soc: Add LRO support
From: Jakub Kicinski @ 2026-05-14 1:53 UTC (permalink / raw)
To: Frank Wunderlich
Cc: Mason Chang, AngeloGioacchino Del Regno, netdev, Russell King,
linux-kernel, Andrew Lunn, Eric Dumazet, linux-mediatek,
Daniel Golle, Matthias Brugger, Paolo Abeni, Lorenzo Bianconi,
David S. Miller, linux-arm-kernel, Felix Fietkau
In-Reply-To: <20260509190938.169290-4-linux@fw-web.de>
On Sat, 9 May 2026 21:09:32 +0200 Frank Wunderlich wrote:
> + mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i)));
> + napi_synchronize(ð->rx_napi[MTK_HW_LRO_RING(eth, i)].napi);
> + napi_disable(ð->rx_napi[MTK_HW_LRO_RING(eth, i)].napi);
What purpose that napi_synchronize() serve?
Also we don't charge for temporary variables, maybe save that
MTK_HW_LRO_RING(eth, i) to make this slightly more readable.
^ permalink raw reply
* Re: [net-next v8 3/3] net: ethernet: mtk_eth_soc: Add LRO support
From: Jakub Kicinski @ 2026-05-14 1:52 UTC (permalink / raw)
To: linux
Cc: Jakub Kicinski, nbd, lorenzo, andrew+netdev, davem, edumazet,
pabeni, matthias.bgg, angelogioacchino.delregno, linux,
mason-cw.chang, netdev, linux-kernel, daniel, linux-mediatek,
linux-arm-kernel
In-Reply-To: <20260509190938.169290-4-linux@fw-web.de>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
Subject: net: ethernet: mtk_eth_soc: Add LRO support
This patch adds Hardware Large Receive Offload support to the
mediatek ethernet driver and enables it on MT7988 by adding
MTK_HWLRO to MT7988_CAPS. The patch parameterizes the LRO
register accessors and ring counts on the SoC version, and adds
LRO-specific NAPI/IRQ wiring.
A few questions on the changes below.
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index 908fd88287ac..8035fc2557de 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -2806,7 +2806,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
> if (!ring->data)
> return -ENOMEM;
>
> - if (mtk_page_pool_enabled(eth)) {
> + if (mtk_page_pool_enabled(eth) && rcu_access_pointer(eth->prog)) {
> struct page_pool *pp;
>
> pp = mtk_create_page_pool(eth, &ring->xdp_q, ring_no,
[High]
Could the rationale for this gating change be explained in the commit
message? The subject is "Add LRO support" but this hunk changes the
page_pool creation policy for every netsys v2+ chip.
Before the patch, every v2+ RX ring was backed by a page_pool (since
mtk_page_pool_enabled() returns mtk_is_netsys_v2_or_greater(eth)).
After the patch, a page_pool is only created when an XDP program is
already attached at ring allocation time.
mtk_xdp_setup() also rejects XDP attach with -EOPNOTSUPP when
eth->hwlro is true:
if (eth->hwlro) {
NL_SET_ERR_MSG_MOD(extack, "HW LRO and XDP are mutually exclusive");
return -EOPNOTSUPP;
}
So on MT7988 (where this patch enables MTK_HWLRO) eth->prog is
permanently NULL and mtk_create_page_pool() is now never reached
for any RX ring, including the non-LRO ring 0.
Does this intentionally disable page_pool/DMA buffer recycling on
MT7988, and on every other v2+ chip until a BPF program is loaded?
mtk_ethtool_pp_stats() depends on ring->page_pool, so the page-pool
counters reported through ethtool would also become empty.
The driver still advertises NETDEV_XDP_ACT_BASIC|REDIRECT|NDO_XMIT|
NDO_XMIT_SG via xdp_features for v2+, which appears to diverge from
the buffer-pool capability after this change.
> @@ -2974,30 +2975,50 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth)
> ring_ctrl_dw2 |= MTK_RING_MAX_AGG_CNT_L;
> ring_ctrl_dw3 |= MTK_RING_MAX_AGG_CNT_H;
>
> - for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) {
> + for (i = 1; i <= MTK_HW_LRO_RING_NUM(eth); i++) {
> mtk_w32(eth, ring_ctrl_dw1, MTK_LRO_CTRL_DW1_CFG(reg_map, i));
[ ... ]
> /* set refresh timer for altering flows to 1 sec. (unit: 20us) */
> mtk_w32(eth, (MTK_HW_LRO_TIMER_UNIT << 16) | MTK_HW_LRO_REFRESH_TIME,
> MTK_PDMA_LRO_ALT_REFRESH_TIMER);
[Medium]
Should MTK_PDMA_LRO_ALT_REFRESH_TIMER also have been converted to
go through reg_map like every other LRO register touched by this
patch? Looking at the header, it is still defined as a hardcoded
absolute offset 0x1c that has lived in the v1 PDMA window since
2016. On MT7988 (newly added to MTK_HWLRO via MT7988_CAPS) the
LRO block lives at 0x6c08-0x6c44 per mt7988_reg_map, while offset
0x1c on v3 falls in the Frame Engine register area between
MTK_FE_INT_ENABLE and MTK_FE_INT_GRP.
Every other LRO register access in this function was switched to
MTK_PDMA_LRO_CTRL_DW0(reg_map), MTK_PDMA_LRO_ALT_SCORE_DELTA(reg_map),
MTK_LRO_DIP_DW0_CFG(reg_map, x) and so on. Was the omission of
this one register intentional, or should it be a similar
reg_map-based accessor so that on MT7988 the auto-learn refresh
timer is programmed in the LRO block instead of in the FE engine
region?
> - /* set HW LRO mode & the max aggregation count for rx packets */
> - lro_ctrl_dw3 |= MTK_ADMA_MODE | (MTK_HW_LRO_MAX_AGG_CNT & 0xff);
> + if (mtk_is_netsys_v3_or_greater(eth)) {
[ ... ]
> /* enable HW LRO */
> lro_ctrl_dw0 |= MTK_LRO_EN;
>
> - mtk_w32(eth, lro_ctrl_dw3, MTK_PDMA_LRO_CTRL_DW3);
> - mtk_w32(eth, lro_ctrl_dw0, MTK_PDMA_LRO_CTRL_DW0);
> + mtk_w32(eth, lro_ctrl_dw3, MTK_PDMA_LRO_CTRL_DW3(reg_map));
> + mtk_w32(eth, lro_ctrl_dw0, MTK_PDMA_LRO_CTRL_DW0(reg_map));
> +
> + if (mtk_is_netsys_v2_or_greater(eth)) {
> + i = (soc->rx.desc_size == sizeof(struct mtk_rx_dma_v2)) ? 1 : 0;
> + mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i)),
> + MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i)), reg_map->pdma.int_grp);
> + mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i + 1)),
> + MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i + 1)),
> + reg_map->pdma.int_grp + 0x4);
> + mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i + 2)),
> + MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i + 2)), reg_map->pdma.int_grp3);
> + }
[Medium]
On v3 (the only chip with both MTK_HWLRO and v2+ enabled by this
patch), the desc_size check yields i = 1, so this block routes
MTK_HW_LRO_RING(eth, 1..3) — physical rings 5, 6, 7 with done bits
BIT(29..31) — into int_grp, int_grp+0x4 and int_grp3 respectively.
What routes MTK_HW_LRO_RING(eth, 0), i.e. physical ring 4 with done
bit BIT(28)?
mtk_probe() registers an IRQ handler for all MTK_HW_LRO_RING_NUM(eth)
= 4 LRO rings using IRQF_SHARED, so a NAPI is attached for ring 4 on
eth->irq_pdma[MTK_HW_LRO_IRQ(eth, 0)] (= irq_pdma[0] on v3). Without
ring 4's BIT(28) being OR'd into any int_grp register, does ring 4's
RX interrupt actually reach NAPI, or does that depend on hardware
reset defaults of int_grp on MT7988?
> return 0;
> }
> @@ -3080,6 +3112,65 @@ static int mtk_hwlro_get_ip_cnt(struct mtk_mac *mac)
> return cnt;
> }
>
> +static int mtk_hwlro_add_ipaddr_idx(struct net_device *dev, u32 ip4dst)
> +{
> + struct mtk_mac *mac = netdev_priv(dev);
> + const struct mtk_reg_map *reg_map;
> + struct mtk_eth *eth = mac->hw;
> + u32 reg_val;
> + int i;
> +
> + reg_map = eth->soc->reg_map;
> +
> + /* check for duplicate IP address in the current DIP list */
> + for (i = 1; i <= MTK_HW_LRO_DIP_NUM(eth); i++) {
> + reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(reg_map, i));
> + if (reg_val == ip4dst)
> + break;
> + }
> +
> + if (i < MTK_HW_LRO_DIP_NUM(eth) + 1) {
> + netdev_warn(dev, "Duplicate IP address at DIP(%d)!\n", i);
> + return -EEXIST;
> + }
> +
> + /* find out available DIP index */
> + for (i = 1; i <= MTK_HW_LRO_DIP_NUM(eth); i++) {
> + reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(reg_map, i));
> + if (reg_val == 0UL)
> + break;
> + }
> +
> + if (i >= MTK_HW_LRO_DIP_NUM(eth) + 1) {
> + netdev_warn(dev, "DIP index is currently out of resource!\n");
> + return -EBUSY;
> + }
> +
> + return i;
> +}
[High]
Is it intentional that the DIP-table allocation policy is changed
from a per-MAC partition (previously hwlro_idx = mac->id *
MTK_MAX_LRO_IP_CNT + fsp->location) to a single global pool searched
across all MACs? The duplicate check and free-slot search above
both iterate every DIP register without scoping by mac->id.
Two observations:
1. Two netdevs that both want HW LRO on the same destination IP
collide on the duplicate-check and the second one fails with
-EEXIST. A single MAC can also fill all DIP slots and starve
the other; non-v3 silicon has only 3 slots while the uAPI
advertises 2 MACs * MTK_MAX_LRO_IP_CNT = 4 rules.
2. mtk_hwlro_add_ipaddr() (below) does not invalidate any
pre-existing entry at mac->hwlro_ip[fsp->location] before
calling this helper, so adding a new IP at a location that
already had one finds a fresh slot for the new IP and then
overwrites the software state. The old slot still has the
original IP with MYIP_VLD set in hardware, and a later del at
the same location only finds and invalidates the new entry.
Together they look like a CAP_NET_ADMIN-reachable way to leak DIP
slots until device reset, while mac->hwlro_ip[] looks consistent.
> +static int mtk_hwlro_get_ipaddr_idx(struct net_device *dev, u32 ip4dst)
> +{
> + struct mtk_mac *mac = netdev_priv(dev);
> + struct mtk_eth *eth = mac->hw;
> + u32 reg_val;
> + int i;
> +
> + /* find out DIP index that matches the given IP address */
> + for (i = 1; i <= MTK_HW_LRO_DIP_NUM(eth); i++) {
> + reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(eth->soc->reg_map, i));
> + if (reg_val == ip4dst)
> + break;
> + }
> +
> + if (i >= MTK_HW_LRO_DIP_NUM(eth) + 1) {
> + netdev_warn(dev, "DIP address is not exist!\n");
> + return -ENOENT;
> + }
> +
> + return i;
> +}
> +
> static int mtk_hwlro_add_ipaddr(struct net_device *dev,
> struct ethtool_rxnfc *cmd)
> {
> @@ -3112,13 +3207,17 @@ static int mtk_hwlro_del_ipaddr(struct net_device *dev,
> struct mtk_mac *mac = netdev_priv(dev);
> struct mtk_eth *eth = mac->hw;
> int hwlro_idx;
> + u32 ip4dst;
>
> if (fsp->location > 1)
> return -EINVAL;
>
> - mac->hwlro_ip[fsp->location] = 0;
> - hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location;
> + ip4dst = mac->hwlro_ip[fsp->location];
> + hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, ip4dst);
> + if (hwlro_idx < 0)
> + return hwlro_idx;
>
> + mac->hwlro_ip[fsp->location] = 0;
> mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac);
>
> mtk_hwlro_inval_ipaddr(eth, hwlro_idx);
[Medium]
Should this path validate that mac->hwlro_ip[fsp->location] is
non-zero before passing it to mtk_hwlro_get_ipaddr_idx()? When the
location was never populated (or was already deleted), ip4dst is 0.
mtk_hwlro_get_ipaddr_idx() then matches the first slot whose register
reads 0 — i.e. an arbitrary unrelated empty slot — and returns a
positive index, after which mtk_hwlro_inval_ipaddr() clears MYIP_VLD
on that unrelated slot and the call returns 0 to userspace.
Either rejecting the call with -ENOENT here when
mac->hwlro_ip[fsp->location] == 0, or having mtk_hwlro_get_ipaddr_idx()
refuse ip4dst == 0, would avoid that.
> @@ -3126,6 +3225,24 @@ static int mtk_hwlro_del_ipaddr(struct net_device *dev,
> return 0;
> }
>
> +static void mtk_hwlro_netdev_enable(struct net_device *dev)
> +{
> + struct mtk_mac *mac = netdev_priv(dev);
> + struct mtk_eth *eth = mac->hw;
> + int i, hwlro_idx;
> +
> + for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
> + if (mac->hwlro_ip[i] == 0)
> + continue;
> +
> + hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, mac->hwlro_ip[i]);
> + if (hwlro_idx < 0)
> + continue;
> +
> + mtk_hwlro_val_ipaddr(eth, hwlro_idx, mac->hwlro_ip[i]);
> + }
> +}
> +
[Low]
This isn't a bug, but is mtk_hwlro_netdev_enable() reachable in
practice? It uses mtk_hwlro_get_ipaddr_idx(), which only succeeds
when the IP is already programmed in hardware. The only path that
disables LRO is mtk_hwlro_netdev_disable() below, which clears
mac->hwlro_ip[i] = 0 (so the first guard always continues) and also
invalidates the DIP entries. After ethtool -K lro off the IPs are
gone from both software and hardware, so the subsequent ethtool -K
lro on appears to do nothing.
If the intent is restore-on-re-enable, should the disable preserve
mac->hwlro_ip[] and/or should this enable path call
mtk_hwlro_add_ipaddr_idx() to allocate fresh slots?
> static void mtk_hwlro_netdev_disable(struct net_device *dev)
> {
> struct mtk_mac *mac = netdev_priv(dev);
> @@ -3133,8 +3250,14 @@ static void mtk_hwlro_netdev_disable(struct net_device *dev)
> int i, hwlro_idx;
>
> for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
> + if (mac->hwlro_ip[i] == 0)
> + continue;
> +
> + hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, mac->hwlro_ip[i]);
> + if (hwlro_idx < 0)
> + continue;
> +
> mac->hwlro_ip[i] = 0;
> - hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + i;
>
> mtk_hwlro_inval_ipaddr(eth, hwlro_idx);
> }
[Medium]
Can this leave mac->hwlro_ip[i] populated while mac->hwlro_ip_cnt is
reset to 0? When mtk_hwlro_get_ipaddr_idx() returns < 0 (for example
because the DIP table was already cleared by a prior
mtk_hwlro_rx_uninit, by a parallel teardown on another MAC, or by a
hardware reset), the continue skips the mac->hwlro_ip[i] = 0
assignment. After the loop, mac->hwlro_ip_cnt = 0 still runs
unconditionally.
The previous code unconditionally cleared mac->hwlro_ip[i]. In the
new shape, ETHTOOL_GRXCLSRLCNT would report 0 while
ETHTOOL_GRXCLSRLALL via mtk_hwlro_get_fdir_all() still enumerates
the stale entries, and mtk_hwlro_get_ip_cnt() called from a later
add would recount them.
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> index 378cf47913ef..f7e7299fef6b 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> @@ -35,7 +35,7 @@
> #define MTK_DMA_SIZE(x) (SZ_##x)
> #define MTK_FQ_DMA_HEAD 32
> #define MTK_FQ_DMA_LENGTH 2048
> -#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN)
> +#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
> #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
[High]
Could this change be called out in the commit message? It widens
MTK_RX_ETH_HLEN from 18 to 26 globally for every supported chip,
not just MT7988/LRO.
mtk_add_mac() sets:
eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN;
(and MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN for MT7628), so the
maximum MTU advertised by every supported MediaTek SoC drops by 8
bytes (e.g. 2030 -> 2022 on the 2K path, 1518 -> 1510 on MT7628).
Userspace configuration that previously set MTU values up to the
prior limit will now be rejected with -EINVAL.
If headroom for stacked VLANs is needed only on the LRO path, would
it be possible to confine the +8 to MTK_MAX_LRO_RX_LENGTH instead
of changing MTK_RX_ETH_HLEN for every chip?
^ permalink raw reply
* Re: [net-next v8 2/3] net: ethernet: mtk_eth_soc: Add RSS support
From: Jakub Kicinski @ 2026-05-14 1:52 UTC (permalink / raw)
To: linux
Cc: Jakub Kicinski, nbd, lorenzo, andrew+netdev, davem, edumazet,
pabeni, matthias.bgg, angelogioacchino.delregno, linux,
mason-cw.chang, netdev, linux-kernel, daniel, linux-mediatek,
linux-arm-kernel
In-Reply-To: <20260509190938.169290-3-linux@fw-web.de>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
Subject: net: ethernet: mtk_eth_soc: Add RSS support
This commit adds Receive Side Scaling support for the mtk_eth_soc driver,
enabling up to four RX rings on MT7988 with ethtool -x and
--set-rxfh-indir support. It also reworks the RX NAPI / IRQ handling
into per-ring instances and renames eth->irq[] to eth->irq_fe[] /
eth->irq_pdma[].
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
[ ... ]
> @@ -2235,16 +2199,15 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
[ ... ]
> @@ -2436,7 +2399,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
> * we continue
> */
> wmb();
> - mtk_update_rx_cpu_idx(eth);
> + mtk_update_rx_cpu_idx(eth, ring);
> }
>
> eth->rx_packets += done;
[High]
With RSS enabled, up to MTK_RX_NAPI_NUM (=4) NAPI instances can run
concurrently on different CPUs. eth->rx_packets, eth->rx_bytes (here)
and eth->rx_events (incremented in mtk_handle_irq_rx with IRQF_SHARED)
are plain u32 fields with no atomic, no spinlock, and no per-CPU
storage:
eth->rx_packets += done;
eth->rx_bytes += bytes;
dim_update_sample(eth->rx_events, eth->rx_packets, eth->rx_bytes,
&dim_sample);
net_dim(ð->rx_dim, &dim_sample);
Pre-patch a single rx_napi serialised these accesses. Are these
unsynchronised cross-CPU updates intentional? The corrupted values
feed dim_update_sample() / net_dim() which drives interrupt
moderation, and eth->rx_dim is a single struct dim shared across all
RX NAPIs.
> @@ -2645,7 +2608,9 @@ static int mtk_napi_tx(struct napi_struct *napi, int budget)
>
> static int mtk_napi_rx(struct napi_struct *napi, int budget)
> {
> - struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi);
> + struct mtk_napi *rx_napi = container_of(napi, struct mtk_napi, napi);
> + struct mtk_eth *eth = rx_napi->eth;
> + struct mtk_rx_ring *ring = rx_napi->rx_ring;
> const struct mtk_reg_map *reg_map = eth->soc->reg_map;
> int rx_done_total = 0;
[Medium]
mtk_napi_rx() calls mtk_handle_status_irq(eth) on entry of every poll.
mtk_handle_status_irq() does an unprotected read / clear of
MTK_INT_STATUS2 and calls mtk_stats_update():
status2 = mtk_r32(eth, MTK_INT_STATUS2);
if (unlikely(status2 & (MTK_GDM1_AF | MTK_GDM2_AF))) {
mtk_stats_update(eth);
mtk_w32(eth, (MTK_GDM1_AF | MTK_GDM2_AF), MTK_INT_STATUS2);
}
With multiple rx_napi instances polling on different CPUs, can a fresh
AF event arriving between the read and the write be silently dropped,
or stats be double-counted? The per-MAC stats_lock taken inside
mtk_stats_update_mac does not synchronise the status read or the
clear.
[ ... ]
> @@ -3222,6 +3192,105 @@ static int mtk_hwlro_get_fdir_all(struct net_device *dev,
[ ... ]
> +static int mtk_rss_init(struct mtk_eth *eth)
> +{
> + const struct mtk_soc_data *soc = eth->soc;
> + const struct mtk_reg_map *reg_map = eth->soc->reg_map;
> + struct mtk_rss_params *rss_params = ð->rss_params;
> + u32 val;
> + int i;
> +
> + netdev_rss_key_fill(rss_params->hash_key, MTK_RSS_HASH_KEYSIZE);
> +
> + for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
> + rss_params->indirection_table[i] = ethtool_rxfh_indir_default(i, eth->soc->rss_num);
> +
> + if (soc->rx.desc_size == sizeof(struct mtk_rx_dma)) {
> + /* Set RSS rings to PSE modes */
> + for (i = 1; i <= MTK_HW_LRO_RING_NUM(eth); i++) {
> + val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
> + val |= MTK_RING_PSE_MODE;
> + mtk_w32(eth, val, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
> + }
> +
> + /* Enable non-lro multiple rx */
> + val = mtk_r32(eth, reg_map->pdma.lro_ctrl_dw0);
> + val |= MTK_NON_LRO_MULTI_EN;
> + mtk_w32(eth, val, reg_map->pdma.lro_ctrl_dw0);
> +
> + /* Enable RSS dly int supoort */
> + val |= MTK_LRO_DLY_INT_EN;
> + mtk_w32(eth, val, reg_map->pdma.lro_ctrl_dw0);
> + }
[Medium]
Is this block reachable on any SoC? mtk_rss_init() is only invoked
from mtk_dma_init() under MTK_HAS_CAPS(MTK_RSS). Only mt7988_data
sets MTK_RSS in caps, and mt7988_data uses
rx.desc_size = sizeof(struct mtk_rx_dma_v2), not
sizeof(struct mtk_rx_dma).
If the PSE-mode / MTK_NON_LRO_MULTI_EN / MTK_LRO_DLY_INT_EN
programming is needed on MT7988, is it being silently skipped? If it
was intended for mt7981 / mt7986, those SoCs never reach this path
because their caps lack MTK_RSS.
There is also a typo above: "RSS dly int supoort" -> "support".
[ ... ]
> + /* Set perRSS GRP INT */
> + mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(1)),
> + MTK_RX_DONE_INT(eth, MTK_RSS_RING(1)), reg_map->pdma.int_grp);
[ ... ]
> +
> + return 0;
> +}
[ ... ]
> @@ -3312,6 +3381,17 @@ static int mtk_dma_init(struct mtk_eth *eth)
[ ... ]
> + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
> + for (i = 1; i < MTK_RX_RSS_NUM(eth); i++) {
> + err = mtk_rx_alloc(eth, MTK_RSS_RING(i), MTK_RX_FLAGS_NORMAL);
> + if (err)
> + return err;
> + }
> + err = mtk_rss_init(eth);
> + if (err)
> + return err;
> + }
> +
[ ... ]
> @@ -3437,14 +3523,36 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth)
> return 0;
> }
>
> -static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
> +static int mtk_get_irqs_pdma(struct platform_device *pdev, struct mtk_eth *eth)
> {
> - struct mtk_eth *eth = _eth;
> + char rxring[] = "pdma0";
> + int i;
> +
> + for (i = 0; i < MTK_PDMA_IRQ_NUM; i++) {
> + rxring[4] = '0' + i;
> + eth->irq_pdma[i] = platform_get_irq_byname(pdev, rxring);
> + if (eth->irq_pdma[i] < 0)
> + return eth->irq_pdma[i];
> + }
> +
> + return 0;
> +}
[High]
This loop demands all four pdma0..pdma3 IRQs whenever
MTK_HAS_CAPS(MTK_PDMA_INT) is set, but the same patch adds
MTK_PDMA_INT to MT7981_CAPS and MT7986_CAPS — SoCs which do not
have MTK_RSS. On those SoCs only rx_napi[0] / pdma0 is ever
referenced (every pdma1..pdma3 use site is gated on
MTK_HAS_CAPS(MTK_RSS) in probe / open / stop / dma_init / dma_free).
Existing MT7981 / MT7986 device trees declare only fe1 / fe2. Does
this turn into a probe-time -ENXIO failure for those boards? Should
the call to mtk_get_irqs_pdma(), or at least the requests for
pdma1..pdma3, be folded under MTK_HAS_CAPS(MTK_RSS) so older DTs
continue to probe?
> +
> +static irqreturn_t mtk_handle_irq_rx(int irq, void *priv)
> +{
> + struct mtk_napi *rx_napi = priv;
> + struct mtk_eth *eth = rx_napi->eth;
> + struct mtk_rx_ring *ring = rx_napi->rx_ring;
>
> eth->rx_events++;
> - if (likely(napi_schedule_prep(ð->rx_napi))) {
> - mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask);
> - __napi_schedule(ð->rx_napi);
> + if (unlikely(!(mtk_r32(eth, eth->soc->reg_map->pdma.irq_status) &
> + mtk_r32(eth, eth->soc->reg_map->pdma.irq_mask) &
> + MTK_RX_DONE_INT(eth, ring->ring_no))))
> + return IRQ_NONE;
[High]
Pre-patch mt7988_data set rx.irq_done_mask = MTK_RX_DONE_INT_V2 =
BIT(14). Post-patch the per-soc field is removed and replaced with
MTK_RX_DONE_INT(eth, ring_no), which for V3 (mt7988) expands to
BIT(24 + ring_no), so MTK_RX_DONE_INT(eth, 0) is now BIT(24) instead
of BIT(14).
Is the bit number change intentional? If MT7988 RX-done is actually
signalled on BIT(14), the new mask never matches, mtk_handle_irq_rx
returns IRQ_NONE, and RX traffic stalls. If BIT(14) was wrong all
along, could the commit message describe the silent fix? The patch
otherwise advertises only RSS.
[ ... ]
> @@ -3888,9 +4011,7 @@ static void mtk_dim_rx(struct work_struct *work)
[ ... ]
> - val = mtk_r32(eth, reg_map->pdma.delay_irq);
> - val &= MTK_PDMA_DELAY_TX_MASK;
> - val |= MTK_PDMA_DELAY_RX_EN;
> + val = MTK_PDMA_DELAY_RX_EN;
[ ... ]
> - mtk_w32(eth, val, reg_map->pdma.delay_irq);
> if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
> - mtk_w32(eth, val, reg_map->qdma.delay_irq);
> + mtk_m32(eth, MTK_PDMA_DELAY_TX_MASK,
> + val << MTK_PDMA_DELAY_TX_PTIME_SHIFT, reg_map->qdma.delay_irq);
> +
> + if (eth->soc->rx.desc_size == sizeof(struct mtk_rx_dma)) {
> + mtk_m32(eth, MTK_PDMA_DELAY_RX_MASK, val, reg_map->pdma.delay_irq);
> + mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int);
> + mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int + 0x4);
> + mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int + 0x8);
> + } else {
> + val = val | (val << MTK_PDMA_DELAY_RX_RING_SHIFT);
> + mtk_w32(eth, val, reg_map->pdma.rx_delay_irq);
> + }
[Critical]
The new branch is gated on rx.desc_size, not on a capability bit.
rt5350_data (MT7628) has rx.desc_size = sizeof(struct mtk_rx_dma) and
uses mt7628_reg_map, which does not initialise lro_rx1_dly_int (it
defaults to 0).
mtk_hw_init() calls mtk_dim_rx(ð->rx_dim.work) inside the MT7628
branch, and net_dim invokes it again on every moderation update. Each
call therefore performs:
mtk_w32(eth, val, 0);
mtk_w32(eth, val, 0x4);
mtk_w32(eth, val, 0x8);
These offsets land in the Frame Engine global config region
(MTK_FE_GLO_CFG(0) = 0x00 etc.) instead of any LRO/RSS register, with
val containing MTK_PDMA_DELAY_RX_EN = BIT(15). Can this corrupt
MT7628 frame-engine state on every boot and every NAPI moderation
update? Should the branch be gated on MTK_HWLRO or MTK_RSS rather
than on rx.desc_size?
[Medium]
On V3 hardware (the only chip enabling RSS) only two ring slots are
programmed here:
val = val | (val << MTK_PDMA_DELAY_RX_RING_SHIFT);
mtk_w32(eth, val, reg_map->pdma.rx_delay_irq);
With MTK_PDMA_DELAY_RX_RING_SHIFT = 16 the register holds two rings,
but RSS uses MTK_RX_RSS_NUM(eth) = 4 rings. Do rings 2 and 3 ever
receive DIM-driven moderation updates after probe, or do they stay at
the hardware default?
[ ... ]
> @@ -4149,6 +4285,25 @@ static void mtk_hw_reset_monitor_work(struct work_struct *work)
[ ... ]
> +static int mtk_napi_init(struct mtk_eth *eth)
> +{
[ ... ]
> +}
[ ... ]
> @@ -4238,12 +4393,11 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset)
[ ... ]
> @@ -4700,8 +4860,13 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
>
> static u32 mtk_get_rx_ring_count(struct net_device *dev)
> {
> + struct mtk_mac *mac = netdev_priv(dev);
> + struct mtk_eth *eth = mac->hw;
> +
> if (dev->hw_features & NETIF_F_LRO)
> return MTK_MAX_RX_RING_NUM;
> + else if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS))
> + return MTK_RX_RSS_NUM(eth);
>
> return 0;
> }
[ ... ]
> @@ -4784,6 +4949,70 @@ static int mtk_set_eee(struct net_device *dev, struct ethtool_keee *eee)
[ ... ]
> +static int mtk_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
> + struct netlink_ext_ack *extack)
> +{
> + struct mtk_mac *mac = netdev_priv(dev);
> + struct mtk_eth *eth = mac->hw;
> + struct mtk_rss_params *rss_params = ð->rss_params;
> + const struct mtk_reg_map *reg_map = eth->soc->reg_map;
> + int i;
> +
> + if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
> + rxfh->hfunc != ETH_RSS_HASH_TOP)
> + return -EOPNOTSUPP;
> +
> + if (rxfh->key) {
> + memcpy(rss_params->hash_key, rxfh->key,
> + sizeof(rss_params->hash_key));
> + for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++)
> + mtk_w32(eth, rss_params->hash_key[i],
> + MTK_RSS_HASH_KEY_DW(reg_map, i));
> + }
> +
> + if (rxfh->indir) {
> + for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
> + rss_params->indirection_table[i] = rxfh->indir[i];
> + for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++)
> + mtk_w32(eth, mtk_rss_indr_table(rss_params, i),
> + MTK_RSS_INDR_TABLE_DW(reg_map, i));
> + }
> +
> + return 0;
> +}
[High]
Should this op (and .get_rxfh / .get_rxfh_key_size /
.get_rxfh_indir_size) be gated on MTK_HAS_CAPS(MTK_RSS)? As written,
mtk_ethtool_ops exposes them unconditionally for every SoC the driver
supports.
MTK_RSS_HASH_KEY_DW(reg_map, x) and MTK_RSS_INDR_TABLE_DW(reg_map, x)
are computed as (reg_map)->pdma.rss_glo_cfg + 0x20 + ... and + 0x50 +
... . mtk_reg_map (mt2701/mt7621/mt7622/mt7623/mt7629) and
mt7628_reg_map do not initialise rss_glo_cfg, so it defaults to 0.
A CAP_NET_ADMIN user invoking ethtool -X dev hkey ... on those SoCs
would write user-controlled u32 values into absolute frame-engine
offsets 0x20..0x44 (and indirection writes to 0x50..0x6c). Can these
ops be made conditional on MTK_RSS, or filled in only for the RSS-
capable SoC?
[Medium]
mtk_set_rxfh() does not validate user-supplied indir[i] entries
against MTK_RX_RSS_NUM(eth). The packing helper allots only 2 bits
per entry:
val |= (rss_params->indirection_table[i] << (2 * (i % 16)));
ethtool core only enforces indir[i] < num_rx_rings when
num_rx_rings is non-zero, and MTK_RSS hardware has at most 4 rings.
Should the driver reject values >= MTK_RX_RSS_NUM(eth) so they don't
silently bleed across the 2-bit slots in the packed register? The
indirection table also stores the raw u32 into a u8 field, which
truncates 4..255 instead of catching them.
[Medium]
mtk_rss_init() wraps key / indirection writes with an
MTK_RSS_CFG_REQ pause / release handshake:
/* Pause */
val |= MTK_RSS_CFG_REQ;
mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
...
/* Release pause */
val &= ~(MTK_RSS_CFG_REQ);
mtk_set_rxfh() writes the same registers at runtime without that
handshake. Can the hardware sample partially-updated key /
indirection state and steer packets to incorrect or out-of-range
rings while the write loop is in flight?
[ ... ]
> @@ -5424,6 +5708,7 @@ static const struct mtk_soc_data mt2701_data = {
[ ... entries for mt2701/mt7621/mt7622/mt7623/mt7629/rt5350 ... ]
> @@ -5567,16 +5851,16 @@ static const struct mtk_soc_data mt7981_data = {
[ ... ]
> .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
> + .rss_num = 4,
[ ... ]
> @@ -5597,6 +5881,7 @@ static const struct mtk_soc_data mt7986_data = {
[ ... ]
> .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
> + .rss_num = 4,
[Low]
mt7981_data and mt7986_data set rss_num = 4, but MT7981_CAPS and
MT7986_CAPS do not include MTK_RSS (only MT7988_CAPS does). Every
RSS code path is gated on MTK_HAS_CAPS(MTK_RSS) before consulting
rss_num, so this has no current effect, but the SoC capability table
becomes internally inconsistent. Should rss_num be 0 on these SoCs
until MTK_RSS is actually wired up and tested for them?
> @@ -5627,20 +5911,20 @@ static const struct mtk_soc_data mt7988_data = {
[ ... ]
> .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE,
> + .rss_num = 4,
[ ... ]
> .rx = {
> .desc_size = sizeof(struct mtk_rx_dma_v2),
> - .irq_done_mask = MTK_RX_DONE_INT_V2,
> .dma_l4_valid = RX_DMA_L4_VALID_V2,
> .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
> .dma_len_offset = 8,
> - .dma_size = MTK_DMA_SIZE(2K),
> + .dma_size = MTK_DMA_SIZE(1K),
> },
> };
[ ... ]
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCH] dt-bindings: PCI: mediatek-gen3: Allow memory-region for restricted DMA buffer
From: Rob Herring @ 2026-05-13 23:15 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Ryder Lee,
Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Bjorn Helgaas, Krzysztof Kozlowski,
Conor Dooley, devicetree, linux-pci, linux-mediatek, linux-kernel
In-Reply-To: <20260508063633.3894348-1-wenst@chromium.org>
On Fri, May 08, 2026 at 02:36:32PM +0800, Chen-Yu Tsai wrote:
> On some SoCs without an IOMMU behind the PCIe controller, the PCIe
> controller memory access could be limited to a small region by the
> firmware configuring a memory protection unit. This memory region
> must be assigned to the PCIe controller so that the OS knows to
> use that region. Otherwise PCIe devices would not work properly.
>
What you are describing is dma-ranges. Why not use that?
> Allow the memory-region property with one item pointing to a
> restricted DMA buffer.
>
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
> ---
> This patch compliments another patch that moved the memory-region from
> the PCIe device to the PCIe controller [1].
>
> [1] https://lore.kernel.org/all/20260430120725.241779-1-wenst@chromium.org/
>
> Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
> index 4db700fc36ba..4a9e41d01628 100644
> --- a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
> +++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
> @@ -115,6 +115,10 @@ properties:
> power-domains:
> maxItems: 1
>
> + memory-region:
> + maxItems: 1
> + description: phandle to restricted DMA buffer
> +
> mediatek,pbus-csr:
> $ref: /schemas/types.yaml#/definitions/phandle-array
> items:
> --
> 2.54.0.563.g4f69b47b94-goog
>
^ permalink raw reply
* Re: [PATCH v6 2/2] PCI: mediatek: Add support for EcoNet EN7528 SoC
From: Caleb James DeLisle @ 2026-05-13 22:17 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: linux-pci, linux-mips, naseefkm, ryder.lee, lpieralisi,
kwilczynski, mani, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, ansuelsmth, linux-mediatek, devicetree,
linux-kernel
In-Reply-To: <20260513220610.GA341225@bhelgaas>
On 14/05/2026 00:06, Bjorn Helgaas wrote:
> On Wed, May 13, 2026 at 11:39:25PM +0200, Caleb James DeLisle wrote:
>> On 13/05/2026 23:07, Bjorn Helgaas wrote:
>>> On Wed, May 13, 2026 at 07:16:52PM +0000, Caleb James DeLisle wrote:
>>>> Add support for the PCIe present on the EcoNet EN7528 (and EN751221) SoCs.
>>>>
>>>> These SoCs have a mix of Gen1 and Gen2 capable ports, but the Gen2 ports
>>>> require re-training after startup.
>>>> +found_port:
>>>> + if (!IS_BUILTIN(CONFIG_PCIE_MEDIATEK)) {
>>>> + /* Let it go because the device will work as Gen1 */
>>>> + dev_warn(dev, "module must be built-in to retrain to Gen2\n");
>>> I suppose this will cause a warning even in cases where Gen2 is
>>> impossible, e.g., the endpoint only supports Gen1?
>> Correct indeed.
>>
>> I imagine in most cases, if the port is Gen1 only then board integrator uses
>> a Gen1 card as well, so I could try being fancy and probe the card to see if
>> it supports Gen2. In OpenWrt the PCI driver is always built-in so I didn't
>> really consider this something to worry about.
> Probing the downstream device sounds like overkill because it hasn't
> been enumerated yet and there's no good place to check after it is
> enumerated. I would consider just logging one message as "info"
> instead of "warn", maybe in mtk_pcie_startup_port_en7528()?
Works for me, worth noting if anybody adds a startup for another device
which has this quirk, they'll also need to copy the log line - but it's
highly likely that no other such device exists, and duplicating 3 lines
of code is not the end of the world.
Thanks,
Caleb
^ permalink raw reply
* Re: [PATCH v6 2/2] PCI: mediatek: Add support for EcoNet EN7528 SoC
From: Bjorn Helgaas @ 2026-05-13 22:06 UTC (permalink / raw)
To: Caleb James DeLisle
Cc: linux-pci, linux-mips, naseefkm, ryder.lee, lpieralisi,
kwilczynski, mani, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, ansuelsmth, linux-mediatek, devicetree,
linux-kernel
In-Reply-To: <65792ada-5e9d-4e3f-aa79-bb4a8ffd9161@cjdns.fr>
On Wed, May 13, 2026 at 11:39:25PM +0200, Caleb James DeLisle wrote:
> On 13/05/2026 23:07, Bjorn Helgaas wrote:
> > On Wed, May 13, 2026 at 07:16:52PM +0000, Caleb James DeLisle wrote:
> > > Add support for the PCIe present on the EcoNet EN7528 (and EN751221) SoCs.
> > >
> > > These SoCs have a mix of Gen1 and Gen2 capable ports, but the Gen2 ports
> > > require re-training after startup.
> > > +found_port:
> > > + if (!IS_BUILTIN(CONFIG_PCIE_MEDIATEK)) {
> > > + /* Let it go because the device will work as Gen1 */
> > > + dev_warn(dev, "module must be built-in to retrain to Gen2\n");
> >
> > I suppose this will cause a warning even in cases where Gen2 is
> > impossible, e.g., the endpoint only supports Gen1?
>
> Correct indeed.
>
> I imagine in most cases, if the port is Gen1 only then board integrator uses
> a Gen1 card as well, so I could try being fancy and probe the card to see if
> it supports Gen2. In OpenWrt the PCI driver is always built-in so I didn't
> really consider this something to worry about.
Probing the downstream device sounds like overkill because it hasn't
been enumerated yet and there's no good place to check after it is
enumerated. I would consider just logging one message as "info"
instead of "warn", maybe in mtk_pcie_startup_port_en7528()?
^ permalink raw reply
* Re: [PATCH v6 2/2] PCI: mediatek: Add support for EcoNet EN7528 SoC
From: Caleb James DeLisle @ 2026-05-13 21:39 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: linux-pci, linux-mips, naseefkm, ryder.lee, lpieralisi,
kwilczynski, mani, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, ansuelsmth, linux-mediatek, devicetree,
linux-kernel
In-Reply-To: <20260513210759.GA331283@bhelgaas>
On 13/05/2026 23:07, Bjorn Helgaas wrote:
> On Wed, May 13, 2026 at 07:16:52PM +0000, Caleb James DeLisle wrote:
>> Add support for the PCIe present on the EcoNet EN7528 (and EN751221) SoCs.
>>
>> These SoCs have a mix of Gen1 and Gen2 capable ports, but the Gen2 ports
>> require re-training after startup.
> s/re-training/retraining/
OK
>
>> + * @MTK_PCIE_RETRAIN: Re-train link to bridge after startup because some
>> + * Gen2-capable devices start as Gen1.
> s/Re-train/Retrain/ to make this consistent and more greppable.
> Also more instances below.
OK
>
>> + * as Gen1, and must be re-trained once after initial configuration in order to
>> + * only Gen1 capable. Therefore it is most convenient to re-train every port
>> + return dev_err_probe(dev, ret, "root bridge not found\n");
> "Root bridge" is not a term used by the specs, but in common usage it
> refers to the host bridge, i.e., the RC. In this case, you didn't
> find a "Root Port".
OK Thanks
>
>> +found_port:
>> + if (!IS_BUILTIN(CONFIG_PCIE_MEDIATEK)) {
>> + /* Let it go because the device will work as Gen1 */
>> + dev_warn(dev, "module must be built-in to retrain to Gen2\n");
> I suppose this will cause a warning even in cases where Gen2 is
> impossible, e.g., the endpoint only supports Gen1?
Correct indeed.
I imagine in most cases, if the port is Gen1 only then board integrator
uses a Gen1 card as well, so I could try being fancy and probe the card
to see if it supports Gen2. In OpenWrt the PCI driver is always built-in
so I didn't really consider this something to worry about.
What's your preference?
Thanks,
Caleb
^ permalink raw reply
* Re: [PATCH v6 2/2] PCI: mediatek: Add support for EcoNet EN7528 SoC
From: Bjorn Helgaas @ 2026-05-13 21:07 UTC (permalink / raw)
To: Caleb James DeLisle
Cc: linux-pci, linux-mips, naseefkm, ryder.lee, lpieralisi,
kwilczynski, mani, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, ansuelsmth, linux-mediatek, devicetree,
linux-kernel
In-Reply-To: <20260513191652.3200607-3-cjd@cjdns.fr>
On Wed, May 13, 2026 at 07:16:52PM +0000, Caleb James DeLisle wrote:
> Add support for the PCIe present on the EcoNet EN7528 (and EN751221) SoCs.
>
> These SoCs have a mix of Gen1 and Gen2 capable ports, but the Gen2 ports
> require re-training after startup.
s/re-training/retraining/
> + * @MTK_PCIE_RETRAIN: Re-train link to bridge after startup because some
> + * Gen2-capable devices start as Gen1.
s/Re-train/Retrain/ to make this consistent and more greppable.
Also more instances below.
> + * as Gen1, and must be re-trained once after initial configuration in order to
> + * only Gen1 capable. Therefore it is most convenient to re-train every port
> + return dev_err_probe(dev, ret, "root bridge not found\n");
"Root bridge" is not a term used by the specs, but in common usage it
refers to the host bridge, i.e., the RC. In this case, you didn't
find a "Root Port".
> +found_port:
> + if (!IS_BUILTIN(CONFIG_PCIE_MEDIATEK)) {
> + /* Let it go because the device will work as Gen1 */
> + dev_warn(dev, "module must be built-in to retrain to Gen2\n");
I suppose this will cause a warning even in cases where Gen2 is
impossible, e.g., the endpoint only supports Gen1?
^ permalink raw reply
* Re: [PATCH 4/8] drm/panthor: Add support for protected memory allocation in panthor
From: Chia-I Wu @ 2026-05-13 19:31 UTC (permalink / raw)
To: Liviu Dudau
Cc: Boris Brezillon, Marcin Ślusarz, Ketil Johnsen, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Jonathan Corbet, Shuah Khan, Sumit Semwal,
Benjamin Gaignard, Brian Starkey, John Stultz, T.J. Mercier,
Christian König, Steven Price, Daniel Almeida, Alice Ryhl,
Matthias Brugger, AngeloGioacchino Del Regno, dri-devel,
linux-doc, linux-kernel, linux-media, linaro-mm-sig,
linux-arm-kernel, linux-mediatek, Florent Tomasin, nd
In-Reply-To: <agNJasayW8VCHTiU@e142607>
On Tue, May 12, 2026 at 8:39 AM Liviu Dudau <liviu.dudau@arm.com> wrote:
>
> On Tue, May 12, 2026 at 04:11:11PM +0200, Boris Brezillon wrote:
> > On Tue, 12 May 2026 14:47:27 +0100
> > Liviu Dudau <liviu.dudau@arm.com> wrote:
> >
> > > On Thu, May 07, 2026 at 01:53:56PM +0200, Boris Brezillon wrote:
> > > > On Thu, 7 May 2026 11:02:26 +0200
> > > > Marcin Ślusarz <marcin.slusarz@arm.com> wrote:
> > > >
> > > > > On Tue, May 05, 2026 at 06:15:23PM +0200, Boris Brezillon wrote:
> > > > > > > @@ -277,9 +286,21 @@ int panthor_device_init(struct panthor_device *ptdev)
> > > > > > > return ret;
> > > > > > > }
> > > > > > >
> > > > > > > + /* If a protected heap name is specified but not found, defer the probe until created */
> > > > > > > + if (protected_heap_name && strlen(protected_heap_name)) {
> > > > > >
> > > > > > Do we really need this strlen() > 0? Won't dma_heap_find() fail is the
> > > > > > name is "" already?
> > > > >
> > > > > If dma_heap_find() will fail, then the whole probe with fail too.
> > > > > This check prevents that.
> > > >
> > > > Yeah, that's also a questionable design choice. I mean, we can
> > > > currently probe and boot the FW even though we never setup the
> > > > protected FW sections, so why should we defer the probe here? Can't we
> > > > just retry the next time a group with the protected bit is created and
> > > > fail if we can find a protected heap?
> > >
> > > The problem we have with the current firmware is that it does a number of setup steps at "boot"
> > > time only. One of the steps is preparing its internal structures for when it enters protected
> > > mode and it stores them in the buffer passed in at firmware loading. We cannot later run the
> > > process when we have a group with protected mode set.
> >
> > No, but we can force a full/slow reset and have that thing
> > re-initialized, can't we? I mean, that's basically what we do when a
> > fast reset fails: we re-initialize all the sections and reset again, at
> > which point the FW should start from a fresh state, and be able to
> > properly initialize the protected-related stuff if protected sections
> > are populated. Am I missing something?
>
> Right, we can do that. For some reason I keep associating the reset with the
> error handling and not with "normal" operations.
I kind of hope we end up with either
- panthor knows the exact heap to use and fails with EPROBE_DEFER if
the heap is missing, or
- panthor gets a dma-buf from userspace and does the full reset
- userspace also needs to provide a dma-buf for each protected
group for the suspend buffer
than something in-between. The latter is more ad-hoc and basically
kicks the issue to the userspace.
For the former, expressing the relation in DT seems to be the best,
but only if possible :-). Otherwise, a kconfig option (instead of
module param) should be easier to work with.
Looking at the userspace implementation, can we also have an panthor
ioctl to return the heap to userspace? A dma-heap ioctl to query the
heap size is also lacking.
>
> Best regards,
> Liviu
>
>
> --
> ====================
> | I would like to |
> | fix the world, |
> | but they're not |
> | giving me the |
> \ source code! /
> ---------------
> ¯\_(ツ)_/¯
>
^ permalink raw reply
* [PATCH v2 2/2] arm64: dts: Add Airoha AN7583 SoC and AN7583 Evaluation Board
From: Lorenzo Bianconi @ 2026-05-13 19:21 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Felix Fietkau,
John Crispin, Matthias Brugger, AngeloGioacchino Del Regno
Cc: Christian Marangi, devicetree, linux-arm-kernel, linux-mediatek,
Lorenzo Bianconi
In-Reply-To: <20260513-airoha-7583-v2-0-ee0d82b37ce7@kernel.org>
Introduce the Airoha AN7583 SoC's dtsi and the Airoha AN7583 Evaluation
Board's dts file.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
arch/arm64/boot/dts/airoha/Makefile | 2 +-
arch/arm64/boot/dts/airoha/an7583-evb.dts | 23 ++++++
arch/arm64/boot/dts/airoha/an7583.dtsi | 133 ++++++++++++++++++++++++++++++
3 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/airoha/Makefile b/arch/arm64/boot/dts/airoha/Makefile
index ebea112ce1d7..6027978a35c2 100644
--- a/arch/arm64/boot/dts/airoha/Makefile
+++ b/arch/arm64/boot/dts/airoha/Makefile
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-dtb-$(CONFIG_ARCH_AIROHA) += en7581-evb.dtb
+dtb-$(CONFIG_ARCH_AIROHA) += en7581-evb.dtb an7583-evb.dtb
diff --git a/arch/arm64/boot/dts/airoha/an7583-evb.dts b/arch/arm64/boot/dts/airoha/an7583-evb.dts
new file mode 100644
index 000000000000..fa260f6e41c1
--- /dev/null
+++ b/arch/arm64/boot/dts/airoha/an7583-evb.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/dts-v1/;
+
+#include "an7583.dtsi"
+
+/ {
+ model = "Airoha AN7583 Evaluation Board";
+ compatible = "airoha,an7583-evb", "airoha,an7583";
+
+ aliases {
+ serial0 = &uart1;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200 earlycon";
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x20000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/airoha/an7583.dtsi b/arch/arm64/boot/dts/airoha/an7583.dtsi
new file mode 100644
index 000000000000..a82ed916e61d
--- /dev/null
+++ b/arch/arm64/boot/dts/airoha/an7583.dtsi
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ atf@80000000 {
+ no-map;
+ reg = <0x0 0x80000000 0x0 0x200000>;
+ };
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+
+ core1 {
+ cpu = <&cpu1>;
+ };
+ };
+ };
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x1>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ l2: l2-cache {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-level = <2>;
+ cache-unified;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ clk25m: clock-25000000 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ clock-output-names = "clkxtal";
+ };
+
+ i2c_clock: clock-20000000 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <20000000>;
+ clock-output-names = "i2c_clock";
+ };
+
+ sys_hclk: clock-100000000 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ clock-output-names = "sys_hclk";
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gic: interrupt-controller@9000000 {
+ compatible = "arm,gic-v3";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0x0 0x09000000 0x0 0x20000>,
+ <0x0 0x09080000 0x0 0x80000>,
+ <0x0 0x09400000 0x0 0x2000>,
+ <0x0 0x09500000 0x0 0x2000>,
+ <0x0 0x09600000 0x0 0x20000>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ uart1: serial@1fbf0000 {
+ compatible = "ns16550a";
+ reg = <0x0 0x1fbf0000 0x0 0x30>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <1843200>;
+ };
+
+ watchdog@1fbf0100 {
+ compatible = "airoha,an7583-wdt", "airoha,en7581-wdt";
+ reg = <0x0 0x1fbf0100 0x0 0x38>;
+
+ clocks = <&sys_hclk>;
+ clock-names = "bus";
+ };
+ };
+};
--
2.54.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox