diff options
author | Peter Chen <peter.chen@freescale.com> | 2011-01-12 11:00:39 +0800 |
---|---|---|
committer | Peter Chen <peter.chen@freescale.com> | 2011-01-12 11:18:01 +0800 |
commit | dbd6186c060af0fe7157d7bd880792aa0b6126fa (patch) | |
tree | d0de54709c2529ef8404ecbcaf182df3282ad43e /arch | |
parent | d570035407de42cc073610b59fe988dc9a0e4293 (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.c | 37 | ||||
-rw-r--r-- | arch/arm/mach-mx5/usb_h1.c | 34 | ||||
-rw-r--r-- | arch/arm/mach-mx5/usb_h2.c | 32 | ||||
-rw-r--r-- | arch/arm/plat-mxc/usb_wakeup.c | 14 |
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); + } } } } |