.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,
};
.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,
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,
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,
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[] = {
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,
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,
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;
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);
/* 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;