public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/11] Various USB improvements
@ 2012-12-13  1:55 Simon Glass
  2012-12-13  1:55 ` [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established Simon Glass
                   ` (10 more replies)
  0 siblings, 11 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

This series adds a few USB improvements for Marek:

- Support for interupt transfers
- Faster start-up and proper shutdown of ASIX USB adapter
- Basic 64-bit controller support (used by x86)
- Fix detection of empty USB media readers
- Clean up after device configuration failure


Michael Spang (1):
  usb: usbeth: smsc95xx: remove EEPROM loaded check

Milind Choudhary (1):
  usb: Clean up newly allocated device nodes in case of configuration
    failure

Patrick Georgi (1):
  usb: ehci: Support interrupt transfers via periodic list

Simon Glass (2):
  usb: net: asix: Do a fast init if link already established
  x86: Enable USB features for coreboot

Vincent Palatin (6):
  usb: ehci: Add 64-bit controller support
  usb: ehci: generic PCI support
  usb: ehci: Fix aliasing issue in EHCI interrupt code
  usb: ehci: Add timeout on interrupt endpoint operations
  usb: properly detect empty mass storage media reader
  usb: Add multiple controllers support for EHCI PCI

 common/usb.c                |   12 ++
 common/usb_hub.c            |    2 +
 common/usb_storage.c        |   10 ++
 drivers/usb/eth/asix.c      |   40 +++++-
 drivers/usb/eth/smsc95xx.c  |    4 -
 drivers/usb/host/ehci-hcd.c |  312 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/usb/host/ehci-pci.c |   55 +++++++-
 drivers/usb/host/ehci.h     |    6 +-
 include/configs/coreboot.h  |   17 +++
 include/usb.h               |    1 +
 include/usb_ether.h         |    1 +
 11 files changed, 437 insertions(+), 23 deletions(-)

