1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright (C) 2020 MediaTek Inc. 4 // 5 // Author: Gene Chen <gene_chen@richtek.com> 6 7 #include <linux/init.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 #include <linux/regulator/driver.h> 14 #include <linux/regulator/machine.h> 15 16 #include <dt-bindings/regulator/mediatek,mt6360-regulator.h> 17 18 enum { 19 MT6360_REGULATOR_BUCK1 = 0, 20 MT6360_REGULATOR_BUCK2, 21 MT6360_REGULATOR_LDO6, 22 MT6360_REGULATOR_LDO7, 23 MT6360_REGULATOR_LDO1, 24 MT6360_REGULATOR_LDO2, 25 MT6360_REGULATOR_LDO3, 26 MT6360_REGULATOR_LDO5, 27 MT6360_REGULATOR_MAX, 28 }; 29 30 struct mt6360_irq_mapping { 31 const char *name; 32 irq_handler_t handler; 33 }; 34 35 struct mt6360_regulator_desc { 36 const struct regulator_desc desc; 37 unsigned int mode_reg; 38 unsigned int mode_mask; 39 unsigned int state_reg; 40 unsigned int state_mask; 41 const struct mt6360_irq_mapping *irq_tables; 42 int irq_table_size; 43 }; 44 45 struct mt6360_regulator_data { 46 struct device *dev; 47 struct regmap *regmap; 48 }; 49 50 static irqreturn_t mt6360_pgb_event_handler(int irq, void *data) 51 { 52 struct regulator_dev *rdev = data; 53 54 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_FAIL, NULL); 55 return IRQ_HANDLED; 56 } 57 58 static irqreturn_t mt6360_oc_event_handler(int irq, void *data) 59 { 60 struct regulator_dev *rdev = data; 61 62 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); 63 return IRQ_HANDLED; 64 } 65 66 static irqreturn_t mt6360_ov_event_handler(int irq, void *data) 67 { 68 struct regulator_dev *rdev = data; 69 70 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_REGULATION_OUT, NULL); 71 return IRQ_HANDLED; 72 } 73 74 static irqreturn_t mt6360_uv_event_handler(int irq, void *data) 75 { 76 struct regulator_dev *rdev = data; 77 78 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); 79 return IRQ_HANDLED; 80 } 81 82 static const struct mt6360_irq_mapping buck1_irq_tbls[] = { 83 { "buck1_pgb_evt", mt6360_pgb_event_handler }, 84 { "buck1_oc_evt", mt6360_oc_event_handler }, 85 { "buck1_ov_evt", mt6360_ov_event_handler }, 86 { "buck1_uv_evt", mt6360_uv_event_handler }, 87 }; 88 89 static const struct mt6360_irq_mapping buck2_irq_tbls[] = { 90 { "buck2_pgb_evt", mt6360_pgb_event_handler }, 91 { "buck2_oc_evt", mt6360_oc_event_handler }, 92 { "buck2_ov_evt", mt6360_ov_event_handler }, 93 { "buck2_uv_evt", mt6360_uv_event_handler }, 94 }; 95 96 static const struct mt6360_irq_mapping ldo6_irq_tbls[] = { 97 { "ldo6_pgb_evt", mt6360_pgb_event_handler }, 98 { "ldo6_oc_evt", mt6360_oc_event_handler }, 99 }; 100 101 static const struct mt6360_irq_mapping ldo7_irq_tbls[] = { 102 { "ldo7_pgb_evt", mt6360_pgb_event_handler }, 103 { "ldo7_oc_evt", mt6360_oc_event_handler }, 104 }; 105 106 static const struct mt6360_irq_mapping ldo1_irq_tbls[] = { 107 { "ldo1_pgb_evt", mt6360_pgb_event_handler }, 108 { "ldo1_oc_evt", mt6360_oc_event_handler }, 109 }; 110 111 static const struct mt6360_irq_mapping ldo2_irq_tbls[] = { 112 { "ldo2_pgb_evt", mt6360_pgb_event_handler }, 113 { "ldo2_oc_evt", mt6360_oc_event_handler }, 114 }; 115 116 static const struct mt6360_irq_mapping ldo3_irq_tbls[] = { 117 { "ldo3_pgb_evt", mt6360_pgb_event_handler }, 118 { "ldo3_oc_evt", mt6360_oc_event_handler }, 119 }; 120 121 static const struct mt6360_irq_mapping ldo5_irq_tbls[] = { 122 { "ldo5_pgb_evt", mt6360_pgb_event_handler }, 123 { "ldo5_oc_evt", mt6360_oc_event_handler }, 124 }; 125 126 static const struct linear_range buck_vout_ranges[] = { 127 REGULATOR_LINEAR_RANGE(300000, 0x00, 0xc7, 5000), 128 REGULATOR_LINEAR_RANGE(1300000, 0xc8, 0xff, 0), 129 }; 130 131 static const struct linear_range ldo_vout_ranges1[] = { 132 REGULATOR_LINEAR_RANGE(500000, 0x00, 0x09, 10000), 133 REGULATOR_LINEAR_RANGE(600000, 0x0a, 0x10, 0), 134 REGULATOR_LINEAR_RANGE(610000, 0x11, 0x19, 10000), 135 REGULATOR_LINEAR_RANGE(700000, 0x1a, 0x20, 0), 136 REGULATOR_LINEAR_RANGE(710000, 0x21, 0x29, 10000), 137 REGULATOR_LINEAR_RANGE(800000, 0x2a, 0x30, 0), 138 REGULATOR_LINEAR_RANGE(810000, 0x31, 0x39, 10000), 139 REGULATOR_LINEAR_RANGE(900000, 0x3a, 0x40, 0), 140 REGULATOR_LINEAR_RANGE(910000, 0x41, 0x49, 10000), 141 REGULATOR_LINEAR_RANGE(1000000, 0x4a, 0x50, 0), 142 REGULATOR_LINEAR_RANGE(1010000, 0x51, 0x59, 10000), 143 REGULATOR_LINEAR_RANGE(1100000, 0x5a, 0x60, 0), 144 REGULATOR_LINEAR_RANGE(1110000, 0x61, 0x69, 10000), 145 REGULATOR_LINEAR_RANGE(1200000, 0x6a, 0x70, 0), 146 REGULATOR_LINEAR_RANGE(1210000, 0x71, 0x79, 10000), 147 REGULATOR_LINEAR_RANGE(1300000, 0x7a, 0x80, 0), 148 REGULATOR_LINEAR_RANGE(1310000, 0x81, 0x89, 10000), 149 REGULATOR_LINEAR_RANGE(1400000, 0x8a, 0x90, 0), 150 REGULATOR_LINEAR_RANGE(1410000, 0x91, 0x99, 10000), 151 REGULATOR_LINEAR_RANGE(1500000, 0x9a, 0xa0, 0), 152 REGULATOR_LINEAR_RANGE(1510000, 0xa1, 0xa9, 10000), 153 REGULATOR_LINEAR_RANGE(1600000, 0xaa, 0xb0, 0), 154 REGULATOR_LINEAR_RANGE(1610000, 0xb1, 0xb9, 10000), 155 REGULATOR_LINEAR_RANGE(1700000, 0xba, 0xc0, 0), 156 REGULATOR_LINEAR_RANGE(1710000, 0xc1, 0xc9, 10000), 157 REGULATOR_LINEAR_RANGE(1800000, 0xca, 0xd0, 0), 158 REGULATOR_LINEAR_RANGE(1810000, 0xd1, 0xd9, 10000), 159 REGULATOR_LINEAR_RANGE(1900000, 0xda, 0xe0, 0), 160 REGULATOR_LINEAR_RANGE(1910000, 0xe1, 0xe9, 10000), 161 REGULATOR_LINEAR_RANGE(2000000, 0xea, 0xf0, 0), 162 REGULATOR_LINEAR_RANGE(2010000, 0xf1, 0xf9, 10000), 163 REGULATOR_LINEAR_RANGE(2100000, 0xfa, 0xff, 0), 164 }; 165 166 static const struct linear_range ldo_vout_ranges2[] = { 167 REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x09, 10000), 168 REGULATOR_LINEAR_RANGE(1300000, 0x0a, 0x10, 0), 169 REGULATOR_LINEAR_RANGE(1310000, 0x11, 0x19, 10000), 170 REGULATOR_LINEAR_RANGE(1400000, 0x1a, 0x1f, 0), 171 REGULATOR_LINEAR_RANGE(1500000, 0x20, 0x29, 10000), 172 REGULATOR_LINEAR_RANGE(1600000, 0x2a, 0x2f, 0), 173 REGULATOR_LINEAR_RANGE(1700000, 0x30, 0x39, 10000), 174 REGULATOR_LINEAR_RANGE(1800000, 0x3a, 0x40, 0), 175 REGULATOR_LINEAR_RANGE(1810000, 0x41, 0x49, 10000), 176 REGULATOR_LINEAR_RANGE(1900000, 0x4a, 0x4f, 0), 177 REGULATOR_LINEAR_RANGE(2000000, 0x50, 0x59, 10000), 178 REGULATOR_LINEAR_RANGE(2100000, 0x5a, 0x60, 0), 179 REGULATOR_LINEAR_RANGE(2110000, 0x61, 0x69, 10000), 180 REGULATOR_LINEAR_RANGE(2200000, 0x6a, 0x6f, 0), 181 REGULATOR_LINEAR_RANGE(2500000, 0x70, 0x79, 10000), 182 REGULATOR_LINEAR_RANGE(2600000, 0x7a, 0x7f, 0), 183 REGULATOR_LINEAR_RANGE(2700000, 0x80, 0x89, 10000), 184 REGULATOR_LINEAR_RANGE(2800000, 0x8a, 0x90, 0), 185 REGULATOR_LINEAR_RANGE(2810000, 0x91, 0x99, 10000), 186 REGULATOR_LINEAR_RANGE(2900000, 0x9a, 0xa0, 0), 187 REGULATOR_LINEAR_RANGE(2910000, 0xa1, 0xa9, 10000), 188 REGULATOR_LINEAR_RANGE(3000000, 0xaa, 0xb0, 0), 189 REGULATOR_LINEAR_RANGE(3010000, 0xb1, 0xb9, 10000), 190 REGULATOR_LINEAR_RANGE(3100000, 0xba, 0xc0, 0), 191 REGULATOR_LINEAR_RANGE(3110000, 0xc1, 0xc9, 10000), 192 REGULATOR_LINEAR_RANGE(3200000, 0xca, 0xcf, 0), 193 REGULATOR_LINEAR_RANGE(3300000, 0xd0, 0xd9, 10000), 194 REGULATOR_LINEAR_RANGE(3400000, 0xda, 0xe0, 0), 195 REGULATOR_LINEAR_RANGE(3410000, 0xe1, 0xe9, 10000), 196 REGULATOR_LINEAR_RANGE(3500000, 0xea, 0xf0, 0), 197 REGULATOR_LINEAR_RANGE(3510000, 0xf1, 0xf9, 10000), 198 REGULATOR_LINEAR_RANGE(3600000, 0xfa, 0xff, 0), 199 }; 200 201 static const struct linear_range ldo_vout_ranges3[] = { 202 REGULATOR_LINEAR_RANGE(2700000, 0x00, 0x09, 10000), 203 REGULATOR_LINEAR_RANGE(2800000, 0x0a, 0x10, 0), 204 REGULATOR_LINEAR_RANGE(2810000, 0x11, 0x19, 10000), 205 REGULATOR_LINEAR_RANGE(2900000, 0x1a, 0x20, 0), 206 REGULATOR_LINEAR_RANGE(2910000, 0x21, 0x29, 10000), 207 REGULATOR_LINEAR_RANGE(3000000, 0x2a, 0x30, 0), 208 REGULATOR_LINEAR_RANGE(3010000, 0x31, 0x39, 10000), 209 REGULATOR_LINEAR_RANGE(3100000, 0x3a, 0x40, 0), 210 REGULATOR_LINEAR_RANGE(3110000, 0x41, 0x49, 10000), 211 REGULATOR_LINEAR_RANGE(3200000, 0x4a, 0x4f, 0), 212 REGULATOR_LINEAR_RANGE(3300000, 0x50, 0x59, 10000), 213 REGULATOR_LINEAR_RANGE(3400000, 0x5a, 0x60, 0), 214 REGULATOR_LINEAR_RANGE(3410000, 0x61, 0x69, 10000), 215 REGULATOR_LINEAR_RANGE(3500000, 0x6a, 0x70, 0), 216 REGULATOR_LINEAR_RANGE(3510000, 0x71, 0x79, 10000), 217 REGULATOR_LINEAR_RANGE(3600000, 0x7a, 0x7f, 0), 218 }; 219 220 static int mt6360_regulator_set_mode(struct regulator_dev *rdev, 221 unsigned int mode) 222 { 223 const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc; 224 struct regmap *regmap = rdev_get_regmap(rdev); 225 int shift = ffs(rdesc->mode_mask) - 1; 226 unsigned int val; 227 int ret; 228 229 switch (mode) { 230 case REGULATOR_MODE_NORMAL: 231 val = MT6360_OPMODE_NORMAL; 232 break; 233 case REGULATOR_MODE_STANDBY: 234 val = MT6360_OPMODE_ULP; 235 break; 236 case REGULATOR_MODE_IDLE: 237 val = MT6360_OPMODE_LP; 238 break; 239 default: 240 return -EINVAL; 241 } 242 243 ret = regmap_update_bits(regmap, rdesc->mode_reg, rdesc->mode_mask, val << shift); 244 if (ret) { 245 dev_err(&rdev->dev, "%s: fail (%d)\n", __func__, ret); 246 return ret; 247 } 248 249 return 0; 250 } 251 252 static unsigned int mt6360_regulator_get_mode(struct regulator_dev *rdev) 253 { 254 const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc; 255 struct regmap *regmap = rdev_get_regmap(rdev); 256 int shift = ffs(rdesc->mode_mask) - 1; 257 unsigned int val; 258 int ret; 259 260 ret = regmap_read(regmap, rdesc->mode_reg, &val); 261 if (ret) 262 return ret; 263 264 val &= rdesc->mode_mask; 265 val >>= shift; 266 267 switch (val) { 268 case MT6360_OPMODE_LP: 269 return REGULATOR_MODE_IDLE; 270 case MT6360_OPMODE_ULP: 271 return REGULATOR_MODE_STANDBY; 272 case MT6360_OPMODE_NORMAL: 273 return REGULATOR_MODE_NORMAL; 274 default: 275 return -EINVAL; 276 } 277 } 278 279 static int mt6360_regulator_get_status(struct regulator_dev *rdev) 280 { 281 const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc; 282 struct regmap *regmap = rdev_get_regmap(rdev); 283 unsigned int val; 284 int ret; 285 286 ret = regmap_read(regmap, rdesc->state_reg, &val); 287 if (ret) 288 return ret; 289 290 if (val & rdesc->state_mask) 291 return REGULATOR_STATUS_ON; 292 293 return REGULATOR_STATUS_OFF; 294 } 295 296 static const struct regulator_ops mt6360_regulator_ops = { 297 .list_voltage = regulator_list_voltage_linear_range, 298 .enable = regulator_enable_regmap, 299 .disable = regulator_disable_regmap, 300 .is_enabled = regulator_is_enabled_regmap, 301 .set_voltage_sel = regulator_set_voltage_sel_regmap, 302 .get_voltage_sel = regulator_get_voltage_sel_regmap, 303 .set_mode = mt6360_regulator_set_mode, 304 .get_mode = mt6360_regulator_get_mode, 305 .get_status = mt6360_regulator_get_status, 306 }; 307 308 static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode) 309 { 310 switch (hw_mode) { 311 case MT6360_OPMODE_NORMAL: 312 return REGULATOR_MODE_NORMAL; 313 case MT6360_OPMODE_LP: 314 return REGULATOR_MODE_IDLE; 315 case MT6360_OPMODE_ULP: 316 return REGULATOR_MODE_STANDBY; 317 default: 318 return REGULATOR_MODE_INVALID; 319 } 320 } 321 322 #define MT6360_REGULATOR_DESC(match, _name, _sname, ereg, emask, vreg, \ 323 vmask, mreg, mmask, streg, stmask, \ 324 vranges, vcnts, offon_delay, irq_tbls) \ 325 { \ 326 .desc = { \ 327 .name = #_name, \ 328 .supply_name = #_sname, \ 329 .id = MT6360_REGULATOR_##_name, \ 330 .of_match = of_match_ptr(match), \ 331 .regulators_node = of_match_ptr("regulator"), \ 332 .of_map_mode = mt6360_regulator_of_map_mode, \ 333 .owner = THIS_MODULE, \ 334 .ops = &mt6360_regulator_ops, \ 335 .type = REGULATOR_VOLTAGE, \ 336 .vsel_reg = vreg, \ 337 .vsel_mask = vmask, \ 338 .enable_reg = ereg, \ 339 .enable_mask = emask, \ 340 .linear_ranges = vranges, \ 341 .n_linear_ranges = ARRAY_SIZE(vranges), \ 342 .n_voltages = vcnts, \ 343 .off_on_delay = offon_delay, \ 344 }, \ 345 .mode_reg = mreg, \ 346 .mode_mask = mmask, \ 347 .state_reg = streg, \ 348 .state_mask = stmask, \ 349 .irq_tables = irq_tbls, \ 350 .irq_table_size = ARRAY_SIZE(irq_tbls), \ 351 } 352 353 static const struct mt6360_regulator_desc mt6360_regulator_descs[] = { 354 MT6360_REGULATOR_DESC("buck1", BUCK1, BUCK1_VIN, 355 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04, 356 buck_vout_ranges, 256, 0, buck1_irq_tbls), 357 MT6360_REGULATOR_DESC("buck2", BUCK2, BUCK2_VIN, 358 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04, 359 buck_vout_ranges, 256, 0, buck2_irq_tbls), 360 MT6360_REGULATOR_DESC("ldo6", LDO6, LDO_VIN3, 361 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04, 362 ldo_vout_ranges1, 256, 0, ldo6_irq_tbls), 363 MT6360_REGULATOR_DESC("ldo7", LDO7, LDO_VIN3, 364 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04, 365 ldo_vout_ranges1, 256, 0, ldo7_irq_tbls), 366 MT6360_REGULATOR_DESC("ldo1", LDO1, LDO_VIN1, 367 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04, 368 ldo_vout_ranges2, 256, 0, ldo1_irq_tbls), 369 MT6360_REGULATOR_DESC("ldo2", LDO2, LDO_VIN1, 370 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04, 371 ldo_vout_ranges2, 256, 0, ldo2_irq_tbls), 372 MT6360_REGULATOR_DESC("ldo3", LDO3, LDO_VIN1, 373 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04, 374 ldo_vout_ranges2, 256, 100, ldo3_irq_tbls), 375 MT6360_REGULATOR_DESC("ldo5", LDO5, LDO_VIN2, 376 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04, 377 ldo_vout_ranges3, 128, 100, ldo5_irq_tbls), 378 }; 379 380 static int mt6360_regulator_irq_register(struct platform_device *pdev, 381 struct regulator_dev *rdev, 382 const struct mt6360_irq_mapping *tbls, 383 int tbl_size) 384 { 385 int i, irq, ret; 386 387 for (i = 0; i < tbl_size; i++) { 388 const struct mt6360_irq_mapping *irq_desc = tbls + i; 389 390 irq = platform_get_irq_byname(pdev, irq_desc->name); 391 if (irq < 0) 392 return irq; 393 394 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, irq_desc->handler, 0, 395 irq_desc->name, rdev); 396 if (ret) { 397 dev_err(&pdev->dev, "Fail to request %s irq\n", irq_desc->name); 398 return ret; 399 } 400 } 401 402 return 0; 403 } 404 405 static int mt6360_regulator_probe(struct platform_device *pdev) 406 { 407 struct mt6360_regulator_data *mrd; 408 struct regulator_config config = {}; 409 int i, ret; 410 411 mrd = devm_kzalloc(&pdev->dev, sizeof(*mrd), GFP_KERNEL); 412 if (!mrd) 413 return -ENOMEM; 414 415 mrd->dev = &pdev->dev; 416 417 mrd->regmap = dev_get_regmap(pdev->dev.parent, NULL); 418 if (!mrd->regmap) { 419 dev_err(&pdev->dev, "Failed to get parent regmap\n"); 420 return -ENODEV; 421 } 422 423 config.dev = pdev->dev.parent; 424 config.driver_data = mrd; 425 config.regmap = mrd->regmap; 426 427 for (i = 0; i < ARRAY_SIZE(mt6360_regulator_descs); i++) { 428 const struct mt6360_regulator_desc *rdesc = mt6360_regulator_descs + i; 429 struct regulator_dev *rdev; 430 431 rdev = devm_regulator_register(&pdev->dev, &rdesc->desc, &config); 432 if (IS_ERR(rdev)) { 433 dev_err(&pdev->dev, "Failed to register %d regulator\n", i); 434 return PTR_ERR(rdev); 435 } 436 437 ret = mt6360_regulator_irq_register(pdev, rdev, rdesc->irq_tables, 438 rdesc->irq_table_size); 439 if (ret) { 440 dev_err(&pdev->dev, "Failed to register %d regulator irqs\n", i); 441 return ret; 442 } 443 } 444 445 return 0; 446 } 447 448 static const struct platform_device_id mt6360_regulator_id_table[] = { 449 { "mt6360-regulator", 0 }, 450 {}, 451 }; 452 MODULE_DEVICE_TABLE(platform, mt6360_regulator_id_table); 453 454 static struct platform_driver mt6360_regulator_driver = { 455 .driver = { 456 .name = "mt6360-regulator", 457 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 458 }, 459 .probe = mt6360_regulator_probe, 460 .id_table = mt6360_regulator_id_table, 461 }; 462 module_platform_driver(mt6360_regulator_driver); 463 464 MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>"); 465 MODULE_DESCRIPTION("MT6360 Regulator Driver"); 466 MODULE_LICENSE("GPL v2"); 467