[PATCH] regulator: mt6363: Serialize BUCK_TOP key access

From: Alexandre Mergnat

Date: Mon Nov 09 2026 - 07:16:30 EST


The bits that select the FAST mode of the bucks only accept writes
while the BUCK_TOP key is unlocked. mt6363_regulator_set_mode() unlocks
the key, updates the bit and locks the key again, but the regulator
core only locks the buck being changed. When two bucks change mode at
the same time, one of them can lock the key between the unlock and
the mode write of the other. The PMIC then ignores that write, and
regulator_set_mode() returns 0 while the buck stays in its previous
mode. mt6363_va15_set_voltage_sel() unlocks and locks the same key,
so it can also lock it during a buck mode change.

Hold a mutex from each unlock of the key to its relock, in the FAST bit
writes and in the VA15 voltage setter.

Fixes: 3c36965df808 ("regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators")
Signed-off-by: Alexandre Mergnat <amergnat@xxxxxxxxxxxx>
---
The race was reproduced on hardware.

The new mutex is static because probe already stores per-device state
in the static regulator table, so the driver only supports one PMIC.
A follow-up series could make that table constant and move this state,
with the mutex, into per-device data.

This patch applies to the for-7.4 branch of the regulator tree, which
has the earlier fixes to this driver.
---
drivers/regulator/mt6363-regulator.c | 41 ++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 14 deletions(-)

diff --git a/drivers/regulator/mt6363-regulator.c b/drivers/regulator/mt6363-regulator.c
index e6c4bd851fef..8ade92c59864 100644
--- a/drivers/regulator/mt6363-regulator.c
+++ b/drivers/regulator/mt6363-regulator.c
@@ -12,6 +12,7 @@
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
@@ -114,6 +115,8 @@ struct mt6363_regulator_info {
int virq;
};

+static DEFINE_MUTEX(mt6363_buck_top_lock);
+
#define MT6363_BUCK(match, vreg, min, max, step, en_reg, lp_reg, \
mset_reg, ocp_intn) \
[MT6363_ID_##vreg] = { \
@@ -388,6 +391,23 @@ static int mt6363_buck_unlock(struct regmap *map, bool unlock)
return regmap_bulk_write(map, MT6363_BUCK_TOP_KEY_PROT_LO, &buf, sizeof(buf));
}

+static int mt6363_buck_top_update_bits(struct regmap *map, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ int ret;
+
+ guard(mutex)(&mt6363_buck_top_lock);
+
+ ret = mt6363_buck_unlock(map, true);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(map, reg, mask, val);
+
+ mt6363_buck_unlock(map, false);
+ return ret;
+}
+
static int mt6363_regulator_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
@@ -400,13 +420,9 @@ static int mt6363_regulator_set_mode(struct regulator_dev *rdev,

switch (mode) {
case REGULATOR_MODE_FAST:
- ret = mt6363_buck_unlock(regmap, true);
- if (ret)
- break;
-
- ret = regmap_set_bits(regmap, info->modeset_reg, info->modeset_mask);
-
- mt6363_buck_unlock(regmap, false);
+ ret = mt6363_buck_top_update_bits(regmap, info->modeset_reg,
+ info->modeset_mask,
+ info->modeset_mask);
break;
case REGULATOR_MODE_NORMAL:
cur_mode = mt6363_regulator_get_mode(rdev);
@@ -416,13 +432,8 @@ static int mt6363_regulator_set_mode(struct regulator_dev *rdev,
}

if (cur_mode == REGULATOR_MODE_FAST) {
- ret = mt6363_buck_unlock(regmap, true);
- if (ret)
- break;
-
- ret = regmap_clear_bits(regmap, info->modeset_reg, info->modeset_mask);
-
- mt6363_buck_unlock(regmap, false);
+ ret = mt6363_buck_top_update_bits(regmap, info->modeset_reg,
+ info->modeset_mask, 0);
break;
} else if (cur_mode == REGULATOR_MODE_IDLE) {
ret = regmap_clear_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
@@ -508,6 +519,8 @@ static int mt6363_va15_set_voltage_sel(struct regulator_dev *rdev, unsigned int
struct regmap *regmap = rdev->regmap;
int ret;

+ guard(mutex)(&mt6363_buck_top_lock);
+
ret = mt6363_buck_unlock(regmap, true);
if (ret)
return ret;

---
base-commit: 7904338c38426d72c5f7cd9402cb9a20232a7af5
change-id: 20261105-rgp-91-mt6363-key-lock-67b5992de5a8

Best regards,
--
Alexandre Mergnat <amergnat@xxxxxxxxxxxx>