USB: EHCI: prepare to make ehci-hcd a library module
This patch (as1624) prepares ehci-hcd for being split up into a core
library and separate platform driver modules. A generic
ehci_hc_driver structure is created, containing all the "standard"
values, and a new mechanism is added whereby a driver module can
specify a set of overrides to those values. In addition the
ehci_setup(), ehci_suspend(), and ehci_resume() routines need to be
EXPORTed for use by the drivers.
As a side effect of this change, a few routines no longer need to be
marked __maybe_unused.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ab4a769a..dee3541 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -649,7 +649,7 @@
return 0;
}
-static int ehci_setup(struct usb_hcd *hcd)
+int ehci_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
int retval;
@@ -680,6 +680,7 @@
return 0;
}
+EXPORT_SYMBOL_GPL(ehci_setup);
/*-------------------------------------------------------------------------*/
@@ -1085,7 +1086,7 @@
/* These routines handle the generic parts of controller suspend/resume */
-static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -1108,9 +1109,10 @@
return 0;
}
+EXPORT_SYMBOL_GPL(ehci_suspend);
/* Returns 0 if power was preserved, 1 if power was lost */
-static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+int ehci_resume(struct usb_hcd *hcd, bool hibernated)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -1168,12 +1170,77 @@
return 1;
}
+EXPORT_SYMBOL_GPL(ehci_resume);
#endif
/*-------------------------------------------------------------------------*/
/*
+ * Generic structure: This gets copied for platform drivers so that
+ * individual entries can be overridden as needed.
+ */
+
+static const struct hc_driver ehci_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "EHCI Host Controller",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ */
+ .reset = ehci_setup,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+};
+
+void ehci_init_driver(struct hc_driver *drv,
+ const struct ehci_driver_overrides *over)
+{
+ /* Copy the generic table to drv and then apply the overrides */
+ *drv = ehci_hc_driver;
+
+ drv->product_desc = over->product_desc;
+ drv->hcd_priv_size += over->extra_priv_size;
+ if (over->reset)
+ drv->reset = over->reset;
+}
+EXPORT_SYMBOL_GPL(ehci_init_driver);
+
+/*-------------------------------------------------------------------------*/
+
+/*
* The EHCI in ChipIdea HDRC cannot be a separate module or device,
* because its registers (and irq) are shared between host/gadget/otg
* functions and in order to facilitate role switching we cannot
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index a59c61f..4ccb97c 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -1109,8 +1109,7 @@
return retval;
}
-static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
- int portnum)
+static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -1119,8 +1118,7 @@
set_owner(ehci, --portnum, PORT_OWNER);
}
-static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
- int portnum)
+static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 __iomem *reg;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 2262dcd..24a8ada 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -781,4 +781,21 @@
/*-------------------------------------------------------------------------*/
+/* Declarations of things exported for use by ehci platform drivers */
+
+struct ehci_driver_overrides {
+ const char *product_desc;
+ size_t extra_priv_size;
+ int (*reset)(struct usb_hcd *hcd);
+};
+
+extern void ehci_init_driver(struct hc_driver *drv,
+ const struct ehci_driver_overrides *over);
+extern int ehci_setup(struct usb_hcd *hcd);
+
+#ifdef CONFIG_PM
+extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
+extern int ehci_resume(struct usb_hcd *hcd, bool hibernated);
+#endif /* CONFIG_PM */
+
#endif /* __LINUX_EHCI_HCD_H */