[U-Boot] [PATCH 2/2] RFC: usb: host: Introduce host translational layer

Vivek Gautam gautam.vivek at samsung.com
Tue Jun 24 16:10:22 CEST 2014


Introduce a wrapper layer to translate submit_**_msg() APIs
as well as usb_lowlevel_**() APIs so as to enable using
mutiple controller types viz. OHCI/EHCI/XHCI.

This is still WIP, with support for APIs translation for
EHCI and XHCI only.

Signed-off-by: Vivek Gautam <gautam.vivek at samsung.com>
---
 common/usb.c                  |    8 ++--
 drivers/usb/host/Makefile     |    2 +
 drivers/usb/host/ehci-hcd.c   |   15 +++---
 drivers/usb/host/host_trans.c |  102 +++++++++++++++++++++++++++++++++++++++++
 drivers/usb/host/host_trans.h |   42 +++++++++++++++++
 drivers/usb/host/xhci.c       |   11 +++--
 include/usb.h                 |   15 +++---
 7 files changed, 174 insertions(+), 21 deletions(-)
 create mode 100644 drivers/usb/host/host_trans.c
 create mode 100644 drivers/usb/host/host_trans.h

diff --git a/common/usb.c b/common/usb.c
index 5dd09aa..ae483d0 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -58,6 +58,7 @@ char usb_started; /* flag for the started/stopped USB status */
 int usb_init(void)
 {
 	void *ctrl;
+	int ctrl_type;
 	struct usb_device *dev;
 	int i, start_index = 0;
 
@@ -75,7 +76,7 @@ int usb_init(void)
 	for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
 		/* init low_level USB */
 		printf("USB%d:   ", i);
-		if (usb_lowlevel_init(i, USB_INIT_HOST, &ctrl)) {
+		if (usb_lowlevel_init(i, USB_INIT_HOST, &ctrl, &ctrl_type)) {
 			puts("lowlevel init failed\n");
 			continue;
 		}
@@ -86,6 +87,7 @@ int usb_init(void)
 		start_index = dev_index;
 		printf("scanning bus %d for devices... ", i);
 		dev = usb_alloc_new_device(ctrl);
+		dev->ctrl_type = ctrl_type;
 		/*
 		 * device 0 is always present
 		 * (root hub, so let it analyze)
@@ -193,7 +195,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
 	      request, requesttype, value, index, size);
 	dev->status = USB_ST_NOT_PROC; /*not yet processed */
 
-	if (submit_control_msg(dev, pipe, data, size, setup_packet) < 0)
+	if (usb_submit_control_msg(dev, pipe, data, size, setup_packet) < 0)
 		return -1;
 	if (timeout == 0)
 		return (int)size;
@@ -226,7 +228,7 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
 	if (len < 0)
 		return -1;
 	dev->status = USB_ST_NOT_PROC; /*not yet processed */
-	if (submit_bulk_msg(dev, pipe, data, len) < 0)
+	if (usb_submit_bulk_msg(dev, pipe, data, len) < 0)
 		return -1;
 	while (timeout--) {
 		if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 7211c6a..9c6eb84 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -43,3 +43,5 @@ obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o
 obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
 obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
 obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
+
+obj-$(CONFIG_USB_HOST_TRANS) += host_trans.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index eaf5913..460c509 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -31,6 +31,7 @@
 #include <linux/compiler.h>
 
 #include "ehci.h"
+#include "host_trans.h"
 
 #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
@@ -917,13 +918,13 @@ unknown:
 	return -1;
 }
 
-int usb_lowlevel_stop(int index)
+int ehci_lowlevel_stop(int index)
 {
 	ehci_shutdown(&ehcic[index]);
 	return ehci_hcd_stop(index);
 }
 
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+int ehci_lowlevel_init(int index, enum usb_init_type init, void **controller)
 {
 	uint32_t reg;
 	uint32_t cmd;
@@ -1052,8 +1053,8 @@ done:
 }
 
 int
-submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-		int length)
+ehci_submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
+			void *buffer, int length)
 {
 
 	if (usb_pipetype(pipe) != PIPE_BULK) {
@@ -1064,8 +1065,8 @@ submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 }
 
 int
-submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-		   int length, struct devrequest *setup)
+ehci_submit_control_msg(struct usb_device *dev, unsigned long pipe,
+			void *buffer, int length, struct devrequest *setup)
 {
 	struct ehci_ctrl *ctrl = dev->controller;
 
@@ -1348,7 +1349,7 @@ out:
 }
 
 int
-submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ehci_submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	       int length, int interval)
 {
 	void *backbuffer;
diff --git a/drivers/usb/host/host_trans.c b/drivers/usb/host/host_trans.c
new file mode 100644
index 0000000..701faa2
--- /dev/null
+++ b/drivers/usb/host/host_trans.c
@@ -0,0 +1,102 @@
+/*
+ * USB HOST Controller translation layer
+ *
+ * Provides a smooth translation from usb_*() APIs from
+ * core usb drivers to controller drivers, enabling simultaneous
+ * use of different types of controller at once.
+ *
+ * Copyright (C) 2014 Samsung Electronics Co.Ltd
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "host_trans.h"
+
+static int ehci_count;
+static int xhci_count;
+
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller,
+			int *ctrl_type)
+{
+	if (index >= CONFIG_USB_MAX_CONTROLLER_COUNT)
+		return 0;
+
+	/* first enumerate available EHCI controllers */
+	if (ehci_count < CONFIG_USB_MAX_EHCI_COUNT) {
+		if (ehci_lowlevel_init) {
+			ehci_count++;
+			*ctrl_type = USB_HOST_EHCI;
+			/* init max number of ehci controllers */
+			return ehci_lowlevel_init(ehci_count, init, controller);
+		}
+	}
+
+	if (xhci_count < CONFIG_USB_MAX_XHCI_COUNT) {
+		if (xhci_lowlevel_init) {
+			xhci_count++;
+			*ctrl_type = USB_HOST_XHCI;
+			/* init max number of xhci controllers */
+			return xhci_lowlevel_init(index, init, controller);
+		}
+	}
+
+	return -1;
+}
+
+int usb_lowlevel_stop(int index)
+{
+	if (index >= CONFIG_USB_MAX_CONTROLLER_COUNT)
+		return 0;
+
+	ehci_count = xhci_count = 0;
+
+	if (ehci_count < CONFIG_USB_MAX_EHCI_COUNT) {
+		if (ehci_lowlevel_init) {
+			ehci_count++;
+			return ehci_lowlevel_stop(index);
+		}
+	}
+
+	if (xhci_count < CONFIG_USB_MAX_XHCI_COUNT) {
+		if (xhci_lowlevel_init) {
+			xhci_count++;
+			return xhci_lowlevel_stop(index);
+		}
+	}
+
+	return -1;
+}
+
+int usb_submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
+			void *buffer, int transfer_len)
+{
+	if (dev->ctrl_type == USB_HOST_EHCI)
+		return ehci_submit_bulk_msg(dev, pipe, buffer, transfer_len);
+
+	if (dev->ctrl_type == USB_HOST_XHCI)
+		return xhci_submit_bulk_msg(dev, pipe, buffer, transfer_len);
+}
+
+int usb_submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+			int transfer_len, struct devrequest *setup)
+{
+	if (dev->ctrl_type == USB_HOST_EHCI)
+		return ehci_submit_control_msg(dev, pipe, buffer,
+						transfer_len, setup);
+
+	if (dev->ctrl_type == USB_HOST_EHCI)
+		return xhci_submit_control_msg(dev, pipe, buffer,
+						transfer_len, setup);
+}
+
+int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+			int transfer_len, int interval)
+{
+	if (dev->ctrl_type == USB_HOST_EHCI)
+		return ehci_submit_int_msg(dev, pipe, buffer,
+						transfer_len, interval);
+
+	if (dev->ctrl_type == USB_HOST_XHCI)
+		return xhci_submit_int_msg(dev, pipe, buffer,
+						transfer_len, interval);
+}
diff --git a/drivers/usb/host/host_trans.h b/drivers/usb/host/host_trans.h
new file mode 100644
index 0000000..90bcc92
--- /dev/null
+++ b/drivers/usb/host/host_trans.h
@@ -0,0 +1,42 @@
+
+#ifndef _HOST_TRANS_H_
+#define _HOST_TRANS_H_
+
+#include <common.h>
+#include <usb.h>
+#include <linux/compat.h>
+
+#ifndef CONFIG_USB_MAX_EHCI_COUNT
+#define CONFIG_USB_MAX_EHCI_COUNT 1
+#endif
+
+#ifndef CONFIG_USB_MAX_XHCI_COUNT
+#define CONFIG_USB_MAX_XHCI_COUNT 1
+#endif
+
+enum usb_ctrl_type {
+	USB_HOST_OHCI,
+	USB_HOST_UHCI,
+	USB_HOST_EHCI,
+	USB_HOST_XHCI,
+};
+
+int ehci_submit_int_msg(struct usb_device *dev, unsigned long pipe,
+			void *buffer, int length, int interval);
+int ehci_submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
+			 void *buffer, int length);
+int ehci_submit_control_msg(struct usb_device *dev, unsigned long pipe,
+			    void *buffer, int length, struct devrequest *setup);
+int ehci_lowlevel_init(int index, enum usb_init_type init, void **controller);
+int ehci_lowlevel_stop(int index);
+
+int xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe,
+			void *buffer, int length, int interval);
+int xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe,
+			 void *buffer, int length);
+int xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,
+			    void *buffer, int length, struct devrequest *setup);
+int xhci_lowlevel_init(int index, enum usb_init_type init, void **controller);
+int xhci_lowlevel_stop(int index);
+
+#endif /* _HOST_TRANS_H_ */
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index d1c2e5c..2e7e3f0 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -29,6 +29,7 @@
 #include <asm/unaligned.h>
 #include <asm-generic/errno.h>
 #include "xhci.h"
+#include "host_trans.h"
 
 #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
@@ -859,7 +860,7 @@ unknown:
  * @return 0
  */
 int
-submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
 						int length, int interval)
 {
 	/*
@@ -879,7 +880,7 @@ submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
  * @return returns 0 if successful else -1 on failure
  */
 int
-submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
 								int length)
 {
 	if (usb_pipetype(pipe) != PIPE_BULK) {
@@ -901,7 +902,7 @@ submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
  * @return returns 0 if successful else -1 on failure
  */
 int
-submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
 					int length, struct devrequest *setup)
 {
 	struct xhci_ctrl *ctrl = udev->controller;
@@ -936,7 +937,7 @@ submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
  * @param index	index to the host controller data structure
  * @return pointer to the intialised controller
  */
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+int xhci_lowlevel_init(int index, enum usb_init_type init, void **controller)
 {
 	uint32_t val;
 	uint32_t val2;
@@ -1009,7 +1010,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
  * @param index	index to the host controller data structure
  * @return none
  */
-int usb_lowlevel_stop(int index)
+int xhci_lowlevel_stop(int index)
 {
 	struct xhci_ctrl *ctrl = (xhcic + index);
 	u32 temp;
diff --git a/include/usb.h b/include/usb.h
index 30fc890..212a34d 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -125,6 +125,7 @@ struct usb_device {
 	struct usb_device *children[USB_MAXCHILDREN];
 
 	void *controller;		/* hardware controller private data */
+	int ctrl_type;			/* controller type - OHCI/EHCI/XHCI */
 	/* slot_id - for xHCI enabled devices */
 	unsigned int slot_id;
 };
@@ -152,15 +153,17 @@ enum usb_init_type {
 	defined(CONFIG_USB_MUSB_DSPS) || defined(CONFIG_USB_MUSB_AM35X) || \
 	defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_XHCI)
 
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller);
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller,
+			int *ctrl_type);
 int usb_lowlevel_stop(int index);
 
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
+int usb_submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
 			void *buffer, int transfer_len);
-int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-			int transfer_len, struct devrequest *setup);
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-			int transfer_len, int interval);
+int usb_submit_control_msg(struct usb_device *dev, unsigned long pipe,
+			void *buffer, int transfer_len,
+			struct devrequest *setup);
+int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
+			void *buffer, int transfer_len, int interval);
 
 /* Defines */
 #define USB_UHCI_VEND_ID	0x8086
-- 
1.7.10.4



More information about the U-Boot mailing list