1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Power supply driver for the RICOH RN5T618 power management chip family 4 * 5 * Copyright (C) 2020 Andreas Kemnade 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/device.h> 10 #include <linux/bitops.h> 11 #include <linux/errno.h> 12 #include <linux/init.h> 13 #include <linux/interrupt.h> 14 #include <linux/module.h> 15 #include <linux/mfd/rn5t618.h> 16 #include <linux/platform_device.h> 17 #include <linux/power_supply.h> 18 #include <linux/regmap.h> 19 #include <linux/slab.h> 20 21 #define CHG_STATE_ADP_INPUT 0x40 22 #define CHG_STATE_USB_INPUT 0x80 23 #define CHG_STATE_MASK 0x1f 24 #define CHG_STATE_CHG_OFF 0 25 #define CHG_STATE_CHG_READY_VADP 1 26 #define CHG_STATE_CHG_TRICKLE 2 27 #define CHG_STATE_CHG_RAPID 3 28 #define CHG_STATE_CHG_COMPLETE 4 29 #define CHG_STATE_SUSPEND 5 30 #define CHG_STATE_VCHG_OVER_VOL 6 31 #define CHG_STATE_BAT_ERROR 7 32 #define CHG_STATE_NO_BAT 8 33 #define CHG_STATE_BAT_OVER_VOL 9 34 #define CHG_STATE_BAT_TEMP_ERR 10 35 #define CHG_STATE_DIE_ERR 11 36 #define CHG_STATE_DIE_SHUTDOWN 12 37 #define CHG_STATE_NO_BAT2 13 38 #define CHG_STATE_CHG_READY_VUSB 14 39 40 #define GCHGDET_TYPE_MASK 0x30 41 #define GCHGDET_TYPE_SDP 0x00 42 #define GCHGDET_TYPE_CDP 0x10 43 #define GCHGDET_TYPE_DCP 0x20 44 45 #define FG_ENABLE 1 46 47 struct rn5t618_power_info { 48 struct rn5t618 *rn5t618; 49 struct platform_device *pdev; 50 struct power_supply *battery; 51 struct power_supply *usb; 52 struct power_supply *adp; 53 int irq; 54 }; 55 56 static enum power_supply_usb_type rn5t618_usb_types[] = { 57 POWER_SUPPLY_USB_TYPE_SDP, 58 POWER_SUPPLY_USB_TYPE_DCP, 59 POWER_SUPPLY_USB_TYPE_CDP, 60 POWER_SUPPLY_USB_TYPE_UNKNOWN 61 }; 62 63 static enum power_supply_property rn5t618_usb_props[] = { 64 POWER_SUPPLY_PROP_STATUS, 65 POWER_SUPPLY_PROP_USB_TYPE, 66 POWER_SUPPLY_PROP_ONLINE, 67 }; 68 69 static enum power_supply_property rn5t618_adp_props[] = { 70 POWER_SUPPLY_PROP_STATUS, 71 POWER_SUPPLY_PROP_ONLINE, 72 }; 73 74 75 static enum power_supply_property rn5t618_battery_props[] = { 76 POWER_SUPPLY_PROP_STATUS, 77 POWER_SUPPLY_PROP_PRESENT, 78 POWER_SUPPLY_PROP_VOLTAGE_NOW, 79 POWER_SUPPLY_PROP_CURRENT_NOW, 80 POWER_SUPPLY_PROP_CAPACITY, 81 POWER_SUPPLY_PROP_TEMP, 82 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 83 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 84 POWER_SUPPLY_PROP_TECHNOLOGY, 85 POWER_SUPPLY_PROP_CHARGE_FULL, 86 POWER_SUPPLY_PROP_CHARGE_NOW, 87 }; 88 89 static int rn5t618_battery_read_doublereg(struct rn5t618_power_info *info, 90 u8 reg, u16 *result) 91 { 92 int ret, i; 93 u8 data[2]; 94 u16 old, new; 95 96 old = 0; 97 /* Prevent races when registers are changing. */ 98 for (i = 0; i < 3; i++) { 99 ret = regmap_bulk_read(info->rn5t618->regmap, 100 reg, data, sizeof(data)); 101 if (ret) 102 return ret; 103 104 new = data[0] << 8; 105 new |= data[1]; 106 if (new == old) 107 break; 108 109 old = new; 110 } 111 112 *result = new; 113 114 return 0; 115 } 116 117 static int rn5t618_decode_status(unsigned int status) 118 { 119 switch (status & CHG_STATE_MASK) { 120 case CHG_STATE_CHG_OFF: 121 case CHG_STATE_SUSPEND: 122 case CHG_STATE_VCHG_OVER_VOL: 123 case CHG_STATE_DIE_SHUTDOWN: 124 return POWER_SUPPLY_STATUS_DISCHARGING; 125 126 case CHG_STATE_CHG_TRICKLE: 127 case CHG_STATE_CHG_RAPID: 128 return POWER_SUPPLY_STATUS_CHARGING; 129 130 case CHG_STATE_CHG_COMPLETE: 131 return POWER_SUPPLY_STATUS_FULL; 132 133 default: 134 return POWER_SUPPLY_STATUS_NOT_CHARGING; 135 } 136 } 137 138 static int rn5t618_battery_status(struct rn5t618_power_info *info, 139 union power_supply_propval *val) 140 { 141 unsigned int v; 142 int ret; 143 144 ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &v); 145 if (ret) 146 return ret; 147 148 val->intval = POWER_SUPPLY_STATUS_UNKNOWN; 149 150 if (v & 0xc0) { /* USB or ADP plugged */ 151 val->intval = rn5t618_decode_status(v); 152 } else 153 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 154 155 return ret; 156 } 157 158 static int rn5t618_battery_present(struct rn5t618_power_info *info, 159 union power_supply_propval *val) 160 { 161 unsigned int v; 162 int ret; 163 164 ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &v); 165 if (ret) 166 return ret; 167 168 v &= CHG_STATE_MASK; 169 if ((v == CHG_STATE_NO_BAT) || (v == CHG_STATE_NO_BAT2)) 170 val->intval = 0; 171 else 172 val->intval = 1; 173 174 return ret; 175 } 176 177 static int rn5t618_battery_voltage_now(struct rn5t618_power_info *info, 178 union power_supply_propval *val) 179 { 180 u16 res; 181 int ret; 182 183 ret = rn5t618_battery_read_doublereg(info, RN5T618_VOLTAGE_1, &res); 184 if (ret) 185 return ret; 186 187 val->intval = res * 2 * 2500 / 4095 * 1000; 188 189 return 0; 190 } 191 192 static int rn5t618_battery_current_now(struct rn5t618_power_info *info, 193 union power_supply_propval *val) 194 { 195 u16 res; 196 int ret; 197 198 ret = rn5t618_battery_read_doublereg(info, RN5T618_CC_AVEREG1, &res); 199 if (ret) 200 return ret; 201 202 /* current is negative when discharging */ 203 val->intval = sign_extend32(res, 13) * 1000; 204 205 return 0; 206 } 207 208 static int rn5t618_battery_capacity(struct rn5t618_power_info *info, 209 union power_supply_propval *val) 210 { 211 unsigned int v; 212 int ret; 213 214 ret = regmap_read(info->rn5t618->regmap, RN5T618_SOC, &v); 215 if (ret) 216 return ret; 217 218 val->intval = v; 219 220 return 0; 221 } 222 223 static int rn5t618_battery_temp(struct rn5t618_power_info *info, 224 union power_supply_propval *val) 225 { 226 u16 res; 227 int ret; 228 229 ret = rn5t618_battery_read_doublereg(info, RN5T618_TEMP_1, &res); 230 if (ret) 231 return ret; 232 233 val->intval = sign_extend32(res, 11) * 10 / 16; 234 235 return 0; 236 } 237 238 static int rn5t618_battery_tte(struct rn5t618_power_info *info, 239 union power_supply_propval *val) 240 { 241 u16 res; 242 int ret; 243 244 ret = rn5t618_battery_read_doublereg(info, RN5T618_TT_EMPTY_H, &res); 245 if (ret) 246 return ret; 247 248 if (res == 65535) 249 return -ENODATA; 250 251 val->intval = res * 60; 252 253 return 0; 254 } 255 256 static int rn5t618_battery_ttf(struct rn5t618_power_info *info, 257 union power_supply_propval *val) 258 { 259 u16 res; 260 int ret; 261 262 ret = rn5t618_battery_read_doublereg(info, RN5T618_TT_FULL_H, &res); 263 if (ret) 264 return ret; 265 266 if (res == 65535) 267 return -ENODATA; 268 269 val->intval = res * 60; 270 271 return 0; 272 } 273 274 static int rn5t618_battery_charge_full(struct rn5t618_power_info *info, 275 union power_supply_propval *val) 276 { 277 u16 res; 278 int ret; 279 280 ret = rn5t618_battery_read_doublereg(info, RN5T618_FA_CAP_H, &res); 281 if (ret) 282 return ret; 283 284 val->intval = res * 1000; 285 286 return 0; 287 } 288 289 static int rn5t618_battery_charge_now(struct rn5t618_power_info *info, 290 union power_supply_propval *val) 291 { 292 u16 res; 293 int ret; 294 295 ret = rn5t618_battery_read_doublereg(info, RN5T618_RE_CAP_H, &res); 296 if (ret) 297 return ret; 298 299 val->intval = res * 1000; 300 301 return 0; 302 } 303 304 static int rn5t618_battery_get_property(struct power_supply *psy, 305 enum power_supply_property psp, 306 union power_supply_propval *val) 307 { 308 int ret = 0; 309 struct rn5t618_power_info *info = power_supply_get_drvdata(psy); 310 311 switch (psp) { 312 case POWER_SUPPLY_PROP_STATUS: 313 ret = rn5t618_battery_status(info, val); 314 break; 315 case POWER_SUPPLY_PROP_PRESENT: 316 ret = rn5t618_battery_present(info, val); 317 break; 318 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 319 ret = rn5t618_battery_voltage_now(info, val); 320 break; 321 case POWER_SUPPLY_PROP_CURRENT_NOW: 322 ret = rn5t618_battery_current_now(info, val); 323 break; 324 case POWER_SUPPLY_PROP_CAPACITY: 325 ret = rn5t618_battery_capacity(info, val); 326 break; 327 case POWER_SUPPLY_PROP_TEMP: 328 ret = rn5t618_battery_temp(info, val); 329 break; 330 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: 331 ret = rn5t618_battery_tte(info, val); 332 break; 333 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: 334 ret = rn5t618_battery_ttf(info, val); 335 break; 336 case POWER_SUPPLY_PROP_TECHNOLOGY: 337 val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 338 break; 339 case POWER_SUPPLY_PROP_CHARGE_FULL: 340 ret = rn5t618_battery_charge_full(info, val); 341 break; 342 case POWER_SUPPLY_PROP_CHARGE_NOW: 343 ret = rn5t618_battery_charge_now(info, val); 344 break; 345 default: 346 return -EINVAL; 347 } 348 349 return ret; 350 } 351 352 static int rn5t618_adp_get_property(struct power_supply *psy, 353 enum power_supply_property psp, 354 union power_supply_propval *val) 355 { 356 struct rn5t618_power_info *info = power_supply_get_drvdata(psy); 357 unsigned int chgstate; 358 bool online; 359 int ret; 360 361 ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &chgstate); 362 if (ret) 363 return ret; 364 365 online = !!(chgstate & CHG_STATE_ADP_INPUT); 366 367 switch (psp) { 368 case POWER_SUPPLY_PROP_ONLINE: 369 val->intval = online; 370 break; 371 case POWER_SUPPLY_PROP_STATUS: 372 if (!online) { 373 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 374 break; 375 } 376 val->intval = rn5t618_decode_status(chgstate); 377 if (val->intval != POWER_SUPPLY_STATUS_CHARGING) 378 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 379 380 break; 381 default: 382 return -EINVAL; 383 } 384 385 return 0; 386 } 387 388 static int rc5t619_usb_get_type(struct rn5t618_power_info *info, 389 union power_supply_propval *val) 390 { 391 unsigned int regval; 392 int ret; 393 394 ret = regmap_read(info->rn5t618->regmap, RN5T618_GCHGDET, ®val); 395 if (ret < 0) 396 return ret; 397 398 switch (regval & GCHGDET_TYPE_MASK) { 399 case GCHGDET_TYPE_SDP: 400 val->intval = POWER_SUPPLY_USB_TYPE_SDP; 401 break; 402 case GCHGDET_TYPE_CDP: 403 val->intval = POWER_SUPPLY_USB_TYPE_CDP; 404 break; 405 case GCHGDET_TYPE_DCP: 406 val->intval = POWER_SUPPLY_USB_TYPE_DCP; 407 break; 408 default: 409 val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN; 410 } 411 412 return 0; 413 } 414 415 static int rn5t618_usb_get_property(struct power_supply *psy, 416 enum power_supply_property psp, 417 union power_supply_propval *val) 418 { 419 struct rn5t618_power_info *info = power_supply_get_drvdata(psy); 420 unsigned int chgstate; 421 bool online; 422 int ret; 423 424 ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &chgstate); 425 if (ret) 426 return ret; 427 428 online = !!(chgstate & CHG_STATE_USB_INPUT); 429 430 switch (psp) { 431 case POWER_SUPPLY_PROP_ONLINE: 432 val->intval = online; 433 break; 434 case POWER_SUPPLY_PROP_STATUS: 435 if (!online) { 436 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 437 break; 438 } 439 val->intval = rn5t618_decode_status(chgstate); 440 if (val->intval != POWER_SUPPLY_STATUS_CHARGING) 441 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 442 443 break; 444 case POWER_SUPPLY_PROP_USB_TYPE: 445 if (!online || (info->rn5t618->variant != RC5T619)) 446 return -ENODATA; 447 448 return rc5t619_usb_get_type(info, val); 449 default: 450 return -EINVAL; 451 } 452 453 return 0; 454 } 455 456 static const struct power_supply_desc rn5t618_battery_desc = { 457 .name = "rn5t618-battery", 458 .type = POWER_SUPPLY_TYPE_BATTERY, 459 .properties = rn5t618_battery_props, 460 .num_properties = ARRAY_SIZE(rn5t618_battery_props), 461 .get_property = rn5t618_battery_get_property, 462 }; 463 464 static const struct power_supply_desc rn5t618_adp_desc = { 465 .name = "rn5t618-adp", 466 .type = POWER_SUPPLY_TYPE_MAINS, 467 .properties = rn5t618_adp_props, 468 .num_properties = ARRAY_SIZE(rn5t618_adp_props), 469 .get_property = rn5t618_adp_get_property, 470 }; 471 472 static const struct power_supply_desc rn5t618_usb_desc = { 473 .name = "rn5t618-usb", 474 .type = POWER_SUPPLY_TYPE_USB, 475 .usb_types = rn5t618_usb_types, 476 .num_usb_types = ARRAY_SIZE(rn5t618_usb_types), 477 .properties = rn5t618_usb_props, 478 .num_properties = ARRAY_SIZE(rn5t618_usb_props), 479 .get_property = rn5t618_usb_get_property, 480 }; 481 482 static irqreturn_t rn5t618_charger_irq(int irq, void *data) 483 { 484 struct device *dev = data; 485 struct rn5t618_power_info *info = dev_get_drvdata(dev); 486 487 unsigned int ctrl, stat1, stat2, err; 488 489 regmap_read(info->rn5t618->regmap, RN5T618_CHGERR_IRR, &err); 490 regmap_read(info->rn5t618->regmap, RN5T618_CHGCTRL_IRR, &ctrl); 491 regmap_read(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR1, &stat1); 492 regmap_read(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR2, &stat2); 493 494 regmap_write(info->rn5t618->regmap, RN5T618_CHGERR_IRR, 0); 495 regmap_write(info->rn5t618->regmap, RN5T618_CHGCTRL_IRR, 0); 496 regmap_write(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR1, 0); 497 regmap_write(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR2, 0); 498 499 dev_dbg(dev, "chgerr: %x chgctrl: %x chgstat: %x chgstat2: %x\n", 500 err, ctrl, stat1, stat2); 501 502 power_supply_changed(info->usb); 503 power_supply_changed(info->adp); 504 power_supply_changed(info->battery); 505 506 return IRQ_HANDLED; 507 } 508 509 static int rn5t618_power_probe(struct platform_device *pdev) 510 { 511 int ret = 0; 512 unsigned int v; 513 struct power_supply_config psy_cfg = {}; 514 struct rn5t618_power_info *info; 515 516 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 517 if (!info) 518 return -ENOMEM; 519 520 info->pdev = pdev; 521 info->rn5t618 = dev_get_drvdata(pdev->dev.parent); 522 info->irq = -1; 523 524 platform_set_drvdata(pdev, info); 525 526 ret = regmap_read(info->rn5t618->regmap, RN5T618_CONTROL, &v); 527 if (ret) 528 return ret; 529 530 if (!(v & FG_ENABLE)) { 531 /* E.g. the vendor kernels of various Kobo and Tolino Ebook 532 * readers disable the fuel gauge on shutdown. If a kernel 533 * without fuel gauge support is booted after that, the fuel 534 * gauge will get decalibrated. 535 */ 536 dev_info(&pdev->dev, "Fuel gauge not enabled, enabling now\n"); 537 dev_info(&pdev->dev, "Expect imprecise results\n"); 538 regmap_update_bits(info->rn5t618->regmap, RN5T618_CONTROL, 539 FG_ENABLE, FG_ENABLE); 540 } 541 542 psy_cfg.drv_data = info; 543 info->battery = devm_power_supply_register(&pdev->dev, 544 &rn5t618_battery_desc, 545 &psy_cfg); 546 if (IS_ERR(info->battery)) { 547 ret = PTR_ERR(info->battery); 548 dev_err(&pdev->dev, "failed to register battery: %d\n", ret); 549 return ret; 550 } 551 552 info->adp = devm_power_supply_register(&pdev->dev, 553 &rn5t618_adp_desc, 554 &psy_cfg); 555 if (IS_ERR(info->adp)) { 556 ret = PTR_ERR(info->adp); 557 dev_err(&pdev->dev, "failed to register adp: %d\n", ret); 558 return ret; 559 } 560 561 info->usb = devm_power_supply_register(&pdev->dev, 562 &rn5t618_usb_desc, 563 &psy_cfg); 564 if (IS_ERR(info->usb)) { 565 ret = PTR_ERR(info->usb); 566 dev_err(&pdev->dev, "failed to register usb: %d\n", ret); 567 return ret; 568 } 569 570 if (info->rn5t618->irq_data) 571 info->irq = regmap_irq_get_virq(info->rn5t618->irq_data, 572 RN5T618_IRQ_CHG); 573 574 if (info->irq < 0) 575 info->irq = -1; 576 else { 577 ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, 578 rn5t618_charger_irq, 579 IRQF_ONESHOT, 580 "rn5t618_power", 581 &pdev->dev); 582 583 if (ret < 0) { 584 dev_err(&pdev->dev, "request IRQ:%d fail\n", 585 info->irq); 586 info->irq = -1; 587 } 588 } 589 590 return 0; 591 } 592 593 static struct platform_driver rn5t618_power_driver = { 594 .driver = { 595 .name = "rn5t618-power", 596 }, 597 .probe = rn5t618_power_probe, 598 }; 599 600 module_platform_driver(rn5t618_power_driver); 601 MODULE_ALIAS("platform:rn5t618-power"); 602 MODULE_DESCRIPTION("Power supply driver for RICOH RN5T618"); 603 MODULE_LICENSE("GPL"); 604