diff options
Diffstat (limited to 'drivers/power/lp8727_charger.c')
-rw-r--r-- | drivers/power/lp8727_charger.c | 360 |
1 files changed, 207 insertions, 153 deletions
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c index 6a364f4798f7..c628224b7f58 100644 --- a/drivers/power/lp8727_charger.c +++ b/drivers/power/lp8727_charger.c | |||
@@ -17,61 +17,65 @@ | |||
17 | #include <linux/power_supply.h> | 17 | #include <linux/power_supply.h> |
18 | #include <linux/platform_data/lp8727.h> | 18 | #include <linux/platform_data/lp8727.h> |
19 | 19 | ||
20 | #define DEBOUNCE_MSEC 270 | 20 | #define LP8788_NUM_INTREGS 2 |
21 | #define DEFAULT_DEBOUNCE_MSEC 270 | ||
21 | 22 | ||
22 | /* Registers */ | 23 | /* Registers */ |
23 | #define CTRL1 0x1 | 24 | #define LP8727_CTRL1 0x1 |
24 | #define CTRL2 0x2 | 25 | #define LP8727_CTRL2 0x2 |
25 | #define SWCTRL 0x3 | 26 | #define LP8727_SWCTRL 0x3 |
26 | #define INT1 0x4 | 27 | #define LP8727_INT1 0x4 |
27 | #define INT2 0x5 | 28 | #define LP8727_INT2 0x5 |
28 | #define STATUS1 0x6 | 29 | #define LP8727_STATUS1 0x6 |
29 | #define STATUS2 0x7 | 30 | #define LP8727_STATUS2 0x7 |
30 | #define CHGCTRL2 0x9 | 31 | #define LP8727_CHGCTRL2 0x9 |
31 | 32 | ||
32 | /* CTRL1 register */ | 33 | /* CTRL1 register */ |
33 | #define CP_EN (1 << 0) | 34 | #define LP8727_CP_EN BIT(0) |
34 | #define ADC_EN (1 << 1) | 35 | #define LP8727_ADC_EN BIT(1) |
35 | #define ID200_EN (1 << 4) | 36 | #define LP8727_ID200_EN BIT(4) |
36 | 37 | ||
37 | /* CTRL2 register */ | 38 | /* CTRL2 register */ |
38 | #define CHGDET_EN (1 << 1) | 39 | #define LP8727_CHGDET_EN BIT(1) |
39 | #define INT_EN (1 << 6) | 40 | #define LP8727_INT_EN BIT(6) |
40 | 41 | ||
41 | /* SWCTRL register */ | 42 | /* SWCTRL register */ |
42 | #define SW_DM1_DM (0x0 << 0) | 43 | #define LP8727_SW_DM1_DM (0x0 << 0) |
43 | #define SW_DM1_U1 (0x1 << 0) | 44 | #define LP8727_SW_DM1_HiZ (0x7 << 0) |
44 | #define SW_DM1_HiZ (0x7 << 0) | 45 | #define LP8727_SW_DP2_DP (0x0 << 3) |
45 | #define SW_DP2_DP (0x0 << 3) | 46 | #define LP8727_SW_DP2_HiZ (0x7 << 3) |
46 | #define SW_DP2_U2 (0x1 << 3) | ||
47 | #define SW_DP2_HiZ (0x7 << 3) | ||
48 | 47 | ||
49 | /* INT1 register */ | 48 | /* INT1 register */ |
50 | #define IDNO (0xF << 0) | 49 | #define LP8727_IDNO (0xF << 0) |
51 | #define VBUS (1 << 4) | 50 | #define LP8727_VBUS BIT(4) |
52 | 51 | ||
53 | /* STATUS1 register */ | 52 | /* STATUS1 register */ |
54 | #define CHGSTAT (3 << 4) | 53 | #define LP8727_CHGSTAT (3 << 4) |
55 | #define CHPORT (1 << 6) | 54 | #define LP8727_CHPORT BIT(6) |
56 | #define DCPORT (1 << 7) | 55 | #define LP8727_DCPORT BIT(7) |
56 | #define LP8727_STAT_EOC 0x30 | ||
57 | 57 | ||
58 | /* STATUS2 register */ | 58 | /* STATUS2 register */ |
59 | #define TEMP_STAT (3 << 5) | 59 | #define LP8727_TEMP_STAT (3 << 5) |
60 | #define LP8727_TEMP_SHIFT 5 | ||
61 | |||
62 | /* CHGCTRL2 register */ | ||
63 | #define LP8727_ICHG_SHIFT 4 | ||
60 | 64 | ||
61 | enum lp8727_dev_id { | 65 | enum lp8727_dev_id { |
62 | ID_NONE, | 66 | LP8727_ID_NONE, |
63 | ID_TA, | 67 | LP8727_ID_TA, |
64 | ID_DEDICATED_CHG, | 68 | LP8727_ID_DEDICATED_CHG, |
65 | ID_USB_CHG, | 69 | LP8727_ID_USB_CHG, |
66 | ID_USB_DS, | 70 | LP8727_ID_USB_DS, |
67 | ID_MAX, | 71 | LP8727_ID_MAX, |
68 | }; | 72 | }; |
69 | 73 | ||
70 | enum lp8727_chg_stat { | 74 | enum lp8727_die_temp { |
71 | PRECHG, | 75 | LP8788_TEMP_75C, |
72 | CC, | 76 | LP8788_TEMP_95C, |
73 | CV, | 77 | LP8788_TEMP_115C, |
74 | EOC, | 78 | LP8788_TEMP_135C, |
75 | }; | 79 | }; |
76 | 80 | ||
77 | struct lp8727_psy { | 81 | struct lp8727_psy { |
@@ -84,12 +88,17 @@ struct lp8727_chg { | |||
84 | struct device *dev; | 88 | struct device *dev; |
85 | struct i2c_client *client; | 89 | struct i2c_client *client; |
86 | struct mutex xfer_lock; | 90 | struct mutex xfer_lock; |
87 | struct delayed_work work; | ||
88 | struct workqueue_struct *irqthread; | ||
89 | struct lp8727_platform_data *pdata; | ||
90 | struct lp8727_psy *psy; | 91 | struct lp8727_psy *psy; |
91 | struct lp8727_chg_param *chg_parm; | 92 | struct lp8727_platform_data *pdata; |
93 | |||
94 | /* Charger Data */ | ||
92 | enum lp8727_dev_id devid; | 95 | enum lp8727_dev_id devid; |
96 | struct lp8727_chg_param *chg_param; | ||
97 | |||
98 | /* Interrupt Handling */ | ||
99 | int irq; | ||
100 | struct delayed_work work; | ||
101 | unsigned long debounce_jiffies; | ||
93 | }; | 102 | }; |
94 | 103 | ||
95 | static int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len) | 104 | static int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len) |
@@ -119,81 +128,84 @@ static int lp8727_write_byte(struct lp8727_chg *pchg, u8 reg, u8 data) | |||
119 | return ret; | 128 | return ret; |
120 | } | 129 | } |
121 | 130 | ||
122 | static int lp8727_is_charger_attached(const char *name, int id) | 131 | static bool lp8727_is_charger_attached(const char *name, int id) |
123 | { | 132 | { |
124 | if (name) { | 133 | if (!strcmp(name, "ac")) |
125 | if (!strcmp(name, "ac")) | 134 | return id == LP8727_ID_TA || id == LP8727_ID_DEDICATED_CHG; |
126 | return (id == ID_TA || id == ID_DEDICATED_CHG) ? 1 : 0; | 135 | else if (!strcmp(name, "usb")) |
127 | else if (!strcmp(name, "usb")) | 136 | return id == LP8727_ID_USB_CHG; |
128 | return (id == ID_USB_CHG) ? 1 : 0; | ||
129 | } | ||
130 | 137 | ||
131 | return (id >= ID_TA && id <= ID_USB_CHG) ? 1 : 0; | 138 | return id >= LP8727_ID_TA && id <= LP8727_ID_USB_CHG; |
132 | } | 139 | } |
133 | 140 | ||
134 | static int lp8727_init_device(struct lp8727_chg *pchg) | 141 | static int lp8727_init_device(struct lp8727_chg *pchg) |
135 | { | 142 | { |
136 | u8 val; | 143 | u8 val; |
137 | int ret; | 144 | int ret; |
145 | u8 intstat[LP8788_NUM_INTREGS]; | ||
138 | 146 | ||
139 | val = ID200_EN | ADC_EN | CP_EN; | 147 | /* clear interrupts */ |
140 | ret = lp8727_write_byte(pchg, CTRL1, val); | 148 | ret = lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS); |
141 | if (ret) | 149 | if (ret) |
142 | return ret; | 150 | return ret; |
143 | 151 | ||
144 | val = INT_EN | CHGDET_EN; | 152 | val = LP8727_ID200_EN | LP8727_ADC_EN | LP8727_CP_EN; |
145 | ret = lp8727_write_byte(pchg, CTRL2, val); | 153 | ret = lp8727_write_byte(pchg, LP8727_CTRL1, val); |
146 | if (ret) | 154 | if (ret) |
147 | return ret; | 155 | return ret; |
148 | 156 | ||
149 | return 0; | 157 | val = LP8727_INT_EN | LP8727_CHGDET_EN; |
158 | return lp8727_write_byte(pchg, LP8727_CTRL2, val); | ||
150 | } | 159 | } |
151 | 160 | ||
152 | static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg) | 161 | static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg) |
153 | { | 162 | { |
154 | u8 val; | 163 | u8 val; |
155 | lp8727_read_byte(pchg, STATUS1, &val); | 164 | |
156 | return val & DCPORT; | 165 | lp8727_read_byte(pchg, LP8727_STATUS1, &val); |
166 | return val & LP8727_DCPORT; | ||
157 | } | 167 | } |
158 | 168 | ||
159 | static int lp8727_is_usb_charger(struct lp8727_chg *pchg) | 169 | static int lp8727_is_usb_charger(struct lp8727_chg *pchg) |
160 | { | 170 | { |
161 | u8 val; | 171 | u8 val; |
162 | lp8727_read_byte(pchg, STATUS1, &val); | 172 | |
163 | return val & CHPORT; | 173 | lp8727_read_byte(pchg, LP8727_STATUS1, &val); |
174 | return val & LP8727_CHPORT; | ||
164 | } | 175 | } |
165 | 176 | ||
166 | static void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw) | 177 | static inline void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw) |
167 | { | 178 | { |
168 | lp8727_write_byte(pchg, SWCTRL, sw); | 179 | lp8727_write_byte(pchg, LP8727_SWCTRL, sw); |
169 | } | 180 | } |
170 | 181 | ||
171 | static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin) | 182 | static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin) |
172 | { | 183 | { |
173 | u8 devid = ID_NONE; | 184 | struct lp8727_platform_data *pdata = pchg->pdata; |
174 | u8 swctrl = SW_DM1_HiZ | SW_DP2_HiZ; | 185 | u8 devid = LP8727_ID_NONE; |
186 | u8 swctrl = LP8727_SW_DM1_HiZ | LP8727_SW_DP2_HiZ; | ||
175 | 187 | ||
176 | switch (id) { | 188 | switch (id) { |
177 | case 0x5: | 189 | case 0x5: |
178 | devid = ID_TA; | 190 | devid = LP8727_ID_TA; |
179 | pchg->chg_parm = &pchg->pdata->ac; | 191 | pchg->chg_param = pdata ? pdata->ac : NULL; |
180 | break; | 192 | break; |
181 | case 0xB: | 193 | case 0xB: |
182 | if (lp8727_is_dedicated_charger(pchg)) { | 194 | if (lp8727_is_dedicated_charger(pchg)) { |
183 | pchg->chg_parm = &pchg->pdata->ac; | 195 | pchg->chg_param = pdata ? pdata->ac : NULL; |
184 | devid = ID_DEDICATED_CHG; | 196 | devid = LP8727_ID_DEDICATED_CHG; |
185 | } else if (lp8727_is_usb_charger(pchg)) { | 197 | } else if (lp8727_is_usb_charger(pchg)) { |
186 | pchg->chg_parm = &pchg->pdata->usb; | 198 | pchg->chg_param = pdata ? pdata->usb : NULL; |
187 | devid = ID_USB_CHG; | 199 | devid = LP8727_ID_USB_CHG; |
188 | swctrl = SW_DM1_DM | SW_DP2_DP; | 200 | swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP; |
189 | } else if (vbusin) { | 201 | } else if (vbusin) { |
190 | devid = ID_USB_DS; | 202 | devid = LP8727_ID_USB_DS; |
191 | swctrl = SW_DM1_DM | SW_DP2_DP; | 203 | swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP; |
192 | } | 204 | } |
193 | break; | 205 | break; |
194 | default: | 206 | default: |
195 | devid = ID_NONE; | 207 | devid = LP8727_ID_NONE; |
196 | pchg->chg_parm = NULL; | 208 | pchg->chg_param = NULL; |
197 | break; | 209 | break; |
198 | } | 210 | } |
199 | 211 | ||
@@ -205,24 +217,26 @@ static void lp8727_enable_chgdet(struct lp8727_chg *pchg) | |||
205 | { | 217 | { |
206 | u8 val; | 218 | u8 val; |
207 | 219 | ||
208 | lp8727_read_byte(pchg, CTRL2, &val); | 220 | lp8727_read_byte(pchg, LP8727_CTRL2, &val); |
209 | val |= CHGDET_EN; | 221 | val |= LP8727_CHGDET_EN; |
210 | lp8727_write_byte(pchg, CTRL2, val); | 222 | lp8727_write_byte(pchg, LP8727_CTRL2, val); |
211 | } | 223 | } |
212 | 224 | ||
213 | static void lp8727_delayed_func(struct work_struct *_work) | 225 | static void lp8727_delayed_func(struct work_struct *_work) |
214 | { | 226 | { |
215 | u8 intstat[2], idno, vbus; | 227 | struct lp8727_chg *pchg = container_of(_work, struct lp8727_chg, |
216 | struct lp8727_chg *pchg = | 228 | work.work); |
217 | container_of(_work, struct lp8727_chg, work.work); | 229 | u8 intstat[LP8788_NUM_INTREGS]; |
230 | u8 idno; | ||
231 | u8 vbus; | ||
218 | 232 | ||
219 | if (lp8727_read_bytes(pchg, INT1, intstat, 2)) { | 233 | if (lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS)) { |
220 | dev_err(pchg->dev, "can not read INT registers\n"); | 234 | dev_err(pchg->dev, "can not read INT registers\n"); |
221 | return; | 235 | return; |
222 | } | 236 | } |
223 | 237 | ||
224 | idno = intstat[0] & IDNO; | 238 | idno = intstat[0] & LP8727_IDNO; |
225 | vbus = intstat[0] & VBUS; | 239 | vbus = intstat[0] & LP8727_VBUS; |
226 | 240 | ||
227 | lp8727_id_detection(pchg, idno, vbus); | 241 | lp8727_id_detection(pchg, idno, vbus); |
228 | lp8727_enable_chgdet(pchg); | 242 | lp8727_enable_chgdet(pchg); |
@@ -235,29 +249,44 @@ static void lp8727_delayed_func(struct work_struct *_work) | |||
235 | static irqreturn_t lp8727_isr_func(int irq, void *ptr) | 249 | static irqreturn_t lp8727_isr_func(int irq, void *ptr) |
236 | { | 250 | { |
237 | struct lp8727_chg *pchg = ptr; | 251 | struct lp8727_chg *pchg = ptr; |
238 | unsigned long delay = msecs_to_jiffies(DEBOUNCE_MSEC); | ||
239 | |||
240 | queue_delayed_work(pchg->irqthread, &pchg->work, delay); | ||
241 | 252 | ||
253 | schedule_delayed_work(&pchg->work, pchg->debounce_jiffies); | ||
242 | return IRQ_HANDLED; | 254 | return IRQ_HANDLED; |
243 | } | 255 | } |
244 | 256 | ||
245 | static int lp8727_intr_config(struct lp8727_chg *pchg) | 257 | static int lp8727_setup_irq(struct lp8727_chg *pchg) |
246 | { | 258 | { |
259 | int ret; | ||
260 | int irq = pchg->client->irq; | ||
261 | unsigned delay_msec = pchg->pdata ? pchg->pdata->debounce_msec : | ||
262 | DEFAULT_DEBOUNCE_MSEC; | ||
263 | |||
247 | INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func); | 264 | INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func); |
248 | 265 | ||
249 | pchg->irqthread = create_singlethread_workqueue("lp8727-irqthd"); | 266 | if (irq <= 0) { |
250 | if (!pchg->irqthread) { | 267 | dev_warn(pchg->dev, "invalid irq number: %d\n", irq); |
251 | dev_err(pchg->dev, "can not create thread for lp8727\n"); | 268 | return 0; |
252 | return -ENOMEM; | ||
253 | } | 269 | } |
254 | 270 | ||
255 | return request_threaded_irq(pchg->client->irq, | 271 | ret = request_threaded_irq(irq, NULL, lp8727_isr_func, |
256 | NULL, | 272 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
257 | lp8727_isr_func, | 273 | "lp8727_irq", pchg); |
258 | IRQF_TRIGGER_FALLING, | 274 | |
259 | "lp8727_irq", | 275 | if (ret) |
260 | pchg); | 276 | return ret; |
277 | |||
278 | pchg->irq = irq; | ||
279 | pchg->debounce_jiffies = msecs_to_jiffies(delay_msec); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static void lp8727_release_irq(struct lp8727_chg *pchg) | ||
285 | { | ||
286 | cancel_delayed_work_sync(&pchg->work); | ||
287 | |||
288 | if (pchg->irq) | ||
289 | free_irq(pchg->irq, pchg); | ||
261 | } | 290 | } |
262 | 291 | ||
263 | static enum power_supply_property lp8727_charger_prop[] = { | 292 | static enum power_supply_property lp8727_charger_prop[] = { |
@@ -283,54 +312,82 @@ static int lp8727_charger_get_property(struct power_supply *psy, | |||
283 | { | 312 | { |
284 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); | 313 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); |
285 | 314 | ||
286 | if (psp == POWER_SUPPLY_PROP_ONLINE) | 315 | if (psp != POWER_SUPPLY_PROP_ONLINE) |
287 | val->intval = lp8727_is_charger_attached(psy->name, | 316 | return -EINVAL; |
288 | pchg->devid); | 317 | |
318 | val->intval = lp8727_is_charger_attached(psy->name, pchg->devid); | ||
289 | 319 | ||
290 | return 0; | 320 | return 0; |
291 | } | 321 | } |
292 | 322 | ||
323 | static bool lp8727_is_high_temperature(enum lp8727_die_temp temp) | ||
324 | { | ||
325 | switch (temp) { | ||
326 | case LP8788_TEMP_95C: | ||
327 | case LP8788_TEMP_115C: | ||
328 | case LP8788_TEMP_135C: | ||
329 | return true; | ||
330 | default: | ||
331 | return false; | ||
332 | } | ||
333 | } | ||
334 | |||
293 | static int lp8727_battery_get_property(struct power_supply *psy, | 335 | static int lp8727_battery_get_property(struct power_supply *psy, |
294 | enum power_supply_property psp, | 336 | enum power_supply_property psp, |
295 | union power_supply_propval *val) | 337 | union power_supply_propval *val) |
296 | { | 338 | { |
297 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); | 339 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); |
340 | struct lp8727_platform_data *pdata = pchg->pdata; | ||
341 | enum lp8727_die_temp temp; | ||
298 | u8 read; | 342 | u8 read; |
299 | 343 | ||
300 | switch (psp) { | 344 | switch (psp) { |
301 | case POWER_SUPPLY_PROP_STATUS: | 345 | case POWER_SUPPLY_PROP_STATUS: |
302 | if (lp8727_is_charger_attached(psy->name, pchg->devid)) { | 346 | if (!lp8727_is_charger_attached(psy->name, pchg->devid)) { |
303 | lp8727_read_byte(pchg, STATUS1, &read); | ||
304 | if (((read & CHGSTAT) >> 4) == EOC) | ||
305 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
306 | else | ||
307 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
308 | } else { | ||
309 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | 347 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; |
348 | return 0; | ||
310 | } | 349 | } |
350 | |||
351 | lp8727_read_byte(pchg, LP8727_STATUS1, &read); | ||
352 | |||
353 | val->intval = (read & LP8727_CHGSTAT) == LP8727_STAT_EOC ? | ||
354 | POWER_SUPPLY_STATUS_FULL : | ||
355 | POWER_SUPPLY_STATUS_CHARGING; | ||
311 | break; | 356 | break; |
312 | case POWER_SUPPLY_PROP_HEALTH: | 357 | case POWER_SUPPLY_PROP_HEALTH: |
313 | lp8727_read_byte(pchg, STATUS2, &read); | 358 | lp8727_read_byte(pchg, LP8727_STATUS2, &read); |
314 | read = (read & TEMP_STAT) >> 5; | 359 | temp = (read & LP8727_TEMP_STAT) >> LP8727_TEMP_SHIFT; |
315 | if (read >= 0x1 && read <= 0x3) | 360 | |
316 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | 361 | val->intval = lp8727_is_high_temperature(temp) ? |
317 | else | 362 | POWER_SUPPLY_HEALTH_OVERHEAT : |
318 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | 363 | POWER_SUPPLY_HEALTH_GOOD; |
319 | break; | 364 | break; |
320 | case POWER_SUPPLY_PROP_PRESENT: | 365 | case POWER_SUPPLY_PROP_PRESENT: |
321 | if (pchg->pdata->get_batt_present) | 366 | if (!pdata) |
367 | return -EINVAL; | ||
368 | |||
369 | if (pdata->get_batt_present) | ||
322 | val->intval = pchg->pdata->get_batt_present(); | 370 | val->intval = pchg->pdata->get_batt_present(); |
323 | break; | 371 | break; |
324 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 372 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
325 | if (pchg->pdata->get_batt_level) | 373 | if (!pdata) |
374 | return -EINVAL; | ||
375 | |||
376 | if (pdata->get_batt_level) | ||
326 | val->intval = pchg->pdata->get_batt_level(); | 377 | val->intval = pchg->pdata->get_batt_level(); |
327 | break; | 378 | break; |
328 | case POWER_SUPPLY_PROP_CAPACITY: | 379 | case POWER_SUPPLY_PROP_CAPACITY: |
329 | if (pchg->pdata->get_batt_capacity) | 380 | if (!pdata) |
381 | return -EINVAL; | ||
382 | |||
383 | if (pdata->get_batt_capacity) | ||
330 | val->intval = pchg->pdata->get_batt_capacity(); | 384 | val->intval = pchg->pdata->get_batt_capacity(); |
331 | break; | 385 | break; |
332 | case POWER_SUPPLY_PROP_TEMP: | 386 | case POWER_SUPPLY_PROP_TEMP: |
333 | if (pchg->pdata->get_batt_temp) | 387 | if (!pdata) |
388 | return -EINVAL; | ||
389 | |||
390 | if (pdata->get_batt_temp) | ||
334 | val->intval = pchg->pdata->get_batt_temp(); | 391 | val->intval = pchg->pdata->get_batt_temp(); |
335 | break; | 392 | break; |
336 | default: | 393 | default: |
@@ -343,16 +400,20 @@ static int lp8727_battery_get_property(struct power_supply *psy, | |||
343 | static void lp8727_charger_changed(struct power_supply *psy) | 400 | static void lp8727_charger_changed(struct power_supply *psy) |
344 | { | 401 | { |
345 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); | 402 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); |
403 | u8 eoc_level; | ||
404 | u8 ichg; | ||
346 | u8 val; | 405 | u8 val; |
347 | u8 eoc_level, ichg; | 406 | |
348 | 407 | /* skip if no charger exists */ | |
349 | if (lp8727_is_charger_attached(psy->name, pchg->devid)) { | 408 | if (!lp8727_is_charger_attached(psy->name, pchg->devid)) |
350 | if (pchg->chg_parm) { | 409 | return; |
351 | eoc_level = pchg->chg_parm->eoc_level; | 410 | |
352 | ichg = pchg->chg_parm->ichg; | 411 | /* update charging parameters */ |
353 | val = (ichg << 4) | eoc_level; | 412 | if (pchg->chg_param) { |
354 | lp8727_write_byte(pchg, CHGCTRL2, val); | 413 | eoc_level = pchg->chg_param->eoc_level; |
355 | } | 414 | ichg = pchg->chg_param->ichg; |
415 | val = (ichg << LP8727_ICHG_SHIFT) | eoc_level; | ||
416 | lp8727_write_byte(pchg, LP8727_CHGCTRL2, val); | ||
356 | } | 417 | } |
357 | } | 418 | } |
358 | 419 | ||
@@ -360,9 +421,9 @@ static int lp8727_register_psy(struct lp8727_chg *pchg) | |||
360 | { | 421 | { |
361 | struct lp8727_psy *psy; | 422 | struct lp8727_psy *psy; |
362 | 423 | ||
363 | psy = kzalloc(sizeof(*psy), GFP_KERNEL); | 424 | psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL); |
364 | if (!psy) | 425 | if (!psy) |
365 | goto err_mem; | 426 | return -ENOMEM; |
366 | 427 | ||
367 | pchg->psy = psy; | 428 | pchg->psy = psy; |
368 | 429 | ||
@@ -375,7 +436,7 @@ static int lp8727_register_psy(struct lp8727_chg *pchg) | |||
375 | psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to); | 436 | psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to); |
376 | 437 | ||
377 | if (power_supply_register(pchg->dev, &psy->ac)) | 438 | if (power_supply_register(pchg->dev, &psy->ac)) |
378 | goto err_psy; | 439 | goto err_psy_ac; |
379 | 440 | ||
380 | psy->usb.name = "usb"; | 441 | psy->usb.name = "usb"; |
381 | psy->usb.type = POWER_SUPPLY_TYPE_USB; | 442 | psy->usb.type = POWER_SUPPLY_TYPE_USB; |
@@ -386,7 +447,7 @@ static int lp8727_register_psy(struct lp8727_chg *pchg) | |||
386 | psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to); | 447 | psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to); |
387 | 448 | ||
388 | if (power_supply_register(pchg->dev, &psy->usb)) | 449 | if (power_supply_register(pchg->dev, &psy->usb)) |
389 | goto err_psy; | 450 | goto err_psy_usb; |
390 | 451 | ||
391 | psy->batt.name = "main_batt"; | 452 | psy->batt.name = "main_batt"; |
392 | psy->batt.type = POWER_SUPPLY_TYPE_BATTERY; | 453 | psy->batt.type = POWER_SUPPLY_TYPE_BATTERY; |
@@ -396,14 +457,15 @@ static int lp8727_register_psy(struct lp8727_chg *pchg) | |||
396 | psy->batt.external_power_changed = lp8727_charger_changed; | 457 | psy->batt.external_power_changed = lp8727_charger_changed; |
397 | 458 | ||
398 | if (power_supply_register(pchg->dev, &psy->batt)) | 459 | if (power_supply_register(pchg->dev, &psy->batt)) |
399 | goto err_psy; | 460 | goto err_psy_batt; |
400 | 461 | ||
401 | return 0; | 462 | return 0; |
402 | 463 | ||
403 | err_mem: | 464 | err_psy_batt: |
404 | return -ENOMEM; | 465 | power_supply_unregister(&psy->usb); |
405 | err_psy: | 466 | err_psy_usb: |
406 | kfree(psy); | 467 | power_supply_unregister(&psy->ac); |
468 | err_psy_ac: | ||
407 | return -EPERM; | 469 | return -EPERM; |
408 | } | 470 | } |
409 | 471 | ||
@@ -417,7 +479,6 @@ static void lp8727_unregister_psy(struct lp8727_chg *pchg) | |||
417 | power_supply_unregister(&psy->ac); | 479 | power_supply_unregister(&psy->ac); |
418 | power_supply_unregister(&psy->usb); | 480 | power_supply_unregister(&psy->usb); |
419 | power_supply_unregister(&psy->batt); | 481 | power_supply_unregister(&psy->batt); |
420 | kfree(psy); | ||
421 | } | 482 | } |
422 | 483 | ||
423 | static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) | 484 | static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) |
@@ -428,7 +489,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) | |||
428 | if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) | 489 | if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) |
429 | return -EIO; | 490 | return -EIO; |
430 | 491 | ||
431 | pchg = kzalloc(sizeof(*pchg), GFP_KERNEL); | 492 | pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL); |
432 | if (!pchg) | 493 | if (!pchg) |
433 | return -ENOMEM; | 494 | return -ENOMEM; |
434 | 495 | ||
@@ -442,37 +503,31 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) | |||
442 | ret = lp8727_init_device(pchg); | 503 | ret = lp8727_init_device(pchg); |
443 | if (ret) { | 504 | if (ret) { |
444 | dev_err(pchg->dev, "i2c communication err: %d", ret); | 505 | dev_err(pchg->dev, "i2c communication err: %d", ret); |
445 | goto error; | 506 | return ret; |
446 | } | 507 | } |
447 | 508 | ||
448 | ret = lp8727_intr_config(pchg); | 509 | ret = lp8727_register_psy(pchg); |
449 | if (ret) { | 510 | if (ret) { |
450 | dev_err(pchg->dev, "irq handler err: %d", ret); | 511 | dev_err(pchg->dev, "power supplies register err: %d", ret); |
451 | goto error; | 512 | return ret; |
452 | } | 513 | } |
453 | 514 | ||
454 | ret = lp8727_register_psy(pchg); | 515 | ret = lp8727_setup_irq(pchg); |
455 | if (ret) { | 516 | if (ret) { |
456 | dev_err(pchg->dev, "power supplies register err: %d", ret); | 517 | dev_err(pchg->dev, "irq handler err: %d", ret); |
457 | goto error; | 518 | lp8727_unregister_psy(pchg); |
519 | return ret; | ||
458 | } | 520 | } |
459 | 521 | ||
460 | return 0; | 522 | return 0; |
461 | |||
462 | error: | ||
463 | kfree(pchg); | ||
464 | return ret; | ||
465 | } | 523 | } |
466 | 524 | ||
467 | static int __devexit lp8727_remove(struct i2c_client *cl) | 525 | static int __devexit lp8727_remove(struct i2c_client *cl) |
468 | { | 526 | { |
469 | struct lp8727_chg *pchg = i2c_get_clientdata(cl); | 527 | struct lp8727_chg *pchg = i2c_get_clientdata(cl); |
470 | 528 | ||
529 | lp8727_release_irq(pchg); | ||
471 | lp8727_unregister_psy(pchg); | 530 | lp8727_unregister_psy(pchg); |
472 | free_irq(pchg->client->irq, pchg); | ||
473 | flush_workqueue(pchg->irqthread); | ||
474 | destroy_workqueue(pchg->irqthread); | ||
475 | kfree(pchg); | ||
476 | return 0; | 531 | return 0; |
477 | } | 532 | } |
478 | 533 | ||
@@ -493,6 +548,5 @@ static struct i2c_driver lp8727_driver = { | |||
493 | module_i2c_driver(lp8727_driver); | 548 | module_i2c_driver(lp8727_driver); |
494 | 549 | ||
495 | MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver"); | 550 | MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver"); |
496 | MODULE_AUTHOR("Woogyom Kim <milo.kim@ti.com>, " | 551 | MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>"); |
497 | "Daniel Jeong <daniel.jeong@ti.com>"); | ||
498 | MODULE_LICENSE("GPL"); | 552 | MODULE_LICENSE("GPL"); |