lp8788-buck.c (13293B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * TI LP8788 MFD - buck regulator driver 4 * 5 * Copyright 2012 Texas Instruments 6 * 7 * Author: Milo(Woogyom) Kim <milo.kim@ti.com> 8 */ 9 10#include <linux/module.h> 11#include <linux/slab.h> 12#include <linux/err.h> 13#include <linux/platform_device.h> 14#include <linux/regulator/driver.h> 15#include <linux/mfd/lp8788.h> 16#include <linux/gpio.h> 17 18/* register address */ 19#define LP8788_EN_BUCK 0x0C 20#define LP8788_BUCK_DVS_SEL 0x1D 21#define LP8788_BUCK1_VOUT0 0x1E 22#define LP8788_BUCK1_VOUT1 0x1F 23#define LP8788_BUCK1_VOUT2 0x20 24#define LP8788_BUCK1_VOUT3 0x21 25#define LP8788_BUCK2_VOUT0 0x22 26#define LP8788_BUCK2_VOUT1 0x23 27#define LP8788_BUCK2_VOUT2 0x24 28#define LP8788_BUCK2_VOUT3 0x25 29#define LP8788_BUCK3_VOUT 0x26 30#define LP8788_BUCK4_VOUT 0x27 31#define LP8788_BUCK1_TIMESTEP 0x28 32#define LP8788_BUCK_PWM 0x2D 33 34/* mask/shift bits */ 35#define LP8788_EN_BUCK1_M BIT(0) /* Addr 0Ch */ 36#define LP8788_EN_BUCK2_M BIT(1) 37#define LP8788_EN_BUCK3_M BIT(2) 38#define LP8788_EN_BUCK4_M BIT(3) 39#define LP8788_BUCK1_DVS_SEL_M 0x04 /* Addr 1Dh */ 40#define LP8788_BUCK1_DVS_M 0x03 41#define LP8788_BUCK1_DVS_S 0 42#define LP8788_BUCK2_DVS_SEL_M 0x40 43#define LP8788_BUCK2_DVS_M 0x30 44#define LP8788_BUCK2_DVS_S 4 45#define LP8788_BUCK1_DVS_I2C BIT(2) 46#define LP8788_BUCK2_DVS_I2C BIT(6) 47#define LP8788_BUCK1_DVS_PIN (0 << 2) 48#define LP8788_BUCK2_DVS_PIN (0 << 6) 49#define LP8788_VOUT_M 0x1F /* Addr 1Eh ~ 27h */ 50#define LP8788_STARTUP_TIME_M 0xF8 /* Addr 28h ~ 2Bh */ 51#define LP8788_STARTUP_TIME_S 3 52#define LP8788_FPWM_BUCK1_M BIT(0) /* Addr 2Dh */ 53#define LP8788_FPWM_BUCK1_S 0 54#define LP8788_FPWM_BUCK2_M BIT(1) 55#define LP8788_FPWM_BUCK2_S 1 56#define LP8788_FPWM_BUCK3_M BIT(2) 57#define LP8788_FPWM_BUCK3_S 2 58#define LP8788_FPWM_BUCK4_M BIT(3) 59#define LP8788_FPWM_BUCK4_S 3 60 61#define INVALID_ADDR 0xFF 62#define LP8788_FORCE_PWM 1 63#define LP8788_AUTO_PWM 0 64#define PIN_LOW 0 65#define PIN_HIGH 1 66#define ENABLE_TIME_USEC 32 67 68#define BUCK_FPWM_MASK(x) (1 << (x)) 69#define BUCK_FPWM_SHIFT(x) (x) 70 71enum lp8788_dvs_state { 72 DVS_LOW = GPIOF_OUT_INIT_LOW, 73 DVS_HIGH = GPIOF_OUT_INIT_HIGH, 74}; 75 76enum lp8788_dvs_mode { 77 REGISTER, 78 EXTPIN, 79}; 80 81enum lp8788_buck_id { 82 BUCK1, 83 BUCK2, 84 BUCK3, 85 BUCK4, 86}; 87 88struct lp8788_buck { 89 struct lp8788 *lp; 90 struct regulator_dev *regulator; 91 void *dvs; 92}; 93 94/* BUCK 1 ~ 4 voltage ranges */ 95static const struct linear_range buck_volt_ranges[] = { 96 REGULATOR_LINEAR_RANGE(500000, 0, 0, 0), 97 REGULATOR_LINEAR_RANGE(800000, 1, 25, 50000), 98}; 99 100static void lp8788_buck1_set_dvs(struct lp8788_buck *buck) 101{ 102 struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs; 103 enum lp8788_dvs_state pinstate; 104 105 if (!dvs) 106 return; 107 108 pinstate = dvs->vsel == DVS_SEL_V0 ? DVS_LOW : DVS_HIGH; 109 if (gpio_is_valid(dvs->gpio)) 110 gpio_set_value(dvs->gpio, pinstate); 111} 112 113static void lp8788_buck2_set_dvs(struct lp8788_buck *buck) 114{ 115 struct lp8788_buck2_dvs *dvs = (struct lp8788_buck2_dvs *)buck->dvs; 116 enum lp8788_dvs_state pin1, pin2; 117 118 if (!dvs) 119 return; 120 121 switch (dvs->vsel) { 122 case DVS_SEL_V0: 123 pin1 = DVS_LOW; 124 pin2 = DVS_LOW; 125 break; 126 case DVS_SEL_V1: 127 pin1 = DVS_HIGH; 128 pin2 = DVS_LOW; 129 break; 130 case DVS_SEL_V2: 131 pin1 = DVS_LOW; 132 pin2 = DVS_HIGH; 133 break; 134 case DVS_SEL_V3: 135 pin1 = DVS_HIGH; 136 pin2 = DVS_HIGH; 137 break; 138 default: 139 return; 140 } 141 142 if (gpio_is_valid(dvs->gpio[0])) 143 gpio_set_value(dvs->gpio[0], pin1); 144 145 if (gpio_is_valid(dvs->gpio[1])) 146 gpio_set_value(dvs->gpio[1], pin2); 147} 148 149static void lp8788_set_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) 150{ 151 switch (id) { 152 case BUCK1: 153 lp8788_buck1_set_dvs(buck); 154 break; 155 case BUCK2: 156 lp8788_buck2_set_dvs(buck); 157 break; 158 default: 159 break; 160 } 161} 162 163static enum lp8788_dvs_mode 164lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id) 165{ 166 u8 val, mask; 167 168 switch (id) { 169 case BUCK1: 170 mask = LP8788_BUCK1_DVS_SEL_M; 171 break; 172 case BUCK2: 173 mask = LP8788_BUCK2_DVS_SEL_M; 174 break; 175 default: 176 return REGISTER; 177 } 178 179 lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); 180 181 return val & mask ? REGISTER : EXTPIN; 182} 183 184static bool lp8788_is_valid_buck_addr(u8 addr) 185{ 186 switch (addr) { 187 case LP8788_BUCK1_VOUT0: 188 case LP8788_BUCK1_VOUT1: 189 case LP8788_BUCK1_VOUT2: 190 case LP8788_BUCK1_VOUT3: 191 case LP8788_BUCK2_VOUT0: 192 case LP8788_BUCK2_VOUT1: 193 case LP8788_BUCK2_VOUT2: 194 case LP8788_BUCK2_VOUT3: 195 return true; 196 default: 197 return false; 198 } 199} 200 201static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck, 202 enum lp8788_buck_id id) 203{ 204 enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id); 205 struct lp8788_buck1_dvs *b1_dvs; 206 struct lp8788_buck2_dvs *b2_dvs; 207 u8 val, idx, addr; 208 int pin1, pin2; 209 210 switch (id) { 211 case BUCK1: 212 if (mode == EXTPIN) { 213 b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs; 214 if (!b1_dvs) 215 goto err; 216 217 idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0; 218 } else { 219 lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); 220 idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S; 221 } 222 addr = LP8788_BUCK1_VOUT0 + idx; 223 break; 224 case BUCK2: 225 if (mode == EXTPIN) { 226 b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs; 227 if (!b2_dvs) 228 goto err; 229 230 pin1 = gpio_get_value(b2_dvs->gpio[0]); 231 pin2 = gpio_get_value(b2_dvs->gpio[1]); 232 233 if (pin1 == PIN_LOW && pin2 == PIN_LOW) 234 idx = 0; 235 else if (pin1 == PIN_LOW && pin2 == PIN_HIGH) 236 idx = 2; 237 else if (pin1 == PIN_HIGH && pin2 == PIN_LOW) 238 idx = 1; 239 else 240 idx = 3; 241 } else { 242 lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); 243 idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S; 244 } 245 addr = LP8788_BUCK2_VOUT0 + idx; 246 break; 247 default: 248 goto err; 249 } 250 251 return addr; 252err: 253 return INVALID_ADDR; 254} 255 256static int lp8788_buck12_set_voltage_sel(struct regulator_dev *rdev, 257 unsigned selector) 258{ 259 struct lp8788_buck *buck = rdev_get_drvdata(rdev); 260 enum lp8788_buck_id id = rdev_get_id(rdev); 261 u8 addr; 262 263 if (buck->dvs) 264 lp8788_set_dvs(buck, id); 265 266 addr = lp8788_select_buck_vout_addr(buck, id); 267 if (!lp8788_is_valid_buck_addr(addr)) 268 return -EINVAL; 269 270 return lp8788_update_bits(buck->lp, addr, LP8788_VOUT_M, selector); 271} 272 273static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev) 274{ 275 struct lp8788_buck *buck = rdev_get_drvdata(rdev); 276 enum lp8788_buck_id id = rdev_get_id(rdev); 277 int ret; 278 u8 val, addr; 279 280 addr = lp8788_select_buck_vout_addr(buck, id); 281 if (!lp8788_is_valid_buck_addr(addr)) 282 return -EINVAL; 283 284 ret = lp8788_read_byte(buck->lp, addr, &val); 285 if (ret) 286 return ret; 287 288 return val & LP8788_VOUT_M; 289} 290 291static int lp8788_buck_enable_time(struct regulator_dev *rdev) 292{ 293 struct lp8788_buck *buck = rdev_get_drvdata(rdev); 294 enum lp8788_buck_id id = rdev_get_id(rdev); 295 u8 val, addr = LP8788_BUCK1_TIMESTEP + id; 296 297 if (lp8788_read_byte(buck->lp, addr, &val)) 298 return -EINVAL; 299 300 val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S; 301 302 return ENABLE_TIME_USEC * val; 303} 304 305static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) 306{ 307 struct lp8788_buck *buck = rdev_get_drvdata(rdev); 308 enum lp8788_buck_id id = rdev_get_id(rdev); 309 u8 mask, val; 310 311 mask = BUCK_FPWM_MASK(id); 312 switch (mode) { 313 case REGULATOR_MODE_FAST: 314 val = LP8788_FORCE_PWM << BUCK_FPWM_SHIFT(id); 315 break; 316 case REGULATOR_MODE_NORMAL: 317 val = LP8788_AUTO_PWM << BUCK_FPWM_SHIFT(id); 318 break; 319 default: 320 return -EINVAL; 321 } 322 323 return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, mask, val); 324} 325 326static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev) 327{ 328 struct lp8788_buck *buck = rdev_get_drvdata(rdev); 329 enum lp8788_buck_id id = rdev_get_id(rdev); 330 u8 val; 331 int ret; 332 333 ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val); 334 if (ret) 335 return ret; 336 337 return val & BUCK_FPWM_MASK(id) ? 338 REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; 339} 340 341static const struct regulator_ops lp8788_buck12_ops = { 342 .list_voltage = regulator_list_voltage_linear_range, 343 .map_voltage = regulator_map_voltage_linear_range, 344 .set_voltage_sel = lp8788_buck12_set_voltage_sel, 345 .get_voltage_sel = lp8788_buck12_get_voltage_sel, 346 .enable = regulator_enable_regmap, 347 .disable = regulator_disable_regmap, 348 .is_enabled = regulator_is_enabled_regmap, 349 .enable_time = lp8788_buck_enable_time, 350 .set_mode = lp8788_buck_set_mode, 351 .get_mode = lp8788_buck_get_mode, 352}; 353 354static const struct regulator_ops lp8788_buck34_ops = { 355 .list_voltage = regulator_list_voltage_linear_range, 356 .map_voltage = regulator_map_voltage_linear_range, 357 .set_voltage_sel = regulator_set_voltage_sel_regmap, 358 .get_voltage_sel = regulator_get_voltage_sel_regmap, 359 .enable = regulator_enable_regmap, 360 .disable = regulator_disable_regmap, 361 .is_enabled = regulator_is_enabled_regmap, 362 .enable_time = lp8788_buck_enable_time, 363 .set_mode = lp8788_buck_set_mode, 364 .get_mode = lp8788_buck_get_mode, 365}; 366 367static const struct regulator_desc lp8788_buck_desc[] = { 368 { 369 .name = "buck1", 370 .id = BUCK1, 371 .ops = &lp8788_buck12_ops, 372 .n_voltages = 26, 373 .linear_ranges = buck_volt_ranges, 374 .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), 375 .type = REGULATOR_VOLTAGE, 376 .owner = THIS_MODULE, 377 .enable_reg = LP8788_EN_BUCK, 378 .enable_mask = LP8788_EN_BUCK1_M, 379 }, 380 { 381 .name = "buck2", 382 .id = BUCK2, 383 .ops = &lp8788_buck12_ops, 384 .n_voltages = 26, 385 .linear_ranges = buck_volt_ranges, 386 .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), 387 .type = REGULATOR_VOLTAGE, 388 .owner = THIS_MODULE, 389 .enable_reg = LP8788_EN_BUCK, 390 .enable_mask = LP8788_EN_BUCK2_M, 391 }, 392 { 393 .name = "buck3", 394 .id = BUCK3, 395 .ops = &lp8788_buck34_ops, 396 .n_voltages = 26, 397 .linear_ranges = buck_volt_ranges, 398 .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), 399 .type = REGULATOR_VOLTAGE, 400 .owner = THIS_MODULE, 401 .vsel_reg = LP8788_BUCK3_VOUT, 402 .vsel_mask = LP8788_VOUT_M, 403 .enable_reg = LP8788_EN_BUCK, 404 .enable_mask = LP8788_EN_BUCK3_M, 405 }, 406 { 407 .name = "buck4", 408 .id = BUCK4, 409 .ops = &lp8788_buck34_ops, 410 .n_voltages = 26, 411 .linear_ranges = buck_volt_ranges, 412 .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), 413 .type = REGULATOR_VOLTAGE, 414 .owner = THIS_MODULE, 415 .vsel_reg = LP8788_BUCK4_VOUT, 416 .vsel_mask = LP8788_VOUT_M, 417 .enable_reg = LP8788_EN_BUCK, 418 .enable_mask = LP8788_EN_BUCK4_M, 419 }, 420}; 421 422static int lp8788_dvs_gpio_request(struct platform_device *pdev, 423 struct lp8788_buck *buck, 424 enum lp8788_buck_id id) 425{ 426 struct lp8788_platform_data *pdata = buck->lp->pdata; 427 char *b1_name = "LP8788_B1_DVS"; 428 char *b2_name[] = { "LP8788_B2_DVS1", "LP8788_B2_DVS2" }; 429 int i, gpio, ret; 430 431 switch (id) { 432 case BUCK1: 433 gpio = pdata->buck1_dvs->gpio; 434 ret = devm_gpio_request_one(&pdev->dev, gpio, DVS_LOW, 435 b1_name); 436 if (ret) 437 return ret; 438 439 buck->dvs = pdata->buck1_dvs; 440 break; 441 case BUCK2: 442 for (i = 0; i < LP8788_NUM_BUCK2_DVS; i++) { 443 gpio = pdata->buck2_dvs->gpio[i]; 444 ret = devm_gpio_request_one(&pdev->dev, gpio, 445 DVS_LOW, b2_name[i]); 446 if (ret) 447 return ret; 448 } 449 buck->dvs = pdata->buck2_dvs; 450 break; 451 default: 452 break; 453 } 454 455 return 0; 456} 457 458static int lp8788_init_dvs(struct platform_device *pdev, 459 struct lp8788_buck *buck, enum lp8788_buck_id id) 460{ 461 struct lp8788_platform_data *pdata = buck->lp->pdata; 462 u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M }; 463 u8 val[] = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN }; 464 u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C }; 465 466 /* no dvs for buck3, 4 */ 467 if (id > BUCK2) 468 return 0; 469 470 /* no dvs platform data, then dvs will be selected by I2C registers */ 471 if (!pdata) 472 goto set_default_dvs_mode; 473 474 if ((id == BUCK1 && !pdata->buck1_dvs) || 475 (id == BUCK2 && !pdata->buck2_dvs)) 476 goto set_default_dvs_mode; 477 478 if (lp8788_dvs_gpio_request(pdev, buck, id)) 479 goto set_default_dvs_mode; 480 481 return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id], 482 val[id]); 483 484set_default_dvs_mode: 485 return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id], 486 default_dvs_mode[id]); 487} 488 489static int lp8788_buck_probe(struct platform_device *pdev) 490{ 491 struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); 492 int id = pdev->id; 493 struct lp8788_buck *buck; 494 struct regulator_config cfg = { }; 495 struct regulator_dev *rdev; 496 int ret; 497 498 if (id >= LP8788_NUM_BUCKS) 499 return -EINVAL; 500 501 buck = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_buck), GFP_KERNEL); 502 if (!buck) 503 return -ENOMEM; 504 505 buck->lp = lp; 506 507 ret = lp8788_init_dvs(pdev, buck, id); 508 if (ret) 509 return ret; 510 511 cfg.dev = pdev->dev.parent; 512 cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL; 513 cfg.driver_data = buck; 514 cfg.regmap = lp->regmap; 515 516 rdev = devm_regulator_register(&pdev->dev, &lp8788_buck_desc[id], &cfg); 517 if (IS_ERR(rdev)) { 518 ret = PTR_ERR(rdev); 519 dev_err(&pdev->dev, "BUCK%d regulator register err = %d\n", 520 id + 1, ret); 521 return ret; 522 } 523 524 buck->regulator = rdev; 525 platform_set_drvdata(pdev, buck); 526 527 return 0; 528} 529 530static struct platform_driver lp8788_buck_driver = { 531 .probe = lp8788_buck_probe, 532 .driver = { 533 .name = LP8788_DEV_BUCK, 534 }, 535}; 536 537static int __init lp8788_buck_init(void) 538{ 539 return platform_driver_register(&lp8788_buck_driver); 540} 541subsys_initcall(lp8788_buck_init); 542 543static void __exit lp8788_buck_exit(void) 544{ 545 platform_driver_unregister(&lp8788_buck_driver); 546} 547module_exit(lp8788_buck_exit); 548 549MODULE_DESCRIPTION("TI LP8788 BUCK Driver"); 550MODULE_AUTHOR("Milo Kim"); 551MODULE_LICENSE("GPL"); 552MODULE_ALIAS("platform:lp8788-buck");