2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-22 04:03:58 +08:00

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>
This commit is contained in:
Pali Rohár 2013-09-08 10:50:37 +02:00 committed by Anton Vorontsov
parent 61e6cfa80d
commit f07c11ea32

View File

@ -2,6 +2,7 @@
* ISP1704 USB Charger Detection driver
*
* Copyright (C) 2010 Nokia Corporation
* Copyright (C) 2012 - 2013 Pali Rohár <pali.rohar@gmail.com>
*
* 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 charger */
detect = isp1704_charger_detect(isp);
/* 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;
}
if (detect) {
isp->present = detect;
isp->psy.type = isp1704_charger_type(isp);
}
switch (isp->psy.type) {
case POWER_SUPPLY_TYPE_USB_DCP:
isp->current_max = 1800;
break;
case POWER_SUPPLY_TYPE_USB_CDP:
/*
* 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->psy.type != POWER_SUPPLY_TYPE_USB_DCP) {
/*
* Only 500mA here or high speed chirp
* handshaking may break
*/
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 @@ out:
}
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: