root/drivers/power/supply/sc2731_charger.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sc2731_charger_stop_charge
  2. sc2731_charger_start_charge
  3. sc2731_charger_set_current_limit
  4. sc2731_charger_set_current
  5. sc2731_charger_get_status
  6. sc2731_charger_get_current
  7. sc2731_charger_get_current_limit
  8. sc2731_charger_usb_set_property
  9. sc2731_charger_usb_get_property
  10. sc2731_charger_property_is_writeable
  11. sc2731_charger_work
  12. sc2731_charger_usb_change
  13. sc2731_charger_hw_init
  14. sc2731_charger_detect_status
  15. sc2731_charger_probe
  16. sc2731_charger_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Copyright (C) 2018 Spreadtrum Communications Inc.
   3 
   4 #include <linux/module.h>
   5 #include <linux/platform_device.h>
   6 #include <linux/power_supply.h>
   7 #include <linux/usb/phy.h>
   8 #include <linux/regmap.h>
   9 #include <linux/notifier.h>
  10 #include <linux/of.h>
  11 
  12 /* PMIC global registers definition */
  13 #define SC2731_CHARGE_STATUS            0xedc
  14 #define SC2731_CHARGE_FULL              BIT(4)
  15 #define SC2731_MODULE_EN1               0xc0c
  16 #define SC2731_CHARGE_EN                BIT(5)
  17 
  18 /* SC2731 switch charger registers definition */
  19 #define SC2731_CHG_CFG0                 0x0
  20 #define SC2731_CHG_CFG1                 0x4
  21 #define SC2731_CHG_CFG2                 0x8
  22 #define SC2731_CHG_CFG3                 0xc
  23 #define SC2731_CHG_CFG4                 0x10
  24 #define SC2731_CHG_CFG5                 0x28
  25 
  26 /* SC2731_CHG_CFG0 register definition */
  27 #define SC2731_PRECHG_RNG_SHIFT         11
  28 #define SC2731_PRECHG_RNG_MASK          GENMASK(12, 11)
  29 
  30 #define SC2731_TERMINATION_VOL_MASK     GENMASK(2, 1)
  31 #define SC2731_TERMINATION_VOL_SHIFT    1
  32 #define SC2731_TERMINATION_VOL_CAL_MASK GENMASK(8, 3)
  33 #define SC2731_TERMINATION_VOL_CAL_SHIFT        3
  34 #define SC2731_TERMINATION_CUR_MASK     GENMASK(2, 0)
  35 
  36 #define SC2731_CC_EN                    BIT(13)
  37 #define SC2731_CHARGER_PD               BIT(0)
  38 
  39 /* SC2731_CHG_CFG1 register definition */
  40 #define SC2731_CUR_MASK                 GENMASK(5, 0)
  41 
  42 /* SC2731_CHG_CFG5 register definition */
  43 #define SC2731_CUR_LIMIT_SHIFT          8
  44 #define SC2731_CUR_LIMIT_MASK           GENMASK(9, 8)
  45 
  46 /* Default current definition (unit is mA) */
  47 #define SC2731_CURRENT_LIMIT_100        100
  48 #define SC2731_CURRENT_LIMIT_500        500
  49 #define SC2731_CURRENT_LIMIT_900        900
  50 #define SC2731_CURRENT_LIMIT_2000       2000
  51 #define SC2731_CURRENT_PRECHG           450
  52 #define SC2731_CURRENT_STEP             50
  53 
  54 struct sc2731_charger_info {
  55         struct device *dev;
  56         struct regmap *regmap;
  57         struct usb_phy *usb_phy;
  58         struct notifier_block usb_notify;
  59         struct power_supply *psy_usb;
  60         struct work_struct work;
  61         struct mutex lock;
  62         bool charging;
  63         u32 base;
  64         u32 limit;
  65 };
  66 
  67 static void sc2731_charger_stop_charge(struct sc2731_charger_info *info)
  68 {
  69         regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0,
  70                            SC2731_CC_EN, 0);
  71 
  72         regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0,
  73                            SC2731_CHARGER_PD, SC2731_CHARGER_PD);
  74 }
  75 
  76 static int sc2731_charger_start_charge(struct sc2731_charger_info *info)
  77 {
  78         int ret;
  79 
  80         /* Enable charger constant current mode */
  81         ret = regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0,
  82                                  SC2731_CC_EN, SC2731_CC_EN);
  83         if (ret)
  84                 return ret;
  85 
  86         /* Start charging */
  87         return regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0,
  88                                   SC2731_CHARGER_PD, 0);
  89 }
  90 
  91 static int sc2731_charger_set_current_limit(struct sc2731_charger_info *info,
  92                                             u32 limit)
  93 {
  94         u32 val;
  95 
  96         if (limit <= SC2731_CURRENT_LIMIT_100)
  97                 val = 0;
  98         else if (limit <= SC2731_CURRENT_LIMIT_500)
  99                 val = 3;
 100         else if (limit <= SC2731_CURRENT_LIMIT_900)
 101                 val = 2;
 102         else
 103                 val = 1;
 104 
 105         return regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG5,
 106                                   SC2731_CUR_LIMIT_MASK,
 107                                   val << SC2731_CUR_LIMIT_SHIFT);
 108 }
 109 
 110 static int sc2731_charger_set_current(struct sc2731_charger_info *info, u32 cur)
 111 {
 112         u32 val;
 113         int ret;
 114 
 115         if (cur > SC2731_CURRENT_LIMIT_2000)
 116                 cur = SC2731_CURRENT_LIMIT_2000;
 117         else if (cur < SC2731_CURRENT_PRECHG)
 118                 cur = SC2731_CURRENT_PRECHG;
 119 
 120         /* Calculate the step value, each step is 50 mA */
 121         val = (cur - SC2731_CURRENT_PRECHG) / SC2731_CURRENT_STEP;
 122 
 123         /* Set pre-charge current as 450 mA */
 124         ret = regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0,
 125                                  SC2731_PRECHG_RNG_MASK,
 126                                  0x3 << SC2731_PRECHG_RNG_SHIFT);
 127         if (ret)
 128                 return ret;
 129 
 130         return regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG1,
 131                                   SC2731_CUR_MASK, val);
 132 }
 133 
 134 static int sc2731_charger_get_status(struct sc2731_charger_info *info)
 135 {
 136         u32 val;
 137         int ret;
 138 
 139         ret = regmap_read(info->regmap, SC2731_CHARGE_STATUS, &val);
 140         if (ret)
 141                 return ret;
 142 
 143         if (val & SC2731_CHARGE_FULL)
 144                 return POWER_SUPPLY_STATUS_FULL;
 145 
 146         return POWER_SUPPLY_STATUS_CHARGING;
 147 }
 148 
 149 static int sc2731_charger_get_current(struct sc2731_charger_info *info,
 150                                       u32 *cur)
 151 {
 152         int ret;
 153         u32 val;
 154 
 155         ret = regmap_read(info->regmap, info->base + SC2731_CHG_CFG1, &val);
 156         if (ret)
 157                 return ret;
 158 
 159         val &= SC2731_CUR_MASK;
 160         *cur = val * SC2731_CURRENT_STEP + SC2731_CURRENT_PRECHG;
 161 
 162         return 0;
 163 }
 164 
 165 static int sc2731_charger_get_current_limit(struct sc2731_charger_info *info,
 166                                             u32 *cur)
 167 {
 168         int ret;
 169         u32 val;
 170 
 171         ret = regmap_read(info->regmap, info->base + SC2731_CHG_CFG5, &val);
 172         if (ret)
 173                 return ret;
 174 
 175         val = (val & SC2731_CUR_LIMIT_MASK) >> SC2731_CUR_LIMIT_SHIFT;
 176 
 177         switch (val) {
 178         case 0:
 179                 *cur = SC2731_CURRENT_LIMIT_100;
 180                 break;
 181 
 182         case 1:
 183                 *cur = SC2731_CURRENT_LIMIT_2000;
 184                 break;
 185 
 186         case 2:
 187                 *cur = SC2731_CURRENT_LIMIT_900;
 188                 break;
 189 
 190         case 3:
 191                 *cur = SC2731_CURRENT_LIMIT_500;
 192                 break;
 193 
 194         default:
 195                 return -EINVAL;
 196         }
 197 
 198         return 0;
 199 }
 200 
 201 static int
 202 sc2731_charger_usb_set_property(struct power_supply *psy,
 203                                 enum power_supply_property psp,
 204                                 const union power_supply_propval *val)
 205 {
 206         struct sc2731_charger_info *info = power_supply_get_drvdata(psy);
 207         int ret;
 208 
 209         mutex_lock(&info->lock);
 210 
 211         if (!info->charging) {
 212                 mutex_unlock(&info->lock);
 213                 return -ENODEV;
 214         }
 215 
 216         switch (psp) {
 217         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 218                 ret = sc2731_charger_set_current(info, val->intval / 1000);
 219                 if (ret < 0)
 220                         dev_err(info->dev, "set charge current failed\n");
 221                 break;
 222 
 223         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 224                 ret = sc2731_charger_set_current_limit(info,
 225                                                        val->intval / 1000);
 226                 if (ret < 0)
 227                         dev_err(info->dev, "set input current limit failed\n");
 228                 break;
 229 
 230         default:
 231                 ret = -EINVAL;
 232         }
 233 
 234         mutex_unlock(&info->lock);
 235         return ret;
 236 }
 237 
 238 static int sc2731_charger_usb_get_property(struct power_supply *psy,
 239                                            enum power_supply_property psp,
 240                                            union power_supply_propval *val)
 241 {
 242         struct sc2731_charger_info *info = power_supply_get_drvdata(psy);
 243         int ret = 0;
 244         u32 cur;
 245 
 246         mutex_lock(&info->lock);
 247 
 248         switch (psp) {
 249         case POWER_SUPPLY_PROP_STATUS:
 250                 if (info->charging)
 251                         val->intval = sc2731_charger_get_status(info);
 252                 else
 253                         val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
 254                 break;
 255 
 256         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 257                 if (!info->charging) {
 258                         val->intval = 0;
 259                 } else {
 260                         ret = sc2731_charger_get_current(info, &cur);
 261                         if (ret)
 262                                 goto out;
 263 
 264                         val->intval = cur * 1000;
 265                 }
 266                 break;
 267 
 268         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 269                 if (!info->charging) {
 270                         val->intval = 0;
 271                 } else {
 272                         ret = sc2731_charger_get_current_limit(info, &cur);
 273                         if (ret)
 274                                 goto out;
 275 
 276                         val->intval = cur * 1000;
 277                 }
 278                 break;
 279 
 280         default:
 281                 ret = -EINVAL;
 282         }
 283 
 284 out:
 285         mutex_unlock(&info->lock);
 286         return ret;
 287 }
 288 
 289 static int sc2731_charger_property_is_writeable(struct power_supply *psy,
 290                                                 enum power_supply_property psp)
 291 {
 292         int ret;
 293 
 294         switch (psp) {
 295         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 296         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 297                 ret = 1;
 298                 break;
 299 
 300         default:
 301                 ret = 0;
 302         }
 303 
 304         return ret;
 305 }
 306 
 307 static enum power_supply_property sc2731_usb_props[] = {
 308         POWER_SUPPLY_PROP_STATUS,
 309         POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
 310         POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 311 };
 312 
 313 static const struct power_supply_desc sc2731_charger_desc = {
 314         .name                   = "sc2731_charger",
 315         .type                   = POWER_SUPPLY_TYPE_USB,
 316         .properties             = sc2731_usb_props,
 317         .num_properties         = ARRAY_SIZE(sc2731_usb_props),
 318         .get_property           = sc2731_charger_usb_get_property,
 319         .set_property           = sc2731_charger_usb_set_property,
 320         .property_is_writeable  = sc2731_charger_property_is_writeable,
 321 };
 322 
 323 static void sc2731_charger_work(struct work_struct *data)
 324 {
 325         struct sc2731_charger_info *info =
 326                 container_of(data, struct sc2731_charger_info, work);
 327         int ret;
 328 
 329         mutex_lock(&info->lock);
 330 
 331         if (info->limit > 0 && !info->charging) {
 332                 /* set current limitation and start to charge */
 333                 ret = sc2731_charger_set_current_limit(info, info->limit);
 334                 if (ret)
 335                         goto out;
 336 
 337                 ret = sc2731_charger_set_current(info, info->limit);
 338                 if (ret)
 339                         goto out;
 340 
 341                 ret = sc2731_charger_start_charge(info);
 342                 if (ret)
 343                         goto out;
 344 
 345                 info->charging = true;
 346         } else if (!info->limit && info->charging) {
 347                 /* Stop charging */
 348                 info->charging = false;
 349                 sc2731_charger_stop_charge(info);
 350         }
 351 
 352 out:
 353         mutex_unlock(&info->lock);
 354 }
 355 
 356 static int sc2731_charger_usb_change(struct notifier_block *nb,
 357                                      unsigned long limit, void *data)
 358 {
 359         struct sc2731_charger_info *info =
 360                 container_of(nb, struct sc2731_charger_info, usb_notify);
 361 
 362         info->limit = limit;
 363 
 364         schedule_work(&info->work);
 365 
 366         return NOTIFY_OK;
 367 }
 368 
 369 static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
 370 {
 371         struct power_supply_battery_info bat_info = { };
 372         u32 term_currrent, term_voltage, cur_val, vol_val;
 373         int ret;
 374 
 375         /* Enable charger module */
 376         ret = regmap_update_bits(info->regmap, SC2731_MODULE_EN1,
 377                                  SC2731_CHARGE_EN, SC2731_CHARGE_EN);
 378         if (ret)
 379                 return ret;
 380 
 381         ret = power_supply_get_battery_info(info->psy_usb, &bat_info);
 382         if (ret) {
 383                 dev_warn(info->dev, "no battery information is supplied\n");
 384 
 385                 /*
 386                  * If no battery information is supplied, we should set
 387                  * default charge termination current to 120 mA, and default
 388                  * charge termination voltage to 4.35V.
 389                  */
 390                 cur_val = 0x2;
 391                 vol_val = 0x1;
 392         } else {
 393                 term_currrent = bat_info.charge_term_current_ua / 1000;
 394 
 395                 if (term_currrent <= 90)
 396                         cur_val = 0;
 397                 else if (term_currrent >= 265)
 398                         cur_val = 0x7;
 399                 else
 400                         cur_val = ((term_currrent - 90) / 25) + 1;
 401 
 402                 term_voltage = bat_info.constant_charge_voltage_max_uv / 1000;
 403 
 404                 if (term_voltage > 4500)
 405                         term_voltage = 4500;
 406 
 407                 if (term_voltage > 4200)
 408                         vol_val = (term_voltage - 4200) / 100;
 409                 else
 410                         vol_val = 0;
 411 
 412                 power_supply_put_battery_info(info->psy_usb, &bat_info);
 413         }
 414 
 415         /* Set charge termination current */
 416         ret = regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG2,
 417                                  SC2731_TERMINATION_CUR_MASK, cur_val);
 418         if (ret)
 419                 goto error;
 420 
 421         /* Set charge termination voltage */
 422         ret = regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0,
 423                                  SC2731_TERMINATION_VOL_MASK |
 424                                  SC2731_TERMINATION_VOL_CAL_MASK,
 425                                  (vol_val << SC2731_TERMINATION_VOL_SHIFT) |
 426                                  (0x6 << SC2731_TERMINATION_VOL_CAL_SHIFT));
 427         if (ret)
 428                 goto error;
 429 
 430         return 0;
 431 
 432 error:
 433         regmap_update_bits(info->regmap, SC2731_MODULE_EN1, SC2731_CHARGE_EN, 0);
 434         return ret;
 435 }
 436 
 437 static void sc2731_charger_detect_status(struct sc2731_charger_info *info)
 438 {
 439         unsigned int min, max;
 440 
 441         /*
 442          * If the USB charger status has been USB_CHARGER_PRESENT before
 443          * registering the notifier, we should start to charge with getting
 444          * the charge current.
 445          */
 446         if (info->usb_phy->chg_state != USB_CHARGER_PRESENT)
 447                 return;
 448 
 449         usb_phy_get_charger_current(info->usb_phy, &min, &max);
 450         info->limit = min;
 451 
 452         schedule_work(&info->work);
 453 }
 454 
 455 static int sc2731_charger_probe(struct platform_device *pdev)
 456 {
 457         struct device_node *np = pdev->dev.of_node;
 458         struct sc2731_charger_info *info;
 459         struct power_supply_config charger_cfg = { };
 460         int ret;
 461 
 462         info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 463         if (!info)
 464                 return -ENOMEM;
 465 
 466         mutex_init(&info->lock);
 467         info->dev = &pdev->dev;
 468         INIT_WORK(&info->work, sc2731_charger_work);
 469 
 470         info->regmap = dev_get_regmap(pdev->dev.parent, NULL);
 471         if (!info->regmap) {
 472                 dev_err(&pdev->dev, "failed to get charger regmap\n");
 473                 return -ENODEV;
 474         }
 475 
 476         ret = of_property_read_u32(np, "reg", &info->base);
 477         if (ret) {
 478                 dev_err(&pdev->dev, "failed to get register address\n");
 479                 return -ENODEV;
 480         }
 481 
 482         charger_cfg.drv_data = info;
 483         charger_cfg.of_node = np;
 484         info->psy_usb = devm_power_supply_register(&pdev->dev,
 485                                                    &sc2731_charger_desc,
 486                                                    &charger_cfg);
 487         if (IS_ERR(info->psy_usb)) {
 488                 dev_err(&pdev->dev, "failed to register power supply\n");
 489                 return PTR_ERR(info->psy_usb);
 490         }
 491 
 492         ret = sc2731_charger_hw_init(info);
 493         if (ret)
 494                 return ret;
 495 
 496         info->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "phys", 0);
 497         if (IS_ERR(info->usb_phy)) {
 498                 dev_err(&pdev->dev, "failed to find USB phy\n");
 499                 return PTR_ERR(info->usb_phy);
 500         }
 501 
 502         info->usb_notify.notifier_call = sc2731_charger_usb_change;
 503         ret = usb_register_notifier(info->usb_phy, &info->usb_notify);
 504         if (ret) {
 505                 dev_err(&pdev->dev, "failed to register notifier: %d\n", ret);
 506                 return ret;
 507         }
 508 
 509         sc2731_charger_detect_status(info);
 510 
 511         return 0;
 512 }
 513 
 514 static int sc2731_charger_remove(struct platform_device *pdev)
 515 {
 516         struct sc2731_charger_info *info = platform_get_drvdata(pdev);
 517 
 518         usb_unregister_notifier(info->usb_phy, &info->usb_notify);
 519 
 520         return 0;
 521 }
 522 
 523 static const struct of_device_id sc2731_charger_of_match[] = {
 524         { .compatible = "sprd,sc2731-charger", },
 525         { }
 526 };
 527 
 528 static struct platform_driver sc2731_charger_driver = {
 529         .driver = {
 530                 .name = "sc2731-charger",
 531                 .of_match_table = sc2731_charger_of_match,
 532         },
 533         .probe = sc2731_charger_probe,
 534         .remove = sc2731_charger_remove,
 535 };
 536 
 537 module_platform_driver(sc2731_charger_driver);
 538 
 539 MODULE_DESCRIPTION("Spreadtrum SC2731 Charger Driver");
 540 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */