540 lines · c
1// SPDX-License-Identifier: GPL-2.02// 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 0xedc14#define SC2731_CHARGE_FULL BIT(4)15#define SC2731_MODULE_EN1 0xc0c16#define SC2731_CHARGE_EN BIT(5)17 18/* SC2731 switch charger registers definition */19#define SC2731_CHG_CFG0 0x020#define SC2731_CHG_CFG1 0x421#define SC2731_CHG_CFG2 0x822#define SC2731_CHG_CFG3 0xc23#define SC2731_CHG_CFG4 0x1024#define SC2731_CHG_CFG5 0x2825 26/* SC2731_CHG_CFG0 register definition */27#define SC2731_PRECHG_RNG_SHIFT 1128#define SC2731_PRECHG_RNG_MASK GENMASK(12, 11)29 30#define SC2731_TERMINATION_VOL_MASK GENMASK(2, 1)31#define SC2731_TERMINATION_VOL_SHIFT 132#define SC2731_TERMINATION_VOL_CAL_MASK GENMASK(8, 3)33#define SC2731_TERMINATION_VOL_CAL_SHIFT 334#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 844#define SC2731_CUR_LIMIT_MASK GENMASK(9, 8)45 46/* Default current definition (unit is mA) */47#define SC2731_CURRENT_LIMIT_100 10048#define SC2731_CURRENT_LIMIT_500 50049#define SC2731_CURRENT_LIMIT_900 90050#define SC2731_CURRENT_LIMIT_2000 200051#define SC2731_CURRENT_PRECHG 45052#define SC2731_CURRENT_STEP 5053 54struct 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 67static 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 76static 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 91static 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 else103 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 110static 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 134static 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 149static 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 165static 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 201static int202sc2731_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 238static 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 else253 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 284out:285 mutex_unlock(&info->lock);286 return ret;287}288 289static 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 307static 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 313static 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 323static 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 352out:353 mutex_unlock(&info->lock);354}355 356static 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 369static 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 set387 * default charge termination current to 120 mA, and default388 * 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 else400 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 else410 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 432error:433 regmap_update_bits(info->regmap, SC2731_MODULE_EN1, SC2731_CHARGE_EN, 0);434 return ret;435}436 437static 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 before443 * registering the notifier, we should start to charge with getting444 * 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 455static 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 514static void 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 521static const struct of_device_id sc2731_charger_of_match[] = {522 { .compatible = "sprd,sc2731-charger", },523 { }524};525MODULE_DEVICE_TABLE(of, sc2731_charger_of_match);526 527static struct platform_driver sc2731_charger_driver = {528 .driver = {529 .name = "sc2731-charger",530 .of_match_table = sc2731_charger_of_match,531 },532 .probe = sc2731_charger_probe,533 .remove_new = sc2731_charger_remove,534};535 536module_platform_driver(sc2731_charger_driver);537 538MODULE_DESCRIPTION("Spreadtrum SC2731 Charger Driver");539MODULE_LICENSE("GPL v2");540