mt6360-regulator.c (14652B)
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 18enum { 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 30struct mt6360_irq_mapping { 31 const char *name; 32 irq_handler_t handler; 33}; 34 35struct 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 45struct mt6360_regulator_data { 46 struct device *dev; 47 struct regmap *regmap; 48}; 49 50static 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 58static 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 66static 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 74static 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 82static 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 89static 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 96static 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 101static 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 106static 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 111static 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 116static 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 121static 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 126static 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 131static 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 166static 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 201static 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 220static 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 252static 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 279static 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 296static 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 308static 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(_name, _sname, ereg, emask, vreg, vmask, \ 323 mreg, mmask, streg, stmask, vranges, \ 324 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(#_name), \ 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 353static const struct mt6360_regulator_desc mt6360_regulator_descs[] = { 354 MT6360_REGULATOR_DESC(BUCK1, BUCK1_VIN, 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04, 355 buck_vout_ranges, 256, 0, buck1_irq_tbls), 356 MT6360_REGULATOR_DESC(BUCK2, BUCK2_VIN, 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04, 357 buck_vout_ranges, 256, 0, buck2_irq_tbls), 358 MT6360_REGULATOR_DESC(LDO6, LDO_VIN3, 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04, 359 ldo_vout_ranges1, 256, 0, ldo6_irq_tbls), 360 MT6360_REGULATOR_DESC(LDO7, LDO_VIN3, 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04, 361 ldo_vout_ranges1, 256, 0, ldo7_irq_tbls), 362 MT6360_REGULATOR_DESC(LDO1, LDO_VIN1, 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04, 363 ldo_vout_ranges2, 256, 0, ldo1_irq_tbls), 364 MT6360_REGULATOR_DESC(LDO2, LDO_VIN1, 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04, 365 ldo_vout_ranges2, 256, 0, ldo2_irq_tbls), 366 MT6360_REGULATOR_DESC(LDO3, LDO_VIN1, 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04, 367 ldo_vout_ranges2, 256, 100, ldo3_irq_tbls), 368 MT6360_REGULATOR_DESC(LDO5, LDO_VIN2, 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04, 369 ldo_vout_ranges3, 128, 100, ldo5_irq_tbls), 370}; 371 372static int mt6360_regulator_irq_register(struct platform_device *pdev, 373 struct regulator_dev *rdev, 374 const struct mt6360_irq_mapping *tbls, 375 int tbl_size) 376{ 377 int i, irq, ret; 378 379 for (i = 0; i < tbl_size; i++) { 380 const struct mt6360_irq_mapping *irq_desc = tbls + i; 381 382 irq = platform_get_irq_byname(pdev, irq_desc->name); 383 if (irq < 0) 384 return irq; 385 386 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, irq_desc->handler, 0, 387 irq_desc->name, rdev); 388 if (ret) { 389 dev_err(&pdev->dev, "Fail to request %s irq\n", irq_desc->name); 390 return ret; 391 } 392 } 393 394 return 0; 395} 396 397static int mt6360_regulator_probe(struct platform_device *pdev) 398{ 399 struct mt6360_regulator_data *mrd; 400 struct regulator_config config = {}; 401 int i, ret; 402 403 mrd = devm_kzalloc(&pdev->dev, sizeof(*mrd), GFP_KERNEL); 404 if (!mrd) 405 return -ENOMEM; 406 407 mrd->dev = &pdev->dev; 408 409 mrd->regmap = dev_get_regmap(pdev->dev.parent, NULL); 410 if (!mrd->regmap) { 411 dev_err(&pdev->dev, "Failed to get parent regmap\n"); 412 return -ENODEV; 413 } 414 415 config.dev = pdev->dev.parent; 416 config.driver_data = mrd; 417 config.regmap = mrd->regmap; 418 419 for (i = 0; i < ARRAY_SIZE(mt6360_regulator_descs); i++) { 420 const struct mt6360_regulator_desc *rdesc = mt6360_regulator_descs + i; 421 struct regulator_dev *rdev; 422 423 rdev = devm_regulator_register(&pdev->dev, &rdesc->desc, &config); 424 if (IS_ERR(rdev)) { 425 dev_err(&pdev->dev, "Failed to register %d regulator\n", i); 426 return PTR_ERR(rdev); 427 } 428 429 ret = mt6360_regulator_irq_register(pdev, rdev, rdesc->irq_tables, 430 rdesc->irq_table_size); 431 if (ret) { 432 dev_err(&pdev->dev, "Failed to register %d regulator irqs\n", i); 433 return ret; 434 } 435 } 436 437 return 0; 438} 439 440static const struct platform_device_id mt6360_regulator_id_table[] = { 441 { "mt6360-regulator", 0 }, 442 {}, 443}; 444MODULE_DEVICE_TABLE(platform, mt6360_regulator_id_table); 445 446static struct platform_driver mt6360_regulator_driver = { 447 .driver = { 448 .name = "mt6360-regulator", 449 }, 450 .probe = mt6360_regulator_probe, 451 .id_table = mt6360_regulator_id_table, 452}; 453module_platform_driver(mt6360_regulator_driver); 454 455MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>"); 456MODULE_DESCRIPTION("MT6360 Regulator Driver"); 457MODULE_LICENSE("GPL v2");