summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2011-01-12 11:00:39 +0800
committerPeter Chen <peter.chen@freescale.com>2011-01-12 11:18:01 +0800
commitdbd6186c060af0fe7157d7bd880792aa0b6126fa (patch)
treed0de54709c2529ef8404ecbcaf182df3282ad43e /arch
parentd570035407de42cc073610b59fe988dc9a0e4293 (diff)
ENGR00137872-2 mx5x_msl: move wakeup handle from driver to MSL
Move mx5x usb wakeup interrupt handler from the driver to MSL Signed-off-by: Peter Chen <peter.chen@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx5/usb_dr.c37
-rw-r--r--arch/arm/mach-mx5/usb_h1.c34
-rw-r--r--arch/arm/mach-mx5/usb_h2.c32
-rw-r--r--arch/arm/plat-mxc/usb_wakeup.c14
4 files changed, 95 insertions, 22 deletions
diff --git a/arch/arm/mach-mx5/usb_dr.c b/arch/arm/mach-mx5/usb_dr.c
index 19bad002e7a1..9864059ab3cc 100644
--- a/arch/arm/mach-mx5/usb_dr.c
+++ b/arch/arm/mach-mx5/usb_dr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -29,6 +29,7 @@ static struct clk *usb_oh3_clk;
static struct clk *usb_ahb_clk;
static void usbotg_wakeup_event_clear(void);
extern int clk_get_usecount(struct clk *clk);
+extern void fsl_usb_recover_hcd(struct platform_device *pdev);
/*
* platform data structs
* - Which one to use is determined by CONFIG options in usb.h
@@ -175,7 +176,7 @@ static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, b
__phy_lowpower_suspend(enable, ENABLED_BY_DEVICE);
}
-static bool _is_host_wakeup(struct fsl_usb2_platform_data *pdata)
+static enum usb_wakeup_event _is_host_wakeup(struct fsl_usb2_platform_data *pdata)
{
int wakeup_req = USBCTRL & UCTRL_OWIR;
int otgsc = UOG_OTGSC;
@@ -185,25 +186,39 @@ static bool _is_host_wakeup(struct fsl_usb2_platform_data *pdata)
printk(KERN_INFO "otg host ID wakeup\n");
/* if host ID wakeup, we must clear the b session change sts */
UOG_OTGSC = otgsc & (~OTGSC_IS_USB_ID);
- return true;
+ return WAKEUP_EVENT_ID;
}
if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) {
printk(KERN_INFO "otg host Remote wakeup\n");
- return true;
+ return WAKEUP_EVENT_DPDM;
}
- return false;
+
+ return WAKEUP_EVENT_INVALID;
}
-static bool _is_device_wakeup(struct fsl_usb2_platform_data *pdata)
+
+static enum usb_wakeup_event _is_device_wakeup(struct fsl_usb2_platform_data *pdata)
{
int wakeup_req = USBCTRL & UCTRL_OWIR;
- /* if not ID change sts, it is a device wakeup event */
- if (wakeup_req && !(UOG_OTGSC & OTGSC_IS_USB_ID) && (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)) {
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)) {
printk(KERN_INFO "otg udc wakeup\n");
- return true;
+ return WAKEUP_EVENT_VBUS;
}
- return false;
+ return WAKEUP_EVENT_INVALID;
+
+}
+static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _host_wakeup_enable(pdata, false);
+ _host_phy_lowpower_suspend(pdata, false);
+ fsl_usb_recover_hcd(&mxc_usbdr_host_device);
+}
+
+static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _device_wakeup_enable(pdata, false);
+ _device_phy_lowpower_suspend(pdata, false);
}
static void usbotg_wakeup_event_clear(void)
@@ -258,6 +273,7 @@ void __init mx5_usb_dr_init(void)
dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend;
dr_utmi_config.is_wakeup_event = _is_host_wakeup;
dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
+ dr_utmi_config.wakeup_handler = host_wakeup_handler;
platform_device_add_data(&mxc_usbdr_host_device, &dr_utmi_config, sizeof(dr_utmi_config));
platform_device_register(&mxc_usbdr_host_device);
dr_wakeup_config.usb_pdata[1] = mxc_usbdr_host_device.dev.platform_data;
@@ -268,6 +284,7 @@ void __init mx5_usb_dr_init(void)
dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend;
dr_utmi_config.is_wakeup_event = _is_device_wakeup;
dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
+ dr_utmi_config.wakeup_handler = device_wakeup_handler;
platform_device_add_data(&mxc_usbdr_udc_device, &dr_utmi_config, sizeof(dr_utmi_config));
platform_device_register(&mxc_usbdr_udc_device);
dr_wakeup_config.usb_pdata[2] = mxc_usbdr_udc_device.dev.platform_data;
diff --git a/arch/arm/mach-mx5/usb_h1.c b/arch/arm/mach-mx5/usb_h1.c
index f7b10147d13f..b2d230e8a8bd 100644
--- a/arch/arm/mach-mx5/usb_h1.c
+++ b/arch/arm/mach-mx5/usb_h1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -28,6 +28,7 @@ static struct clk *usb_phy2_clk;
static struct clk *usb_oh3_clk;
static struct clk *usb_ahb_clk;
extern int clk_get_usecount(struct clk *clk);
+extern void fsl_usb_recover_hcd(struct platform_device *pdev);
/*
* USB Host1 HS port
*/
@@ -106,16 +107,37 @@ static void usbh1_clock_gate(bool on)
}
}
-static bool _is_usbh1_wakeup(struct fsl_usb2_platform_data *pdata)
+static enum usb_wakeup_event _is_usbh1_wakeup(struct fsl_usb2_platform_data *pdata)
{
int wakeup_req = USBCTRL & UCTRL_H1WIR;
if (wakeup_req)
- return true;
+ return !WAKEUP_EVENT_INVALID;
- return false;
+ return WAKEUP_EVENT_INVALID;
}
+static void h1_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _wake_up_enable(pdata, false);
+ _phy_lowpower_suspend(pdata, false);
+ fsl_usb_recover_hcd(&mxc_usbh1_device);
+}
+
+static void usbh1_wakeup_event_clear(void)
+{
+ int wakeup_req = USBCTRL & UCTRL_H1WIR;
+
+ if (wakeup_req != 0) {
+ printk(KERN_INFO "Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC);
+ /* Disable H1WIE to clear H1WIR, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ USBCTRL &= ~UCTRL_H1WIE;
+ udelay(100);
+ USBCTRL |= UCTRL_H1WIE;
+ }
+}
static int fsl_usb_host_init_ext(struct platform_device *pdev)
{
int ret;
@@ -194,17 +216,21 @@ static struct fsl_usb2_platform_data usbh1_config = {
.usb_clock_for_pm = usbh1_clock_gate,
.phy_lowpower_suspend = _phy_lowpower_suspend,
.is_wakeup_event = _is_usbh1_wakeup,
+ .wakeup_handler = h1_wakeup_handler,
.transceiver = "utmi",
};
static struct fsl_usb2_wakeup_platform_data usbh1_wakeup_config = {
.name = "USBH1 wakeup",
.usb_clock_for_pm = usbh1_clock_gate,
.usb_pdata = {&usbh1_config, NULL, NULL},
+ .usb_wakeup_exhandle = usbh1_wakeup_event_clear,
};
+
void mx5_set_host1_vbus_func(driver_vbus_func driver_vbus)
{
usbh1_config.platform_driver_vbus = driver_vbus;
}
+
void __init mx5_usbh1_init(void)
{
if (cpu_is_mx51()) {
diff --git a/arch/arm/mach-mx5/usb_h2.c b/arch/arm/mach-mx5/usb_h2.c
index 237aa980e98a..bdc2dded7613 100644
--- a/arch/arm/mach-mx5/usb_h2.c
+++ b/arch/arm/mach-mx5/usb_h2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -22,6 +22,7 @@
#include "iomux.h"
#include "mx51_pins.h"
+extern void fsl_usb_recover_hcd(struct platform_device *pdev);
/*
* USB Host2 HS port
*/
@@ -89,16 +90,37 @@ static void fsl_usbh2_clock_gate(bool on)
}
}
-static bool _is_usbh2_wakeup(struct fsl_usb2_platform_data *pdata)
+static enum usb_wakeup_event _is_usbh2_wakeup(struct fsl_usb2_platform_data *pdata)
{
int wakeup_req = USBCTRL & UCTRL_H2WIR;
if (wakeup_req)
- return true;
+ return !WAKEUP_EVENT_INVALID;
- return false;
+ return WAKEUP_EVENT_INVALID;
}
+static void h2_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _wake_up_enable(pdata, false);
+ _phy_lowpower_suspend(pdata, false);
+ fsl_usb_recover_hcd(&mxc_usbh2_device);
+}
+
+static void usbh2_wakeup_event_clear(void)
+{
+ int wakeup_req = USBCTRL & UCTRL_H2WIR;
+
+ if (wakeup_req != 0) {
+ printk(KERN_INFO "Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC);
+ /* Disable H2WIE to clear H2WIR, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ USBCTRL &= ~UCTRL_H2WIE;
+ udelay(100);
+ USBCTRL |= UCTRL_H2WIE;
+ }
+}
static int fsl_usb_host_init_ext(struct platform_device *pdev)
{
int ret = 0;
@@ -154,12 +176,14 @@ static struct fsl_usb2_platform_data usbh2_config = {
.gpio_usb_active = gpio_usbh2_active,
.gpio_usb_inactive = gpio_usbh2_inactive,
.is_wakeup_event = _is_usbh2_wakeup,
+ .wakeup_handler = h2_wakeup_handler,
.transceiver = "isp1504",
};
static struct fsl_usb2_wakeup_platform_data usbh2_wakeup_config = {
.name = "USBH2 wakeup",
.usb_clock_for_pm = fsl_usbh2_clock_gate,
.usb_pdata = {&usbh2_config, NULL, NULL},
+ .usb_wakeup_exhandle = usbh2_wakeup_event_clear,
};
void __init mx5_usbh2_init(void)
{
diff --git a/arch/arm/plat-mxc/usb_wakeup.c b/arch/arm/plat-mxc/usb_wakeup.c
index 24300fb4012d..1945f7a461f5 100644
--- a/arch/arm/plat-mxc/usb_wakeup.c
+++ b/arch/arm/plat-mxc/usb_wakeup.c
@@ -84,16 +84,19 @@ static irqreturn_t usb_wakeup_handler(int irq, void *_dev)
return ret;
}
-static bool is_wakeup(struct fsl_usb2_platform_data *pdata)
+static enum usb_wakeup_event is_wakeup(struct fsl_usb2_platform_data *pdata)
{
if (pdata->is_wakeup_event)
return pdata->is_wakeup_event(pdata);
- return false;
+ else
+ return WAKEUP_EVENT_INVALID;
}
+
static void wakeup_event_handler(struct wakeup_ctrl *ctrl)
{
struct fsl_usb2_wakeup_platform_data *pdata = ctrl->pdata;
int already_waked = 0;
+ enum usb_wakeup_event wakeup_evt;
int i;
wakeup_clk_gate(ctrl->pdata, true);
@@ -106,12 +109,15 @@ static void wakeup_event_handler(struct wakeup_ctrl *ctrl)
struct fsl_usb2_platform_data *usb_pdata = pdata->usb_pdata[i];
if (usb_pdata) {
usb_pdata->irq_delay = 0;
- if (is_wakeup(usb_pdata)) {
- usb_pdata->wakeup_event = 1;
+ wakeup_evt = is_wakeup(usb_pdata);
+ if (wakeup_evt != WAKEUP_EVENT_INVALID) {
if (usb_pdata->usb_clock_for_pm)
usb_pdata->usb_clock_for_pm(true);
usb_pdata->lowpower = 0;
already_waked = 1;
+ if (usb_pdata->wakeup_handler) {
+ usb_pdata->wakeup_handler(usb_pdata);
+ }
}
}
}