forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Signed-off-by: Anton Vorontsov <[email protected]>
- Loading branch information
Showing
1 changed file
with
40 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
* ISP1704 USB Charger Detection driver | ||
* | ||
* Copyright (C) 2010 Nokia Corporation | ||
* Copyright (C) 2012 - 2013 Pali Rohár <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
|
@@ -65,10 +66,6 @@ struct isp1704_charger { | |
unsigned present:1; | ||
unsigned online:1; | ||
unsigned current_max; | ||
|
||
/* temp storage variables */ | ||
unsigned long event; | ||
unsigned max_power; | ||
}; | ||
|
||
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) | |
return ret; | ||
} | ||
|
||
static inline int isp1704_charger_detect_dcp(struct isp1704_charger *isp) | ||
{ | ||
if (isp1704_charger_detect(isp) && | ||
isp1704_charger_type(isp) == POWER_SUPPLY_TYPE_USB_DCP) | ||
return true; | ||
else | ||
return false; | ||
} | ||
|
||
static void isp1704_charger_work(struct work_struct *data) | ||
{ | ||
int detect; | ||
unsigned long event; | ||
unsigned power; | ||
struct isp1704_charger *isp = | ||
container_of(data, struct isp1704_charger, work); | ||
static DEFINE_MUTEX(lock); | ||
|
||
event = isp->event; | ||
power = isp->max_power; | ||
|
||
mutex_lock(&lock); | ||
|
||
if (event != USB_EVENT_NONE) | ||
isp1704_charger_set_power(isp, 1); | ||
|
||
switch (event) { | ||
switch (isp->phy->last_event) { | ||
case USB_EVENT_VBUS: | ||
isp->online = true; | ||
/* do not call wall charger detection more times */ | ||
if (!isp->present) { | ||
isp->online = true; | ||
isp->present = 1; | ||
isp1704_charger_set_power(isp, 1); | ||
|
||
/* detect wall charger */ | ||
if (isp1704_charger_detect_dcp(isp)) { | ||
isp->psy.type = POWER_SUPPLY_TYPE_USB_DCP; | ||
isp->current_max = 1800; | ||
} else { | ||
isp->psy.type = POWER_SUPPLY_TYPE_USB; | ||
isp->current_max = 500; | ||
} | ||
|
||
/* detect charger */ | ||
detect = isp1704_charger_detect(isp); | ||
|
||
if (detect) { | ||
isp->present = detect; | ||
isp->psy.type = isp1704_charger_type(isp); | ||
/* enable data pullups */ | ||
if (isp->phy->otg->gadget) | ||
usb_gadget_connect(isp->phy->otg->gadget); | ||
} | ||
|
||
switch (isp->psy.type) { | ||
case POWER_SUPPLY_TYPE_USB_DCP: | ||
isp->current_max = 1800; | ||
break; | ||
case POWER_SUPPLY_TYPE_USB_CDP: | ||
if (isp->psy.type != POWER_SUPPLY_TYPE_USB_DCP) { | ||
/* | ||
* Only 500mA here or high speed chirp | ||
* handshaking may break | ||
*/ | ||
isp->current_max = 500; | ||
/* FALLTHROUGH */ | ||
case POWER_SUPPLY_TYPE_USB: | ||
default: | ||
/* enable data pullups */ | ||
if (isp->phy->otg->gadget) | ||
usb_gadget_connect(isp->phy->otg->gadget); | ||
if (isp->current_max > 500) | ||
isp->current_max = 500; | ||
|
||
if (isp->current_max > 100) | ||
isp->psy.type = POWER_SUPPLY_TYPE_USB_CDP; | ||
} | ||
break; | ||
case USB_EVENT_NONE: | ||
isp->online = false; | ||
isp->current_max = 0; | ||
isp->present = 0; | ||
isp->current_max = 0; | ||
isp->psy.type = POWER_SUPPLY_TYPE_USB; | ||
|
@@ -298,12 +298,6 @@ static void isp1704_charger_work(struct work_struct *data) | |
|
||
isp1704_charger_set_power(isp, 0); | ||
break; | ||
case USB_EVENT_ENUMERATED: | ||
if (isp->present) | ||
isp->current_max = 1800; | ||
else | ||
isp->current_max = power; | ||
break; | ||
default: | ||
goto out; | ||
} | ||
|
@@ -314,16 +308,11 @@ static void isp1704_charger_work(struct work_struct *data) | |
} | ||
|
||
static int isp1704_notifier_call(struct notifier_block *nb, | ||
unsigned long event, void *power) | ||
unsigned long val, void *v) | ||
{ | ||
struct isp1704_charger *isp = | ||
container_of(nb, struct isp1704_charger, nb); | ||
|
||
isp->event = event; | ||
|
||
if (power) | ||
isp->max_power = *((unsigned *)power); | ||
|
||
schedule_work(&isp->work); | ||
|
||
return NOTIFY_OK; | ||
|
@@ -462,13 +451,13 @@ static int isp1704_charger_probe(struct platform_device *pdev) | |
if (isp->phy->otg->gadget) | ||
usb_gadget_disconnect(isp->phy->otg->gadget); | ||
|
||
if (isp->phy->last_event == USB_EVENT_NONE) | ||
isp1704_charger_set_power(isp, 0); | ||
|
||
/* Detect charger if VBUS is valid (the cable was already plugged). */ | ||
ret = isp1704_read(isp, ULPI_USB_INT_STS); | ||
isp1704_charger_set_power(isp, 0); | ||
if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) { | ||
isp->event = USB_EVENT_VBUS; | ||
if (isp->phy->last_event == USB_EVENT_VBUS && | ||
!isp->phy->otg->default_a) | ||
schedule_work(&isp->work); | ||
} | ||
|
||
return 0; | ||
fail2: | ||
|