606 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for LP8727 Micro/Mini USB IC with integrated charger4 *5 * Copyright (C) 2011 Texas Instruments6 * Copyright (C) 2011 National Semiconductor7 */8 9#include <linux/module.h>10#include <linux/slab.h>11#include <linux/interrupt.h>12#include <linux/i2c.h>13#include <linux/power_supply.h>14#include <linux/platform_data/lp8727.h>15#include <linux/of.h>16 17#define LP8788_NUM_INTREGS 218#define DEFAULT_DEBOUNCE_MSEC 27019 20/* Registers */21#define LP8727_CTRL1 0x122#define LP8727_CTRL2 0x223#define LP8727_SWCTRL 0x324#define LP8727_INT1 0x425#define LP8727_INT2 0x526#define LP8727_STATUS1 0x627#define LP8727_STATUS2 0x728#define LP8727_CHGCTRL2 0x929 30/* CTRL1 register */31#define LP8727_CP_EN BIT(0)32#define LP8727_ADC_EN BIT(1)33#define LP8727_ID200_EN BIT(4)34 35/* CTRL2 register */36#define LP8727_CHGDET_EN BIT(1)37#define LP8727_INT_EN BIT(6)38 39/* SWCTRL register */40#define LP8727_SW_DM1_DM (0x0 << 0)41#define LP8727_SW_DM1_HiZ (0x7 << 0)42#define LP8727_SW_DP2_DP (0x0 << 3)43#define LP8727_SW_DP2_HiZ (0x7 << 3)44 45/* INT1 register */46#define LP8727_IDNO (0xF << 0)47#define LP8727_VBUS BIT(4)48 49/* STATUS1 register */50#define LP8727_CHGSTAT (3 << 4)51#define LP8727_CHPORT BIT(6)52#define LP8727_DCPORT BIT(7)53#define LP8727_STAT_EOC 0x3054 55/* STATUS2 register */56#define LP8727_TEMP_STAT (3 << 5)57#define LP8727_TEMP_SHIFT 558 59/* CHGCTRL2 register */60#define LP8727_ICHG_SHIFT 461 62enum lp8727_dev_id {63 LP8727_ID_NONE,64 LP8727_ID_TA,65 LP8727_ID_DEDICATED_CHG,66 LP8727_ID_USB_CHG,67 LP8727_ID_USB_DS,68 LP8727_ID_MAX,69};70 71enum lp8727_die_temp {72 LP8788_TEMP_75C,73 LP8788_TEMP_95C,74 LP8788_TEMP_115C,75 LP8788_TEMP_135C,76};77 78struct lp8727_psy {79 struct power_supply *ac;80 struct power_supply *usb;81 struct power_supply *batt;82};83 84struct lp8727_chg {85 struct device *dev;86 struct i2c_client *client;87 struct mutex xfer_lock;88 struct lp8727_psy *psy;89 struct lp8727_platform_data *pdata;90 91 /* Charger Data */92 enum lp8727_dev_id devid;93 struct lp8727_chg_param *chg_param;94 95 /* Interrupt Handling */96 int irq;97 struct delayed_work work;98 unsigned long debounce_jiffies;99};100 101static int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)102{103 s32 ret;104 105 mutex_lock(&pchg->xfer_lock);106 ret = i2c_smbus_read_i2c_block_data(pchg->client, reg, len, data);107 mutex_unlock(&pchg->xfer_lock);108 109 return (ret != len) ? -EIO : 0;110}111 112static inline int lp8727_read_byte(struct lp8727_chg *pchg, u8 reg, u8 *data)113{114 return lp8727_read_bytes(pchg, reg, data, 1);115}116 117static int lp8727_write_byte(struct lp8727_chg *pchg, u8 reg, u8 data)118{119 int ret;120 121 mutex_lock(&pchg->xfer_lock);122 ret = i2c_smbus_write_byte_data(pchg->client, reg, data);123 mutex_unlock(&pchg->xfer_lock);124 125 return ret;126}127 128static bool lp8727_is_charger_attached(const char *name, int id)129{130 if (!strcmp(name, "ac"))131 return id == LP8727_ID_TA || id == LP8727_ID_DEDICATED_CHG;132 else if (!strcmp(name, "usb"))133 return id == LP8727_ID_USB_CHG;134 135 return id >= LP8727_ID_TA && id <= LP8727_ID_USB_CHG;136}137 138static int lp8727_init_device(struct lp8727_chg *pchg)139{140 u8 val;141 int ret;142 u8 intstat[LP8788_NUM_INTREGS];143 144 /* clear interrupts */145 ret = lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS);146 if (ret)147 return ret;148 149 val = LP8727_ID200_EN | LP8727_ADC_EN | LP8727_CP_EN;150 ret = lp8727_write_byte(pchg, LP8727_CTRL1, val);151 if (ret)152 return ret;153 154 val = LP8727_INT_EN | LP8727_CHGDET_EN;155 return lp8727_write_byte(pchg, LP8727_CTRL2, val);156}157 158static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg)159{160 u8 val;161 162 lp8727_read_byte(pchg, LP8727_STATUS1, &val);163 return val & LP8727_DCPORT;164}165 166static int lp8727_is_usb_charger(struct lp8727_chg *pchg)167{168 u8 val;169 170 lp8727_read_byte(pchg, LP8727_STATUS1, &val);171 return val & LP8727_CHPORT;172}173 174static inline void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)175{176 lp8727_write_byte(pchg, LP8727_SWCTRL, sw);177}178 179static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin)180{181 struct lp8727_platform_data *pdata = pchg->pdata;182 u8 devid = LP8727_ID_NONE;183 u8 swctrl = LP8727_SW_DM1_HiZ | LP8727_SW_DP2_HiZ;184 185 switch (id) {186 case 0x5:187 devid = LP8727_ID_TA;188 pchg->chg_param = pdata ? pdata->ac : NULL;189 break;190 case 0xB:191 if (lp8727_is_dedicated_charger(pchg)) {192 pchg->chg_param = pdata ? pdata->ac : NULL;193 devid = LP8727_ID_DEDICATED_CHG;194 } else if (lp8727_is_usb_charger(pchg)) {195 pchg->chg_param = pdata ? pdata->usb : NULL;196 devid = LP8727_ID_USB_CHG;197 swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP;198 } else if (vbusin) {199 devid = LP8727_ID_USB_DS;200 swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP;201 }202 break;203 default:204 devid = LP8727_ID_NONE;205 pchg->chg_param = NULL;206 break;207 }208 209 pchg->devid = devid;210 lp8727_ctrl_switch(pchg, swctrl);211}212 213static void lp8727_enable_chgdet(struct lp8727_chg *pchg)214{215 u8 val;216 217 lp8727_read_byte(pchg, LP8727_CTRL2, &val);218 val |= LP8727_CHGDET_EN;219 lp8727_write_byte(pchg, LP8727_CTRL2, val);220}221 222static void lp8727_delayed_func(struct work_struct *_work)223{224 struct lp8727_chg *pchg = container_of(_work, struct lp8727_chg,225 work.work);226 u8 intstat[LP8788_NUM_INTREGS];227 u8 idno;228 u8 vbus;229 230 if (lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS)) {231 dev_err(pchg->dev, "can not read INT registers\n");232 return;233 }234 235 idno = intstat[0] & LP8727_IDNO;236 vbus = intstat[0] & LP8727_VBUS;237 238 lp8727_id_detection(pchg, idno, vbus);239 lp8727_enable_chgdet(pchg);240 241 power_supply_changed(pchg->psy->ac);242 power_supply_changed(pchg->psy->usb);243 power_supply_changed(pchg->psy->batt);244}245 246static irqreturn_t lp8727_isr_func(int irq, void *ptr)247{248 struct lp8727_chg *pchg = ptr;249 250 schedule_delayed_work(&pchg->work, pchg->debounce_jiffies);251 return IRQ_HANDLED;252}253 254static int lp8727_setup_irq(struct lp8727_chg *pchg)255{256 int ret;257 int irq = pchg->client->irq;258 unsigned delay_msec = pchg->pdata ? pchg->pdata->debounce_msec :259 DEFAULT_DEBOUNCE_MSEC;260 261 INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func);262 263 if (irq <= 0) {264 dev_warn(pchg->dev, "invalid irq number: %d\n", irq);265 return 0;266 }267 268 ret = request_threaded_irq(irq, NULL, lp8727_isr_func,269 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,270 "lp8727_irq", pchg);271 272 if (ret)273 return ret;274 275 pchg->irq = irq;276 pchg->debounce_jiffies = msecs_to_jiffies(delay_msec);277 278 return 0;279}280 281static void lp8727_release_irq(struct lp8727_chg *pchg)282{283 cancel_delayed_work_sync(&pchg->work);284 285 if (pchg->irq)286 free_irq(pchg->irq, pchg);287}288 289static enum power_supply_property lp8727_charger_prop[] = {290 POWER_SUPPLY_PROP_ONLINE,291};292 293static enum power_supply_property lp8727_battery_prop[] = {294 POWER_SUPPLY_PROP_STATUS,295 POWER_SUPPLY_PROP_HEALTH,296 POWER_SUPPLY_PROP_PRESENT,297 POWER_SUPPLY_PROP_VOLTAGE_NOW,298 POWER_SUPPLY_PROP_CAPACITY,299 POWER_SUPPLY_PROP_TEMP,300};301 302static char *battery_supplied_to[] = {303 "main_batt",304};305 306static int lp8727_charger_get_property(struct power_supply *psy,307 enum power_supply_property psp,308 union power_supply_propval *val)309{310 struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);311 312 if (psp != POWER_SUPPLY_PROP_ONLINE)313 return -EINVAL;314 315 val->intval = lp8727_is_charger_attached(psy->desc->name, pchg->devid);316 317 return 0;318}319 320static bool lp8727_is_high_temperature(enum lp8727_die_temp temp)321{322 switch (temp) {323 case LP8788_TEMP_95C:324 case LP8788_TEMP_115C:325 case LP8788_TEMP_135C:326 return true;327 default:328 return false;329 }330}331 332static int lp8727_battery_get_property(struct power_supply *psy,333 enum power_supply_property psp,334 union power_supply_propval *val)335{336 struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);337 struct lp8727_platform_data *pdata = pchg->pdata;338 enum lp8727_die_temp temp;339 u8 read;340 341 switch (psp) {342 case POWER_SUPPLY_PROP_STATUS:343 if (!lp8727_is_charger_attached(psy->desc->name, pchg->devid)) {344 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;345 return 0;346 }347 348 lp8727_read_byte(pchg, LP8727_STATUS1, &read);349 350 val->intval = (read & LP8727_CHGSTAT) == LP8727_STAT_EOC ?351 POWER_SUPPLY_STATUS_FULL :352 POWER_SUPPLY_STATUS_CHARGING;353 break;354 case POWER_SUPPLY_PROP_HEALTH:355 lp8727_read_byte(pchg, LP8727_STATUS2, &read);356 temp = (read & LP8727_TEMP_STAT) >> LP8727_TEMP_SHIFT;357 358 val->intval = lp8727_is_high_temperature(temp) ?359 POWER_SUPPLY_HEALTH_OVERHEAT :360 POWER_SUPPLY_HEALTH_GOOD;361 break;362 case POWER_SUPPLY_PROP_PRESENT:363 if (!pdata)364 return -EINVAL;365 366 if (pdata->get_batt_present)367 val->intval = pdata->get_batt_present();368 break;369 case POWER_SUPPLY_PROP_VOLTAGE_NOW:370 if (!pdata)371 return -EINVAL;372 373 if (pdata->get_batt_level)374 val->intval = pdata->get_batt_level();375 break;376 case POWER_SUPPLY_PROP_CAPACITY:377 if (!pdata)378 return -EINVAL;379 380 if (pdata->get_batt_capacity)381 val->intval = pdata->get_batt_capacity();382 break;383 case POWER_SUPPLY_PROP_TEMP:384 if (!pdata)385 return -EINVAL;386 387 if (pdata->get_batt_temp)388 val->intval = pdata->get_batt_temp();389 break;390 default:391 break;392 }393 394 return 0;395}396 397static void lp8727_charger_changed(struct power_supply *psy)398{399 struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);400 u8 eoc_level;401 u8 ichg;402 u8 val;403 404 /* skip if no charger exists */405 if (!lp8727_is_charger_attached(psy->desc->name, pchg->devid))406 return;407 408 /* update charging parameters */409 if (pchg->chg_param) {410 eoc_level = pchg->chg_param->eoc_level;411 ichg = pchg->chg_param->ichg;412 val = (ichg << LP8727_ICHG_SHIFT) | eoc_level;413 lp8727_write_byte(pchg, LP8727_CHGCTRL2, val);414 }415}416 417static const struct power_supply_desc lp8727_ac_desc = {418 .name = "ac",419 .type = POWER_SUPPLY_TYPE_MAINS,420 .properties = lp8727_charger_prop,421 .num_properties = ARRAY_SIZE(lp8727_charger_prop),422 .get_property = lp8727_charger_get_property,423};424 425static const struct power_supply_desc lp8727_usb_desc = {426 .name = "usb",427 .type = POWER_SUPPLY_TYPE_USB,428 .properties = lp8727_charger_prop,429 .num_properties = ARRAY_SIZE(lp8727_charger_prop),430 .get_property = lp8727_charger_get_property,431};432 433static const struct power_supply_desc lp8727_batt_desc = {434 .name = "main_batt",435 .type = POWER_SUPPLY_TYPE_BATTERY,436 .properties = lp8727_battery_prop,437 .num_properties = ARRAY_SIZE(lp8727_battery_prop),438 .get_property = lp8727_battery_get_property,439 .external_power_changed = lp8727_charger_changed,440};441 442static int lp8727_register_psy(struct lp8727_chg *pchg)443{444 struct power_supply_config psy_cfg = {}; /* Only for ac and usb */445 struct lp8727_psy *psy;446 447 psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL);448 if (!psy)449 return -ENOMEM;450 451 pchg->psy = psy;452 453 psy_cfg.supplied_to = battery_supplied_to;454 psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);455 456 psy->ac = devm_power_supply_register(pchg->dev, &lp8727_ac_desc, &psy_cfg);457 if (IS_ERR(psy->ac))458 return -EPERM;459 460 psy->usb = devm_power_supply_register(pchg->dev, &lp8727_usb_desc,461 &psy_cfg);462 if (IS_ERR(psy->usb))463 return -EPERM;464 465 psy->batt = devm_power_supply_register(pchg->dev, &lp8727_batt_desc, NULL);466 if (IS_ERR(psy->batt))467 return -EPERM;468 469 return 0;470}471 472#ifdef CONFIG_OF473static struct lp8727_chg_param474*lp8727_parse_charge_pdata(struct device *dev, struct device_node *np)475{476 struct lp8727_chg_param *param;477 478 param = devm_kzalloc(dev, sizeof(*param), GFP_KERNEL);479 if (!param)480 goto out;481 482 of_property_read_u8(np, "eoc-level", (u8 *)¶m->eoc_level);483 of_property_read_u8(np, "charging-current", (u8 *)¶m->ichg);484out:485 return param;486}487 488static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)489{490 struct device_node *np = dev->of_node;491 struct device_node *child;492 struct lp8727_platform_data *pdata;493 const char *type;494 495 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);496 if (!pdata)497 return ERR_PTR(-ENOMEM);498 499 of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec);500 501 /* If charging parameter is not defined, just skip parsing the dt */502 if (of_get_child_count(np) == 0)503 return pdata;504 505 for_each_child_of_node(np, child) {506 of_property_read_string(child, "charger-type", &type);507 508 if (!strcmp(type, "ac"))509 pdata->ac = lp8727_parse_charge_pdata(dev, child);510 511 if (!strcmp(type, "usb"))512 pdata->usb = lp8727_parse_charge_pdata(dev, child);513 }514 515 return pdata;516}517#else518static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)519{520 return NULL;521}522#endif523 524static int lp8727_probe(struct i2c_client *cl)525{526 struct lp8727_chg *pchg;527 struct lp8727_platform_data *pdata;528 int ret;529 530 if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))531 return -EIO;532 533 if (cl->dev.of_node) {534 pdata = lp8727_parse_dt(&cl->dev);535 if (IS_ERR(pdata))536 return PTR_ERR(pdata);537 } else {538 pdata = dev_get_platdata(&cl->dev);539 }540 541 pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL);542 if (!pchg)543 return -ENOMEM;544 545 pchg->client = cl;546 pchg->dev = &cl->dev;547 pchg->pdata = pdata;548 i2c_set_clientdata(cl, pchg);549 550 mutex_init(&pchg->xfer_lock);551 552 ret = lp8727_init_device(pchg);553 if (ret) {554 dev_err(pchg->dev, "i2c communication err: %d", ret);555 return ret;556 }557 558 ret = lp8727_register_psy(pchg);559 if (ret) {560 dev_err(pchg->dev, "power supplies register err: %d", ret);561 return ret;562 }563 564 ret = lp8727_setup_irq(pchg);565 if (ret) {566 dev_err(pchg->dev, "irq handler err: %d", ret);567 return ret;568 }569 570 return 0;571}572 573static void lp8727_remove(struct i2c_client *cl)574{575 struct lp8727_chg *pchg = i2c_get_clientdata(cl);576 577 lp8727_release_irq(pchg);578}579 580static const struct of_device_id lp8727_dt_ids[] __maybe_unused = {581 { .compatible = "ti,lp8727", },582 { }583};584MODULE_DEVICE_TABLE(of, lp8727_dt_ids);585 586static const struct i2c_device_id lp8727_ids[] = {587 { "lp8727" },588 { }589};590MODULE_DEVICE_TABLE(i2c, lp8727_ids);591 592static struct i2c_driver lp8727_driver = {593 .driver = {594 .name = "lp8727",595 .of_match_table = of_match_ptr(lp8727_dt_ids),596 },597 .probe = lp8727_probe,598 .remove = lp8727_remove,599 .id_table = lp8727_ids,600};601module_i2c_driver(lp8727_driver);602 603MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver");604MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");605MODULE_LICENSE("GPL");606