12165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim/* 2f7bae49aa1247a195a3fe4235edf6811c175bb7bKim, Milo * Driver for LP8727 Micro/Mini USB IC with integrated charger 32165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim * 4e39b828f5355e41a8fd24f413fb9dfb81d808397Kim, Milo * Copyright (C) 2011 Texas Instruments 52165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim * Copyright (C) 2011 National Semiconductor 62165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim * 72165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim * This program is free software; you can redistribute it and/or modify 82165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim * it under the terms of the GNU General Public License version 2 as 92165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim * published by the Free Software Foundation. 102165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim * 112165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim */ 122165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 132165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#include <linux/module.h> 142165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#include <linux/slab.h> 152165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#include <linux/interrupt.h> 162165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#include <linux/i2c.h> 172165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#include <linux/power_supply.h> 182165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#include <linux/lp8727.h> 192165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 202165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define DEBOUNCE_MSEC 270 212165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 222165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim/* Registers */ 232165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define CTRL1 0x1 242165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define CTRL2 0x2 252165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define SWCTRL 0x3 262165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define INT1 0x4 272165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define INT2 0x5 282165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define STATUS1 0x6 297336880e3d73ee38b0c2bb99674e7e79d87dd43eKim, Milo#define STATUS2 0x7 302165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define CHGCTRL2 0x9 312165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 322165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim/* CTRL1 register */ 332165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define CP_EN (1 << 0) 342165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define ADC_EN (1 << 1) 352165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define ID200_EN (1 << 4) 362165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 372165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim/* CTRL2 register */ 382165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define CHGDET_EN (1 << 1) 392165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define INT_EN (1 << 6) 402165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 412165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim/* SWCTRL register */ 422165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define SW_DM1_DM (0x0 << 0) 432165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define SW_DM1_U1 (0x1 << 0) 442165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define SW_DM1_HiZ (0x7 << 0) 452165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define SW_DP2_DP (0x0 << 3) 462165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define SW_DP2_U2 (0x1 << 3) 472165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define SW_DP2_HiZ (0x7 << 3) 482165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 492165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim/* INT1 register */ 502165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define IDNO (0xF << 0) 512165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define VBUS (1 << 4) 522165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 532165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim/* STATUS1 register */ 542165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define CHGSTAT (3 << 4) 552165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define CHPORT (1 << 6) 562165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define DCPORT (1 << 7) 572165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 582165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim/* STATUS2 register */ 592165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim#define TEMP_STAT (3 << 5) 602165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 612165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimenum lp8727_dev_id { 622165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ID_NONE, 632165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ID_TA, 642165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ID_DEDICATED_CHG, 652165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ID_USB_CHG, 662165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ID_USB_DS, 672165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ID_MAX, 682165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 692165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 702165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimenum lp8727_chg_stat { 712165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim PRECHG, 722165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim CC, 732165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim CV, 742165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim EOC, 752165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 762165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 772165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstruct lp8727_psy { 782165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct power_supply ac; 792165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct power_supply usb; 802165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct power_supply batt; 812165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 822165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 832165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstruct lp8727_chg { 842165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct device *dev; 852165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct i2c_client *client; 862165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct mutex xfer_lock; 872165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct delayed_work work; 882165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct workqueue_struct *irqthread; 892165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_platform_data *pdata; 902165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_psy *psy; 912165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_chg_param *chg_parm; 922165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim enum lp8727_dev_id devid; 932165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 942165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 9527aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milostatic int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len) 962165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 972165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim s32 ret; 982165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 992165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim mutex_lock(&pchg->xfer_lock); 1002165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ret = i2c_smbus_read_i2c_block_data(pchg->client, reg, len, data); 1012165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim mutex_unlock(&pchg->xfer_lock); 1022165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1032165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return (ret != len) ? -EIO : 0; 1042165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 1052165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 10627aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milostatic inline int lp8727_read_byte(struct lp8727_chg *pchg, u8 reg, u8 *data) 1072165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 10827aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo return lp8727_read_bytes(pchg, reg, data, 1); 10927aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo} 11027aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo 11127aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milostatic int lp8727_write_byte(struct lp8727_chg *pchg, u8 reg, u8 data) 11227aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo{ 11327aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo int ret; 1142165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1152165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim mutex_lock(&pchg->xfer_lock); 11627aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo ret = i2c_smbus_write_byte_data(pchg->client, reg, data); 1172165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim mutex_unlock(&pchg->xfer_lock); 1182165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1192165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return ret; 1202165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 1212165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1222165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic int lp8727_is_charger_attached(const char *name, int id) 1232165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 1242165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (name) { 1252165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (!strcmp(name, "ac")) 1262165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return (id == ID_TA || id == ID_DEDICATED_CHG) ? 1 : 0; 1272165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim else if (!strcmp(name, "usb")) 1282165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return (id == ID_USB_CHG) ? 1 : 0; 1292165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 1302165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1312165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return (id >= ID_TA && id <= ID_USB_CHG) ? 1 : 0; 1322165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 1332165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1347da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milostatic int lp8727_init_device(struct lp8727_chg *pchg) 1352165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 1362165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 val; 1377da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo int ret; 1382165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1392165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val = ID200_EN | ADC_EN | CP_EN; 14027aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo ret = lp8727_write_byte(pchg, CTRL1, val); 1417da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo if (ret) 1427da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo return ret; 1432165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1442165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val = INT_EN | CHGDET_EN; 14527aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo ret = lp8727_write_byte(pchg, CTRL2, val); 1467da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo if (ret) 1477da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo return ret; 1487da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo 1497da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo return 0; 1502165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 1512165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1522165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic int lp8727_is_dedicated_charger(struct lp8727_chg *pchg) 1532165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 1542165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 val; 15527aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo lp8727_read_byte(pchg, STATUS1, &val); 1567336880e3d73ee38b0c2bb99674e7e79d87dd43eKim, Milo return val & DCPORT; 1572165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 1582165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1592165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic int lp8727_is_usb_charger(struct lp8727_chg *pchg) 1602165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 1612165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 val; 16227aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo lp8727_read_byte(pchg, STATUS1, &val); 1637336880e3d73ee38b0c2bb99674e7e79d87dd43eKim, Milo return val & CHPORT; 1642165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 1652165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1662165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw) 1672165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 16827aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo lp8727_write_byte(pchg, SWCTRL, sw); 1692165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 1702165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1712165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin) 1722165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 1732165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 devid = ID_NONE; 1742165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 swctrl = SW_DM1_HiZ | SW_DP2_HiZ; 1752165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 1762165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim switch (id) { 1772165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim case 0x5: 1782165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim devid = ID_TA; 1792165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->chg_parm = &pchg->pdata->ac; 1802165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 1812165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim case 0xB: 1822165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (lp8727_is_dedicated_charger(pchg)) { 1832165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->chg_parm = &pchg->pdata->ac; 1842165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim devid = ID_DEDICATED_CHG; 1852165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } else if (lp8727_is_usb_charger(pchg)) { 1862165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->chg_parm = &pchg->pdata->usb; 1872165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim devid = ID_USB_CHG; 1882165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim swctrl = SW_DM1_DM | SW_DP2_DP; 1892165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } else if (vbusin) { 1902165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim devid = ID_USB_DS; 1912165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim swctrl = SW_DM1_DM | SW_DP2_DP; 1922165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 1932165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 1942165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim default: 1952165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim devid = ID_NONE; 1962165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->chg_parm = NULL; 1972165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 1982165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 1992165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2002165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->devid = devid; 2012165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim lp8727_ctrl_switch(pchg, swctrl); 2022165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 2032165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2042165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic void lp8727_enable_chgdet(struct lp8727_chg *pchg) 2052165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 2062165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 val; 2072165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 20827aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo lp8727_read_byte(pchg, CTRL2, &val); 2092165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val |= CHGDET_EN; 21027aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo lp8727_write_byte(pchg, CTRL2, val); 2112165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 2122165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2132165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic void lp8727_delayed_func(struct work_struct *_work) 2142165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 2152165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 intstat[2], idno, vbus; 2162165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_chg *pchg = 2172165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim container_of(_work, struct lp8727_chg, work.work); 2182165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 21927aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo if (lp8727_read_bytes(pchg, INT1, intstat, 2)) { 2202165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim dev_err(pchg->dev, "can not read INT registers\n"); 2212165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return; 2222165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 2232165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2242165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim idno = intstat[0] & IDNO; 2252165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim vbus = intstat[0] & VBUS; 2262165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2272165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim lp8727_id_detection(pchg, idno, vbus); 2282165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim lp8727_enable_chgdet(pchg); 2292165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2302165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim power_supply_changed(&pchg->psy->ac); 2312165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim power_supply_changed(&pchg->psy->usb); 2322165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim power_supply_changed(&pchg->psy->batt); 2332165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 2342165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2352165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic irqreturn_t lp8727_isr_func(int irq, void *ptr) 2362165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 2372165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_chg *pchg = ptr; 2382165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim unsigned long delay = msecs_to_jiffies(DEBOUNCE_MSEC); 2392165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2402165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim queue_delayed_work(pchg->irqthread, &pchg->work, delay); 2412165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2422165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return IRQ_HANDLED; 2432165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 2442165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2457da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milostatic int lp8727_intr_config(struct lp8727_chg *pchg) 2462165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 2472165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func); 2482165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2492165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->irqthread = create_singlethread_workqueue("lp8727-irqthd"); 2507da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo if (!pchg->irqthread) { 2512165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim dev_err(pchg->dev, "can not create thread for lp8727\n"); 2527da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo return -ENOMEM; 2532165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 2547da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo 2557da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo return request_threaded_irq(pchg->client->irq, 2567da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo NULL, 2577da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo lp8727_isr_func, 2587da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo IRQF_TRIGGER_FALLING, 2597da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo "lp8727_irq", 2607da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo pchg); 2612165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 2622165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2632165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic enum power_supply_property lp8727_charger_prop[] = { 2642165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim POWER_SUPPLY_PROP_ONLINE, 2652165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 2662165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2672165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic enum power_supply_property lp8727_battery_prop[] = { 2682165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim POWER_SUPPLY_PROP_STATUS, 2692165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim POWER_SUPPLY_PROP_HEALTH, 2702165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim POWER_SUPPLY_PROP_PRESENT, 2712165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim POWER_SUPPLY_PROP_VOLTAGE_NOW, 2722165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim POWER_SUPPLY_PROP_CAPACITY, 2732165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim POWER_SUPPLY_PROP_TEMP, 2742165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 2752165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2762165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic char *battery_supplied_to[] = { 2772165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim "main_batt", 2782165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 2792165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2802165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic int lp8727_charger_get_property(struct power_supply *psy, 2812165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim enum power_supply_property psp, 2822165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim union power_supply_propval *val) 2832165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 2842165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); 2852165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 286ce09affc59bca2a1ac1f77b75915fd914fab1f70Kim, Milo if (psp == POWER_SUPPLY_PROP_ONLINE) 2872165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = lp8727_is_charger_attached(psy->name, 2882165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->devid); 2892165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2902165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return 0; 2912165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 2922165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 2932165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic int lp8727_battery_get_property(struct power_supply *psy, 2942165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim enum power_supply_property psp, 2952165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim union power_supply_propval *val) 2962165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 2972165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); 2982165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 read; 2992165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3002165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim switch (psp) { 3012165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim case POWER_SUPPLY_PROP_STATUS: 3022165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (lp8727_is_charger_attached(psy->name, pchg->devid)) { 30327aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo lp8727_read_byte(pchg, STATUS1, &read); 3042165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (((read & CHGSTAT) >> 4) == EOC) 3052165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = POWER_SUPPLY_STATUS_FULL; 3062165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim else 3072165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = POWER_SUPPLY_STATUS_CHARGING; 3082165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } else { 3092165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 3102165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 3112165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 3122165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim case POWER_SUPPLY_PROP_HEALTH: 31327aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo lp8727_read_byte(pchg, STATUS2, &read); 3142165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim read = (read & TEMP_STAT) >> 5; 3152165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (read >= 0x1 && read <= 0x3) 3162165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 3172165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim else 3182165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = POWER_SUPPLY_HEALTH_GOOD; 3192165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 3202165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim case POWER_SUPPLY_PROP_PRESENT: 3212165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (pchg->pdata->get_batt_present) 3222165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = pchg->pdata->get_batt_present(); 3232165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 3242165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim case POWER_SUPPLY_PROP_VOLTAGE_NOW: 3252165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (pchg->pdata->get_batt_level) 3262165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = pchg->pdata->get_batt_level(); 3272165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 3282165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim case POWER_SUPPLY_PROP_CAPACITY: 3292165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (pchg->pdata->get_batt_capacity) 3302165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = pchg->pdata->get_batt_capacity(); 3312165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 3322165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim case POWER_SUPPLY_PROP_TEMP: 3332165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (pchg->pdata->get_batt_temp) 3342165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val->intval = pchg->pdata->get_batt_temp(); 3352165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 3362165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim default: 3372165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim break; 3382165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 3392165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3402165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return 0; 3412165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 3422165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3432165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic void lp8727_charger_changed(struct power_supply *psy) 3442165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 3452165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); 3462165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 val; 3472165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim u8 eoc_level, ichg; 3482165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3492165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (lp8727_is_charger_attached(psy->name, pchg->devid)) { 3502165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (pchg->chg_parm) { 3512165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim eoc_level = pchg->chg_parm->eoc_level; 3522165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ichg = pchg->chg_parm->ichg; 3532165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim val = (ichg << 4) | eoc_level; 35427aefa3b7d8b1c37e0bc21cbd0ce3c93bdf163caKim, Milo lp8727_write_byte(pchg, CHGCTRL2, val); 3552165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 3562165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim } 3572165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 3582165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3592165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic int lp8727_register_psy(struct lp8727_chg *pchg) 3602165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 3612165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_psy *psy; 3622165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3632165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy = kzalloc(sizeof(*psy), GFP_KERNEL); 3642165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (!psy) 3652165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim goto err_mem; 3662165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3672165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->psy = psy; 3682165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3692165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->ac.name = "ac"; 3702165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->ac.type = POWER_SUPPLY_TYPE_MAINS; 3712165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->ac.properties = lp8727_charger_prop; 3722165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->ac.num_properties = ARRAY_SIZE(lp8727_charger_prop); 3732165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->ac.get_property = lp8727_charger_get_property; 3742165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->ac.supplied_to = battery_supplied_to; 3752165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to); 3762165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3772165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (power_supply_register(pchg->dev, &psy->ac)) 3782165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim goto err_psy; 3792165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3802165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->usb.name = "usb"; 3812165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->usb.type = POWER_SUPPLY_TYPE_USB; 3822165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->usb.properties = lp8727_charger_prop; 3832165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->usb.num_properties = ARRAY_SIZE(lp8727_charger_prop); 3842165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->usb.get_property = lp8727_charger_get_property; 3852165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->usb.supplied_to = battery_supplied_to; 3862165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to); 3872165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3882165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (power_supply_register(pchg->dev, &psy->usb)) 3892165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim goto err_psy; 3902165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3912165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->batt.name = "main_batt"; 3922165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->batt.type = POWER_SUPPLY_TYPE_BATTERY; 3932165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->batt.properties = lp8727_battery_prop; 3942165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->batt.num_properties = ARRAY_SIZE(lp8727_battery_prop); 3952165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->batt.get_property = lp8727_battery_get_property; 3962165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim psy->batt.external_power_changed = lp8727_charger_changed; 3972165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 3982165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (power_supply_register(pchg->dev, &psy->batt)) 3992165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim goto err_psy; 4002165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4012165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return 0; 4022165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4032165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimerr_mem: 4042165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return -ENOMEM; 4052165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimerr_psy: 4062165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim kfree(psy); 4072165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return -EPERM; 4082165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 4092165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4102165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic void lp8727_unregister_psy(struct lp8727_chg *pchg) 4112165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 4122165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_psy *psy = pchg->psy; 4132165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 414ce09affc59bca2a1ac1f77b75915fd914fab1f70Kim, Milo if (!psy) 415ce09affc59bca2a1ac1f77b75915fd914fab1f70Kim, Milo return; 416ce09affc59bca2a1ac1f77b75915fd914fab1f70Kim, Milo 417ce09affc59bca2a1ac1f77b75915fd914fab1f70Kim, Milo power_supply_unregister(&psy->ac); 418ce09affc59bca2a1ac1f77b75915fd914fab1f70Kim, Milo power_supply_unregister(&psy->usb); 419ce09affc59bca2a1ac1f77b75915fd914fab1f70Kim, Milo power_supply_unregister(&psy->batt); 420ce09affc59bca2a1ac1f77b75915fd914fab1f70Kim, Milo kfree(psy); 4212165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 4222165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4232165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) 4242165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 4252165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_chg *pchg; 4262165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim int ret; 4272165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 428998a8e7a72f6a81f540d3a3774d8e8aae6c7f9f2Kim, Milo if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) 429998a8e7a72f6a81f540d3a3774d8e8aae6c7f9f2Kim, Milo return -EIO; 430998a8e7a72f6a81f540d3a3774d8e8aae6c7f9f2Kim, Milo 4312165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg = kzalloc(sizeof(*pchg), GFP_KERNEL); 4322165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim if (!pchg) 4332165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return -ENOMEM; 4342165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4352165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->client = cl; 4362165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->dev = &cl->dev; 4372165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim pchg->pdata = cl->dev.platform_data; 4382165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim i2c_set_clientdata(cl, pchg); 4392165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4402165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim mutex_init(&pchg->xfer_lock); 4412165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4427da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo ret = lp8727_init_device(pchg); 4437da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo if (ret) { 4447da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo dev_err(pchg->dev, "i2c communication err: %d", ret); 4457da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo goto error; 4467da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo } 4477da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo 4487da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo ret = lp8727_intr_config(pchg); 4497da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo if (ret) { 4507da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo dev_err(pchg->dev, "irq handler err: %d", ret); 4517da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo goto error; 4527da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo } 4532165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4542165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim ret = lp8727_register_psy(pchg); 4557da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo if (ret) { 4567da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo dev_err(pchg->dev, "power supplies register err: %d", ret); 4577da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo goto error; 4587da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo } 4592165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4602165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return 0; 4617da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo 4627da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Miloerror: 4637da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo kfree(pchg); 4647da6334e73fe3c0579d8c6a56001336a430a5d99Kim, Milo return ret; 4652165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 4662165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4672165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic int __devexit lp8727_remove(struct i2c_client *cl) 4682165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim{ 4692165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim struct lp8727_chg *pchg = i2c_get_clientdata(cl); 4702165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4712165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim lp8727_unregister_psy(pchg); 4722165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim free_irq(pchg->client->irq, pchg); 4732165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim flush_workqueue(pchg->irqthread); 4742165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim destroy_workqueue(pchg->irqthread); 4752165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim kfree(pchg); 4762165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim return 0; 4772165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim} 4782165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4792165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic const struct i2c_device_id lp8727_ids[] = { 4802165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim {"lp8727", 0}, 481455a0e2cd80f7a2849b2e6d3be85c053ee44446bAxel Lin { } 4822165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 483e2c5f7db789a5be8ba131e9fe3e87b66bc606e3bAxel LinMODULE_DEVICE_TABLE(i2c, lp8727_ids); 4842165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 4852165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kimstatic struct i2c_driver lp8727_driver = { 4862165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim .driver = { 4872165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim .name = "lp8727", 4882165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim }, 4892165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim .probe = lp8727_probe, 4902165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim .remove = __devexit_p(lp8727_remove), 4912165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim .id_table = lp8727_ids, 4922165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim}; 4935ff92e7ab3591299089cfba440acb4d2ba8ab92fAxel Linmodule_i2c_driver(lp8727_driver); 4942165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom Kim 495e39b828f5355e41a8fd24f413fb9dfb81d808397Kim, MiloMODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver"); 4967336880e3d73ee38b0c2bb99674e7e79d87dd43eKim, MiloMODULE_AUTHOR("Woogyom Kim <milo.kim@ti.com>, " 4977336880e3d73ee38b0c2bb99674e7e79d87dd43eKim, Milo "Daniel Jeong <daniel.jeong@ti.com>"); 4982165c8a45bf2fba49f54fb81a50914f883bd14dfWoogyom KimMODULE_LICENSE("GPL"); 499