diff options
author | Pali Rohár <pali.rohar@gmail.com> | 2013-09-08 04:50:37 -0400 |
---|---|---|
committer | Anton Vorontsov <anton@enomsg.org> | 2013-10-22 16:57:16 -0400 |
commit | f07c11ea32eebf81b7c1e59da2d119bf023882f2 (patch) | |
tree | 4815c7aeb693fa134904f3d2536ec26e2e1d2b05 /drivers/power | |
parent | 61e6cfa80de5760bbe406f4e815b7739205754d2 (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.c | 91 |
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 | ||
74 | static inline int isp1704_read(struct isp1704_charger *isp, u32 reg) | 71 | static 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 | ||
231 | static 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 | |||
234 | static void isp1704_charger_work(struct work_struct *data) | 240 | static 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 | ||
316 | static int isp1704_notifier_call(struct notifier_block *nb, | 310 | static 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; |
474 | fail2: | 463 | fail2: |