usb: chipidea: add host role
This adds EHCI host support to the chipidea driver. We want it to be
part of the hdrc driver and not a standalone (sub-)driver module, as
the structure of ehci-hcd.c suggests, so for chipidea controller we
hack it to not provide platform-related code, but only the ehci hcd.
The ehci-platform driver won't work for us here too, because the
controller uses the same registers for both device and host mode and
also otg-related bits, so it's not really possible to put ehci registers
into a separate resource.
This is not a pretty solution, but the alternative is exporting symbols
from the chipidea driver to a ehci-chipidea driver and doing all the
module refcounting.
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 3d48c9b..f568b8e 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -70,6 +70,7 @@
#include "ci.h"
#include "udc.h"
#include "bits.h"
+#include "host.h"
#include "debug.h"
/* Controller register map */
@@ -215,7 +216,7 @@
*
* This function returns an error code
*/
-int hw_device_reset(struct ci13xxx *ci)
+int hw_device_reset(struct ci13xxx *ci, u32 mode)
{
/* should flush & stop before reset */
hw_write(ci, OP_ENDPTFLUSH, ~0, ~0);
@@ -235,12 +236,12 @@
/* USBMODE should be configured step by step */
hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
- hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_DC);
+ hw_write(ci, OP_USBMODE, USBMODE_CM, mode);
/* HW >= 2.3 */
hw_write(ci, OP_USBMODE, USBMODE_SLOM, USBMODE_SLOM);
- if (hw_read(ci, OP_USBMODE, USBMODE_CM) != USBMODE_CM_DC) {
- pr_err("cannot enter in device mode");
+ if (hw_read(ci, OP_USBMODE, USBMODE_CM) != mode) {
+ pr_err("cannot enter in %s mode", ci_role(ci)->name);
pr_err("lpm = %i", ci->hw_bank.lpm);
return -ENODEV;
}
@@ -371,6 +372,8 @@
return -ENODEV;
}
+ ci->hw_bank.phys = res->start;
+
ci->irq = platform_get_irq(pdev, 0);
if (ci->irq < 0) {
dev_err(dev, "missing IRQ\n");
@@ -385,6 +388,10 @@
}
/* initialize role(s) before the interrupt is requested */
+ ret = ci_hdrc_host_init(ci);
+ if (ret)
+ dev_info(dev, "doesn't support host\n");
+
ret = ci_hdrc_gadget_init(ci);
if (ret)
dev_info(dev, "doesn't support gadget\n");