aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2013-09-08 04:50:37 -0400
committerAnton Vorontsov <anton@enomsg.org>2013-10-22 16:57:16 -0400
commitf07c11ea32eebf81b7c1e59da2d119bf023882f2 (patch)
tree4815c7aeb693fa134904f3d2536ec26e2e1d2b05 /drivers/power
parent61e6cfa80de5760bbe406f4e815b7739205754d2 (diff)
isp1704_charger: Fix driver to work with changes introduced in v3.5
* omap musb driver does not report USB_EVENT_ENUMERATED event anymore * omap musb driver reporting USB_EVENT_VBUS when charger is connected * read last event from phy->last_event (instead from ulpi register) * do not call wall charger detection more times Signed-off-by: Pali Rohár <pali.rohar@gmail.com> Signed-off-by: Anton Vorontsov <anton@enomsg.org>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/isp1704_charger.c91
1 files changed, 40 insertions, 51 deletions
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index fc04d191579b..1bb3a91b1acc 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -2,6 +2,7 @@
2 * ISP1704 USB Charger Detection driver 2 * ISP1704 USB Charger Detection driver
3 * 3 *
4 * Copyright (C) 2010 Nokia Corporation 4 * Copyright (C) 2010 Nokia Corporation
5 * Copyright (C) 2012 - 2013 Pali Rohár <pali.rohar@gmail.com>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -65,10 +66,6 @@ struct isp1704_charger {
65 unsigned present:1; 66 unsigned present:1;
66 unsigned online:1; 67 unsigned online:1;
67 unsigned current_max; 68 unsigned current_max;
68
69 /* temp storage variables */
70 unsigned long event;
71 unsigned max_power;
72}; 69};
73 70
74static inline int isp1704_read(struct isp1704_charger *isp, u32 reg) 71static inline int isp1704_read(struct isp1704_charger *isp, u32 reg)
@@ -231,56 +228,59 @@ static inline int isp1704_charger_detect(struct isp1704_charger *isp)
231 return ret; 228 return ret;
232} 229}
233 230
231static inline int isp1704_charger_detect_dcp(struct isp1704_charger *isp)
232{
233 if (isp1704_charger_detect(isp) &&
234 isp1704_charger_type(isp) == POWER_SUPPLY_TYPE_USB_DCP)
235 return true;
236 else
237 return false;
238}
239
234static void isp1704_charger_work(struct work_struct *data) 240static void isp1704_charger_work(struct work_struct *data)
235{ 241{
236 int detect;
237 unsigned long event;
238 unsigned power;
239 struct isp1704_charger *isp = 242 struct isp1704_charger *isp =
240 container_of(data, struct isp1704_charger, work); 243 container_of(data, struct isp1704_charger, work);
241 static DEFINE_MUTEX(lock); 244 static DEFINE_MUTEX(lock);
242 245
243 event = isp->event;
244 power = isp->max_power;
245
246 mutex_lock(&lock); 246 mutex_lock(&lock);
247 247
248 if (event != USB_EVENT_NONE) 248 switch (isp->phy->last_event) {
249 isp1704_charger_set_power(isp, 1);
250
251 switch (event) {
252 case USB_EVENT_VBUS: 249 case USB_EVENT_VBUS:
253 isp->online = true; 250 /* do not call wall charger detection more times */
251 if (!isp->present) {
252 isp->online = true;
253 isp->present = 1;
254 isp1704_charger_set_power(isp, 1);
255
256 /* detect wall charger */
257 if (isp1704_charger_detect_dcp(isp)) {
258 isp->psy.type = POWER_SUPPLY_TYPE_USB_DCP;
259 isp->current_max = 1800;
260 } else {
261 isp->psy.type = POWER_SUPPLY_TYPE_USB;
262 isp->current_max = 500;
263 }
254 264
255 /* detect charger */ 265 /* enable data pullups */
256 detect = isp1704_charger_detect(isp); 266 if (isp->phy->otg->gadget)
257 267 usb_gadget_connect(isp->phy->otg->gadget);
258 if (detect) {
259 isp->present = detect;
260 isp->psy.type = isp1704_charger_type(isp);
261 } 268 }
262 269
263 switch (isp->psy.type) { 270 if (isp->psy.type != POWER_SUPPLY_TYPE_USB_DCP) {
264 case POWER_SUPPLY_TYPE_USB_DCP:
265 isp->current_max = 1800;
266 break;
267 case POWER_SUPPLY_TYPE_USB_CDP:
268 /* 271 /*
269 * Only 500mA here or high speed chirp 272 * Only 500mA here or high speed chirp
270 * handshaking may break 273 * handshaking may break
271 */ 274 */
272 isp->current_max = 500; 275 if (isp->current_max > 500)
273 /* FALLTHROUGH */ 276 isp->current_max = 500;
274 case POWER_SUPPLY_TYPE_USB: 277
275 default: 278 if (isp->current_max > 100)
276 /* enable data pullups */ 279 isp->psy.type = POWER_SUPPLY_TYPE_USB_CDP;
277 if (isp->phy->otg->gadget)
278 usb_gadget_connect(isp->phy->otg->gadget);
279 } 280 }
280 break; 281 break;
281 case USB_EVENT_NONE: 282 case USB_EVENT_NONE:
282 isp->online = false; 283 isp->online = false;
283 isp->current_max = 0;
284 isp->present = 0; 284 isp->present = 0;
285 isp->current_max = 0; 285 isp->current_max = 0;
286 isp->psy.type = POWER_SUPPLY_TYPE_USB; 286 isp->psy.type = POWER_SUPPLY_TYPE_USB;
@@ -298,12 +298,6 @@ static void isp1704_charger_work(struct work_struct *data)
298 298
299 isp1704_charger_set_power(isp, 0); 299 isp1704_charger_set_power(isp, 0);
300 break; 300 break;
301 case USB_EVENT_ENUMERATED:
302 if (isp->present)
303 isp->current_max = 1800;
304 else
305 isp->current_max = power;
306 break;
307 default: 301 default:
308 goto out; 302 goto out;
309 } 303 }
@@ -314,16 +308,11 @@ out:
314} 308}
315 309
316static int isp1704_notifier_call(struct notifier_block *nb, 310static int isp1704_notifier_call(struct notifier_block *nb,
317 unsigned long event, void *power) 311 unsigned long val, void *v)
318{ 312{
319 struct isp1704_charger *isp = 313 struct isp1704_charger *isp =
320 container_of(nb, struct isp1704_charger, nb); 314 container_of(nb, struct isp1704_charger, nb);
321 315
322 isp->event = event;
323
324 if (power)
325 isp->max_power = *((unsigned *)power);
326
327 schedule_work(&isp->work); 316 schedule_work(&isp->work);
328 317
329 return NOTIFY_OK; 318 return NOTIFY_OK;
@@ -462,13 +451,13 @@ static int isp1704_charger_probe(struct platform_device *pdev)
462 if (isp->phy->otg->gadget) 451 if (isp->phy->otg->gadget)
463 usb_gadget_disconnect(isp->phy->otg->gadget); 452 usb_gadget_disconnect(isp->phy->otg->gadget);
464 453
454 if (isp->phy->last_event == USB_EVENT_NONE)
455 isp1704_charger_set_power(isp, 0);
456
465 /* Detect charger if VBUS is valid (the cable was already plugged). */ 457 /* Detect charger if VBUS is valid (the cable was already plugged). */
466 ret = isp1704_read(isp, ULPI_USB_INT_STS); 458 if (isp->phy->last_event == USB_EVENT_VBUS &&
467 isp1704_charger_set_power(isp, 0); 459 !isp->phy->otg->default_a)
468 if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) {
469 isp->event = USB_EVENT_VBUS;
470 schedule_work(&isp->work); 460 schedule_work(&isp->work);
471 }
472 461
473 return 0; 462 return 0;
474fail2: 463fail2: