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");