[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