2 * Driver for LP8727 Micro/Mini USB IC with integrated charger
4 * Copyright (C) 2011 Texas Instruments
5 * Copyright (C) 2011 National Semiconductor
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/interrupt.h>
16 #include <linux/i2c.h>
17 #include <linux/power_supply.h>
18 #include <linux/platform_data/lp8727.h>
20 #define DEFAULT_DEBOUNCE_MSEC 270
33 #define CP_EN (1 << 0)
34 #define ADC_EN (1 << 1)
35 #define ID200_EN (1 << 4)
38 #define CHGDET_EN (1 << 1)
39 #define INT_EN (1 << 6)
42 #define SW_DM1_DM (0x0 << 0)
43 #define SW_DM1_U1 (0x1 << 0)
44 #define SW_DM1_HiZ (0x7 << 0)
45 #define SW_DP2_DP (0x0 << 3)
46 #define SW_DP2_U2 (0x1 << 3)
47 #define SW_DP2_HiZ (0x7 << 3)
50 #define IDNO (0xF << 0)
53 /* STATUS1 register */
54 #define CHGSTAT (3 << 4)
55 #define CHPORT (1 << 6)
56 #define DCPORT (1 << 7)
58 /* STATUS2 register */
59 #define TEMP_STAT (3 << 5)
70 enum lp8727_chg_stat
{
78 struct power_supply ac
;
79 struct power_supply usb
;
80 struct power_supply batt
;
85 struct i2c_client
*client
;
86 struct mutex xfer_lock
;
87 struct delayed_work work
;
88 struct lp8727_platform_data
*pdata
;
89 struct lp8727_psy
*psy
;
90 struct lp8727_chg_param
*chg_parm
;
91 enum lp8727_dev_id devid
;
92 unsigned long debounce_jiffies
;
96 static int lp8727_read_bytes(struct lp8727_chg
*pchg
, u8 reg
, u8
*data
, u8 len
)
100 mutex_lock(&pchg
->xfer_lock
);
101 ret
= i2c_smbus_read_i2c_block_data(pchg
->client
, reg
, len
, data
);
102 mutex_unlock(&pchg
->xfer_lock
);
104 return (ret
!= len
) ? -EIO
: 0;
107 static inline int lp8727_read_byte(struct lp8727_chg
*pchg
, u8 reg
, u8
*data
)
109 return lp8727_read_bytes(pchg
, reg
, data
, 1);
112 static int lp8727_write_byte(struct lp8727_chg
*pchg
, u8 reg
, u8 data
)
116 mutex_lock(&pchg
->xfer_lock
);
117 ret
= i2c_smbus_write_byte_data(pchg
->client
, reg
, data
);
118 mutex_unlock(&pchg
->xfer_lock
);
123 static int lp8727_is_charger_attached(const char *name
, int id
)
126 if (!strcmp(name
, "ac"))
127 return (id
== ID_TA
|| id
== ID_DEDICATED_CHG
) ? 1 : 0;
128 else if (!strcmp(name
, "usb"))
129 return (id
== ID_USB_CHG
) ? 1 : 0;
132 return (id
>= ID_TA
&& id
<= ID_USB_CHG
) ? 1 : 0;
135 static int lp8727_init_device(struct lp8727_chg
*pchg
)
140 val
= ID200_EN
| ADC_EN
| CP_EN
;
141 ret
= lp8727_write_byte(pchg
, CTRL1
, val
);
145 val
= INT_EN
| CHGDET_EN
;
146 ret
= lp8727_write_byte(pchg
, CTRL2
, val
);
153 static int lp8727_is_dedicated_charger(struct lp8727_chg
*pchg
)
156 lp8727_read_byte(pchg
, STATUS1
, &val
);
160 static int lp8727_is_usb_charger(struct lp8727_chg
*pchg
)
163 lp8727_read_byte(pchg
, STATUS1
, &val
);
167 static void lp8727_ctrl_switch(struct lp8727_chg
*pchg
, u8 sw
)
169 lp8727_write_byte(pchg
, SWCTRL
, sw
);
172 static void lp8727_id_detection(struct lp8727_chg
*pchg
, u8 id
, int vbusin
)
174 struct lp8727_platform_data
*pdata
= pchg
->pdata
;
176 u8 swctrl
= SW_DM1_HiZ
| SW_DP2_HiZ
;
181 pchg
->chg_parm
= pdata
? pdata
->ac
: NULL
;
184 if (lp8727_is_dedicated_charger(pchg
)) {
185 pchg
->chg_parm
= pdata
? pdata
->ac
: NULL
;
186 devid
= ID_DEDICATED_CHG
;
187 } else if (lp8727_is_usb_charger(pchg
)) {
188 pchg
->chg_parm
= pdata
? pdata
->usb
: NULL
;
190 swctrl
= SW_DM1_DM
| SW_DP2_DP
;
193 swctrl
= SW_DM1_DM
| SW_DP2_DP
;
198 pchg
->chg_parm
= NULL
;
203 lp8727_ctrl_switch(pchg
, swctrl
);
206 static void lp8727_enable_chgdet(struct lp8727_chg
*pchg
)
210 lp8727_read_byte(pchg
, CTRL2
, &val
);
212 lp8727_write_byte(pchg
, CTRL2
, val
);
215 static void lp8727_delayed_func(struct work_struct
*_work
)
217 u8 intstat
[2], idno
, vbus
;
218 struct lp8727_chg
*pchg
=
219 container_of(_work
, struct lp8727_chg
, work
.work
);
221 if (lp8727_read_bytes(pchg
, INT1
, intstat
, 2)) {
222 dev_err(pchg
->dev
, "can not read INT registers\n");
226 idno
= intstat
[0] & IDNO
;
227 vbus
= intstat
[0] & VBUS
;
229 lp8727_id_detection(pchg
, idno
, vbus
);
230 lp8727_enable_chgdet(pchg
);
232 power_supply_changed(&pchg
->psy
->ac
);
233 power_supply_changed(&pchg
->psy
->usb
);
234 power_supply_changed(&pchg
->psy
->batt
);
237 static irqreturn_t
lp8727_isr_func(int irq
, void *ptr
)
239 struct lp8727_chg
*pchg
= ptr
;
241 schedule_delayed_work(&pchg
->work
, pchg
->debounce_jiffies
);
245 static int lp8727_setup_irq(struct lp8727_chg
*pchg
)
248 int irq
= pchg
->client
->irq
;
249 unsigned delay_msec
= pchg
->pdata
? pchg
->pdata
->debounce_msec
:
250 DEFAULT_DEBOUNCE_MSEC
;
252 INIT_DELAYED_WORK(&pchg
->work
, lp8727_delayed_func
);
255 dev_warn(pchg
->dev
, "invalid irq number: %d\n", irq
);
259 ret
= request_threaded_irq(irq
, NULL
, lp8727_isr_func
,
260 IRQF_TRIGGER_FALLING
| IRQF_ONESHOT
,
267 pchg
->debounce_jiffies
= msecs_to_jiffies(delay_msec
);
272 static void lp8727_release_irq(struct lp8727_chg
*pchg
)
274 cancel_delayed_work_sync(&pchg
->work
);
277 free_irq(pchg
->irq
, pchg
);
280 static enum power_supply_property lp8727_charger_prop
[] = {
281 POWER_SUPPLY_PROP_ONLINE
,
284 static enum power_supply_property lp8727_battery_prop
[] = {
285 POWER_SUPPLY_PROP_STATUS
,
286 POWER_SUPPLY_PROP_HEALTH
,
287 POWER_SUPPLY_PROP_PRESENT
,
288 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
289 POWER_SUPPLY_PROP_CAPACITY
,
290 POWER_SUPPLY_PROP_TEMP
,
293 static char *battery_supplied_to
[] = {
297 static int lp8727_charger_get_property(struct power_supply
*psy
,
298 enum power_supply_property psp
,
299 union power_supply_propval
*val
)
301 struct lp8727_chg
*pchg
= dev_get_drvdata(psy
->dev
->parent
);
303 if (psp
== POWER_SUPPLY_PROP_ONLINE
)
304 val
->intval
= lp8727_is_charger_attached(psy
->name
,
310 static int lp8727_battery_get_property(struct power_supply
*psy
,
311 enum power_supply_property psp
,
312 union power_supply_propval
*val
)
314 struct lp8727_chg
*pchg
= dev_get_drvdata(psy
->dev
->parent
);
315 struct lp8727_platform_data
*pdata
= pchg
->pdata
;
319 case POWER_SUPPLY_PROP_STATUS
:
320 if (lp8727_is_charger_attached(psy
->name
, pchg
->devid
)) {
321 lp8727_read_byte(pchg
, STATUS1
, &read
);
322 if (((read
& CHGSTAT
) >> 4) == EOC
)
323 val
->intval
= POWER_SUPPLY_STATUS_FULL
;
325 val
->intval
= POWER_SUPPLY_STATUS_CHARGING
;
327 val
->intval
= POWER_SUPPLY_STATUS_DISCHARGING
;
330 case POWER_SUPPLY_PROP_HEALTH
:
331 lp8727_read_byte(pchg
, STATUS2
, &read
);
332 read
= (read
& TEMP_STAT
) >> 5;
333 if (read
>= 0x1 && read
<= 0x3)
334 val
->intval
= POWER_SUPPLY_HEALTH_OVERHEAT
;
336 val
->intval
= POWER_SUPPLY_HEALTH_GOOD
;
338 case POWER_SUPPLY_PROP_PRESENT
:
342 if (pdata
->get_batt_present
)
343 val
->intval
= pchg
->pdata
->get_batt_present();
345 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
349 if (pdata
->get_batt_level
)
350 val
->intval
= pchg
->pdata
->get_batt_level();
352 case POWER_SUPPLY_PROP_CAPACITY
:
356 if (pdata
->get_batt_capacity
)
357 val
->intval
= pchg
->pdata
->get_batt_capacity();
359 case POWER_SUPPLY_PROP_TEMP
:
363 if (pdata
->get_batt_temp
)
364 val
->intval
= pchg
->pdata
->get_batt_temp();
373 static void lp8727_charger_changed(struct power_supply
*psy
)
375 struct lp8727_chg
*pchg
= dev_get_drvdata(psy
->dev
->parent
);
379 if (lp8727_is_charger_attached(psy
->name
, pchg
->devid
)) {
380 if (pchg
->chg_parm
) {
381 eoc_level
= pchg
->chg_parm
->eoc_level
;
382 ichg
= pchg
->chg_parm
->ichg
;
383 val
= (ichg
<< 4) | eoc_level
;
384 lp8727_write_byte(pchg
, CHGCTRL2
, val
);
389 static int lp8727_register_psy(struct lp8727_chg
*pchg
)
391 struct lp8727_psy
*psy
;
393 psy
= devm_kzalloc(pchg
->dev
, sizeof(*psy
), GFP_KERNEL
);
400 psy
->ac
.type
= POWER_SUPPLY_TYPE_MAINS
;
401 psy
->ac
.properties
= lp8727_charger_prop
;
402 psy
->ac
.num_properties
= ARRAY_SIZE(lp8727_charger_prop
);
403 psy
->ac
.get_property
= lp8727_charger_get_property
;
404 psy
->ac
.supplied_to
= battery_supplied_to
;
405 psy
->ac
.num_supplicants
= ARRAY_SIZE(battery_supplied_to
);
407 if (power_supply_register(pchg
->dev
, &psy
->ac
))
410 psy
->usb
.name
= "usb";
411 psy
->usb
.type
= POWER_SUPPLY_TYPE_USB
;
412 psy
->usb
.properties
= lp8727_charger_prop
;
413 psy
->usb
.num_properties
= ARRAY_SIZE(lp8727_charger_prop
);
414 psy
->usb
.get_property
= lp8727_charger_get_property
;
415 psy
->usb
.supplied_to
= battery_supplied_to
;
416 psy
->usb
.num_supplicants
= ARRAY_SIZE(battery_supplied_to
);
418 if (power_supply_register(pchg
->dev
, &psy
->usb
))
421 psy
->batt
.name
= "main_batt";
422 psy
->batt
.type
= POWER_SUPPLY_TYPE_BATTERY
;
423 psy
->batt
.properties
= lp8727_battery_prop
;
424 psy
->batt
.num_properties
= ARRAY_SIZE(lp8727_battery_prop
);
425 psy
->batt
.get_property
= lp8727_battery_get_property
;
426 psy
->batt
.external_power_changed
= lp8727_charger_changed
;
428 if (power_supply_register(pchg
->dev
, &psy
->batt
))
434 power_supply_unregister(&psy
->usb
);
436 power_supply_unregister(&psy
->ac
);
441 static void lp8727_unregister_psy(struct lp8727_chg
*pchg
)
443 struct lp8727_psy
*psy
= pchg
->psy
;
448 power_supply_unregister(&psy
->ac
);
449 power_supply_unregister(&psy
->usb
);
450 power_supply_unregister(&psy
->batt
);
453 static int lp8727_probe(struct i2c_client
*cl
, const struct i2c_device_id
*id
)
455 struct lp8727_chg
*pchg
;
458 if (!i2c_check_functionality(cl
->adapter
, I2C_FUNC_SMBUS_I2C_BLOCK
))
461 pchg
= devm_kzalloc(&cl
->dev
, sizeof(*pchg
), GFP_KERNEL
);
466 pchg
->dev
= &cl
->dev
;
467 pchg
->pdata
= cl
->dev
.platform_data
;
468 i2c_set_clientdata(cl
, pchg
);
470 mutex_init(&pchg
->xfer_lock
);
472 ret
= lp8727_init_device(pchg
);
474 dev_err(pchg
->dev
, "i2c communication err: %d", ret
);
478 ret
= lp8727_register_psy(pchg
);
480 dev_err(pchg
->dev
, "power supplies register err: %d", ret
);
484 ret
= lp8727_setup_irq(pchg
);
486 dev_err(pchg
->dev
, "irq handler err: %d", ret
);
487 lp8727_unregister_psy(pchg
);
494 static int __devexit
lp8727_remove(struct i2c_client
*cl
)
496 struct lp8727_chg
*pchg
= i2c_get_clientdata(cl
);
498 lp8727_release_irq(pchg
);
499 lp8727_unregister_psy(pchg
);
503 static const struct i2c_device_id lp8727_ids
[] = {
507 MODULE_DEVICE_TABLE(i2c
, lp8727_ids
);
509 static struct i2c_driver lp8727_driver
= {
513 .probe
= lp8727_probe
,
514 .remove
= __devexit_p(lp8727_remove
),
515 .id_table
= lp8727_ids
,
517 module_i2c_driver(lp8727_driver
);
519 MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver");
520 MODULE_AUTHOR("Woogyom Kim <milo.kim@ti.com>, "
521 "Daniel Jeong <daniel.jeong@ti.com>");
522 MODULE_LICENSE("GPL");