1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2020 ROHM Semiconductors 3 // ROHM BD9576MUF/BD9573MUF regulator driver 4 5 #include <linux/delay.h> 6 #include <linux/err.h> 7 #include <linux/gpio/consumer.h> 8 #include <linux/interrupt.h> 9 #include <linux/kernel.h> 10 #include <linux/mfd/rohm-bd957x.h> 11 #include <linux/mfd/rohm-generic.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/platform_device.h> 15 #include <linux/regulator/driver.h> 16 #include <linux/regulator/machine.h> 17 #include <linux/regulator/of_regulator.h> 18 #include <linux/slab.h> 19 20 #define BD957X_VOUTS1_VOLT 3300000 21 #define BD957X_VOUTS4_BASE_VOLT 1030000 22 #define BD957X_VOUTS34_NUM_VOLT 32 23 24 static int vout1_volt_table[] = {5000000, 4900000, 4800000, 4700000, 4600000, 25 4500000, 4500000, 4500000, 5000000, 5100000, 26 5200000, 5300000, 5400000, 5500000, 5500000, 27 5500000}; 28 29 static int vout2_volt_table[] = {1800000, 1780000, 1760000, 1740000, 1720000, 30 1700000, 1680000, 1660000, 1800000, 1820000, 31 1840000, 1860000, 1880000, 1900000, 1920000, 32 1940000}; 33 34 static int voutl1_volt_table[] = {2500000, 2540000, 2580000, 2620000, 2660000, 35 2700000, 2740000, 2780000, 2500000, 2460000, 36 2420000, 2380000, 2340000, 2300000, 2260000, 37 2220000}; 38 39 struct bd957x_regulator_data { 40 struct regulator_desc desc; 41 int base_voltage; 42 }; 43 44 static int bd957x_vout34_list_voltage(struct regulator_dev *rdev, 45 unsigned int selector) 46 { 47 const struct regulator_desc *desc = rdev->desc; 48 int multiplier = selector & desc->vsel_mask & 0x7f; 49 int tune; 50 51 /* VOUT3 and 4 has 10mV step */ 52 tune = multiplier * 10000; 53 54 if (!(selector & 0x80)) 55 return desc->fixed_uV - tune; 56 57 return desc->fixed_uV + tune; 58 } 59 60 static int bd957x_list_voltage(struct regulator_dev *rdev, 61 unsigned int selector) 62 { 63 const struct regulator_desc *desc = rdev->desc; 64 int index = selector & desc->vsel_mask & 0x7f; 65 66 if (!(selector & 0x80)) 67 index += desc->n_voltages/2; 68 69 if (index >= desc->n_voltages) 70 return -EINVAL; 71 72 return desc->volt_table[index]; 73 } 74 75 static const struct regulator_ops bd957x_vout34_ops = { 76 .is_enabled = regulator_is_enabled_regmap, 77 .list_voltage = bd957x_vout34_list_voltage, 78 .get_voltage_sel = regulator_get_voltage_sel_regmap, 79 }; 80 81 static const struct regulator_ops bd957X_vouts1_regulator_ops = { 82 .is_enabled = regulator_is_enabled_regmap, 83 }; 84 85 static const struct regulator_ops bd957x_ops = { 86 .is_enabled = regulator_is_enabled_regmap, 87 .list_voltage = bd957x_list_voltage, 88 .get_voltage_sel = regulator_get_voltage_sel_regmap, 89 }; 90 91 static struct bd957x_regulator_data bd9576_regulators[] = { 92 { 93 .desc = { 94 .name = "VD50", 95 .of_match = of_match_ptr("regulator-vd50"), 96 .regulators_node = of_match_ptr("regulators"), 97 .id = BD957X_VD50, 98 .type = REGULATOR_VOLTAGE, 99 .ops = &bd957x_ops, 100 .volt_table = &vout1_volt_table[0], 101 .n_voltages = ARRAY_SIZE(vout1_volt_table), 102 .vsel_reg = BD957X_REG_VOUT1_TUNE, 103 .vsel_mask = BD957X_MASK_VOUT1_TUNE, 104 .enable_reg = BD957X_REG_POW_TRIGGER1, 105 .enable_mask = BD957X_REGULATOR_EN_MASK, 106 .enable_val = BD957X_REGULATOR_DIS_VAL, 107 .enable_is_inverted = true, 108 .owner = THIS_MODULE, 109 }, 110 }, 111 { 112 .desc = { 113 .name = "VD18", 114 .of_match = of_match_ptr("regulator-vd18"), 115 .regulators_node = of_match_ptr("regulators"), 116 .id = BD957X_VD18, 117 .type = REGULATOR_VOLTAGE, 118 .ops = &bd957x_ops, 119 .volt_table = &vout2_volt_table[0], 120 .n_voltages = ARRAY_SIZE(vout2_volt_table), 121 .vsel_reg = BD957X_REG_VOUT2_TUNE, 122 .vsel_mask = BD957X_MASK_VOUT2_TUNE, 123 .enable_reg = BD957X_REG_POW_TRIGGER2, 124 .enable_mask = BD957X_REGULATOR_EN_MASK, 125 .enable_val = BD957X_REGULATOR_DIS_VAL, 126 .enable_is_inverted = true, 127 .owner = THIS_MODULE, 128 }, 129 }, 130 { 131 .desc = { 132 .name = "VDDDR", 133 .of_match = of_match_ptr("regulator-vdddr"), 134 .regulators_node = of_match_ptr("regulators"), 135 .id = BD957X_VDDDR, 136 .ops = &bd957x_vout34_ops, 137 .type = REGULATOR_VOLTAGE, 138 .n_voltages = BD957X_VOUTS34_NUM_VOLT, 139 .vsel_reg = BD957X_REG_VOUT3_TUNE, 140 .vsel_mask = BD957X_MASK_VOUT3_TUNE, 141 .enable_reg = BD957X_REG_POW_TRIGGER3, 142 .enable_mask = BD957X_REGULATOR_EN_MASK, 143 .enable_val = BD957X_REGULATOR_DIS_VAL, 144 .enable_is_inverted = true, 145 .owner = THIS_MODULE, 146 }, 147 }, 148 { 149 .desc = { 150 .name = "VD10", 151 .of_match = of_match_ptr("regulator-vd10"), 152 .regulators_node = of_match_ptr("regulators"), 153 .id = BD957X_VD10, 154 .ops = &bd957x_vout34_ops, 155 .type = REGULATOR_VOLTAGE, 156 .fixed_uV = BD957X_VOUTS4_BASE_VOLT, 157 .n_voltages = BD957X_VOUTS34_NUM_VOLT, 158 .vsel_reg = BD957X_REG_VOUT4_TUNE, 159 .vsel_mask = BD957X_MASK_VOUT4_TUNE, 160 .enable_reg = BD957X_REG_POW_TRIGGER4, 161 .enable_mask = BD957X_REGULATOR_EN_MASK, 162 .enable_val = BD957X_REGULATOR_DIS_VAL, 163 .enable_is_inverted = true, 164 .owner = THIS_MODULE, 165 }, 166 }, 167 { 168 .desc = { 169 .name = "VOUTL1", 170 .of_match = of_match_ptr("regulator-voutl1"), 171 .regulators_node = of_match_ptr("regulators"), 172 .id = BD957X_VOUTL1, 173 .ops = &bd957x_ops, 174 .type = REGULATOR_VOLTAGE, 175 .volt_table = &voutl1_volt_table[0], 176 .n_voltages = ARRAY_SIZE(voutl1_volt_table), 177 .vsel_reg = BD957X_REG_VOUTL1_TUNE, 178 .vsel_mask = BD957X_MASK_VOUTL1_TUNE, 179 .enable_reg = BD957X_REG_POW_TRIGGERL1, 180 .enable_mask = BD957X_REGULATOR_EN_MASK, 181 .enable_val = BD957X_REGULATOR_DIS_VAL, 182 .enable_is_inverted = true, 183 .owner = THIS_MODULE, 184 }, 185 }, 186 { 187 .desc = { 188 .name = "VOUTS1", 189 .of_match = of_match_ptr("regulator-vouts1"), 190 .regulators_node = of_match_ptr("regulators"), 191 .id = BD957X_VOUTS1, 192 .ops = &bd957X_vouts1_regulator_ops, 193 .type = REGULATOR_VOLTAGE, 194 .n_voltages = 1, 195 .fixed_uV = BD957X_VOUTS1_VOLT, 196 .enable_reg = BD957X_REG_POW_TRIGGERS1, 197 .enable_mask = BD957X_REGULATOR_EN_MASK, 198 .enable_val = BD957X_REGULATOR_DIS_VAL, 199 .enable_is_inverted = true, 200 .owner = THIS_MODULE, 201 }, 202 }, 203 }; 204 205 static int bd957x_probe(struct platform_device *pdev) 206 { 207 struct regmap *regmap; 208 struct regulator_config config = { 0 }; 209 int i; 210 bool vout_mode, ddr_sel; 211 const struct bd957x_regulator_data *reg_data = &bd9576_regulators[0]; 212 unsigned int num_reg_data = ARRAY_SIZE(bd9576_regulators); 213 enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; 214 215 regmap = dev_get_regmap(pdev->dev.parent, NULL); 216 if (!regmap) { 217 dev_err(&pdev->dev, "No regmap\n"); 218 return -EINVAL; 219 } 220 vout_mode = of_property_read_bool(pdev->dev.parent->of_node, 221 "rohm,vout1-en-low"); 222 if (vout_mode) { 223 struct gpio_desc *en; 224 225 dev_dbg(&pdev->dev, "GPIO controlled mode\n"); 226 227 /* VOUT1 enable state judged by VOUT1_EN pin */ 228 /* See if we have GPIO defined */ 229 en = devm_gpiod_get_from_of_node(&pdev->dev, 230 pdev->dev.parent->of_node, 231 "rohm,vout1-en-gpios", 0, 232 GPIOD_OUT_LOW, "vout1-en"); 233 if (!IS_ERR(en)) { 234 /* VOUT1_OPS gpio ctrl */ 235 /* 236 * Regulator core prioritizes the ena_gpio over 237 * enable/disable/is_enabled callbacks so no need to 238 * clear them. We can still use same ops 239 */ 240 config.ena_gpiod = en; 241 } else { 242 /* 243 * In theory it is possible someone wants to set 244 * vout1-en LOW during OTP loading and set VOUT1 to be 245 * controlled by GPIO - but control the GPIO from some 246 * where else than this driver. For that to work we 247 * should unset the is_enabled callback here. 248 * 249 * I believe such case where rohm,vout1-en-low is set 250 * and vout1-en-gpios is not is likely to be a 251 * misconfiguration. So let's just err out for now. 252 */ 253 dev_err(&pdev->dev, 254 "Failed to get VOUT1 control GPIO\n"); 255 return PTR_ERR(en); 256 } 257 } 258 259 /* 260 * If more than one PMIC needs to be controlled by same processor then 261 * allocate the regulator data array here and use bd9576_regulators as 262 * template. At the moment I see no such use-case so I spare some 263 * bytes and use bd9576_regulators directly for non-constant configs 264 * like DDR voltage selection. 265 */ 266 ddr_sel = of_property_read_bool(pdev->dev.parent->of_node, 267 "rohm,ddr-sel-low"); 268 if (ddr_sel) 269 bd9576_regulators[2].desc.fixed_uV = 1350000; 270 else 271 bd9576_regulators[2].desc.fixed_uV = 1500000; 272 273 switch (chip) { 274 case ROHM_CHIP_TYPE_BD9576: 275 dev_dbg(&pdev->dev, "Found BD9576MUF\n"); 276 break; 277 case ROHM_CHIP_TYPE_BD9573: 278 dev_dbg(&pdev->dev, "Found BD9573MUF\n"); 279 break; 280 default: 281 dev_err(&pdev->dev, "Unsupported chip type\n"); 282 return -EINVAL; 283 } 284 285 config.dev = pdev->dev.parent; 286 config.regmap = regmap; 287 288 for (i = 0; i < num_reg_data; i++) { 289 290 const struct regulator_desc *desc; 291 struct regulator_dev *rdev; 292 const struct bd957x_regulator_data *r; 293 294 r = ®_data[i]; 295 desc = &r->desc; 296 297 rdev = devm_regulator_register(&pdev->dev, desc, &config); 298 if (IS_ERR(rdev)) { 299 dev_err(&pdev->dev, 300 "failed to register %s regulator\n", 301 desc->name); 302 return PTR_ERR(rdev); 303 } 304 /* 305 * Clear the VOUT1 GPIO setting - rest of the regulators do not 306 * support GPIO control 307 */ 308 config.ena_gpiod = NULL; 309 } 310 311 return 0; 312 } 313 314 static const struct platform_device_id bd957x_pmic_id[] = { 315 { "bd9573-pmic", ROHM_CHIP_TYPE_BD9573 }, 316 { "bd9576-pmic", ROHM_CHIP_TYPE_BD9576 }, 317 { }, 318 }; 319 MODULE_DEVICE_TABLE(platform, bd957x_pmic_id); 320 321 static struct platform_driver bd957x_regulator = { 322 .driver = { 323 .name = "bd957x-pmic", 324 }, 325 .probe = bd957x_probe, 326 .id_table = bd957x_pmic_id, 327 }; 328 329 module_platform_driver(bd957x_regulator); 330 331 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 332 MODULE_DESCRIPTION("ROHM BD9576/BD9573 voltage regulator driver"); 333 MODULE_LICENSE("GPL"); 334 MODULE_ALIAS("platform:bd957x-pmic"); 335