-- 
1.7.7.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13 17:26   ` Marek Vasut
  2012-12-15  7:28   ` Joe Hershberger
  2012-12-13  1:55 ` [U-Boot] [PATCH 02/11] usb: ehci: Add 64-bit controller support Simon Glass
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

The Asix driver takes the link down during init() and then brings it back up.
This commit changes this so that if a link has already been established
successfully we simply check that the link is still good.

Also fix up asix_halt() to actually halt RX on the interface. Previously this
was not done, so the device would continue to operate evern when halted,
violating a U-Boot requirement.

This reduces the delay between successive network commands.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/usb/eth/asix.c |   40 ++++++++++++++++++++++++++++++++--------
 include/usb_ether.h    |    1 +
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c
index 75ec8f7..a991fea 100644
--- a/drivers/usb/eth/asix.c
+++ b/drivers/usb/eth/asix.c
@@ -84,6 +84,7 @@
 
 #define AX_DEFAULT_RX_CTL	\
 	(AX_RX_CTL_SO | AX_RX_CTL_AB)
+#define AX_DISABLE_RX_CTL	AX_RX_CTL_AB
 
 /* GPIO 2 toggles */
 #define AX_GPIO_GPO2EN		0x10	/* GPIO2 Output enable */
@@ -410,17 +411,16 @@ static int asix_basic_reset(struct ueth_data *dev)
 	return 0;
 }
 
-/*
- * Asix callbacks
- */
-static int asix_init(struct eth_device *eth, bd_t *bd)
+static int full_init(struct eth_device *eth)
 {
-	struct ueth_data	*dev = (struct ueth_data *)eth->priv;
-	int timeout = 0;
-#define TIMEOUT_RESOLUTION 50	/* ms */
-	int link_detected;
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
 
 	debug("** %s()\n", __func__);
+	if (asix_basic_reset(dev))
+		goto out_err;
+
+	if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0)
+		goto out_err;
 
 	dev->phy_id = asix_get_phy_addr(dev);
 	if (dev->phy_id < 0)
@@ -446,6 +446,25 @@ static int asix_init(struct eth_device *eth, bd_t *bd)
 		debug("Write IPG,IPG1,IPG2 failed\n");
 		goto out_err;
 	}
+	return 0;
+out_err:
+	return -1;
+}
+
+/*
+ * Asix callbacks
+ */
+static int asix_init(struct eth_device *eth, bd_t *bd)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	int timeout = 0;
+#define TIMEOUT_RESOLUTION 50	/* ms */
+	int link_detected;
+
+	debug("** %s()\n", __func__);
+
+	if (!dev->has_been_running && full_init(eth))
+		return -1;
 
 	if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0)
 		goto out_err;
@@ -467,6 +486,7 @@ static int asix_init(struct eth_device *eth, bd_t *bd)
 		printf("unable to connect.\n");
 		goto out_err;
 	}
+	dev->has_been_running = 1;
 
 	return 0;
 out_err:
@@ -571,7 +591,11 @@ static int asix_recv(struct eth_device *eth)
 
 static void asix_halt(struct eth_device *eth)
 {
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+	/* Disable packet reception */
 	debug("** %s()\n", __func__);
+	(void)asix_write_rx_ctl(dev, AX_DISABLE_RX_CTL);
 }
 
 /*
diff --git a/include/usb_ether.h b/include/usb_ether.h
index 7c7aecb..6145210 100644
--- a/include/usb_ether.h
+++ b/include/usb_ether.h
@@ -49,6 +49,7 @@ struct ueth_data {
 	unsigned char	subclass;		/* as in overview */
 	unsigned char	protocol;		/* .............. */
 	unsigned char	irqinterval;	/* Intervall for IRQ Pipe */
+	char has_been_running;		/* PHY already inited */
 
 	/* driver private */
 	void *dev_priv;
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 02/11] usb: ehci: Add 64-bit controller support
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
  2012-12-13  1:55 ` [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13 17:27   ` Marek Vasut
  2012-12-13  1:55 ` [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support Simon Glass
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Vincent Palatin <vpalatin@chromium.org>

On EHCI controller with 64-bit address space support, we must initialize
properly the high word for the PCI bus master accesses.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/usb/host/ehci-hcd.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 7f98a63..20309ad 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -870,6 +870,9 @@ int usb_lowlevel_init(int index, void **controller)
 	if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
 		return -1;
 #endif
+	/* Set the high address word (aka segment) for 64-bit controller */
+	if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1)
+		ehci_writel(ehcic[index].hcor->or_ctrldssegment, 0);
 
 	qh_list = &ehcic[index].qh_list;
 
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
  2012-12-13  1:55 ` [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established Simon Glass
  2012-12-13  1:55 ` [U-Boot] [PATCH 02/11] usb: ehci: Add 64-bit controller support Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13 17:30   ` Marek Vasut
  2012-12-14  6:58   ` [U-Boot] [PATCH v3 2/7] " Simon Glass
  2012-12-13  1:55 ` [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list Simon Glass
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Vincent Palatin <vpalatin@chromium.org>

Instead of hardcoding the PCI IDs on the USB controller, use the PCI
class to detect them.

Ensure the busmaster bit is properly set in the PCI configuration.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/usb/host/ehci-pci.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 29af02d..0dc0e6e 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -32,6 +32,34 @@ static struct pci_device_id ehci_pci_ids[] = {
 	{0x12D8, 0x400F},	/* Pericom */
 	{0, 0}
 };
+#else
+static pci_dev_t ehci_find_class(void)
+{
+	int bus;
+	int devnum;
+	pci_dev_t bdf;
+	uint32_t class;
+
+	for (bus = 0; bus < pci_last_busno(); bus++) {
+		for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) {
+			pci_read_config_dword(PCI_BDF(bus, devnum, 0),
+					      PCI_CLASS_REVISION, &class);
+			if (class >> 16 == 0xffff)
+				continue;
+
+			for (bdf = PCI_BDF(bus, devnum, 0);
+					bdf <= PCI_BDF(bus, devnum,
+						PCI_MAX_PCI_FUNCTIONS - 1);
+					bdf += PCI_BDF(0, 0, 1)) {
+				pci_read_config_dword(bdf, PCI_CLASS_REVISION,
+						      &class);
+				if (class >> 8 == 0x0c0320)
+					return bdf;
+			}
+		}
+	}
+	return -1;
+}
 #endif
 
 /*
@@ -41,8 +69,13 @@ static struct pci_device_id ehci_pci_ids[] = {
 int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
 	pci_dev_t pdev;
+	uint32_t cmd;
 
+#ifdef CONFIG_PCI_EHCI_DEVICE
 	pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
+#else
+	pdev = ehci_find_class();
+#endif
 	if (pdev == -1) {
 		printf("EHCI host controller not found\n");
 		return -1;
@@ -57,6 +90,10 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 			(uint32_t)*hccr, (uint32_t)*hcor,
 			(uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
 
+	/* enable busmaster */
+	pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
+	cmd |= PCI_COMMAND_MASTER;
+	pci_write_config_dword(pdev, PCI_COMMAND, cmd);
 	return 0;
 }
 
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
                   ` (2 preceding siblings ...)
  2012-12-13  1:55 ` [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13 17:32   ` Marek Vasut
  2012-12-13  1:55 ` [U-Boot] [PATCH 05/11] usb: ehci: Fix aliasing issue in EHCI interrupt code Simon Glass
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Patrick Georgi <patrick@georgi-clan.de>

Interrupt transfers aren't meant to be used from the async list
(the EHCI spec indicates trouble with low/full-speed intr on async).

Build a periodic list instead, and provide an API to make use of it.
Then, use that API from the existing interrupt transfer API.

This provides support for USB keyboards using EHCI.

Signed-off-by: Patrick Georgi <patrick@georgi-clan.de>
Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/usb/host/ehci-hcd.c |  295 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/usb/host/ehci.h     |    6 +-
 2 files changed, 296 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 20309ad..0f4bc49 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -27,6 +27,7 @@
 #include <asm/io.h>
 #include <malloc.h>
 #include <watchdog.h>
+#include <linux/compiler.h>
 
 #include "ehci.h"
 
@@ -39,7 +40,10 @@ static struct ehci_ctrl {
 	struct ehci_hcor *hcor;
 	int rootdev;
 	uint16_t portreset;
-	struct QH qh_list __attribute__((aligned(USB_DMA_MINALIGN)));
+	struct QH qh_list __aligned(USB_DMA_MINALIGN);
+	struct QH periodic_queue __aligned(USB_DMA_MINALIGN);
+	uint32_t *periodic_list;
+	int ntds;
 } ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
 
 #define ALIGN_END_ADDR(type, ptr, size)			\
@@ -858,6 +862,7 @@ int usb_lowlevel_init(int index, void **controller)
 	uint32_t reg;
 	uint32_t cmd;
 	struct QH *qh_list;
+	struct QH *periodic;
 
 	if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
 		return -1;
@@ -887,6 +892,38 @@ int usb_lowlevel_init(int index, void **controller)
 	qh_list->qh_overlay.qt_token =
 			cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED));
 
+	/* Set async. queue head pointer. */
+	ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list);
+
+	/*
+	 * Set up periodic list
+	 * Step 1: Parent QH for all periodic transfers.
+	 */
+	periodic = &ehcic[index].periodic_queue;
+	memset(periodic, 0, sizeof(*periodic));
+	periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE);
+	periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+	periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+
+	/*
+	 * Step 2: Setup frame-list: Every microframe, USB tries the same list.
+	 *         In particular, device specifications on polling frequency
+	 *         are disregarded. Keyboards seem to send NAK/NYet reliably
+	 *         when polled with an empty buffer.
+	 *
+	 *         Split Transactions will be spread across microframes using
+	 *         S-mask and C-mask.
+	 */
+	ehcic[index].periodic_list = memalign(4096, 1024*4);
+	int i;
+	for (i = 0; i < 1024; i++)
+		ehcic[index].periodic_list[i] = (uint32_t)periodic
+						| QH_LINK_TYPE_QH;
+
+	/* Set periodic list base address */
+	ehci_writel(&ehcic[index].hcor->or_periodiclistbase,
+		(uint32_t)ehcic[index].periodic_list);
+
 	reg = ehci_readl(&ehcic[index].hccr->cr_hcsparams);
 	descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
 	debug("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
@@ -956,10 +993,243 @@ submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	return ehci_submit_async(dev, pipe, buffer, length, setup);
 }
 
+struct int_queue {
+	struct QH *first;
+	struct QH *current;
+	struct QH *last;
+	struct qTD *tds;
+};
+
+#define NEXT_QH(qh) (struct QH *)((qh)->qh_link & ~0x1f)
+
+static int
+enable_periodic(struct ehci_ctrl *ctrl)
+{
+	uint32_t cmd;
+	struct ehci_hcor *hcor = ctrl->hcor;
+
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	cmd |= CMD_PSE;
+	ehci_writel(&hcor->or_usbcmd, cmd);
+
+	int ret = handshake((uint32_t *)&hcor->or_usbsts,
+			STD_PSS, STD_PSS, 100 * 1000);
+	if (ret < 0) {
+		printf("EHCI failed: timeout when enabling periodic list\n");
+		return -1;
+	}
+	udelay(1000);
+	return 0;
+}
+
+static int
+disable_periodic(struct ehci_ctrl *ctrl)
+{
+	uint32_t cmd;
+	struct ehci_hcor *hcor = ctrl->hcor;
+
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	cmd &= ~CMD_PSE;
+	ehci_writel(&hcor->or_usbcmd, cmd);
+
+	int ret = handshake((uint32_t *)&hcor->or_usbsts,
+			STD_PSS, 0, 100 * 1000);
+	if (ret < 0) {
+		printf("EHCI failed: timeout when enabling periodic list\n");
+		return -1;
+	}
+	return 0;
+}
+
+int periodic_schedules;
+
+struct int_queue *
+create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
+		 int elementsize, void *buffer)
+{
+	int i;
+	struct ehci_ctrl *ctrl = dev->controller;
+	struct int_queue *result = NULL;
+	debug("Enter create_int_queue\n");
+	if (usb_pipetype(pipe) != PIPE_INTERRUPT) {
+		debug("non-interrupt pipe (type=%lu)", usb_pipetype(pipe));
+		return NULL;
+	}
+
+	/* limit to 4 full pages worth of data -
+	 * we can safely fit them in a single TD,
+	 * no matter the alignment
+	 */
+	if (elementsize >= 16384) {
+		debug("too large elements for interrupt transfers\n");
+		return NULL;
+	}
+
+	result = malloc(sizeof(*result));
+	if (!result) {
+		debug("ehci intr queue: out of memory\n");
+		goto fail1;
+	}
+	result->first = memalign(32, sizeof(struct QH) * queuesize);
+	if (!result->first) {
+		debug("ehci intr queue: out of memory\n");
+		goto fail2;
+	}
+	result->current = result->first;
+	result->last = result->first + elementsize - 1;
+	result->tds = memalign(32, sizeof(struct qTD) * queuesize);
+	if (!result->tds) {
+		debug("ehci intr queue: out of memory\n");
+		goto fail3;
+	}
+	memset(result->first, 0, sizeof(struct QH) * queuesize);
+	memset(result->tds, 0, sizeof(struct qTD) * queuesize);
+
+	for (i = 0; i < queuesize; i++) {
+		struct QH *qh = result->first + i;
+		struct qTD *td = result->tds + i;
+		void **buf = &qh->buffer;
+
+		qh->qh_link = (uint32_t)(qh+1) | QH_LINK_TYPE_QH;
+		if (i == queuesize - 1)
+			qh->qh_link = QH_LINK_TERMINATE;
+
+		qh->qh_overlay.qt_next = (uint32_t)td;
+		qh->qh_endpt1 = (0 << 28) | /* No NAK reload (ehci 4.9) */
+			(usb_maxpacket(dev, pipe) << 16) | /* MPS */
+			(1 << 14) | /* TODO: Data Toggle Control */
+			QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) |
+			(usb_pipeendpoint(pipe) << 8) | /* Endpoint Number */
+			(usb_pipedevice(pipe) << 0);
+		qh->qh_endpt2 = (1 << 30); /* 1 Tx per mframe */
+		if (dev->speed == USB_SPEED_LOW ||
+				dev->speed == USB_SPEED_FULL) {
+			debug("TT: port: %d, hub address: %d\n",
+				dev->portnr, dev->parent->devnum);
+			qh->qh_endpt2 |= (dev->portnr << 23) |
+				(dev->parent->devnum << 16) |
+				(0x1c << 8) | /* C-mask: microframes 2-4 */
+				(1 << 0); /* S-mask: microframe 0 */
+		}
+
+		td->qt_next = QT_NEXT_TERMINATE;
+		td->qt_altnext = QT_NEXT_TERMINATE;
+		debug("communication direction is '%s'\n",
+		      usb_pipein(pipe) ? "in" : "out");
+		td->qt_token = (elementsize << 16) |
+			((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */
+			0x80; /* active */
+		td->qt_buffer[0] = (uint32_t)buffer + i * elementsize;
+		td->qt_buffer[1] = (td->qt_buffer[0] + 0x1000) & ~0xfff;
+		td->qt_buffer[2] = (td->qt_buffer[0] + 0x2000) & ~0xfff;
+		td->qt_buffer[3] = (td->qt_buffer[0] + 0x3000) & ~0xfff;
+		td->qt_buffer[4] = (td->qt_buffer[0] + 0x4000) & ~0xfff;
+
+		*buf = buffer + i * elementsize;
+	}
+
+	if (disable_periodic(ctrl) < 0) {
+		debug("FATAL: periodic should never fail, but did");
+		goto fail3;
+	}
+
+	/* hook up to periodic list */
+	struct QH *list = &ctrl->periodic_queue;
+	result->last->qh_link = list->qh_link;
+	list->qh_link = (uint32_t)result->first | QH_LINK_TYPE_QH;
+
+	if (enable_periodic(ctrl) < 0) {
+		debug("FATAL: periodic should never fail, but did");
+		goto fail3;
+	}
+	periodic_schedules++;
+
+	debug("Exit create_int_queue\n");
+	return result;
+fail3:
+	if (result->tds)
+		free(result->tds);
+fail2:
+	if (result->first)
+		free(result->first);
+	if (result)
+		free(result);
+fail1:
+	return NULL;
+}
+
+/* TODO: requeue depleted buffers */
+void *
+poll_int_queue(struct usb_device *dev, struct int_queue *queue)
+{
+	struct QH *cur = queue->current;
+	/* depleted queue */
+	if (cur == NULL) {
+		debug("Exit poll_int_queue with completed queue\n");
+		return NULL;
+	}
+	/* still active */
+	if (cur->qh_overlay.qt_token & 0x80) {
+		debug("Exit poll_int_queue with no completed intr transfer. "
+		      "token is %x\n", cur->qh_overlay.qt_token);
+		return NULL;
+	}
+	/* TODO: Handle failures */
+	if (!(cur->qh_link & QH_LINK_TERMINATE))
+		queue->current++;
+	else
+		queue->current = NULL;
+	debug("Exit poll_int_queue with completed intr transfer. "
+	      "token is %x at %p (first at %p)\n", cur->qh_overlay.qt_token,
+	      &cur->qh_overlay.qt_token, queue->first);
+	return cur->buffer;
+}
+
+/* Do not free buffers associated with QHs, they're owned by someone else */
+int
+destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
+{
+	struct ehci_ctrl *ctrl = dev->controller;
+	int result = -1;
+
+	if (disable_periodic(ctrl) < 0) {
+		debug("FATAL: periodic should never fail, but did");
+		goto out;
+	}
+	periodic_schedules--;
+
+	struct QH *cur = &ctrl->periodic_queue;
+	while (!(cur->qh_link & QH_LINK_TERMINATE)) {
+		debug("considering %p, with qh_link %x\n", cur, cur->qh_link);
+		if (NEXT_QH(cur) == queue->first) {
+			debug("found candidate. removing from chain\n");
+			cur->qh_link = queue->last->qh_link;
+			result = 0;
+			goto out;
+		}
+		cur = NEXT_QH(cur);
+	}
+
+	if (periodic_schedules > 0)
+		if (enable_periodic(ctrl) < 0) {
+			debug("FATAL: periodic should never fail, but did");
+			result = -1;
+		}
+
+out:
+	free(queue->tds);
+	free(queue->first);
+	free(queue);
+	return result;
+}
+
 int
 submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	       int length, int interval)
 {
+	void *backbuffer;
+	struct int_queue *queue;
+
 	debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
 	      dev, pipe, buffer, length, interval);
 
@@ -975,9 +1245,26 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	 * not require more than a single qTD.
 	 */
 	if (length > usb_maxpacket(dev, pipe)) {
-		printf("%s: Interrupt transfers requiring several transactions "
-			"are not supported.\n", __func__);
+		printf("%s: Interrupt transfers requiring several "
+			"transactions are not supported.\n", __func__);
 		return -1;
 	}
-	return ehci_submit_async(dev, pipe, buffer, length, NULL);
+
+	queue = create_int_queue(dev, pipe, 1, length, buffer);
+
+	/* TODO: pick some useful timeout rule */
+	while ((backbuffer = poll_int_queue(dev, queue)) == NULL)
+		;
+
+	if (backbuffer != buffer) {
+		debug("got wrong buffer back (%x instead of %x)\n",
+		      (uint32_t)backbuffer, (uint32_t)buffer);
+		return -1;
+	}
+
+	if (destroy_int_queue(dev, queue) == -1)
+		return -1;
+
+	/* everything worked out fine */
+	return 0;
 }
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 1e3cd79..8bc2ba1 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -69,6 +69,7 @@ struct ehci_hcor {
 #define CMD_RUN		(1 << 0)		/* start/stop HC */
 	uint32_t or_usbsts;
 #define STS_ASS		(1 << 15)
+#define	STD_PSS		(1 << 14)
 #define STS_HALT	(1 << 12)
 	uint32_t or_usbintr;
 #define INTR_UE         (1 << 0)                /* USB interrupt enable */
@@ -245,7 +246,10 @@ struct QH {
 	 * Add dummy fill value to make the size of this struct
 	 * aligned to 32 bytes
 	 */
-	uint8_t fill[16];
+	union {
+		uint8_t fill[16];
+		void *buffer;
+	};
 };
 
 /* Low level init functions */
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 05/11] usb: ehci: Fix aliasing issue in EHCI interrupt code
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
                   ` (3 preceding siblings ...)
  2012-12-13  1:55 ` [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13  1:55 ` [U-Boot] [PATCH 06/11] usb: ehci: Add timeout on interrupt endpoint operations Simon Glass
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Vincent Palatin <vpalatin@chromium.org>

The interrupt endpoint handling code stores the buffer pointer in the QH
padding field. We need to make it the size of a pointer to avoid strict
aliasing issue with the compiler.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/usb/host/ehci.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 8bc2ba1..5370eb0 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -247,7 +247,7 @@ struct QH {
 	 * aligned to 32 bytes
 	 */
 	union {
-		uint8_t fill[16];
+		uint32_t fill[4];
 		void *buffer;
 	};
 };
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 06/11] usb: ehci: Add timeout on interrupt endpoint operations
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
                   ` (4 preceding siblings ...)
  2012-12-13  1:55 ` [U-Boot] [PATCH 05/11] usb: ehci: Fix aliasing issue in EHCI interrupt code Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13 17:35   ` Marek Vasut
  2012-12-13  1:55 ` [U-Boot] [PATCH 07/11] usb: usbeth: smsc95xx: remove EEPROM loaded check Simon Glass
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Vincent Palatin <vpalatin@chromium.org>

