From: Hao Wu <hao.wu@xxxxxxxxx> This patch modified ehci host pci controller driver for langwell, support common OTG data structure for Intel MID platform. Main changes: - Update OTG related data structure. - Provide start_host/stop_host function to transceiver. - Provide register/unregister function. modified: drivers/usb/host/ehci-hcd.c modified: drivers/usb/host/ehci-langwell-pci.c Signed-off-by: Hao Wu <hao.wu@xxxxxxxxx> --- drivers/usb/host/ehci-hcd.c | 16 ++-- drivers/usb/host/ehci-langwell-pci.c | 151 +++++++++++++++++++++++++--------- 2 files changed, 119 insertions(+), 48 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 1dafad0..d399eaf 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -43,8 +43,6 @@ #include <asm/irq.h> #include <asm/system.h> #include <asm/unaligned.h> -#include <linux/usb/otg.h> -#include <linux/usb/langwell_otg.h> /*-------------------------------------------------------------------------*/ @@ -1159,7 +1157,7 @@ MODULE_LICENSE ("GPL"); #define PCI_DRIVER ehci_pci_driver #ifdef CONFIG_USB_LANGWELL_OTG #include "ehci-langwell-pci.c" -#define LNW_OTG_HOST_DRIVER ehci_otg_driver +#define INTEL_MID_OTG_HOST_DRIVER ehci_otg_driver #endif #endif @@ -1286,16 +1284,16 @@ static int __init ehci_hcd_init(void) goto clean4; #endif -#ifdef LNW_OTG_HOST_DRIVER - retval = langwell_register_host(&LNW_OTG_HOST_DRIVER); +#ifdef INTEL_MID_OTG_HOST_DRIVER + retval = intel_mid_ehci_driver_register(&INTEL_MID_OTG_HOST_DRIVER); if (retval < 0) goto clean5; #endif return retval; -#ifdef LNW_OTG_HOST_DRIVER +#ifdef INTEL_MID_OTG_HOST_DRIVER clean5: - langwell_unregister_host(&LNW_OTG_HOST_DRIVER); + intel_mid_ehci_driver_unregister(&INTEL_MID_OTG_HOST_DRIVER); #endif #ifdef XILINX_OF_PLATFORM_DRIVER /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */ @@ -1329,8 +1327,8 @@ module_init(ehci_hcd_init); static void __exit ehci_hcd_cleanup(void) { -#ifdef LNW_OTG_HOST_DRIVER - langwell_unregister_host(&LNW_OTG_HOST_DRIVER); +#ifdef INTEL_MID_OTG_HOST_DRIVER + intel_mid_ehci_driver_unregister(&INTEL_MID_OTG_HOST_DRIVER); #endif #ifdef XILINX_OF_PLATFORM_DRIVER of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); diff --git a/drivers/usb/host/ehci-langwell-pci.c b/drivers/usb/host/ehci-langwell-pci.c index 64ffd60..46b0985 100644 --- a/drivers/usb/host/ehci-langwell-pci.c +++ b/drivers/usb/host/ehci-langwell-pci.c @@ -1,7 +1,7 @@ /* - * Intel Moorestown Platform Langwell OTG EHCI Controller PCI Bus Glue. + * Intel MID Platform Langwell/Penwell OTG EHCI Controller PCI Bus Glue. * - * Copyright (c) 2008 - 2009, Intel Corporation. + * Copyright (c) 2008 - 2010, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License 2 as published by the @@ -17,23 +17,24 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/usb/otg.h> +#include <linux/usb/intel_mid_otg.h> + static int usb_otg_suspend(struct usb_hcd *hcd) { struct otg_transceiver *otg; - struct langwell_otg *iotg; + struct intel_mid_otg_xceiv *iotg; otg = otg_get_transceiver(); if (otg == NULL) { printk(KERN_ERR "%s Failed to get otg transceiver\n", __func__); return -EINVAL; } - iotg = container_of(otg, struct langwell_otg, otg); + iotg = otg_to_mid_xceiv(otg); printk(KERN_INFO "%s OTG HNP update suspend\n", __func__); - if (iotg->otg.default_a) - iotg->hsm.a_suspend_req = 1; - else - iotg->hsm.b_bus_req = 0; - langwell_update_transceiver(); + + atomic_notifier_call_chain(&iotg->iotg_notifier, + MID_OTG_NOTIFY_HSUSPEND, iotg); otg_put_transceiver(otg); return 0; } @@ -41,19 +42,18 @@ static int usb_otg_suspend(struct usb_hcd *hcd) static int usb_otg_resume(struct usb_hcd *hcd) { struct otg_transceiver *otg; - struct langwell_otg *iotg; + struct intel_mid_otg_xceiv *iotg; otg = otg_get_transceiver(); if (otg == NULL) { printk(KERN_ERR "%s Failed to get otg transceiver\n", __func__); return -EINVAL; } - iotg = container_of(otg, struct langwell_otg, otg); + iotg = otg_to_mid_xceiv(otg); printk(KERN_INFO "%s OTG HNP update resume\n", __func__); - if (iotg->otg.default_a) { - iotg->hsm.b_bus_resume = 1; - langwell_update_transceiver(); - } + + atomic_notifier_call_chain(&iotg->iotg_notifier, + MID_OTG_NOTIFY_HRESUME, iotg); otg_put_transceiver(otg); return 0; } @@ -62,54 +62,52 @@ static int usb_otg_resume(struct usb_hcd *hcd) static void otg_notify(struct usb_device *udev, unsigned action) { struct otg_transceiver *otg; - struct langwell_otg *iotg; + struct intel_mid_otg_xceiv *iotg; + + /* Ignore root hub add/remove event */ + if (!udev->parent) { + printk(KERN_INFO "%s Ignore root hub otg_notify\n", __func__); + return; + } otg = otg_get_transceiver(); if (otg == NULL) { printk(KERN_ERR "%s Failed to get otg transceiver\n", __func__); return; } - iotg = container_of(otg, struct langwell_otg, otg); + iotg = otg_to_mid_xceiv(otg); switch (action) { case USB_DEVICE_ADD: pr_debug("Notify OTG HNP add device\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_conn = 1; - else - iotg->hsm.a_conn = 1; + atomic_notifier_call_chain(&iotg->iotg_notifier, + MID_OTG_NOTIFY_CONNECT, iotg); break; case USB_DEVICE_REMOVE: pr_debug("Notify OTG HNP delete device\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_conn = 0; - else - iotg->hsm.a_conn = 0; + atomic_notifier_call_chain(&iotg->iotg_notifier, + MID_OTG_NOTIFY_DISCONN, iotg); break; default: otg_put_transceiver(otg); return ; } - if (spin_trylock(&iotg->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&iotg->wq_lock); - } otg_put_transceiver(otg); return; } -static int ehci_langwell_probe(struct pci_dev *pdev, +static int ehci_mid_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct hc_driver *driver; - struct langwell_otg *iotg; struct otg_transceiver *otg; + struct intel_mid_otg_xceiv *iotg; struct usb_hcd *hcd; struct ehci_hcd *ehci; int irq; int retval; - pr_debug("initializing Langwell USB OTG Host Controller\n"); + pr_debug("initializing Intel MID USB OTG Host Controller\n"); /* we need not call pci_enable_dev since otg transceiver already take * the control of this device and this probe actaully gets called by @@ -142,8 +140,10 @@ static int ehci_langwell_probe(struct pci_dev *pdev, retval = -EINVAL; goto err1; } - iotg = container_of(otg, struct langwell_otg, otg); - hcd->regs = iotg->regs; + + iotg = otg_to_mid_xceiv(otg); + hcd->regs = iotg->base; + hcd->rsrc_start = pci_resource_start(pdev, 0); hcd->rsrc_len = pci_resource_len(pdev, 0); @@ -168,7 +168,7 @@ err1: return retval; } -void ehci_langwell_remove(struct pci_dev *dev) +void ehci_mid_remove(struct pci_dev *dev) { struct usb_hcd *hcd = pci_get_drvdata(dev); @@ -178,13 +178,13 @@ void ehci_langwell_remove(struct pci_dev *dev) usb_put_hcd(hcd); } -/* Langwell OTG EHCI driver */ +/* Intel MID OTG EHCI driver */ static struct pci_driver ehci_otg_driver = { - .name = "ehci-langwell", + .name = "ehci-intel-mid", .id_table = pci_ids, - .probe = ehci_langwell_probe, - .remove = ehci_langwell_remove, + .probe = ehci_mid_probe, + .remove = ehci_mid_remove, #ifdef CONFIG_PM_SLEEP .driver = { @@ -193,3 +193,76 @@ static struct pci_driver ehci_otg_driver = { #endif .shutdown = usb_hcd_pci_shutdown, }; + +static int ehci_mid_start_host(struct intel_mid_otg_xceiv *iotg) +{ + struct pci_dev *pdev; + int retval; + + if (iotg == NULL) + return -EINVAL; + + pdev = to_pci_dev(iotg->otg.dev); + + retval = ehci_mid_probe(pdev, ehci_otg_driver.id_table); + if (retval) + dev_dbg(iotg->otg.dev, "Failed to start host\n"); + + return retval; +} + +static int ehci_mid_stop_host(struct intel_mid_otg_xceiv *iotg) +{ + struct pci_dev *pdev; + + if (iotg == NULL) + return -EINVAL; + + pdev = to_pci_dev(iotg->otg.dev); + + ehci_mid_remove(pdev); + + return 0; +} + +static int intel_mid_ehci_driver_register(struct pci_driver *host_driver) +{ + struct otg_transceiver *otg; + struct intel_mid_otg_xceiv *iotg; + + otg = otg_get_transceiver(); + if (otg == NULL) + return -EINVAL; + + iotg = otg_to_mid_xceiv(otg); + iotg->start_host = ehci_mid_start_host; + iotg->stop_host = ehci_mid_stop_host; + + /* notify host driver is registered */ + atomic_notifier_call_chain(&iotg->iotg_notifier, + MID_OTG_NOTIFY_HOSTADD, iotg); + + otg_put_transceiver(otg); + + return 0; +} + +static void intel_mid_ehci_driver_unregister(struct pci_driver *host_driver) +{ + struct otg_transceiver *otg; + struct intel_mid_otg_xceiv *iotg; + + otg = otg_get_transceiver(); + if (otg == NULL) + return ; + + iotg = otg_to_mid_xceiv(otg); + iotg->start_host = NULL; + iotg->stop_host = NULL; + + /* notify host driver is unregistered */ + atomic_notifier_call_chain(&iotg->iotg_notifier, + MID_OTG_NOTIFY_HOSTREMOVE, iotg); + + otg_put_transceiver(otg); +} -- 1.6.0.6 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html