639 lines · c
1// SPDX-License-Identifier: GPL-2.02//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 0x0111#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 0x0216#define IP5XXX_SYS_CTL1_LIGHT_SHDN_EN BIT(1)17#define IP5XXX_SYS_CTL1_LOAD_PWRUP_EN BIT(0)18#define IP5XXX_SYS_CTL2 0x0c19#define IP5XXX_SYS_CTL2_LIGHT_SHDN_TH GENMASK(7, 3)20#define IP5XXX_SYS_CTL3 0x0321#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 0x0424#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 0x0727#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 0x2231#define IP5XXX_CHG_CTL1_BOOST_UVP_SEL GENMASK(3, 2)32#define IP5XXX_CHG_CTL2 0x2433#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 0x2639#define IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN BIT(6)40#define IP5XXX_CHG_CTL4A 0x2541#define IP5XXX_CHG_CTL4A_CONST_CUR_SEL GENMASK(4, 0)42#define IP5XXX_MFP_CTL0 0x5143#define IP5XXX_MFP_CTL1 0x5244#define IP5XXX_GPIO_CTL2 0x5345#define IP5XXX_GPIO_CTL2A 0x5446#define IP5XXX_GPIO_CTL3 0x5547#define IP5XXX_READ0 0x7148#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 0x7263#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 0x7767#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 0xa271#define IP5XXX_BATVADC_DAT1 0xa372#define IP5XXX_BATIADC_DAT0 0xa473#define IP5XXX_BATIADC_DAT1 0xa574#define IP5XXX_BATOCV_DAT0 0xa875#define IP5XXX_BATOCV_DAT1 0xa976 77struct 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 is84 * generally only awake when VIN is powered or when its boost converter is85 * 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 access88 * until it succeeds.89 */90static 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 102static 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 114static 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 170static 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 184static 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 216static 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 246static 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 else258 *val = POWER_SUPPLY_HEALTH_GOOD;259 260 return 0;261}262 263static 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 if274 * 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 293static 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 312static 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 397static 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 430static 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 480static 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 489static 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 499static const enum power_supply_property ip5xxx_boost_properties[] = {500 POWER_SUPPLY_PROP_ONLINE,501 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,502};503 504static 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 539static 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 567static int ip5xxx_boost_property_is_writeable(struct power_supply *psy,568 enum power_supply_property psp)569{570 return true;571}572 573static 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 583static const struct regmap_config ip5xxx_regmap_config = {584 .reg_bits = 8,585 .val_bits = 8,586 .max_register = IP5XXX_BATOCV_DAT1,587};588 589static 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 618static 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};625MODULE_DEVICE_TABLE(of, ip5xxx_power_of_match);626 627static 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};634module_i2c_driver(ip5xxx_power_driver);635 636MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");637MODULE_DESCRIPTION("Injoinic IP5xxx power bank IC driver");638MODULE_LICENSE("GPL");639