Ensure we cannot get stuck in the keyboard scanning if something wrong
happens (USB device unplugged or fatal I/O error)

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/usb/host/ehci-hcd.c |   18 ++++++++++++++++--
 1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 0f4bc49..51aa4b3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1191,6 +1191,7 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 {
 	struct ehci_ctrl *ctrl = dev->controller;
 	int result = -1;
+	unsigned long timeout;
 
 	if (disable_periodic(ctrl) < 0) {
 		debug("FATAL: periodic should never fail, but did");
@@ -1199,6 +1200,7 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 	periodic_schedules--;
 
 	struct QH *cur = &ctrl->periodic_queue;
+	timeout = get_timer(0) + 500; /* abort after 500ms */
 	while (!(cur->qh_link & QH_LINK_TERMINATE)) {
 		debug("considering %p, with qh_link %x\n", cur, cur->qh_link);
 		if (NEXT_QH(cur) == queue->first) {
@@ -1208,6 +1210,11 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 			goto out;
 		}
 		cur = NEXT_QH(cur);
+		if (get_timer(0) > timeout) {
+			printf("Timeout destroying interrupt endpoint queue\n");
+			result = -1;
+			break;
+		}
 	}
 
 	if (periodic_schedules > 0)
@@ -1229,6 +1236,8 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 {
 	void *backbuffer;
 	struct int_queue *queue;
+	unsigned long timeout;
+	int result = 0;
 
 	debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
 	      dev, pipe, buffer, length, interval);
@@ -1253,8 +1262,13 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	queue = create_int_queue(dev, pipe, 1, length, buffer);
 
 	/* TODO: pick some useful timeout rule */
+	timeout = get_timer(0) + USB_TIMEOUT_MS(pipe);
 	while ((backbuffer = poll_int_queue(dev, queue)) == NULL)
-		;
+		if (get_timer(0) > timeout) {
+			printf("Timeout poll on interrupt endpoint\n");
+			result = -1;
+			break;
+		}
 
 	if (backbuffer != buffer) {
 		debug("got wrong buffer back (%x instead of %x)\n",
@@ -1266,5 +1280,5 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 		return -1;
 
 	/* everything worked out fine */
-	return 0;
+	return result;
 }
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 07/11] usb: usbeth: smsc95xx: remove EEPROM loaded check
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
                   ` (5 preceding siblings ...)
  2012-12-13  1:55 ` [U-Boot] [PATCH 06/11] usb: ehci: Add timeout on interrupt endpoint operations Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13 17:35   ` Marek Vasut
  2012-12-13  1:55 ` [U-Boot] [PATCH 08/11] usb: Clean up newly allocated device nodes in case of configuration failure Simon Glass
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Michael Spang <spang@chromium.org>

[port of Linux kernel commit bcd218be5aeb by Steve Glendinning]

The eeprom read & write commands currently check the E2P_CMD_LOADED_ bit is
set before allowing any operations.  This prevents any reading or writing
unless a correctly programmed EEPROM is installed.

Signed-off-by: Michael Spang <spang@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/usb/eth/smsc95xx.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index dc5ca65..fd8f8a7 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -265,10 +265,6 @@ static int smsc95xx_eeprom_confirm_not_busy(struct ueth_data *dev)
 
 	do {
 		smsc95xx_read_reg(dev, E2P_CMD, &val);
-		if (!(val & E2P_CMD_LOADED_)) {
-			debug("No EEPROM present\n");
-			return -1;
-		}
 		if (!(val & E2P_CMD_BUSY_))
 			return 0;
 		udelay(40);
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 08/11] usb: Clean up newly allocated device nodes in case of configuration failure
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
                   ` (6 preceding siblings ...)
  2012-12-13  1:55 ` [U-Boot] [PATCH 07/11] usb: usbeth: smsc95xx: remove EEPROM loaded check Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13 17:36   ` Marek Vasut
  2012-12-13  1:55 ` [U-Boot] [PATCH 09/11] usb: properly detect empty mass storage media reader Simon Glass
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Milind Choudhary <milindc@codeaurora.org>

If probe of a newly connected device fails for some reason, clean up
the allocated entry in usb_dev array.

Signed-off-by: Milind Choudhary <milindc@codeaurora.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
---
 common/usb.c     |   12 ++++++++++++
 common/usb_hub.c |    2 ++
 include/usb.h    |    1 +
 3 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/common/usb.c b/common/usb.c
index ac9b4ca..6fc0fc1 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -805,6 +805,18 @@ struct usb_device *usb_alloc_new_device(void *controller)
 	return &usb_dev[dev_index - 1];
 }
 
+/*
+ * Free the newly created device node.
+ * Called in error cases where configuring a newly attached
+ * device fails for some reason.
+ */
+void usb_free_device(void)
+{
+	dev_index--;
+	USB_PRINTF("Freeing device node: %d\n", dev_index);
+	memset(&usb_dev[dev_index], 0, sizeof(struct usb_device));
+	usb_dev[dev_index].devnum = -1;
+}
 
 /*
  * By the time we get here, the device has gotten a new device ID
diff --git a/common/usb_hub.c b/common/usb_hub.c
index e4a1201..a3c5f22 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -259,6 +259,8 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
 	/* Run it through the hoops (find a driver, etc) */
 	if (usb_new_device(usb)) {
 		/* Woops, disable the port */
+		usb_free_device();
+		dev->children[port] = NULL;
 		USB_HUB_PRINTF("hub: disabling port %d\n", port + 1);
 		usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
 	}
diff --git a/include/usb.h b/include/usb.h
index 8d8a2c9..d79c865 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -392,5 +392,6 @@ int hub_port_reset(struct usb_device *dev, int port,
 struct usb_device *usb_alloc_new_device(void *controller);
 
 int usb_new_device(struct usb_device *dev);
+void usb_free_device(void);
 
 #endif /*_USB_H_ */
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 09/11] usb: properly detect empty mass storage media reader
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
                   ` (7 preceding siblings ...)
  2012-12-13  1:55 ` [U-Boot] [PATCH 08/11] usb: Clean up newly allocated device nodes in case of configuration failure Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13 17:37   ` Marek Vasut
  2012-12-13  1:55 ` [U-Boot] [PATCH 10/11] usb: Add multiple controllers support for EHCI PCI Simon Glass
  2012-12-13  1:55 ` [U-Boot] [PATCH 11/11] x86: Enable USB features for coreboot Simon Glass
  10 siblings, 1 reply; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Vincent Palatin <vpalatin@chromium.org>

When a USB card reader is empty, it will return "Not Ready - medium not
present" as Key Code Qualifier. In that situation, it's useless waiting
for the full timeout since the result won't change until the user
inserts a card.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
---
 common/usb_storage.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/common/usb_storage.c b/common/usb_storage.c
index 2d92ee1..fb322b4 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -970,6 +970,16 @@ static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
 			return 0;
 		}
 		usb_request_sense(srb, ss);
+		/*
+		 * Check the Key Code Qualifier, if it matches
+		 * "Not Ready - medium not present"
+		 * (the sense Key equals 0x2 and the ASC is 0x3a)
+		 * return immediately as the medium being absent won't change
+		 * unless there is a user action.
+		 */
+		if ((srb->sense_buf[2] == 0x02) &&
+		    (srb->sense_buf[12] == 0x3a))
+			return -1;
 		mdelay(100);
 	} while (retries--);
 
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 10/11] usb: Add multiple controllers support for EHCI PCI
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
                   ` (8 preceding siblings ...)
  2012-12-13  1:55 ` [U-Boot] [PATCH 09/11] usb: properly detect empty mass storage media reader Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  2012-12-13  1:55 ` [U-Boot] [PATCH 11/11] x86: Enable USB features for coreboot Simon Glass
  10 siblings, 0 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

From: Vincent Palatin <vpalatin@chromium.org>

Use the ability to have several active EHCI controller on a system
in the PCI EHCI controller implementation.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 drivers/usb/host/ehci-pci.c |   24 +++++++++++++++---------
 1 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 0dc0e6e..2a3cb31 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -33,7 +33,7 @@ static struct pci_device_id ehci_pci_ids[] = {
 	{0, 0}
 };
 #else
-static pci_dev_t ehci_find_class(void)
+static pci_dev_t ehci_find_class(int index)
 {
 	int bus;
 	int devnum;
@@ -53,7 +53,7 @@ static pci_dev_t ehci_find_class(void)
 					bdf += PCI_BDF(0, 0, 1)) {
 				pci_read_config_dword(bdf, PCI_CLASS_REVISION,
 						      &class);
-				if (class >> 8 == 0x0c0320)
+				if ((class >> 8 == 0x0c0320) && !index--)
 					return bdf;
 			}
 		}
