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: |
