1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include <linux/bits.h> 4 #include <linux/gpio/consumer.h> 5 #include <linux/interrupt.h> 6 #include <linux/kernel.h> 7 #include <linux/mod_devicetable.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/platform_device.h> 11 #include <linux/regmap.h> 12 #include <linux/regulator/driver.h> 13 #include <linux/regulator/machine.h> 14 15 enum { 16 MT6370_IDX_DSVBOOST = 0, 17 MT6370_IDX_DSVPOS, 18 MT6370_IDX_DSVNEG, 19 MT6370_IDX_VIBLDO, 20 MT6370_MAX_IDX 21 }; 22 23 #define MT6370_REG_LDO_CFG 0x180 24 #define MT6370_REG_LDO_VOUT 0x181 25 #define MT6370_REG_DB_CTRL1 0x1B0 26 #define MT6370_REG_DB_CTRL2 0x1B1 27 #define MT6370_REG_DB_VBST 0x1B2 28 #define MT6370_REG_DB_VPOS 0x1B3 29 #define MT6370_REG_DB_VNEG 0x1B4 30 #define MT6370_REG_LDO_STAT 0x1DC 31 #define MT6370_REG_DB_STAT 0x1DF 32 33 #define MT6370_LDOOMS_MASK BIT(7) 34 #define MT6370_LDOEN_MASK BIT(7) 35 #define MT6370_LDOVOUT_MASK GENMASK(3, 0) 36 #define MT6370_DBPERD_MASK (BIT(7) | BIT(4)) 37 #define MT6370_DBEXTEN_MASK BIT(0) 38 #define MT6370_DBVPOSEN_MASK BIT(6) 39 #define MT6370_DBVPOSDISG_MASK BIT(5) 40 #define MT6370_DBVNEGEN_MASK BIT(3) 41 #define MT6370_DBVNEGDISG_MASK BIT(2) 42 #define MT6370_DBALLON_MASK (MT6370_DBVPOSEN_MASK | MT6370_DBVNEGEN_MASK) 43 #define MT6370_DBSLEW_MASK GENMASK(7, 6) 44 #define MT6370_DBVOUT_MASK GENMASK(5, 0) 45 #define MT6370_LDOOC_EVT_MASK BIT(7) 46 #define MT6370_POSSCP_EVT_MASK BIT(7) 47 #define MT6370_NEGSCP_EVT_MASK BIT(6) 48 #define MT6370_BSTOCP_EVT_MASK BIT(5) 49 #define MT6370_POSOCP_EVT_MASK BIT(4) 50 #define MT6370_NEGOCP_EVT_MASK BIT(3) 51 52 #define MT6370_LDO_MINUV 1600000 53 #define MT6370_LDO_STPUV 200000 54 #define MT6370_LDO_N_VOLT 13 55 #define MT6370_DBVBOOST_MINUV 4000000 56 #define MT6370_DBVBOOST_STPUV 50000 57 #define MT6370_DBVBOOST_N_VOLT 45 58 #define MT6370_DBVOUT_MINUV 4000000 59 #define MT6370_DBVOUT_STPUV 50000 60 #define MT6370_DBVOUT_N_VOLT 41 61 62 struct mt6370_priv { 63 struct device *dev; 64 struct regmap *regmap; 65 struct regulator_dev *rdev[MT6370_MAX_IDX]; 66 bool use_external_ctrl; 67 }; 68 69 static const unsigned int mt6370_vpos_ramp_tbl[] = { 8540, 5840, 4830, 3000 }; 70 static const unsigned int mt6370_vneg_ramp_tbl[] = { 10090, 6310, 5050, 3150 }; 71 72 static int mt6370_get_error_flags(struct regulator_dev *rdev, 73 unsigned int *flags) 74 { 75 struct regmap *regmap = rdev_get_regmap(rdev); 76 unsigned int stat_reg, stat, rpt_flags = 0; 77 int rid = rdev_get_id(rdev), ret; 78 79 if (rid == MT6370_IDX_VIBLDO) 80 stat_reg = MT6370_REG_LDO_STAT; 81 else 82 stat_reg = MT6370_REG_DB_STAT; 83 84 ret = regmap_read(regmap, stat_reg, &stat); 85 if (ret) 86 return ret; 87 88 switch (rid) { 89 case MT6370_IDX_DSVBOOST: 90 if (stat & MT6370_BSTOCP_EVT_MASK) 91 rpt_flags |= REGULATOR_ERROR_OVER_CURRENT; 92 break; 93 case MT6370_IDX_DSVPOS: 94 if (stat & MT6370_POSSCP_EVT_MASK) 95 rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE; 96 97 if (stat & MT6370_POSOCP_EVT_MASK) 98 rpt_flags |= REGULATOR_ERROR_OVER_CURRENT; 99 break; 100 case MT6370_IDX_DSVNEG: 101 if (stat & MT6370_NEGSCP_EVT_MASK) 102 rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE; 103 104 if (stat & MT6370_NEGOCP_EVT_MASK) 105 rpt_flags |= REGULATOR_ERROR_OVER_CURRENT; 106 break; 107 default: 108 if (stat & MT6370_LDOOC_EVT_MASK) 109 rpt_flags |= REGULATOR_ERROR_OVER_CURRENT; 110 break; 111 } 112 113 *flags = rpt_flags; 114 return 0; 115 } 116 117 static const struct regulator_ops mt6370_dbvboost_ops = { 118 .get_voltage_sel = regulator_get_voltage_sel_regmap, 119 .set_voltage_sel = regulator_set_voltage_sel_regmap, 120 .list_voltage = regulator_list_voltage_linear, 121 .get_bypass = regulator_get_bypass_regmap, 122 .set_bypass = regulator_set_bypass_regmap, 123 .get_error_flags = mt6370_get_error_flags, 124 }; 125 126 static const struct regulator_ops mt6370_dbvout_ops = { 127 .get_voltage_sel = regulator_get_voltage_sel_regmap, 128 .set_voltage_sel = regulator_set_voltage_sel_regmap, 129 .list_voltage = regulator_list_voltage_linear, 130 .is_enabled = regulator_is_enabled_regmap, 131 .enable = regulator_enable_regmap, 132 .disable = regulator_disable_regmap, 133 .set_active_discharge = regulator_set_active_discharge_regmap, 134 .set_ramp_delay = regulator_set_ramp_delay_regmap, 135 .get_error_flags = mt6370_get_error_flags, 136 }; 137 138 static const struct regulator_ops mt6370_ldo_ops = { 139 .get_voltage_sel = regulator_get_voltage_sel_regmap, 140 .set_voltage_sel = regulator_set_voltage_sel_regmap, 141 .list_voltage = regulator_list_voltage_linear, 142 .is_enabled = regulator_is_enabled_regmap, 143 .enable = regulator_enable_regmap, 144 .disable = regulator_disable_regmap, 145 .set_active_discharge = regulator_set_active_discharge_regmap, 146 .get_error_flags = mt6370_get_error_flags, 147 }; 148 149 static int mt6370_of_parse_cb(struct device_node *np, 150 const struct regulator_desc *desc, 151 struct regulator_config *config) 152 { 153 struct mt6370_priv *priv = config->driver_data; 154 struct gpio_desc *enable_gpio; 155 int ret; 156 157 enable_gpio = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0, 158 GPIOD_OUT_HIGH | 159 GPIOD_FLAGS_BIT_NONEXCLUSIVE, 160 desc->name); 161 if (IS_ERR(enable_gpio)) { 162 config->ena_gpiod = NULL; 163 return 0; 164 } 165 166 /* 167 * RG control by default 168 * Only if all are using external pin, change all by external control 169 */ 170 if (priv->use_external_ctrl) { 171 ret = regmap_update_bits(priv->regmap, MT6370_REG_DB_CTRL1, 172 MT6370_DBEXTEN_MASK, 173 MT6370_DBEXTEN_MASK); 174 if (ret) 175 return ret; 176 } 177 178 config->ena_gpiod = enable_gpio; 179 priv->use_external_ctrl = true; 180 return 0; 181 } 182 183 static const struct regulator_desc mt6370_regulator_descs[] = { 184 { 185 .name = "mt6370-dsv-vbst", 186 .of_match = of_match_ptr("dsvbst"), 187 .regulators_node = of_match_ptr("regulators"), 188 .id = MT6370_IDX_DSVBOOST, 189 .type = REGULATOR_VOLTAGE, 190 .owner = THIS_MODULE, 191 .ops = &mt6370_dbvboost_ops, 192 .min_uV = MT6370_DBVBOOST_MINUV, 193 .uV_step = MT6370_DBVBOOST_STPUV, 194 .n_voltages = MT6370_DBVBOOST_N_VOLT, 195 .vsel_reg = MT6370_REG_DB_VBST, 196 .vsel_mask = MT6370_DBVOUT_MASK, 197 .bypass_reg = MT6370_REG_DB_CTRL1, 198 .bypass_mask = MT6370_DBPERD_MASK, 199 .bypass_val_on = MT6370_DBPERD_MASK, 200 }, 201 { 202 .name = "mt6370-dsv-vpos", 203 .of_match = of_match_ptr("dsvpos"), 204 .regulators_node = of_match_ptr("regulators"), 205 .id = MT6370_IDX_DSVPOS, 206 .type = REGULATOR_VOLTAGE, 207 .owner = THIS_MODULE, 208 .of_parse_cb = mt6370_of_parse_cb, 209 .ops = &mt6370_dbvout_ops, 210 .min_uV = MT6370_DBVOUT_MINUV, 211 .uV_step = MT6370_DBVOUT_STPUV, 212 .n_voltages = MT6370_DBVOUT_N_VOLT, 213 .vsel_reg = MT6370_REG_DB_VPOS, 214 .vsel_mask = MT6370_DBVOUT_MASK, 215 .enable_reg = MT6370_REG_DB_CTRL2, 216 .enable_mask = MT6370_DBVPOSEN_MASK, 217 .ramp_reg = MT6370_REG_DB_VPOS, 218 .ramp_mask = MT6370_DBSLEW_MASK, 219 .ramp_delay_table = mt6370_vpos_ramp_tbl, 220 .n_ramp_values = ARRAY_SIZE(mt6370_vpos_ramp_tbl), 221 .active_discharge_reg = MT6370_REG_DB_CTRL2, 222 .active_discharge_mask = MT6370_DBVPOSDISG_MASK, 223 .active_discharge_on = MT6370_DBVPOSDISG_MASK, 224 }, 225 { 226 .name = "mt6370-dsv-vneg", 227 .of_match = of_match_ptr("dsvneg"), 228 .regulators_node = of_match_ptr("regulators"), 229 .id = MT6370_IDX_DSVNEG, 230 .type = REGULATOR_VOLTAGE, 231 .owner = THIS_MODULE, 232 .of_parse_cb = mt6370_of_parse_cb, 233 .ops = &mt6370_dbvout_ops, 234 .min_uV = MT6370_DBVOUT_MINUV, 235 .uV_step = MT6370_DBVOUT_STPUV, 236 .n_voltages = MT6370_DBVOUT_N_VOLT, 237 .vsel_reg = MT6370_REG_DB_VNEG, 238 .vsel_mask = MT6370_DBVOUT_MASK, 239 .enable_reg = MT6370_REG_DB_CTRL2, 240 .enable_mask = MT6370_DBVNEGEN_MASK, 241 .ramp_reg = MT6370_REG_DB_VNEG, 242 .ramp_mask = MT6370_DBSLEW_MASK, 243 .ramp_delay_table = mt6370_vneg_ramp_tbl, 244 .n_ramp_values = ARRAY_SIZE(mt6370_vneg_ramp_tbl), 245 .active_discharge_reg = MT6370_REG_DB_CTRL2, 246 .active_discharge_mask = MT6370_DBVNEGDISG_MASK, 247 .active_discharge_on = MT6370_DBVNEGDISG_MASK, 248 }, 249 { 250 .name = "mt6370-vib-ldo", 251 .of_match = of_match_ptr("vibldo"), 252 .regulators_node = of_match_ptr("regulators"), 253 .id = MT6370_IDX_VIBLDO, 254 .type = REGULATOR_VOLTAGE, 255 .owner = THIS_MODULE, 256 .ops = &mt6370_ldo_ops, 257 .min_uV = MT6370_LDO_MINUV, 258 .uV_step = MT6370_LDO_STPUV, 259 .n_voltages = MT6370_LDO_N_VOLT, 260 .vsel_reg = MT6370_REG_LDO_VOUT, 261 .vsel_mask = MT6370_LDOVOUT_MASK, 262 .enable_reg = MT6370_REG_LDO_VOUT, 263 .enable_mask = MT6370_LDOEN_MASK, 264 .active_discharge_reg = MT6370_REG_LDO_CFG, 265 .active_discharge_mask = MT6370_LDOOMS_MASK, 266 .active_discharge_on = MT6370_LDOOMS_MASK, 267 } 268 }; 269 270 static irqreturn_t mt6370_scp_handler(int irq, void *data) 271 { 272 struct regulator_dev *rdev = data; 273 274 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, 275 NULL); 276 return IRQ_HANDLED; 277 } 278 279 static irqreturn_t mt6370_ocp_handler(int irq, void *data) 280 { 281 struct regulator_dev *rdev = data; 282 283 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); 284 return IRQ_HANDLED; 285 } 286 287 static int mt6370_regulator_irq_register(struct mt6370_priv *priv) 288 { 289 struct platform_device *pdev = to_platform_device(priv->dev); 290 static const struct { 291 const char *name; 292 int rid; 293 irq_handler_t handler; 294 } mt6370_irqs[] = { 295 { "db_vpos_scp", MT6370_IDX_DSVPOS, mt6370_scp_handler }, 296 { "db_vneg_scp", MT6370_IDX_DSVNEG, mt6370_scp_handler }, 297 { "db_vbst_ocp", MT6370_IDX_DSVBOOST, mt6370_ocp_handler }, 298 { "db_vpos_ocp", MT6370_IDX_DSVPOS, mt6370_ocp_handler }, 299 { "db_vneg_ocp", MT6370_IDX_DSVNEG, mt6370_ocp_handler }, 300 { "ldo_oc", MT6370_IDX_VIBLDO, mt6370_ocp_handler } 301 }; 302 struct regulator_dev *rdev; 303 int i, irq, ret; 304 305 for (i = 0; i < ARRAY_SIZE(mt6370_irqs); i++) { 306 irq = platform_get_irq_byname(pdev, mt6370_irqs[i].name); 307 308 rdev = priv->rdev[mt6370_irqs[i].rid]; 309 310 ret = devm_request_threaded_irq(priv->dev, irq, NULL, 311 mt6370_irqs[i].handler, 0, 312 mt6370_irqs[i].name, rdev); 313 if (ret) { 314 dev_err(priv->dev, 315 "Failed to register (%d) interrupt\n", i); 316 return ret; 317 } 318 } 319 320 return 0; 321 } 322 323 static int mt6370_regualtor_register(struct mt6370_priv *priv) 324 { 325 struct regulator_dev *rdev; 326 struct regulator_config cfg = {}; 327 struct device *parent = priv->dev->parent; 328 int i; 329 330 cfg.dev = parent; 331 cfg.driver_data = priv; 332 333 for (i = 0; i < MT6370_MAX_IDX; i++) { 334 rdev = devm_regulator_register(priv->dev, 335 mt6370_regulator_descs + i, 336 &cfg); 337 if (IS_ERR(rdev)) { 338 dev_err(priv->dev, 339 "Failed to register (%d) regulator\n", i); 340 return PTR_ERR(rdev); 341 } 342 343 priv->rdev[i] = rdev; 344 } 345 346 return 0; 347 } 348 349 static int mt6370_regulator_probe(struct platform_device *pdev) 350 { 351 struct mt6370_priv *priv; 352 int ret; 353 354 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 355 if (!priv) 356 return -ENOMEM; 357 358 priv->dev = &pdev->dev; 359 360 priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); 361 if (!priv->regmap) { 362 dev_err(&pdev->dev, "Failed to init regmap\n"); 363 return -ENODEV; 364 } 365 366 ret = mt6370_regualtor_register(priv); 367 if (ret) 368 return ret; 369 370 return mt6370_regulator_irq_register(priv); 371 } 372 373 static const struct platform_device_id mt6370_devid_table[] = { 374 { "mt6370-regulator", 0}, 375 {} 376 }; 377 MODULE_DEVICE_TABLE(platform, mt6370_devid_table); 378 379 static struct platform_driver mt6370_regulator_driver = { 380 .driver = { 381 .name = "mt6370-regulator", 382 }, 383 .id_table = mt6370_devid_table, 384 .probe = mt6370_regulator_probe, 385 }; 386 module_platform_driver(mt6370_regulator_driver); 387 388 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 389 MODULE_DESCRIPTION("Mediatek MT6370 Regulator Driver"); 390 MODULE_LICENSE("GPL v2"); 391