@@ -66,34 +66,40 @@ static pci_dev_t ehci_find_class(void)
  * Create the appropriate control structures to manage
  * a new EHCI host controller.
  */
-int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
+int ehci_hcd_init(int index, struct ehci_hccr **ret_hccr,
+		struct ehci_hcor **ret_hcor)
 {
 	pci_dev_t pdev;
 	uint32_t cmd;
+	struct ehci_hccr *hccr;
+	struct ehci_hcor *hcor;
 
 #ifdef CONFIG_PCI_EHCI_DEVICE
 	pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
 #else
-	pdev = ehci_find_class();
+	pdev = ehci_find_class(index);
 #endif
 	if (pdev == -1) {
 		printf("EHCI host controller not found\n");
 		return -1;
 	}
 
-	*hccr = (struct ehci_hccr *)pci_map_bar(pdev,
+	hccr = (struct ehci_hccr *)pci_map_bar(pdev,
 			PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
-	*hcor = (struct ehci_hcor *)((uint32_t) *hccr +
-			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+	hcor = (struct ehci_hcor *)((uint32_t) hccr +
+			HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
 	debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
-			(uint32_t)*hccr, (uint32_t)*hcor,
-			(uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+			(uint32_t)hccr, (uint32_t)hcor,
+			(uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
 	/* enable busmaster */
 	pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
 	cmd |= PCI_COMMAND_MASTER;
 	pci_write_config_dword(pdev, PCI_COMMAND, cmd);
+
+	*ret_hccr = hccr;
+	*ret_hcor = hcor;
 	return 0;
 }
 
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 11/11] x86: Enable USB features for coreboot
  2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
                   ` (9 preceding siblings ...)
  2012-12-13  1:55 ` [U-Boot] [PATCH 10/11] usb: Add multiple controllers support for EHCI PCI Simon Glass
@ 2012-12-13  1:55 ` Simon Glass
  10 siblings, 0 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-13  1:55 UTC (permalink / raw)
  To: u-boot

Enable PCI EHCI, storage, keyboard and Ethernet for USB.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 include/configs/coreboot.h |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h
index adeace0..79adbc0 100644
--- a/include/configs/coreboot.h
+++ b/include/configs/coreboot.h
@@ -267,6 +267,23 @@
  */
 #define CONFIG_PCI
 
+/*-----------------------------------------------------------------------
+ * USB configuration
+ */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_PCI
+#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS     12
+#define CONFIG_USB_MAX_CONTROLLER_COUNT        2
+#define CONFIG_USB_STORAGE
+#define CONFIG_USB_KEYBOARD
+#define CONFIG_SYS_USB_EVENT_POLL
+
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_SMSC95XX
+
+#define CONFIG_CMD_USB
+
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	CONFIG_STD_DEVICES_SETTINGS
 
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established
  2012-12-13  1:55 ` [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established Simon Glass
@ 2012-12-13 17:26   ` Marek Vasut
  2012-12-15  7:28   ` Joe Hershberger
  1 sibling, 0 replies; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:26 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> The Asix driver takes the link down during init() and then brings it back
> up. This commit changes this so that if a link has already been
> established successfully we simply check that the link is still good.
> 
> Also fix up asix_halt() to actually halt RX on the interface. Previously
> this was not done, so the device would continue to operate evern when
> halted, violating a U-Boot requirement.
> 
> This reduces the delay between successive network commands.
> Signed-off-by: Simon Glass <sjg@chromium.org>

Joe, this is yours. Gimme a go/no-go and an Ack ;-)

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 02/11] usb: ehci: Add 64-bit controller support
  2012-12-13  1:55 ` [U-Boot] [PATCH 02/11] usb: ehci: Add 64-bit controller support Simon Glass
@ 2012-12-13 17:27   ` Marek Vasut
  0 siblings, 0 replies; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:27 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> From: Vincent Palatin <vpalatin@chromium.org>
> 
> On EHCI controller with 64-bit address space support, we must initialize
> properly the high word for the PCI bus master accesses.
> 
> Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>  drivers/usb/host/ehci-hcd.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index 7f98a63..20309ad 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -870,6 +870,9 @@ int usb_lowlevel_init(int index, void **controller)
>  	if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
>  		return -1;
>  #endif
> +	/* Set the high address word (aka segment) for 64-bit controller */
> +	if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1)
> +		ehci_writel(ehcic[index].hcor->or_ctrldssegment, 0);
> 
>  	qh_list = &ehcic[index].qh_list;

Applied, thanks

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support
  2012-12-13  1:55 ` [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support Simon Glass
@ 2012-12-13 17:30   ` Marek Vasut
  2012-12-13 17:49     ` Vincent Palatin
  2012-12-14  1:41     ` Simon Glass
  2012-12-14  6:58   ` [U-Boot] [PATCH v3 2/7] " Simon Glass
  1 sibling, 2 replies; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:30 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> From: Vincent Palatin <vpalatin@chromium.org>
> 
> Instead of hardcoding the PCI IDs on the USB controller, use the PCI
> class to detect them.
> 
> Ensure the busmaster bit is properly set in the PCI configuration.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>  drivers/usb/host/ehci-pci.c |   37 +++++++++++++++++++++++++++++++++++++
>  1 files changed, 37 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
> index 29af02d..0dc0e6e 100644
> --- a/drivers/usb/host/ehci-pci.c
> +++ b/drivers/usb/host/ehci-pci.c
> @@ -32,6 +32,34 @@ static struct pci_device_id ehci_pci_ids[] = {
>  	{0x12D8, 0x400F},	/* Pericom */
>  	{0, 0}
>  };
> +#else
> +static pci_dev_t ehci_find_class(void)
> +{
> +	int bus;
> +	int devnum;
> +	pci_dev_t bdf;
> +	uint32_t class;
> +
> +	for (bus = 0; bus < pci_last_busno(); bus++) {
> +		for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) {
> +			pci_read_config_dword(PCI_BDF(bus, devnum, 0),
> +					      PCI_CLASS_REVISION, &class);
> +			if (class >> 16 == 0xffff)
> +				continue;
> +
> +			for (bdf = PCI_BDF(bus, devnum, 0);
> +					bdf <= PCI_BDF(bus, devnum,
> +						PCI_MAX_PCI_FUNCTIONS - 1);
> +					bdf += PCI_BDF(0, 0, 1)) {
> +				pci_read_config_dword(bdf, PCI_CLASS_REVISION,
> +						      &class);
> +				if (class >> 8 == 0x0c0320)

Can we at least describe this magic please?

> +					return bdf;
> +			}
> +		}
> +	}
> +	return -1;

Let's try to use errno.h please. It won't be consistent for a while, but we'll 
get there.

> +}
>  #endif
> 
>  /*
> @@ -41,8 +69,13 @@ static struct pci_device_id ehci_pci_ids[] = {
>  int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor
> **hcor) {
>  	pci_dev_t pdev;
> +	uint32_t cmd;
> 
> +#ifdef CONFIG_PCI_EHCI_DEVICE
>  	pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
> +#else
> +	pdev = ehci_find_class();
> +#endif
>  	if (pdev == -1) {
>  		printf("EHCI host controller not found\n");
>  		return -1;
> @@ -57,6 +90,10 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr,
> struct ehci_hcor **hcor) (uint32_t)*hccr, (uint32_t)*hcor,
>  			(uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
> 
> +	/* enable busmaster */
> +	pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
> +	cmd |= PCI_COMMAND_MASTER;
> +	pci_write_config_dword(pdev, PCI_COMMAND, cmd);
>  	return 0;
>  }

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list
  2012-12-13  1:55 ` [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list Simon Glass
@ 2012-12-13 17:32   ` Marek Vasut
  2012-12-14  1:46     ` Simon Glass
  0 siblings, 1 reply; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:32 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> From: Patrick Georgi <patrick@georgi-clan.de>
> 
> Interrupt transfers aren't meant to be used from the async list
> (the EHCI spec indicates trouble with low/full-speed intr on async).
> 
> Build a periodic list instead, and provide an API to make use of it.
> Then, use that API from the existing interrupt transfer API.
> 
> This provides support for USB keyboards using EHCI.
> 
> Signed-off-by: Patrick Georgi <patrick@georgi-clan.de>
> Signed-off-by: Simon Glass <sjg@chromium.org>
[...]

Looks good in general. Clear up those ToDos please. Also, some while() cycles 
are endless, make use of some timeout please.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 06/11] usb: ehci: Add timeout on interrupt endpoint operations
  2012-12-13  1:55 ` [U-Boot] [PATCH 06/11] usb: ehci: Add timeout on interrupt endpoint operations Simon Glass
@ 2012-12-13 17:35   ` Marek Vasut
  2012-12-14  2:04     ` Simon Glass
  0 siblings, 1 reply; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:35 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> From: Vincent Palatin <vpalatin@chromium.org>
> 
> Ensure we cannot get stuck in the keyboard scanning if something wrong
> happens (USB device unplugged or fatal I/O error)
> 
> Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---

I like it. Let's use errno.h and rebase on top of u-boot-usb.git ... I just 
pushed it.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 07/11] usb: usbeth: smsc95xx: remove EEPROM loaded check
  2012-12-13  1:55 ` [U-Boot] [PATCH 07/11] usb: usbeth: smsc95xx: remove EEPROM loaded check Simon Glass
@ 2012-12-13 17:35   ` Marek Vasut
  0 siblings, 0 replies; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:35 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> From: Michael Spang <spang@chromium.org>
> 
> [port of Linux kernel commit bcd218be5aeb by Steve Glendinning]
> 
> The eeprom read & write commands currently check the E2P_CMD_LOADED_ bit is
> set before allowing any operations.  This prevents any reading or writing
> unless a correctly programmed EEPROM is installed.
> 
> Signed-off-by: Michael Spang <spang@chromium.org>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Acked-by: Marek Vasut <marex@denx.de>

> ---
>  drivers/usb/eth/smsc95xx.c |    4 ----
>  1 files changed, 0 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
> index dc5ca65..fd8f8a7 100644
> --- a/drivers/usb/eth/smsc95xx.c
> +++ b/drivers/usb/eth/smsc95xx.c
> @@ -265,10 +265,6 @@ static int smsc95xx_eeprom_confirm_not_busy(struct
> ueth_data *dev)
> 
>  	do {
>  		smsc95xx_read_reg(dev, E2P_CMD, &val);
> -		if (!(val & E2P_CMD_LOADED_)) {
> -			debug("No EEPROM present\n");
> -			return -1;
> -		}
>  		if (!(val & E2P_CMD_BUSY_))
>  			return 0;
>  		udelay(40);

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 08/11] usb: Clean up newly allocated device nodes in case of configuration failure
  2012-12-13  1:55 ` [U-Boot] [PATCH 08/11] usb: Clean up newly allocated device nodes in case of configuration failure Simon Glass
@ 2012-12-13 17:36   ` Marek Vasut
  0 siblings, 0 replies; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:36 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> From: Milind Choudhary <milindc@codeaurora.org>
> 
> If probe of a newly connected device fails for some reason, clean up
> the allocated entry in usb_dev array.

Applied, thanks

> Signed-off-by: Milind Choudhary <milindc@codeaurora.org>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>  common/usb.c     |   12 ++++++++++++
>  common/usb_hub.c |    2 ++
>  include/usb.h    |    1 +
>  3 files changed, 15 insertions(+), 0 deletions(-)
> 
> diff --git a/common/usb.c b/common/usb.c
> index ac9b4ca..6fc0fc1 100644
> --- a/common/usb.c
> +++ b/common/usb.c
> @@ -805,6 +805,18 @@ struct usb_device *usb_alloc_new_device(void
> *controller) return &usb_dev[dev_index - 1];
>  }
> 
> +/*
> + * Free the newly created device node.
> + * Called in error cases where configuring a newly attached
> + * device fails for some reason.
> + */
> +void usb_free_device(void)
> +{
> +	dev_index--;
> +	USB_PRINTF("Freeing device node: %d\n", dev_index);
> +	memset(&usb_dev[dev_index], 0, sizeof(struct usb_device));
> +	usb_dev[dev_index].devnum = -1;
> +}
> 
>  /*
>   * By the time we get here, the device has gotten a new device ID
> diff --git a/common/usb_hub.c b/common/usb_hub.c
> index e4a1201..a3c5f22 100644
> --- a/common/usb_hub.c
> +++ b/common/usb_hub.c
> @@ -259,6 +259,8 @@ void usb_hub_port_connect_change(struct usb_device
> *dev, int port) /* Run it through the hoops (find a driver, etc) */
>  	if (usb_new_device(usb)) {
>  		/* Woops, disable the port */
> +		usb_free_device();
> +		dev->children[port] = NULL;
>  		USB_HUB_PRINTF("hub: disabling port %d\n", port + 1);
>  		usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
>  	}
> diff --git a/include/usb.h b/include/usb.h
> index 8d8a2c9..d79c865 100644
> --- a/include/usb.h
> +++ b/include/usb.h
> @@ -392,5 +392,6 @@ int hub_port_reset(struct usb_device *dev, int port,
>  struct usb_device *usb_alloc_new_device(void *controller);
> 
>  int usb_new_device(struct usb_device *dev);
> +void usb_free_device(void);
> 
>  #endif /*_USB_H_ */

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 09/11] usb: properly detect empty mass storage media reader
  2012-12-13  1:55 ` [U-Boot] [PATCH 09/11] usb: properly detect empty mass storage media reader Simon Glass
@ 2012-12-13 17:37   ` Marek Vasut
  0 siblings, 0 replies; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:37 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> From: Vincent Palatin <vpalatin@chromium.org>
> 
> When a USB card reader is empty, it will return "Not Ready - medium not
> present" as Key Code Qualifier. In that situation, it's useless waiting
> for the full timeout since the result won't change until the user
> inserts a card.

Applied, thanks!

> Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
> Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>  common/usb_storage.c |   10 ++++++++++
>  1 files changed, 10 insertions(+), 0 deletions(-)
> 
> diff --git a/common/usb_storage.c b/common/usb_storage.c
> index 2d92ee1..fb322b4 100644
> --- a/common/usb_storage.c
> +++ b/common/usb_storage.c
> @@ -970,6 +970,16 @@ static int usb_test_unit_ready(ccb *srb, struct
> us_data *ss) return 0;
>  		}
>  		usb_request_sense(srb, ss);
> +		/*
> +		 * Check the Key Code Qualifier, if it matches
> +		 * "Not Ready - medium not present"
> +		 * (the sense Key equals 0x2 and the ASC is 0x3a)
> +		 * return immediately as the medium being absent won't change
> +		 * unless there is a user action.
> +		 */
> +		if ((srb->sense_buf[2] == 0x02) &&
> +		    (srb->sense_buf[12] == 0x3a))
> +			return -1;
>  		mdelay(100);
>  	} while (retries--);

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support
  2012-12-13 17:30   ` Marek Vasut
@ 2012-12-13 17:49     ` Vincent Palatin
  2012-12-13 17:54       ` Marek Vasut
  2012-12-14  1:41     ` Simon Glass
  1 sibling, 1 reply; 29+ messages in thread
From: Vincent Palatin @ 2012-12-13 17:49 UTC (permalink / raw)
  To: u-boot

On Thu, Dec 13, 2012 at 9:30 AM, Marek Vasut <marex@denx.de> wrote:
> Dear Simon Glass,
>
>> From: Vincent Palatin <vpalatin@chromium.org>
>>
>> Instead of hardcoding the PCI IDs on the USB controller, use the PCI
>> class to detect them.
>>
>> Ensure the busmaster bit is properly set in the PCI configuration.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>  drivers/usb/host/ehci-pci.c |   37 +++++++++++++++++++++++++++++++++++++
>>  1 files changed, 37 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
>> index 29af02d..0dc0e6e 100644
>> --- a/drivers/usb/host/ehci-pci.c
>> +++ b/drivers/usb/host/ehci-pci.c
>> @@ -32,6 +32,34 @@ static struct pci_device_id ehci_pci_ids[] = {
>>       {0x12D8, 0x400F},       /* Pericom */
>>       {0, 0}
>>  };
>> +#else
>> +static pci_dev_t ehci_find_class(void)
>> +{
>> +     int bus;
>> +     int devnum;
>> +     pci_dev_t bdf;
>> +     uint32_t class;
>> +
>> +     for (bus = 0; bus < pci_last_busno(); bus++) {
>> +             for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) {
>> +                     pci_read_config_dword(PCI_BDF(bus, devnum, 0),
>> +                                           PCI_CLASS_REVISION, &class);
>> +                     if (class >> 16 == 0xffff)
>> +                             continue;
>> +
>> +                     for (bdf = PCI_BDF(bus, devnum, 0);
>> +                                     bdf <= PCI_BDF(bus, devnum,
>> +                                             PCI_MAX_PCI_FUNCTIONS - 1);
>> +                                     bdf += PCI_BDF(0, 0, 1)) {
>> +                             pci_read_config_dword(bdf, PCI_CLASS_REVISION,
>> +                                                   &class);
>> +                             if (class >> 8 == 0x0c0320)
>
> Can we at least describe this magic please?

The PCI class word is something like that :
class = [31:24] class code [23:16] subclass [15:8] Prog if [7:0] Revision ID
For this use case :
class code = 0x0C (Serial bus controller)
subclass = 0x03 (USB controller)
Program interface = 0x20 (EHCI)

This is available in include/pci_ids.h as "#define
PCI_CLASS_SERIAL_USB_EHCI       0x0c0320"
so just replacing the numeric constant by this define should be ok ?

>> +                                     return bdf;
>> +                     }
>> +             }
>> +     }
>> +     return -1;
>
> Let's try to use errno.h please. It won't be consistent for a while, but we'll
> get there.
>
>> +}
>>  #endif
>>
>>  /*
>> @@ -41,8 +69,13 @@ static struct pci_device_id ehci_pci_ids[] = {
>>  int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor
>> **hcor) {
>>       pci_dev_t pdev;
>> +     uint32_t cmd;
>>
>> +#ifdef CONFIG_PCI_EHCI_DEVICE
>>       pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
>> +#else
>> +     pdev = ehci_find_class();
>> +#endif
>>       if (pdev == -1) {
>>               printf("EHCI host controller not found\n");
>>               return -1;
>> @@ -57,6 +90,10 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr,
>> struct ehci_hcor **hcor) (uint32_t)*hccr, (uint32_t)*hcor,
>>                       (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
>>
>> +     /* enable busmaster */
>> +     pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
>> +     cmd |= PCI_COMMAND_MASTER;
>> +     pci_write_config_dword(pdev, PCI_COMMAND, cmd);
>>       return 0;
>>  }
>
> Best regards,
> Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support
  2012-12-13 17:49     ` Vincent Palatin
@ 2012-12-13 17:54       ` Marek Vasut
  0 siblings, 0 replies; 29+ messages in thread
From: Marek Vasut @ 2012-12-13 17:54 UTC (permalink / raw)
  To: u-boot

Dear Vincent Palatin,

> On Thu, Dec 13, 2012 at 9:30 AM, Marek Vasut <marex@denx.de> wrote:
> > Dear Simon Glass,
> > 
> >> From: Vincent Palatin <vpalatin@chromium.org>
> >> 
> >> Instead of hardcoding the PCI IDs on the USB controller, use the PCI
> >> class to detect them.
> >> 
> >> Ensure the busmaster bit is properly set in the PCI configuration.
> >> 
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> ---
> >> 
> >>  drivers/usb/host/ehci-pci.c |   37
> >>  +++++++++++++++++++++++++++++++++++++ 1 files changed, 37
> >>  insertions(+), 0 deletions(-)
> >> 
> >> diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
> >> index 29af02d..0dc0e6e 100644
> >> --- a/drivers/usb/host/ehci-pci.c
> >> +++ b/drivers/usb/host/ehci-pci.c
> >> @@ -32,6 +32,34 @@ static struct pci_device_id ehci_pci_ids[] = {
> >> 
> >>       {0x12D8, 0x400F},       /* Pericom */
> >>       {0, 0}
> >>  
> >>  };
> >> 
> >> +#else
> >> +static pci_dev_t ehci_find_class(void)
> >> +{
> >> +     int bus;
> >> +     int devnum;
> >> +     pci_dev_t bdf;
> >> +     uint32_t class;
> >> +
> >> +     for (bus = 0; bus < pci_last_busno(); bus++) {
> >> +             for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++)
> >> { +                     pci_read_config_dword(PCI_BDF(bus, devnum, 0),
> >> +                                           PCI_CLASS_REVISION,
> >> &class); +                     if (class >> 16 == 0xffff)
> >> +                             continue;
> >> +
> >> +                     for (bdf = PCI_BDF(bus, devnum, 0);
> >> +                                     bdf <= PCI_BDF(bus, devnum,
> >> +                                             PCI_MAX_PCI_FUNCTIONS -
> >> 1); +                                     bdf += PCI_BDF(0, 0, 1)) { + 
> >>                            pci_read_config_dword(bdf,
> >> PCI_CLASS_REVISION, +                                                  
> >> &class);
> >> +                             if (class >> 8 == 0x0c0320)
> > 
> > Can we at least describe this magic please?
> 
> The PCI class word is something like that :
> class = [31:24] class code [23:16] subclass [15:8] Prog if [7:0] Revision
> ID For this use case :
> class code = 0x0C (Serial bus controller)
> subclass = 0x03 (USB controller)
> Program interface = 0x20 (EHCI)
> 
> This is available in include/pci_ids.h as "#define
> PCI_CLASS_SERIAL_USB_EHCI       0x0c0320"
> so just replacing the numeric constant by this define should be ok ?

Of course :)

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support
  2012-12-13 17:30   ` Marek Vasut
  2012-12-13 17:49     ` Vincent Palatin
@ 2012-12-14  1:41     ` Simon Glass
  1 sibling, 0 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-14  1:41 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Thu, Dec 13, 2012 at 9:30 AM, Marek Vasut <marex@denx.de> wrote:
> Dear Simon Glass,
>
>> From: Vincent Palatin <vpalatin@chromium.org>
>>
>> Instead of hardcoding the PCI IDs on the USB controller, use the PCI
>> class to detect them.
>>
>> Ensure the busmaster bit is properly set in the PCI configuration.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>  drivers/usb/host/ehci-pci.c |   37 +++++++++++++++++++++++++++++++++++++
>>  1 files changed, 37 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
>> index 29af02d..0dc0e6e 100644
>> --- a/drivers/usb/host/ehci-pci.c
>> +++ b/drivers/usb/host/ehci-pci.c
>> @@ -32,6 +32,34 @@ static struct pci_device_id ehci_pci_ids[] = {
>>       {0x12D8, 0x400F},       /* Pericom */
>>       {0, 0}
>>  };
>> +#else
>> +static pci_dev_t ehci_find_class(void)
>> +{
>> +     int bus;
>> +     int devnum;
>> +     pci_dev_t bdf;
>> +     uint32_t class;
>> +
>> +     for (bus = 0; bus < pci_last_busno(); bus++) {
>> +             for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) {
>> +                     pci_read_config_dword(PCI_BDF(bus, devnum, 0),
>> +                                           PCI_CLASS_REVISION, &class);
>> +                     if (class >> 16 == 0xffff)
>> +                             continue;
>> +
>> +                     for (bdf = PCI_BDF(bus, devnum, 0);
>> +                                     bdf <= PCI_BDF(bus, devnum,
>> +                                             PCI_MAX_PCI_FUNCTIONS - 1);
>> +                                     bdf += PCI_BDF(0, 0, 1)) {
>> +                             pci_read_config_dword(bdf, PCI_CLASS_REVISION,
>> +                                                   &class);
>> +                             if (class >> 8 == 0x0c0320)
>
> Can we at least describe this magic please?

Changed to PCI_CLASS_SERIAL_USB_EHCI.

>
>> +                                     return bdf;
>> +                     }
>> +             }
>> +     }
>> +     return -1;
>
> Let's try to use errno.h please. It won't be consistent for a while, but we'll
> get there.

Yes, although pci_find_devices() doesn't, so I will just check for < 0 below.

>
>> +}
>>  #endif
>>
>>  /*
>> @@ -41,8 +69,13 @@ static struct pci_device_id ehci_pci_ids[] = {
>>  int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor
>> **hcor) {
>>       pci_dev_t pdev;
>> +     uint32_t cmd;
>>
>> +#ifdef CONFIG_PCI_EHCI_DEVICE
>>       pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
>> +#else
>> +     pdev = ehci_find_class();
>> +#endif
>>       if (pdev == -1) {
>>               printf("EHCI host controller not found\n");
>>               return -1;
>> @@ -57,6 +90,10 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr,
>> struct ehci_hcor **hcor) (uint32_t)*hccr, (uint32_t)*hcor,
>>                       (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
>>
>> +     /* enable busmaster */
>> +     pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
>> +     cmd |= PCI_COMMAND_MASTER;
>> +     pci_write_config_dword(pdev, PCI_COMMAND, cmd);
>>       return 0;
>>  }
>
> Best regards,
> Marek Vasut

Regards,
Simon

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list
  2012-12-13 17:32   ` Marek Vasut
@ 2012-12-14  1:46     ` Simon Glass
  2012-12-14  2:00       ` Marek Vasut
  0 siblings, 1 reply; 29+ messages in thread
From: Simon Glass @ 2012-12-14  1:46 UTC (permalink / raw)
  To: u-boot

Hi,

On Thu, Dec 13, 2012 at 9:32 AM, Marek Vasut <marex@denx.de> wrote:
> Dear Simon Glass,
>
>> From: Patrick Georgi <patrick@georgi-clan.de>
>>
>> Interrupt transfers aren't meant to be used from the async list
>> (the EHCI spec indicates trouble with low/full-speed intr on async).
>>
>> Build a periodic list instead, and provide an API to make use of it.
>> Then, use that API from the existing interrupt transfer API.
>>
>> This provides support for USB keyboards using EHCI.
>>
>> Signed-off-by: Patrick Georgi <patrick@georgi-clan.de>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
> [...]
>
> Looks good in general. Clear up those ToDos please. Also, some while() cycles
> are endless, make use of some timeout please.

Not much ability to do anything other than remove them...

The timeouts come in the next patch - should I squash them?

Regards,
Simon

>
> Best regards,
> Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list
  2012-12-14  1:46     ` Simon Glass
@ 2012-12-14  2:00       ` Marek Vasut
  2012-12-14  2:05         ` Simon Glass
  0 siblings, 1 reply; 29+ messages in thread
From: Marek Vasut @ 2012-12-14  2:00 UTC (permalink / raw)
  To: u-boot

Dear Simon Glass,

> Hi,
> 
> On Thu, Dec 13, 2012 at 9:32 AM, Marek Vasut <marex@denx.de> wrote:
> > Dear Simon Glass,
> > 
> >> From: Patrick Georgi <patrick@georgi-clan.de>
> >> 
> >> Interrupt transfers aren't meant to be used from the async list
> >> (the EHCI spec indicates trouble with low/full-speed intr on async).
> >> 
> >> Build a periodic list instead, and provide an API to make use of it.
> >> Then, use that API from the existing interrupt transfer API.
> >> 
> >> This provides support for USB keyboards using EHCI.
> >> 
> >> Signed-off-by: Patrick Georgi <patrick@georgi-clan.de>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> > 
> > [...]
> > 
> > Looks good in general. Clear up those ToDos please. Also, some while()
> > cycles are endless, make use of some timeout please.
> 
> Not much ability to do anything other than remove them...
> 
> The timeouts come in the next patch - should I squash them?

Yeah, squash them. Was there any reason to split them ?

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 06/11] usb: ehci: Add timeout on interrupt endpoint operations
  2012-12-13 17:35   ` Marek Vasut
@ 2012-12-14  2:04     ` Simon Glass
  0 siblings, 0 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-14  2:04 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Thu, Dec 13, 2012 at 9:35 AM, Marek Vasut <marex@denx.de> wrote:
