]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
regulator: rtq2208: Fix incorrect buck converter phase mapping
authorChiYuan Huang <cy_huang@richtek.com>
Mon, 17 Mar 2025 10:06:21 +0000 (18:06 +0800)
committerMark Brown <broonie@kernel.org>
Mon, 17 Mar 2025 12:45:36 +0000 (12:45 +0000)
Use the hidden bank RG to get the correct buck converter phase mapping.

Fixes: 85a11f55621a ("regulator: rtq2208: Add Richtek RTQ2208 SubPMIC")
Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
Link: https://patch.msgid.link/ae3245aa713f76000dbd20b4ad6f66d30611d3b8.1742204502.git.cy_huang@richtek.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/regulator/rtq2208-regulator.c

index 5925fa7a9a06f0aa675bdc652bfbb58ee2b12462..2a2f6a54de11b1cd9db0ddd6639db040568207d6 100644 (file)
@@ -27,6 +27,9 @@
 #define RTQ2208_REG_LDO1_CFG                   0xB1
 #define RTQ2208_REG_LDO2_CFG                   0xC1
 #define RTQ2208_REG_LDO_DVS_CTRL               0xD0
+#define RTQ2208_REG_HIDDEN_BUCKPH              0x55
+#define RTQ2208_REG_HIDDEN0                    0xFE
+#define RTQ2208_REG_HIDDEN1                    0xFF
 
 /* Mask */
 #define RTQ2208_BUCK_NR_MTP_SEL_MASK           GENMASK(7, 0)
@@ -45,6 +48,8 @@
 #define RTQ2208_LDO1_VOSEL_SD_MASK             BIT(5)
 #define RTQ2208_LDO2_DISCHG_EN_MASK            BIT(6)
 #define RTQ2208_LDO2_VOSEL_SD_MASK             BIT(7)
+#define RTQ2208_MASK_BUCKPH_GROUP1             GENMASK(6, 4)
+#define RTQ2208_MASK_BUCKPH_GROUP2             GENMASK(2, 0)
 
 /* Size */
 #define RTQ2208_VOUT_MAXNUM                    256
@@ -524,27 +529,75 @@ static int rtq2208_parse_regulator_dt_data(int n_regulator, const unsigned int *
 
 }
 
-/** different slave address corresponds different used bucks
- * slave address 0x10: BUCK[BCA FGE]
- * slave address 0x20: BUCK[BC FGHE]
- * slave address 0x40: BUCK[C G]
- */
-static int rtq2208_regulator_check(int slave_addr, int *num,
+static int rtq2208_regulator_check(struct device *dev, int *num,
                                int *regulator_idx_table, unsigned int *buck_masks)
 {
-       static bool rtq2208_used_table[3][RTQ2208_LDO_MAX] = {
-               /* BUCK[BCA FGE], LDO[12] */
-               {1, 1, 0, 1, 1, 1, 0, 1, 1, 1},
-               /* BUCK[BC FGHE], LDO[12]*/
-               {1, 1, 0, 0, 1, 1, 1, 1, 1, 1},
-               /* BUCK[C G], LDO[12] */
-               {0, 1, 0, 0, 0, 1, 0, 0, 1, 1},
-       };
-       int i, idx = ffs(slave_addr >> 4) - 1;
+       struct regmap *regmap = dev_get_regmap(dev, NULL);
+       bool rtq2208_used_table[RTQ2208_LDO_MAX] = {0};
+       u8 entry_key[] = { 0x69, 0x01 };
+       unsigned int buck_phase;
+       int i, ret;
        u8 mask;
 
+       ret = regmap_raw_write(regmap, RTQ2208_REG_HIDDEN0, entry_key, ARRAY_SIZE(entry_key));
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to enter hidden page\n");
+
+       ret = regmap_read(regmap, RTQ2208_REG_HIDDEN_BUCKPH, &buck_phase);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to read buck phase configuration\n");
+
+       ret = regmap_write(regmap, RTQ2208_REG_HIDDEN1, 0x00);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to exit hidden page\n");
+
+       dev_info(dev, "BUCK Phase 0x%x\n", buck_phase);
+       /*
+        * Use buck phase configuration to assign used table mask
+        *                                 GROUP1       GROUP2
+        * 0      -> 2P + 2P                BC           FG
+        * 1      -> 2P + 1P + 1P           BCA          FGE
+        * 2      -> 1P + 1P + 1P + 1P      BCDA         FGHE
+        * 3      -> 3P + 1P                BC           FG
+        * others -> 4P                     C            G
+        */
+       switch (FIELD_GET(RTQ2208_MASK_BUCKPH_GROUP1, buck_phase)) {
+       case 2:
+               rtq2208_used_table[RTQ2208_BUCK_D] = true;
+               fallthrough;
+       case 1:
+               rtq2208_used_table[RTQ2208_BUCK_A] = true;
+               fallthrough;
+       case 0:
+       case 3:
+               rtq2208_used_table[RTQ2208_BUCK_B] = true;
+               fallthrough;
+       default:
+               rtq2208_used_table[RTQ2208_BUCK_C] = true;
+               break;
+       }
+
+       switch (FIELD_GET(RTQ2208_MASK_BUCKPH_GROUP2, buck_phase)) {
+       case 2:
+               rtq2208_used_table[RTQ2208_BUCK_F] = true;
+               fallthrough;
+       case 1:
+               rtq2208_used_table[RTQ2208_BUCK_E] = true;
+               fallthrough;
+       case 0:
+       case 3:
+               rtq2208_used_table[RTQ2208_BUCK_H] = true;
+               fallthrough;
+       default:
+               rtq2208_used_table[RTQ2208_BUCK_G] = true;
+               break;
+       }
+
+       /* By default, LDO1 & LDO2 are always used */
+       rtq2208_used_table[RTQ2208_LDO1] = rtq2208_used_table[RTQ2208_LDO2] = true;
+
        for (i = 0; i < RTQ2208_LDO_MAX; i++) {
-               if (!rtq2208_used_table[idx][i])
+               if (!rtq2208_used_table[i])
                        continue;
 
                regulator_idx_table[(*num)++] = i;
@@ -559,7 +612,7 @@ static int rtq2208_regulator_check(int slave_addr, int *num,
 static const struct regmap_config rtq2208_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
-       .max_register = 0xEF,
+       .max_register = 0xFF,
 };
 
 static int rtq2208_probe(struct i2c_client *i2c)
@@ -583,7 +636,7 @@ static int rtq2208_probe(struct i2c_client *i2c)
                return dev_err_probe(dev, PTR_ERR(regmap), "Failed to allocate regmap\n");
 
        /* get needed regulator */
-       ret = rtq2208_regulator_check(i2c->addr, &n_regulator, regulator_idx_table, buck_masks);
+       ret = rtq2208_regulator_check(dev, &n_regulator, regulator_idx_table, buck_masks);
        if (ret)
                return dev_err_probe(dev, ret, "Failed to check used regulators\n");