1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Copyright (C) 2021 Samuel Holland <samuel@sholland.org> 4 5 #include <linux/i2c.h> 6 #include <linux/module.h> 7 #include <linux/power_supply.h> 8 #include <linux/regmap.h> 9 10 #define IP5XXX_SYS_CTL0 0x01 11 #define IP5XXX_SYS_CTL0_WLED_DET_EN BIT(4) 12 #define IP5XXX_SYS_CTL0_WLED_EN BIT(3) 13 #define IP5XXX_SYS_CTL0_BOOST_EN BIT(2) 14 #define IP5XXX_SYS_CTL0_CHARGER_EN BIT(1) 15 #define IP5XXX_SYS_CTL1 0x02 16 #define IP5XXX_SYS_CTL1_LIGHT_SHDN_EN BIT(1) 17 #define IP5XXX_SYS_CTL1_LOAD_PWRUP_EN BIT(0) 18 #define IP5XXX_SYS_CTL2 0x0c 19 #define IP5XXX_SYS_CTL2_LIGHT_SHDN_TH GENMASK(7, 3) 20 #define IP5XXX_SYS_CTL3 0x03 21 #define IP5XXX_SYS_CTL3_LONG_PRESS_TIME_SEL GENMASK(7, 6) 22 #define IP5XXX_SYS_CTL3_BTN_SHDN_EN BIT(5) 23 #define IP5XXX_SYS_CTL4 0x04 24 #define IP5XXX_SYS_CTL4_SHDN_TIME_SEL GENMASK(7, 6) 25 #define IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN BIT(5) 26 #define IP5XXX_SYS_CTL5 0x07 27 #define IP5XXX_SYS_CTL5_NTC_DIS BIT(6) 28 #define IP5XXX_SYS_CTL5_WLED_MODE_SEL BIT(1) 29 #define IP5XXX_SYS_CTL5_BTN_SHDN_SEL BIT(0) 30 #define IP5XXX_CHG_CTL1 0x22 31 #define IP5XXX_CHG_CTL1_BOOST_UVP_SEL GENMASK(3, 2) 32 #define IP5XXX_CHG_CTL2 0x24 33 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL GENMASK(6, 5) 34 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V (0x0 << 5) 35 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V (0x1 << 5) 36 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V (0x2 << 5) 37 #define IP5XXX_CHG_CTL2_CONST_VOLT_SEL GENMASK(2, 1) 38 #define IP5XXX_CHG_CTL4 0x26 39 #define IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN BIT(6) 40 #define IP5XXX_CHG_CTL4A 0x25 41 #define IP5XXX_CHG_CTL4A_CONST_CUR_SEL GENMASK(4, 0) 42 #define IP5XXX_MFP_CTL0 0x51 43 #define IP5XXX_MFP_CTL1 0x52 44 #define IP5XXX_GPIO_CTL2 0x53 45 #define IP5XXX_GPIO_CTL2A 0x54 46 #define IP5XXX_GPIO_CTL3 0x55 47 #define IP5XXX_READ0 0x71 48 #define IP5XXX_READ0_CHG_STAT GENMASK(7, 5) 49 #define IP5XXX_READ0_CHG_STAT_IDLE (0x0 << 5) 50 #define IP5XXX_READ0_CHG_STAT_TRICKLE (0x1 << 5) 51 #define IP5XXX_READ0_CHG_STAT_CONST_VOLT (0x2 << 5) 52 #define IP5XXX_READ0_CHG_STAT_CONST_CUR (0x3 << 5) 53 #define IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP (0x4 << 5) 54 #define IP5XXX_READ0_CHG_STAT_FULL (0x5 << 5) 55 #define IP5XXX_READ0_CHG_STAT_TIMEOUT (0x6 << 5) 56 #define IP5XXX_READ0_CHG_OP BIT(4) 57 #define IP5XXX_READ0_CHG_END BIT(3) 58 #define IP5XXX_READ0_CONST_VOLT_TIMEOUT BIT(2) 59 #define IP5XXX_READ0_CHG_TIMEOUT BIT(1) 60 #define IP5XXX_READ0_TRICKLE_TIMEOUT BIT(0) 61 #define IP5XXX_READ0_TIMEOUT GENMASK(2, 0) 62 #define IP5XXX_READ1 0x72 63 #define IP5XXX_READ1_WLED_PRESENT BIT(7) 64 #define IP5XXX_READ1_LIGHT_LOAD BIT(6) 65 #define IP5XXX_READ1_VIN_OVERVOLT BIT(5) 66 #define IP5XXX_READ2 0x77 67 #define IP5XXX_READ2_BTN_PRESS BIT(3) 68 #define IP5XXX_READ2_BTN_LONG_PRESS BIT(1) 69 #define IP5XXX_READ2_BTN_SHORT_PRESS BIT(0) 70 #define IP5XXX_BATVADC_DAT0 0xa2 71 #define IP5XXX_BATVADC_DAT1 0xa3 72 #define IP5XXX_BATIADC_DAT0 0xa4 73 #define IP5XXX_BATIADC_DAT1 0xa5 74 #define IP5XXX_BATOCV_DAT0 0xa8 75 #define IP5XXX_BATOCV_DAT1 0xa9 76 77 struct ip5xxx { 78 struct regmap *regmap; 79 bool initialized; 80 }; 81 82 /* 83 * The IP5xxx charger only responds on I2C when it is "awake". The charger is 84 * generally only awake when VIN is powered or when its boost converter is 85 * enabled. Going into shutdown resets all register values. To handle this: 86 * 1) When any bus error occurs, assume the charger has gone into shutdown. 87 * 2) Attempt the initialization sequence on each subsequent register access 88 * until it succeeds. 89 */ 90 static int ip5xxx_read(struct ip5xxx *ip5xxx, unsigned int reg, 91 unsigned int *val) 92 { 93 int ret; 94 95 ret = regmap_read(ip5xxx->regmap, reg, val); 96 if (ret) 97 ip5xxx->initialized = false; 98 99 return ret; 100 } 101 102 static int ip5xxx_update_bits(struct ip5xxx *ip5xxx, unsigned int reg, 103 unsigned int mask, unsigned int val) 104 { 105 int ret; 106 107 ret = regmap_update_bits(ip5xxx->regmap, reg, mask, val); 108 if (ret) 109 ip5xxx->initialized = false; 110 111 return ret; 112 } 113 114 static int ip5xxx_initialize(struct power_supply *psy) 115 { 116 struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 117 int ret; 118 119 if (ip5xxx->initialized) 120 return 0; 121 122 /* 123 * Disable shutdown under light load. 124 * Enable power on when under load. 125 */ 126 ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL1, 127 IP5XXX_SYS_CTL1_LIGHT_SHDN_EN | 128 IP5XXX_SYS_CTL1_LOAD_PWRUP_EN, 129 IP5XXX_SYS_CTL1_LOAD_PWRUP_EN); 130 if (ret) 131 return ret; 132 133 /* 134 * Enable shutdown after a long button press (as configured below). 135 */ 136 ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL3, 137 IP5XXX_SYS_CTL3_BTN_SHDN_EN, 138 IP5XXX_SYS_CTL3_BTN_SHDN_EN); 139 if (ret) 140 return ret; 141 142 /* 143 * Power on automatically when VIN is removed. 144 */ 145 ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL4, 146 IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN, 147 IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN); 148 if (ret) 149 return ret; 150 151 /* 152 * Enable the NTC. 153 * Configure the button for two presses => LED, long press => shutdown. 154 */ 155 ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL5, 156 IP5XXX_SYS_CTL5_NTC_DIS | 157 IP5XXX_SYS_CTL5_WLED_MODE_SEL | 158 IP5XXX_SYS_CTL5_BTN_SHDN_SEL, 159 IP5XXX_SYS_CTL5_WLED_MODE_SEL | 160 IP5XXX_SYS_CTL5_BTN_SHDN_SEL); 161 if (ret) 162 return ret; 163 164 ip5xxx->initialized = true; 165 dev_dbg(psy->dev.parent, "Initialized after power on\n"); 166 167 return 0; 168 } 169 170 static const enum power_supply_property ip5xxx_battery_properties[] = { 171 POWER_SUPPLY_PROP_STATUS, 172 POWER_SUPPLY_PROP_CHARGE_TYPE, 173 POWER_SUPPLY_PROP_HEALTH, 174 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 175 POWER_SUPPLY_PROP_VOLTAGE_NOW, 176 POWER_SUPPLY_PROP_VOLTAGE_OCV, 177 POWER_SUPPLY_PROP_CURRENT_NOW, 178 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 179 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 180 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 181 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 182 }; 183 184 static int ip5xxx_battery_get_status(struct ip5xxx *ip5xxx, int *val) 185 { 186 unsigned int rval; 187 int ret; 188 189 ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 190 if (ret) 191 return ret; 192 193 switch (rval & IP5XXX_READ0_CHG_STAT) { 194 case IP5XXX_READ0_CHG_STAT_IDLE: 195 *val = POWER_SUPPLY_STATUS_DISCHARGING; 196 break; 197 case IP5XXX_READ0_CHG_STAT_TRICKLE: 198 case IP5XXX_READ0_CHG_STAT_CONST_CUR: 199 case IP5XXX_READ0_CHG_STAT_CONST_VOLT: 200 *val = POWER_SUPPLY_STATUS_CHARGING; 201 break; 202 case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP: 203 case IP5XXX_READ0_CHG_STAT_FULL: 204 *val = POWER_SUPPLY_STATUS_FULL; 205 break; 206 case IP5XXX_READ0_CHG_STAT_TIMEOUT: 207 *val = POWER_SUPPLY_STATUS_NOT_CHARGING; 208 break; 209 default: 210 return -EINVAL; 211 } 212 213 return 0; 214 } 215 216 static int ip5xxx_battery_get_charge_type(struct ip5xxx *ip5xxx, int *val) 217 { 218 unsigned int rval; 219 int ret; 220 221 ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 222 if (ret) 223 return ret; 224 225 switch (rval & IP5XXX_READ0_CHG_STAT) { 226 case IP5XXX_READ0_CHG_STAT_IDLE: 227 case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP: 228 case IP5XXX_READ0_CHG_STAT_FULL: 229 case IP5XXX_READ0_CHG_STAT_TIMEOUT: 230 *val = POWER_SUPPLY_CHARGE_TYPE_NONE; 231 break; 232 case IP5XXX_READ0_CHG_STAT_TRICKLE: 233 *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 234 break; 235 case IP5XXX_READ0_CHG_STAT_CONST_CUR: 236 case IP5XXX_READ0_CHG_STAT_CONST_VOLT: 237 *val = POWER_SUPPLY_CHARGE_TYPE_STANDARD; 238 break; 239 default: 240 return -EINVAL; 241 } 242 243 return 0; 244 } 245 246 static int ip5xxx_battery_get_health(struct ip5xxx *ip5xxx, int *val) 247 { 248 unsigned int rval; 249 int ret; 250 251 ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 252 if (ret) 253 return ret; 254 255 if (rval & IP5XXX_READ0_TIMEOUT) 256 *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; 257 else 258 *val = POWER_SUPPLY_HEALTH_GOOD; 259 260 return 0; 261 } 262 263 static int ip5xxx_battery_get_voltage_max(struct ip5xxx *ip5xxx, int *val) 264 { 265 unsigned int rval; 266 int ret; 267 268 ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL2, &rval); 269 if (ret) 270 return ret; 271 272 /* 273 * It is not clear what this will return if 274 * IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN is not set... 275 */ 276 switch (rval & IP5XXX_CHG_CTL2_BAT_TYPE_SEL) { 277 case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V: 278 *val = 4200000; 279 break; 280 case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V: 281 *val = 4300000; 282 break; 283 case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V: 284 *val = 4350000; 285 break; 286 default: 287 return -EINVAL; 288 } 289 290 return 0; 291 } 292 293 static int ip5xxx_battery_read_adc(struct ip5xxx *ip5xxx, 294 u8 lo_reg, u8 hi_reg, int *val) 295 { 296 unsigned int hi, lo; 297 int ret; 298 299 ret = ip5xxx_read(ip5xxx, lo_reg, &lo); 300 if (ret) 301 return ret; 302 303 ret = ip5xxx_read(ip5xxx, hi_reg, &hi); 304 if (ret) 305 return ret; 306 307 *val = sign_extend32(hi << 8 | lo, 13); 308 309 return 0; 310 } 311 312 static int ip5xxx_battery_get_property(struct power_supply *psy, 313 enum power_supply_property psp, 314 union power_supply_propval *val) 315 { 316 struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 317 int raw, ret, vmax; 318 unsigned int rval; 319 320 ret = ip5xxx_initialize(psy); 321 if (ret) 322 return ret; 323 324 switch (psp) { 325 case POWER_SUPPLY_PROP_STATUS: 326 return ip5xxx_battery_get_status(ip5xxx, &val->intval); 327 328 case POWER_SUPPLY_PROP_CHARGE_TYPE: 329 return ip5xxx_battery_get_charge_type(ip5xxx, &val->intval); 330 331 case POWER_SUPPLY_PROP_HEALTH: 332 return ip5xxx_battery_get_health(ip5xxx, &val->intval); 333 334 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 335 return ip5xxx_battery_get_voltage_max(ip5xxx, &val->intval); 336 337 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 338 ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATVADC_DAT0, 339 IP5XXX_BATVADC_DAT1, &raw); 340 341 val->intval = 2600000 + DIV_ROUND_CLOSEST(raw * 26855, 100); 342 return 0; 343 344 case POWER_SUPPLY_PROP_VOLTAGE_OCV: 345 ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATOCV_DAT0, 346 IP5XXX_BATOCV_DAT1, &raw); 347 348 val->intval = 2600000 + DIV_ROUND_CLOSEST(raw * 26855, 100); 349 return 0; 350 351 case POWER_SUPPLY_PROP_CURRENT_NOW: 352 ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATIADC_DAT0, 353 IP5XXX_BATIADC_DAT1, &raw); 354 355 val->intval = DIV_ROUND_CLOSEST(raw * 149197, 200); 356 return 0; 357 358 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 359 ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL4A, &rval); 360 if (ret) 361 return ret; 362 363 rval &= IP5XXX_CHG_CTL4A_CONST_CUR_SEL; 364 val->intval = 100000 * rval; 365 return 0; 366 367 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 368 val->intval = 100000 * 0x1f; 369 return 0; 370 371 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 372 ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax); 373 if (ret) 374 return ret; 375 376 ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL2, &rval); 377 if (ret) 378 return ret; 379 380 rval &= IP5XXX_CHG_CTL2_CONST_VOLT_SEL; 381 val->intval = vmax + 14000 * (rval >> 1); 382 return 0; 383 384 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 385 ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax); 386 if (ret) 387 return ret; 388 389 val->intval = vmax + 14000 * 3; 390 return 0; 391 392 default: 393 return -EINVAL; 394 } 395 } 396 397 static int ip5xxx_battery_set_voltage_max(struct ip5xxx *ip5xxx, int val) 398 { 399 unsigned int rval; 400 int ret; 401 402 switch (val) { 403 case 4200000: 404 rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V; 405 break; 406 case 4300000: 407 rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V; 408 break; 409 case 4350000: 410 rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V; 411 break; 412 default: 413 return -EINVAL; 414 } 415 416 ret = ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2, 417 IP5XXX_CHG_CTL2_BAT_TYPE_SEL, rval); 418 if (ret) 419 return ret; 420 421 ret = ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL4, 422 IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN, 423 IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN); 424 if (ret) 425 return ret; 426 427 return 0; 428 } 429 430 static int ip5xxx_battery_set_property(struct power_supply *psy, 431 enum power_supply_property psp, 432 const union power_supply_propval *val) 433 { 434 struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 435 unsigned int rval; 436 int ret, vmax; 437 438 ret = ip5xxx_initialize(psy); 439 if (ret) 440 return ret; 441 442 switch (psp) { 443 case POWER_SUPPLY_PROP_STATUS: 444 switch (val->intval) { 445 case POWER_SUPPLY_STATUS_CHARGING: 446 rval = IP5XXX_SYS_CTL0_CHARGER_EN; 447 break; 448 case POWER_SUPPLY_STATUS_DISCHARGING: 449 case POWER_SUPPLY_STATUS_NOT_CHARGING: 450 rval = 0; 451 break; 452 default: 453 return -EINVAL; 454 } 455 return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0, 456 IP5XXX_SYS_CTL0_CHARGER_EN, rval); 457 458 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 459 return ip5xxx_battery_set_voltage_max(ip5xxx, val->intval); 460 461 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 462 rval = val->intval / 100000; 463 return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL4A, 464 IP5XXX_CHG_CTL4A_CONST_CUR_SEL, rval); 465 466 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 467 ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax); 468 if (ret) 469 return ret; 470 471 rval = ((val->intval - vmax) / 14000) << 1; 472 return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2, 473 IP5XXX_CHG_CTL2_CONST_VOLT_SEL, rval); 474 475 default: 476 return -EINVAL; 477 } 478 } 479 480 static int ip5xxx_battery_property_is_writeable(struct power_supply *psy, 481 enum power_supply_property psp) 482 { 483 return psp == POWER_SUPPLY_PROP_STATUS || 484 psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN || 485 psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT || 486 psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE; 487 } 488 489 static const struct power_supply_desc ip5xxx_battery_desc = { 490 .name = "ip5xxx-battery", 491 .type = POWER_SUPPLY_TYPE_BATTERY, 492 .properties = ip5xxx_battery_properties, 493 .num_properties = ARRAY_SIZE(ip5xxx_battery_properties), 494 .get_property = ip5xxx_battery_get_property, 495 .set_property = ip5xxx_battery_set_property, 496 .property_is_writeable = ip5xxx_battery_property_is_writeable, 497 }; 498 499 static const enum power_supply_property ip5xxx_boost_properties[] = { 500 POWER_SUPPLY_PROP_ONLINE, 501 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 502 }; 503 504 static int ip5xxx_boost_get_property(struct power_supply *psy, 505 enum power_supply_property psp, 506 union power_supply_propval *val) 507 { 508 struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 509 unsigned int rval; 510 int ret; 511 512 ret = ip5xxx_initialize(psy); 513 if (ret) 514 return ret; 515 516 switch (psp) { 517 case POWER_SUPPLY_PROP_ONLINE: 518 ret = ip5xxx_read(ip5xxx, IP5XXX_SYS_CTL0, &rval); 519 if (ret) 520 return ret; 521 522 val->intval = !!(rval & IP5XXX_SYS_CTL0_BOOST_EN); 523 return 0; 524 525 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 526 ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL1, &rval); 527 if (ret) 528 return ret; 529 530 rval &= IP5XXX_CHG_CTL1_BOOST_UVP_SEL; 531 val->intval = 4530000 + 100000 * (rval >> 2); 532 return 0; 533 534 default: 535 return -EINVAL; 536 } 537 } 538 539 static int ip5xxx_boost_set_property(struct power_supply *psy, 540 enum power_supply_property psp, 541 const union power_supply_propval *val) 542 { 543 struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 544 unsigned int rval; 545 int ret; 546 547 ret = ip5xxx_initialize(psy); 548 if (ret) 549 return ret; 550 551 switch (psp) { 552 case POWER_SUPPLY_PROP_ONLINE: 553 rval = val->intval ? IP5XXX_SYS_CTL0_BOOST_EN : 0; 554 return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0, 555 IP5XXX_SYS_CTL0_BOOST_EN, rval); 556 557 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 558 rval = ((val->intval - 4530000) / 100000) << 2; 559 return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL1, 560 IP5XXX_CHG_CTL1_BOOST_UVP_SEL, rval); 561 562 default: 563 return -EINVAL; 564 } 565 } 566 567 static int ip5xxx_boost_property_is_writeable(struct power_supply *psy, 568 enum power_supply_property psp) 569 { 570 return true; 571 } 572 573 static const struct power_supply_desc ip5xxx_boost_desc = { 574 .name = "ip5xxx-boost", 575 .type = POWER_SUPPLY_TYPE_USB, 576 .properties = ip5xxx_boost_properties, 577 .num_properties = ARRAY_SIZE(ip5xxx_boost_properties), 578 .get_property = ip5xxx_boost_get_property, 579 .set_property = ip5xxx_boost_set_property, 580 .property_is_writeable = ip5xxx_boost_property_is_writeable, 581 }; 582 583 static const struct regmap_config ip5xxx_regmap_config = { 584 .reg_bits = 8, 585 .val_bits = 8, 586 .max_register = IP5XXX_BATOCV_DAT1, 587 }; 588 589 static int ip5xxx_power_probe(struct i2c_client *client) 590 { 591 struct power_supply_config psy_cfg = {}; 592 struct device *dev = &client->dev; 593 struct power_supply *psy; 594 struct ip5xxx *ip5xxx; 595 596 ip5xxx = devm_kzalloc(dev, sizeof(*ip5xxx), GFP_KERNEL); 597 if (!ip5xxx) 598 return -ENOMEM; 599 600 ip5xxx->regmap = devm_regmap_init_i2c(client, &ip5xxx_regmap_config); 601 if (IS_ERR(ip5xxx->regmap)) 602 return PTR_ERR(ip5xxx->regmap); 603 604 psy_cfg.of_node = dev->of_node; 605 psy_cfg.drv_data = ip5xxx; 606 607 psy = devm_power_supply_register(dev, &ip5xxx_battery_desc, &psy_cfg); 608 if (IS_ERR(psy)) 609 return PTR_ERR(psy); 610 611 psy = devm_power_supply_register(dev, &ip5xxx_boost_desc, &psy_cfg); 612 if (IS_ERR(psy)) 613 return PTR_ERR(psy); 614 615 return 0; 616 } 617 618 static const struct of_device_id ip5xxx_power_of_match[] = { 619 { .compatible = "injoinic,ip5108" }, 620 { .compatible = "injoinic,ip5109" }, 621 { .compatible = "injoinic,ip5207" }, 622 { .compatible = "injoinic,ip5209" }, 623 { } 624 }; 625 MODULE_DEVICE_TABLE(of, ip5xxx_power_of_match); 626 627 static struct i2c_driver ip5xxx_power_driver = { 628 .probe = ip5xxx_power_probe, 629 .driver = { 630 .name = "ip5xxx-power", 631 .of_match_table = ip5xxx_power_of_match, 632 } 633 }; 634 module_i2c_driver(ip5xxx_power_driver); 635 636 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>"); 637 MODULE_DESCRIPTION("Injoinic IP5xxx power bank IC driver"); 638 MODULE_LICENSE("GPL"); 639