> Dear Simon Glass,
>
>> From: Vincent Palatin <vpalatin@chromium.org>
>>
>> Ensure we cannot get stuck in the keyboard scanning if something wrong
>> happens (USB device unplugged or fatal I/O error)
>>
>> Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>
> I like it. Let's use errno.h and rebase on top of u-boot-usb.git ... I just
> pushed it.

OK I have had a crack at that and will resend.

Regards,
Simon

>
> Best regards,
> Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list
  2012-12-14  2:00       ` Marek Vasut
@ 2012-12-14  2:05         ` Simon Glass
  0 siblings, 0 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-14  2:05 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Thu, Dec 13, 2012 at 6:00 PM, Marek Vasut <marex@denx.de> wrote:
> Dear Simon Glass,
>
>> Hi,
>>
>> On Thu, Dec 13, 2012 at 9:32 AM, Marek Vasut <marex@denx.de> wrote:
>> > Dear Simon Glass,
>> >
>> >> From: Patrick Georgi <patrick@georgi-clan.de>
>> >>
>> >> Interrupt transfers aren't meant to be used from the async list
>> >> (the EHCI spec indicates trouble with low/full-speed intr on async).
>> >>
>> >> Build a periodic list instead, and provide an API to make use of it.
>> >> Then, use that API from the existing interrupt transfer API.
>> >>
>> >> This provides support for USB keyboards using EHCI.
>> >>
>> >> Signed-off-by: Patrick Georgi <patrick@georgi-clan.de>
>> >> Signed-off-by: Simon Glass <sjg@chromium.org>
>> >
>> > [...]
>> >
>> > Looks good in general. Clear up those ToDos please. Also, some while()
>> > cycles are endless, make use of some timeout please.
>>
>> Not much ability to do anything other than remove them...
>>
>> The timeouts come in the next patch - should I squash them?
>
> Yeah, squash them. Was there any reason to split them ?

