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