Not really - just a bug fix that we did. Will squash.

Regards,
Simon

>
> Best regards,
> Marek Vasut

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH v3 2/7] usb: ehci: generic PCI support
  2012-12-13  1:55 ` [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support Simon Glass
  2012-12-13 17:30   ` Marek Vasut
@ 2012-12-14  6:58   ` Simon Glass
  1 sibling, 0 replies; 29+ messages in thread
From: Simon Glass @ 2012-12-14  6:58 UTC (permalink / raw)
  To: u-boot

From: Vincent Palatin <vpalatin@chromium.org>

Instead of hardcoding the PCI IDs on the USB controller, use the PCI
class to detect them.

Ensure the busmaster bit is properly set in the PCI configuration.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Check the last PCI bus (this was unfortunately omitted in v2)

Changes in v2:
- Use errno where possible
- Use PCI_CLASS_SERIAL_USB_EHCI instead of the number

 drivers/usb/host/ehci-pci.c |   41 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 29af02d..001d141 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -19,6 +19,7 @@
  */
 
 #include <common.h>
+#include <errno.h>
 #include <pci.h>
 #include <usb.h>
 
@@ -32,6 +33,35 @@ static struct pci_device_id ehci_pci_ids[] = {
 	{0x12D8, 0x400F},	/* Pericom */
 	{0, 0}
 };
+#else
+static pci_dev_t ehci_find_class(void)
+{
+	int bus;
+	int devnum;
+	pci_dev_t bdf;
+	uint32_t class;
+
+	for (bus = 0; bus <= pci_last_busno(); bus++) {
+		for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) {
+			pci_read_config_dword(PCI_BDF(bus, devnum, 0),
+					      PCI_CLASS_REVISION, &class);
+			if (class >> 16 == 0xffff)
+				continue;
+
+			for (bdf = PCI_BDF(bus, devnum, 0);
+					bdf <= PCI_BDF(bus, devnum,
+						PCI_MAX_PCI_FUNCTIONS - 1);
+					bdf += PCI_BDF(0, 0, 1)) {
+				pci_read_config_dword(bdf, PCI_CLASS_REVISION,
+						      &class);
+				if (class >> 8 == PCI_CLASS_SERIAL_USB_EHCI)
+					return bdf;
+			}
+		}
+	}
+
+	return -ENODEV;
+}
 #endif
 
 /*
@@ -41,9 +71,14 @@ static struct pci_device_id ehci_pci_ids[] = {
 int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
 	pci_dev_t pdev;
+	uint32_t cmd;
 
+#ifdef CONFIG_PCI_EHCI_DEVICE
 	pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
-	if (pdev == -1) {
+#else
+	pdev = ehci_find_class();
+#endif
+	if (pdev < 0) {
 		printf("EHCI host controller not found\n");
 		return -1;
 	}
@@ -57,6 +92,10 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 			(uint32_t)*hccr, (uint32_t)*hcor,
 			(uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
 
+	/* enable busmaster */
+	pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
+	cmd |= PCI_COMMAND_MASTER;
+	pci_write_config_dword(pdev, PCI_COMMAND, cmd);
 	return 0;
 }
 
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established
  2012-12-13  1:55 ` [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established Simon Glass
  2012-12-13 17:26   ` Marek Vasut
@ 2012-12-15  7:28   ` Joe Hershberger
  1 sibling, 0 replies; 29+ messages in thread
From: Joe Hershberger @ 2012-12-15  7:28 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Dec 12, 2012 at 7:55 PM, Simon Glass <sjg@chromium.org> wrote:
> The Asix driver takes the link down during init() and then brings it back up.
> This commit changes this so that if a link has already been established
> successfully we simply check that the link is still good.
>
> Also fix up asix_halt() to actually halt RX on the interface. Previously this
> was not done, so the device would continue to operate evern when halted,
> violating a U-Boot requirement.
>
> This reduces the delay between successive network commands.
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>  drivers/usb/eth/asix.c |   40 ++++++++++++++++++++++++++++++++--------
>  include/usb_ether.h    |    1 +
>  2 files changed, 33 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c
> index 75ec8f7..a991fea 100644
> --- a/drivers/usb/eth/asix.c
> +++ b/drivers/usb/eth/asix.c
> @@ -84,6 +84,7 @@
>
>  #define AX_DEFAULT_RX_CTL      \
>         (AX_RX_CTL_SO | AX_RX_CTL_AB)
> +#define AX_DISABLE_RX_CTL      AX_RX_CTL_AB
>
>  /* GPIO 2 toggles */
>  #define AX_GPIO_GPO2EN         0x10    /* GPIO2 Output enable */
> @@ -410,17 +411,16 @@ static int asix_basic_reset(struct ueth_data *dev)
>         return 0;
>  }
>
> -/*
> - * Asix callbacks
> - */
> -static int asix_init(struct eth_device *eth, bd_t *bd)
> +static int full_init(struct eth_device *eth)
>  {
> -       struct ueth_data        *dev = (struct ueth_data *)eth->priv;
> -       int timeout = 0;
> -#define TIMEOUT_RESOLUTION 50  /* ms */
> -       int link_detected;
> +       struct ueth_data *dev = (struct ueth_data *)eth->priv;
>
>         debug("** %s()\n", __func__);
> +       if (asix_basic_reset(dev))
> +               goto out_err;
> +
> +       if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0)
> +               goto out_err;
>
>         dev->phy_id = asix_get_phy_addr(dev);
>         if (dev->phy_id < 0)
> @@ -446,6 +446,25 @@ static int asix_init(struct eth_device *eth, bd_t *bd)
>                 debug("Write IPG,IPG1,IPG2 failed\n");
>                 goto out_err;
>         }
> +       return 0;
> +out_err:
> +       return -1;
> +}
> +
> +/*
> + * Asix callbacks
> + */
> +static int asix_init(struct eth_device *eth, bd_t *bd)
> +{
> +       struct ueth_data *dev = (struct ueth_data *)eth->priv;
> +       int timeout = 0;
> +#define TIMEOUT_RESOLUTION 50  /* ms */
> +       int link_detected;
> +
> +       debug("** %s()\n", __func__);
> +
> +       if (!dev->has_been_running && full_init(eth))
> +               return -1;
>
>         if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0)
>                 goto out_err;
> @@ -467,6 +486,7 @@ static int asix_init(struct eth_device *eth, bd_t *bd)
>                 printf("unable to connect.\n");
>                 goto out_err;
>         }
> +       dev->has_been_running = 1;
>
>         return 0;
>  out_err:
> @@ -571,7 +591,11 @@ static int asix_recv(struct eth_device *eth)
>
>  static void asix_halt(struct eth_device *eth)
>  {
> +       struct ueth_data *dev = (struct ueth_data *)eth->priv;
> +
> +       /* Disable packet reception */
>         debug("** %s()\n", __func__);
> +       (void)asix_write_rx_ctl(dev, AX_DISABLE_RX_CTL);
>  }
>
>  /*
> diff --git a/include/usb_ether.h b/include/usb_ether.h
> index 7c7aecb..6145210 100644
> --- a/include/usb_ether.h
> +++ b/include/usb_ether.h
> @@ -49,6 +49,7 @@ struct ueth_data {
>         unsigned char   subclass;               /* as in overview */
>         unsigned char   protocol;               /* .............. */
>         unsigned char   irqinterval;    /* Intervall for IRQ Pipe */
> +       char has_been_running;          /* PHY already inited */
>
>         /* driver private */
>         void *dev_priv;

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2012-12-15  7:28 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-13  1:55 [U-Boot] [PATCH 0/11] Various USB improvements Simon Glass
2012-12-13  1:55 ` [U-Boot] [PATCH 01/11] usb: net: asix: Do a fast init if link already established Simon Glass
2012-12-13 17:26   ` Marek Vasut
2012-12-15  7:28   ` Joe Hershberger
2012-12-13  1:55 ` [U-Boot] [PATCH 02/11] usb: ehci: Add 64-bit controller support Simon Glass
2012-12-13 17:27   ` Marek Vasut
2012-12-13  1:55 ` [U-Boot] [PATCH 03/11] usb: ehci: generic PCI support Simon Glass
2012-12-13 17:30   ` Marek Vasut
2012-12-13 17:49     ` Vincent Palatin
2012-12-13 17:54       ` Marek Vasut
2012-12-14  1:41     ` Simon Glass
2012-12-14  6:58   ` [U-Boot] [PATCH v3 2/7] " Simon Glass
2012-12-13  1:55 ` [U-Boot] [PATCH 04/11] usb: ehci: Support interrupt transfers via periodic list Simon Glass
2012-12-13 17:32   ` Marek Vasut
2012-12-14  1:46     ` Simon Glass
2012-12-14  2:00       ` Marek Vasut
2012-12-14  2:05         ` Simon Glass
2012-12-13  1:55 ` [U-Boot] [PATCH 05/11] usb: ehci: Fix aliasing issue in EHCI interrupt code Simon Glass
2012-12-13  1:55 ` [U-Boot] [PATCH 06/11] usb: ehci: Add timeout on interrupt endpoint operations Simon Glass
2012-12-13 17:35   ` Marek Vasut
2012-12-14  2:04     ` Simon Glass
2012-12-13  1:55 ` [U-Boot] [PATCH 07/11] usb: usbeth: smsc95xx: remove EEPROM loaded check Simon Glass
2012-12-13 17:35   ` Marek Vasut
2012-12-13  1:55 ` [U-Boot] [PATCH 08/11] usb: Clean up newly allocated device nodes in case of configuration failure Simon Glass
2012-12-13 17:36   ` Marek Vasut
2012-12-13  1:55 ` [U-Boot] [PATCH 09/11] usb: properly detect empty mass storage media reader Simon Glass
2012-12-13 17:37   ` Marek Vasut
2012-12-13  1:55 ` [U-Boot] [PATCH 10/11] usb: Add multiple controllers support for EHCI PCI Simon Glass
2012-12-13  1:55 ` [U-Boot] [PATCH 11/11] x86: Enable USB features for coreboot Simon Glass

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox