ehci-hcd.c 39.9 KB
Newer Older
Michael Trimarchi's avatar
Michael Trimarchi committed
1 2
/*-
 * Copyright (c) 2007-2008, Juniper Networks, Inc.
3
 * Copyright (c) 2008, Excito Elektronik i Skåne AB
Remy Böhmer's avatar
Remy Böhmer committed
4 5
 * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
 *
Michael Trimarchi's avatar
Michael Trimarchi committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2 of
 * the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */
#include <common.h>
24
#include <errno.h>
25
#include <asm/byteorder.h>
26
#include <asm/unaligned.h>
Michael Trimarchi's avatar
Michael Trimarchi committed
27 28
#include <usb.h>
#include <asm/io.h>
29
#include <malloc.h>
30
#include <watchdog.h>
31
#include <linux/compiler.h>
32 33

#include "ehci.h"
Michael Trimarchi's avatar
Michael Trimarchi committed
34

35 36 37
#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
#endif
Michael Trimarchi's avatar
Michael Trimarchi committed
38

39 40 41 42 43 44
/*
 * EHCI spec page 20 says that the HC may take up to 16 uFrames (= 4ms) to halt.
 * Let's time out after 8 to have a little safety margin on top of that.
 */
#define HCHALT_TIMEOUT (8 * 1000)

45
static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
46 47

#define ALIGN_END_ADDR(type, ptr, size)			\
48
	((unsigned long)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
Michael Trimarchi's avatar
Michael Trimarchi committed
49

50 51 52 53 54 55 56 57 58 59 60 61
static struct descriptor {
	struct usb_hub_descriptor hub;
	struct usb_device_descriptor device;
	struct usb_linux_config_descriptor config;
	struct usb_linux_interface_descriptor interface;
	struct usb_endpoint_descriptor endpoint;
}  __attribute__ ((packed)) descriptor = {
	{
		0x8,		/* bDescLength */
		0x29,		/* bDescriptorType: hub descriptor */
		2,		/* bNrPorts -- runtime modified */
		0,		/* wHubCharacteristics */
62
		10,		/* bPwrOn2PwrGood */
63 64 65 66 67 68 69
		0,		/* bHubCntrCurrent */
		{},		/* Device removable */
		{}		/* at most 7 ports! XXX */
	},
	{
		0x12,		/* bLength */
		1,		/* bDescriptorType: UDESC_DEVICE */
70
		cpu_to_le16(0x0200), /* bcdUSB: v2.0 */
71 72 73 74 75 76
		9,		/* bDeviceClass: UDCLASS_HUB */
		0,		/* bDeviceSubClass: UDSUBCLASS_HUB */
		1,		/* bDeviceProtocol: UDPROTO_HSHUBSTT */
		64,		/* bMaxPacketSize: 64 bytes */
		0x0000,		/* idVendor */
		0x0000,		/* idProduct */
77
		cpu_to_le16(0x0100), /* bcdDevice */
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
		1,		/* iManufacturer */
		2,		/* iProduct */
		0,		/* iSerialNumber */
		1		/* bNumConfigurations: 1 */
	},
	{
		0x9,
		2,		/* bDescriptorType: UDESC_CONFIG */
		cpu_to_le16(0x19),
		1,		/* bNumInterface */
		1,		/* bConfigurationValue */
		0,		/* iConfiguration */
		0x40,		/* bmAttributes: UC_SELF_POWER */
		0		/* bMaxPower */
	},
	{
		0x9,		/* bLength */
		4,		/* bDescriptorType: UDESC_INTERFACE */
		0,		/* bInterfaceNumber */
		0,		/* bAlternateSetting */
		1,		/* bNumEndpoints */
		9,		/* bInterfaceClass: UICLASS_HUB */
		0,		/* bInterfaceSubClass: UISUBCLASS_HUB */
		0,		/* bInterfaceProtocol: UIPROTO_HSHUBSTT */
		0		/* iInterface */
	},
	{
		0x7,		/* bLength */
		5,		/* bDescriptorType: UDESC_ENDPOINT */
		0x81,		/* bEndpointAddress:
				 * UE_DIR_IN | EHCI_INTR_ENDPT
				 */
		3,		/* bmAttributes: UE_INTERRUPT */
111
		8,		/* wMaxPacketSize */
112 113
		255		/* bInterval */
	},
Michael Trimarchi's avatar
Michael Trimarchi committed
114 115
};

Remy Böhmer's avatar
Remy Böhmer committed
116 117 118 119 120 121
#if defined(CONFIG_EHCI_IS_TDI)
#define ehci_is_TDI()	(1)
#else
#define ehci_is_TDI()	(0)
#endif

Jeroen Hofstee's avatar
Jeroen Hofstee committed
122
__weak int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg)
123 124 125 126
{
	return PORTSC_PSPD(reg);
}

Jeroen Hofstee's avatar
Jeroen Hofstee committed
127
__weak void ehci_set_usbmode(int index)
128 129 130 131 132 133 134 135 136 137 138 139 140
{
	uint32_t tmp;
	uint32_t *reg_ptr;

	reg_ptr = (uint32_t *)((u8 *)&ehcic[index].hcor->or_usbcmd + USBMODE);
	tmp = ehci_readl(reg_ptr);
	tmp |= USBMODE_CM_HC;
#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
	tmp |= USBMODE_BE;
#endif
	ehci_writel(reg_ptr, tmp);
}

Jeroen Hofstee's avatar
Jeroen Hofstee committed
141
__weak void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
142 143 144 145
{
	mdelay(50);
}

146 147 148 149 150 151 152 153 154 155 156
__weak uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port)
{
	if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
		/* Printing the message would cause a scan failure! */
		debug("The request port(%u) is not configured\n", port);
		return NULL;
	}

	return (uint32_t *)&hcor->or_portsc[port];
}

157
static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
158
{
159 160 161
	uint32_t result;
	do {
		result = ehci_readl(ptr);
162
		udelay(5);
163 164 165 166 167
		if (result == ~(uint32_t)0)
			return -1;
		result &= mask;
		if (result == done)
			return 0;
168 169
		usec--;
	} while (usec > 0);
170 171 172
	return -1;
}

173
static int ehci_reset(int index)
174 175 176 177
{
	uint32_t cmd;
	int ret = 0;

178
	cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
179
	cmd = (cmd & ~CMD_RUN) | CMD_RESET;
180 181 182
	ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd);
	ret = handshake((uint32_t *)&ehcic[index].hcor->or_usbcmd,
			CMD_RESET, 0, 250 * 1000);
183 184 185 186 187
	if (ret < 0) {
		printf("EHCI fail to reset\n");
		goto out;
	}

188 189
	if (ehci_is_TDI())
		ehci_set_usbmode(index);
190 191

#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
192
	cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning);
193
	cmd &= ~TXFIFO_THRESH_MASK;
194
	cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH);
195
	ehci_writel(&ehcic[index].hcor->or_txfilltuning, cmd);
196
#endif
197 198
out:
	return ret;
199
}
Michael Trimarchi's avatar
Michael Trimarchi committed
200

201 202 203 204 205
static int ehci_shutdown(struct ehci_ctrl *ctrl)
{
	int i, ret = 0;
	uint32_t cmd, reg;

206 207 208
	if (!ctrl || !ctrl->hcor)
		return -EINVAL;

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
	cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
	cmd &= ~(CMD_PSE | CMD_ASE);
	ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
	ret = handshake(&ctrl->hcor->or_usbsts, STS_ASS | STS_PSS, 0,
		100 * 1000);

	if (!ret) {
		for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) {
			reg = ehci_readl(&ctrl->hcor->or_portsc[i]);
			reg |= EHCI_PS_SUSP;
			ehci_writel(&ctrl->hcor->or_portsc[i], reg);
		}

		cmd &= ~CMD_RUN;
		ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
		ret = handshake(&ctrl->hcor->or_usbsts, STS_HALT, STS_HALT,
			HCHALT_TIMEOUT);
	}

	if (ret)
		puts("EHCI failed to shut down host controller.\n");

	return ret;
}

Michael Trimarchi's avatar
Michael Trimarchi committed
234 235
static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
{
236
	uint32_t delta, next;
237
	uint32_t addr = (unsigned long)buf;
Michael Trimarchi's avatar
Michael Trimarchi committed
238 239
	int idx;

240
	if (addr != ALIGN(addr, ARCH_DMA_MINALIGN))
241 242
		debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf);

243 244
	flush_dcache_range(addr, ALIGN(addr + sz, ARCH_DMA_MINALIGN));

Michael Trimarchi's avatar
Michael Trimarchi committed
245
	idx = 0;
246
	while (idx < QT_BUFFER_CNT) {
247
		td->qt_buffer[idx] = cpu_to_hc32(addr);
248
		td->qt_buffer_hi[idx] = 0;
249
		next = (addr + EHCI_PAGE_SIZE) & ~(EHCI_PAGE_SIZE - 1);
Michael Trimarchi's avatar
Michael Trimarchi committed
250 251 252 253 254 255 256 257
		delta = next - addr;
		if (delta >= sz)
			break;
		sz -= delta;
		addr = next;
		idx++;
	}

258
	if (idx == QT_BUFFER_CNT) {
259
		printf("out of buffer pointers (%zu bytes left)\n", sz);
Michael Trimarchi's avatar
Michael Trimarchi committed
260 261 262 263 264 265
		return -1;
	}

	return 0;
}

266 267 268 269 270 271 272 273 274 275 276 277
static inline u8 ehci_encode_speed(enum usb_device_speed speed)
{
	#define QH_HIGH_SPEED	2
	#define QH_FULL_SPEED	0
	#define QH_LOW_SPEED	1
	if (speed == USB_SPEED_HIGH)
		return QH_HIGH_SPEED;
	if (speed == USB_SPEED_LOW)
		return QH_LOW_SPEED;
	return QH_FULL_SPEED;
}

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
static void ehci_update_endpt2_dev_n_port(struct usb_device *dev,
					  struct QH *qh)
{
	struct usb_device *ttdev;

	if (dev->speed != USB_SPEED_LOW && dev->speed != USB_SPEED_FULL)
		return;

	/*
	 * For full / low speed devices we need to get the devnum and portnr of
	 * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs
	 * in the tree before that one!
	 */
	ttdev = dev;
	while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH)
		ttdev = ttdev->parent;
	if (!ttdev->parent)
		return;

	qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) |
				     QH_ENDPT2_HUBADDR(ttdev->parent->devnum));
}

Michael Trimarchi's avatar
Michael Trimarchi committed
301 302 303 304
static int
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
		   int length, struct devrequest *req)
{
305
	ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN);
306 307
	struct qTD *qtd;
	int qtd_count = 0;
308
	int qtd_counter = 0;
Michael Trimarchi's avatar
Michael Trimarchi committed
309 310 311
	volatile struct qTD *vtd;
	unsigned long ts;
	uint32_t *tdp;
312
	uint32_t endpt, maxpacket, token, usbsts;
Michael Trimarchi's avatar
Michael Trimarchi committed
313
	uint32_t c, toggle;
314
	uint32_t cmd;
315
	int timeout;
316
	int ret = 0;
317
	struct ehci_ctrl *ctrl = dev->controller;
Michael Trimarchi's avatar
Michael Trimarchi committed
318

319
	debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
Michael Trimarchi's avatar
Michael Trimarchi committed
320 321
	      buffer, length, req);
	if (req != NULL)
322
		debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n",
Michael Trimarchi's avatar
Michael Trimarchi committed
323 324 325
		      req->request, req->request,
		      req->requesttype, req->requesttype,
		      le16_to_cpu(req->value), le16_to_cpu(req->value),
326
		      le16_to_cpu(req->index));
Michael Trimarchi's avatar
Michael Trimarchi committed
327

328
#define PKT_ALIGN	512
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
	/*
	 * The USB transfer is split into qTD transfers. Eeach qTD transfer is
	 * described by a transfer descriptor (the qTD). The qTDs form a linked
	 * list with a queue head (QH).
	 *
	 * Each qTD transfer starts with a new USB packet, i.e. a packet cannot
	 * have its beginning in a qTD transfer and its end in the following
	 * one, so the qTD transfer lengths have to be chosen accordingly.
	 *
	 * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to
	 * single pages. The first data buffer can start at any offset within a
	 * page (not considering the cache-line alignment issues), while the
	 * following buffers must be page-aligned. There is no alignment
	 * constraint on the size of a qTD transfer.
	 */
	if (req != NULL)
		/* 1 qTD will be needed for SETUP, and 1 for ACK. */
		qtd_count += 1 + 1;
	if (length > 0 || req == NULL) {
		/*
		 * Determine the qTD transfer size that will be used for the
350 351 352
		 * data payload (not considering the first qTD transfer, which
		 * may be longer or shorter, and the final one, which may be
		 * shorter).
353 354
		 *
		 * In order to keep each packet within a qTD transfer, the qTD
355 356 357
		 * transfer size is aligned to PKT_ALIGN, which is a multiple of
		 * wMaxPacketSize (except in some cases for interrupt transfers,
		 * see comment in submit_int_msg()).
358
		 *
359
		 * By default, i.e. if the input buffer is aligned to PKT_ALIGN,
360 361 362 363
		 * QT_BUFFER_CNT full pages will be used.
		 */
		int xfr_sz = QT_BUFFER_CNT;
		/*
364 365
		 * However, if the input buffer is not aligned to PKT_ALIGN, the
		 * qTD transfer size will be one page shorter, and the first qTD
366 367
		 * data buffer of each transfer will be page-unaligned.
		 */
368
		if ((unsigned long)buffer & (PKT_ALIGN - 1))
369 370 371 372
			xfr_sz--;
		/* Convert the qTD transfer size to bytes. */
		xfr_sz *= EHCI_PAGE_SIZE;
		/*
373 374 375 376
		 * Approximate by excess the number of qTDs that will be
		 * required for the data payload. The exact formula is way more
		 * complicated and saves at most 2 qTDs, i.e. a total of 128
		 * bytes.
377
		 */
378
		qtd_count += 2 + length / xfr_sz;
379 380
	}
/*
381 382
 * Threshold value based on the worst-case total size of the allocated qTDs for
 * a mass-storage transfer of 65535 blocks of 512 bytes.
383
 */
384
#if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024
385 386 387 388 389 390 391 392
#warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI
#endif
	qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD));
	if (qtd == NULL) {
		printf("unable to allocate TDs\n");
		return -1;
	}

393
	memset(qh, 0, sizeof(struct QH));
394
	memset(qtd, 0, qtd_count * sizeof(*qtd));
395

396 397
	toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));

398 399 400 401 402 403 404 405 406 407
	/*
	 * Setup QH (3.6 in ehci-r10.pdf)
	 *
	 *   qh_link ................. 03-00 H
	 *   qh_endpt1 ............... 07-04 H
	 *   qh_endpt2 ............... 0B-08 H
	 * - qh_curtd
	 *   qh_overlay.qt_next ...... 13-10 H
	 * - qh_overlay.qt_altnext
	 */
408
	qh->qh_link = cpu_to_hc32((unsigned long)&ctrl->qh_list | QH_LINK_TYPE_QH);
409
	c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe);
410
	maxpacket = usb_maxpacket(dev, pipe);
411
	endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
412
		QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) |
413
		QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) |
414
		QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) |
415 416
		QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) |
		QH_ENDPT1_DEVADDR(usb_pipedevice(pipe));
417
	qh->qh_endpt1 = cpu_to_hc32(endpt);
418
	endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0);
419
	qh->qh_endpt2 = cpu_to_hc32(endpt);
420
	ehci_update_endpt2_dev_n_port(dev, qh);
421
	qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
422
	qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
Michael Trimarchi's avatar
Michael Trimarchi committed
423

424
	tdp = &qh->qh_overlay.qt_next;
Michael Trimarchi's avatar
Michael Trimarchi committed
425 426

	if (req != NULL) {
427 428 429 430 431 432 433 434 435
		/*
		 * Setup request qTD (3.5 in ehci-r10.pdf)
		 *
		 *   qt_next ................ 03-00 H
		 *   qt_altnext ............. 07-04 H
		 *   qt_token ............... 0B-08 H
		 *
		 *   [ buffer, buffer_hi ] loaded with "req".
		 */
436 437
		qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
		qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
438 439 440 441
		token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) |
			QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
			QT_TOKEN_PID(QT_TOKEN_PID_SETUP) |
			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
442
		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
443 444
		if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) {
			printf("unable to construct SETUP TD\n");
Michael Trimarchi's avatar
Michael Trimarchi committed
445 446
			goto fail;
		}
447
		/* Update previous qTD! */
448
		*tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
449
		tdp = &qtd[qtd_counter++].qt_next;
Michael Trimarchi's avatar
Michael Trimarchi committed
450 451 452 453
		toggle = 1;
	}

	if (length > 0 || req == NULL) {
454 455 456 457 458 459 460 461 462 463 464 465 466 467
		uint8_t *buf_ptr = buffer;
		int left_length = length;

		do {
			/*
			 * Determine the size of this qTD transfer. By default,
			 * QT_BUFFER_CNT full pages can be used.
			 */
			int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE;
			/*
			 * However, if the input buffer is not page-aligned, the
			 * portion of the first page before the buffer start
			 * offset within that page is unusable.
			 */
468
			xfr_bytes -= (unsigned long)buf_ptr & (EHCI_PAGE_SIZE - 1);
469 470
			/*
			 * In order to keep each packet within a qTD transfer,
471
			 * align the qTD transfer size to PKT_ALIGN.
472
			 */
473
			xfr_bytes &= ~(PKT_ALIGN - 1);
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
			/*
			 * This transfer may be shorter than the available qTD
			 * transfer size that has just been computed.
			 */
			xfr_bytes = min(xfr_bytes, left_length);

			/*
			 * Setup request qTD (3.5 in ehci-r10.pdf)
			 *
			 *   qt_next ................ 03-00 H
			 *   qt_altnext ............. 07-04 H
			 *   qt_token ............... 0B-08 H
			 *
			 *   [ buffer, buffer_hi ] loaded with "buffer".
			 */
			qtd[qtd_counter].qt_next =
					cpu_to_hc32(QT_NEXT_TERMINATE);
			qtd[qtd_counter].qt_altnext =
					cpu_to_hc32(QT_NEXT_TERMINATE);
			token = QT_TOKEN_DT(toggle) |
				QT_TOKEN_TOTALBYTES(xfr_bytes) |
				QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) |
				QT_TOKEN_CERR(3) |
				QT_TOKEN_PID(usb_pipein(pipe) ?
					QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) |
				QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
			qtd[qtd_counter].qt_token = cpu_to_hc32(token);
			if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr,
						xfr_bytes)) {
				printf("unable to construct DATA TD\n");
				goto fail;
			}
			/* Update previous qTD! */
507
			*tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
508
			tdp = &qtd[qtd_counter++].qt_next;
509 510 511 512 513 514 515
			/*
			 * Data toggle has to be adjusted since the qTD transfer
			 * size is not always an even multiple of
			 * wMaxPacketSize.
			 */
			if ((xfr_bytes / maxpacket) & 1)
				toggle ^= 1;
516 517 518
			buf_ptr += xfr_bytes;
			left_length -= xfr_bytes;
		} while (left_length > 0);
Michael Trimarchi's avatar
Michael Trimarchi committed
519 520 521
	}

	if (req != NULL) {
522 523 524 525 526 527 528
		/*
		 * Setup request qTD (3.5 in ehci-r10.pdf)
		 *
		 *   qt_next ................ 03-00 H
		 *   qt_altnext ............. 07-04 H
		 *   qt_token ............... 0B-08 H
		 */
529 530
		qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
		qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
531
		token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) |
532 533 534 535
			QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
			QT_TOKEN_PID(usb_pipein(pipe) ?
				QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) |
			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
536
		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
537
		/* Update previous qTD! */
538
		*tdp = cpu_to_hc32((unsigned long)&qtd[qtd_counter]);
539
		tdp = &qtd[qtd_counter++].qt_next;
Michael Trimarchi's avatar
Michael Trimarchi committed
540 541
	}

542
	ctrl->qh_list.qh_link = cpu_to_hc32((unsigned long)qh | QH_LINK_TYPE_QH);
Michael Trimarchi's avatar
Michael Trimarchi committed
543

544
	/* Flush dcache */
545
	flush_dcache_range((unsigned long)&ctrl->qh_list,
546
		ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
547 548
	flush_dcache_range((unsigned long)qh, ALIGN_END_ADDR(struct QH, qh, 1));
	flush_dcache_range((unsigned long)qtd,
549
			   ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
550

551
	/* Set async. queue head pointer. */
552
	ehci_writel(&ctrl->hcor->or_asynclistaddr, (unsigned long)&ctrl->qh_list);
553

554 555
	usbsts = ehci_readl(&ctrl->hcor->or_usbsts);
	ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f));
Michael Trimarchi's avatar
Michael Trimarchi committed
556 557

	/* Enable async. schedule. */
558
	cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
559
	cmd |= CMD_ASE;
560
	ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
561

562
	ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS,
563 564
			100 * 1000);
	if (ret < 0) {
565
		printf("EHCI fail timeout STS_ASS set\n");
566
		goto fail;
567
	}
Michael Trimarchi's avatar
Michael Trimarchi committed
568 569 570

	/* Wait for TDs to be processed. */
	ts = get_timer(0);
571
	vtd = &qtd[qtd_counter - 1];
572
	timeout = USB_TIMEOUT_MS(pipe);
Michael Trimarchi's avatar
Michael Trimarchi committed
573
	do {
574
		/* Invalidate dcache */
575
		invalidate_dcache_range((unsigned long)&ctrl->qh_list,
576
			ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
577
		invalidate_dcache_range((unsigned long)qh,
578
			ALIGN_END_ADDR(struct QH, qh, 1));
579
		invalidate_dcache_range((unsigned long)qtd,
580
			ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
581

582
		token = hc32_to_cpu(vtd->qt_token);
583
		if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE))
Michael Trimarchi's avatar
Michael Trimarchi committed
584
			break;
585
		WATCHDOG_RESET();
586 587
	} while (get_timer(ts) < timeout);

588 589 590 591 592 593 594 595 596
	/*
	 * Invalidate the memory area occupied by buffer
	 * Don't try to fix the buffer alignment, if it isn't properly
	 * aligned it's upper layer's fault so let invalidate_dcache_range()
	 * vow about it. But we have to fix the length as it's actual
	 * transfer length and can be unaligned. This is potentially
	 * dangerous operation, it's responsibility of the calling
	 * code to make sure enough space is reserved.
	 */
597 598
	invalidate_dcache_range((unsigned long)buffer,
		ALIGN((unsigned long)buffer + length, ARCH_DMA_MINALIGN));
599

600
	/* Check that the TD processing happened */
601
	if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)
602
		printf("EHCI timed out on TD - token=%#x\n", token);
Michael Trimarchi's avatar
Michael Trimarchi committed
603 604

	/* Disable async schedule. */
605
	cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
606
	cmd &= ~CMD_ASE;
607
	ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
608

609
	ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0,
610 611
			100 * 1000);
	if (ret < 0) {
612
		printf("EHCI fail timeout STS_ASS reset\n");
613
		goto fail;
614
	}
Michael Trimarchi's avatar
Michael Trimarchi committed
615

616
	token = hc32_to_cpu(qh->qh_overlay.qt_token);
617
	if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) {
618
		debug("TOKEN=%#x\n", token);
619 620
		switch (QT_TOKEN_GET_STATUS(token) &
			~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) {
Michael Trimarchi's avatar
Michael Trimarchi committed
621
		case 0:
622
			toggle = QT_TOKEN_GET_DT(token);
Michael Trimarchi's avatar
Michael Trimarchi committed
623 624 625 626
			usb_settoggle(dev, usb_pipeendpoint(pipe),
				       usb_pipeout(pipe), toggle);
			dev->status = 0;
			break;
627
		case QT_TOKEN_STATUS_HALTED:
Michael Trimarchi's avatar
Michael Trimarchi committed
628 629
			dev->status = USB_ST_STALLED;
			break;
630 631
		case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR:
		case QT_TOKEN_STATUS_DATBUFERR:
Michael Trimarchi's avatar
Michael Trimarchi committed
632 633
			dev->status = USB_ST_BUF_ERR;
			break;
634 635
		case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET:
		case QT_TOKEN_STATUS_BABBLEDET:
Michael Trimarchi's avatar
Michael Trimarchi committed
636 637 638 639
			dev->status = USB_ST_BABBLE_DET;
			break;
		default:
			dev->status = USB_ST_CRC_ERR;
640
			if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED)
641
				dev->status |= USB_ST_STALLED;
Michael Trimarchi's avatar
Michael Trimarchi committed
642 643
			break;
		}
644
		dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token);
Michael Trimarchi's avatar
Michael Trimarchi committed
645 646
	} else {
		dev->act_len = 0;
647
#ifndef CONFIG_USB_EHCI_FARADAY
648
		debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
649 650 651
		      dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts),
		      ehci_readl(&ctrl->hcor->or_portsc[0]),
		      ehci_readl(&ctrl->hcor->or_portsc[1]));
652
#endif
Michael Trimarchi's avatar
Michael Trimarchi committed
653 654
	}

655
	free(qtd);
Michael Trimarchi's avatar
Michael Trimarchi committed
656 657 658
	return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;

fail:
659
	free(qtd);
Michael Trimarchi's avatar
Michael Trimarchi committed
660 661 662
	return -1;
}

663
int
Michael Trimarchi's avatar
Michael Trimarchi committed
664 665 666 667 668
ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
		 int length, struct devrequest *req)
{
	uint8_t tmpbuf[4];
	u16 typeReq;
669
	void *srcptr = NULL;
Michael Trimarchi's avatar
Michael Trimarchi committed
670 671
	int len, srclen;
	uint32_t reg;
Remy Böhmer's avatar
Remy Böhmer committed
672
	uint32_t *status_reg;
673
	int port = le16_to_cpu(req->index) & 0xff;
674
	struct ehci_ctrl *ctrl = dev->controller;
Michael Trimarchi's avatar
Michael Trimarchi committed
675 676 677

	srclen = 0;

678
	debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n",
Michael Trimarchi's avatar
Michael Trimarchi committed
679 680 681 682
	      req->request, req->request,
	      req->requesttype, req->requesttype,
	      le16_to_cpu(req->value), le16_to_cpu(req->index));

683
	typeReq = req->request | req->requesttype << 8;
Michael Trimarchi's avatar
Michael Trimarchi committed
684

685 686 687 688
	switch (typeReq) {
	case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
	case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
	case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
689 690
		status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1);
		if (!status_reg)
691 692 693 694 695 696 697
			return -1;
		break;
	default:
		status_reg = NULL;
		break;
	}

698
	switch (typeReq) {
Michael Trimarchi's avatar
Michael Trimarchi committed
699 700 701
	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
		switch (le16_to_cpu(req->value) >> 8) {
		case USB_DT_DEVICE:
702 703
			debug("USB_DT_DEVICE request\n");
			srcptr = &descriptor.device;
704
			srclen = descriptor.device.bLength;
Michael Trimarchi's avatar
Michael Trimarchi committed
705 706
			break;
		case USB_DT_CONFIG:
707 708
			debug("USB_DT_CONFIG config\n");
			srcptr = &descriptor.config;
709 710 711
			srclen = descriptor.config.bLength +
					descriptor.interface.bLength +
					descriptor.endpoint.bLength;
Michael Trimarchi's avatar
Michael Trimarchi committed
712 713
			break;
		case USB_DT_STRING:
714
			debug("USB_DT_STRING config\n");
Michael Trimarchi's avatar
Michael Trimarchi committed
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
			switch (le16_to_cpu(req->value) & 0xff) {
			case 0:	/* Language */
				srcptr = "\4\3\1\0";
				srclen = 4;
				break;
			case 1:	/* Vendor */
				srcptr = "\16\3u\0-\0b\0o\0o\0t\0";
				srclen = 14;
				break;
			case 2:	/* Product */
				srcptr = "\52\3E\0H\0C\0I\0 "
					 "\0H\0o\0s\0t\0 "
					 "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0";
				srclen = 42;
				break;
			default:
731 732
				debug("unknown value DT_STRING %x\n",
					le16_to_cpu(req->value));
Michael Trimarchi's avatar
Michael Trimarchi committed
733 734 735 736
				goto unknown;
			}
			break;
		default:
737
			debug("unknown value %x\n", le16_to_cpu(req->value));
Michael Trimarchi's avatar
Michael Trimarchi committed
738 739 740 741 742 743
			goto unknown;
		}
		break;
	case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
		switch (le16_to_cpu(req->value) >> 8) {
		case USB_DT_HUB:
744 745
			debug("USB_DT_HUB config\n");
			srcptr = &descriptor.hub;
746
			srclen = descriptor.hub.bLength;
Michael Trimarchi's avatar
Michael Trimarchi committed
747 748
			break;
		default:
749
			debug("unknown value %x\n", le16_to_cpu(req->value));
Michael Trimarchi's avatar
Michael Trimarchi committed
750 751 752 753
			goto unknown;
		}
		break;
	case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
754
		debug("USB_REQ_SET_ADDRESS\n");
755
		ctrl->rootdev = le16_to_cpu(req->value);
Michael Trimarchi's avatar
Michael Trimarchi committed
756 757
		break;
	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
758
		debug("USB_REQ_SET_CONFIGURATION\n");
Michael Trimarchi's avatar
Michael Trimarchi committed
759 760 761 762 763 764 765 766
		/* Nothing to do */
		break;
	case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
		tmpbuf[0] = 1;	/* USB_STATUS_SELFPOWERED */
		tmpbuf[1] = 0;
		srcptr = tmpbuf;
		srclen = 2;
		break;
767
	case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
Michael Trimarchi's avatar
Michael Trimarchi committed
768
		memset(tmpbuf, 0, 4);
Remy Böhmer's avatar
Remy Böhmer committed
769
		reg = ehci_readl(status_reg);
Michael Trimarchi's avatar
Michael Trimarchi committed
770 771 772 773 774 775 776 777
		if (reg & EHCI_PS_CS)
			tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
		if (reg & EHCI_PS_PE)
			tmpbuf[0] |= USB_PORT_STAT_ENABLE;
		if (reg & EHCI_PS_SUSP)
			tmpbuf[0] |= USB_PORT_STAT_SUSPEND;
		if (reg & EHCI_PS_OCA)
			tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
778 779
		if (reg & EHCI_PS_PR)
			tmpbuf[0] |= USB_PORT_STAT_RESET;
Michael Trimarchi's avatar
Michael Trimarchi committed
780 781
		if (reg & EHCI_PS_PP)
			tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
782 783

		if (ehci_is_TDI()) {
784
			switch (ehci_get_port_speed(ctrl->hcor, reg)) {
785
			case PORTSC_PSPD_FS:
786
				break;
787
			case PORTSC_PSPD_LS:
788 789
				tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
				break;
790
			case PORTSC_PSPD_HS:
791 792 793 794 795 796 797
			default:
				tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
				break;
			}
		} else {
			tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
		}
Michael Trimarchi's avatar
Michael Trimarchi committed
798 799 800 801 802 803 804

		if (reg & EHCI_PS_CSC)
			tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
		if (reg & EHCI_PS_PEC)
			tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
		if (reg & EHCI_PS_OCC)
			tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
805
		if (ctrl->portreset & (1 << port))
Michael Trimarchi's avatar
Michael Trimarchi committed
806
			tmpbuf[2] |= USB_PORT_STAT_C_RESET;
Remy Böhmer's avatar
Remy Böhmer committed
807

Michael Trimarchi's avatar
Michael Trimarchi committed
808 809 810
		srcptr = tmpbuf;
		srclen = 4;
		break;
811
	case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
Remy Böhmer's avatar
Remy Böhmer committed
812
		reg = ehci_readl(status_reg);
Michael Trimarchi's avatar
Michael Trimarchi committed
813 814
		reg &= ~EHCI_PS_CLEAR;
		switch (le16_to_cpu(req->value)) {
815 816
		case USB_PORT_FEAT_ENABLE:
			reg |= EHCI_PS_PE;
Remy Böhmer's avatar
Remy Böhmer committed
817
			ehci_writel(status_reg, reg);
818
			break;
Michael Trimarchi's avatar
Michael Trimarchi committed
819
		case USB_PORT_FEAT_POWER:
820
			if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) {
Remy Böhmer's avatar
Remy Böhmer committed
821 822 823
				reg |= EHCI_PS_PP;
				ehci_writel(status_reg, reg);
			}
Michael Trimarchi's avatar
Michael Trimarchi committed
824 825
			break;
		case USB_PORT_FEAT_RESET:
Remy Böhmer's avatar
Remy Böhmer committed
826 827 828
			if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS &&
			    !ehci_is_TDI() &&
			    EHCI_PS_IS_LOWSPEED(reg)) {
Michael Trimarchi's avatar
Michael Trimarchi committed
829
				/* Low speed device, give up ownership. */
Remy Böhmer's avatar
Remy Böhmer committed
830
				debug("port %d low speed --> companion\n",
831
				      port - 1);
Michael Trimarchi's avatar
Michael Trimarchi committed
832
				reg |= EHCI_PS_PO;
Remy Böhmer's avatar
Remy Böhmer committed
833
				ehci_writel(status_reg, reg);
Michael Trimarchi's avatar
Michael Trimarchi committed
834
				break;
Remy Böhmer's avatar
Remy Böhmer committed
835
			} else {
836 837
				int ret;

Remy Böhmer's avatar
Remy Böhmer committed
838 839 840 841 842 843 844 845
				reg |= EHCI_PS_PR;
				reg &= ~EHCI_PS_PE;
				ehci_writel(status_reg, reg);
				/*
				 * caller must wait, then call GetPortStatus
				 * usb 2.0 specification say 50 ms resets on
				 * root
				 */
846 847
				ehci_powerup_fixup(status_reg, &reg);

Chris Zhang's avatar
Chris Zhang committed
848
				ehci_writel(status_reg, reg & ~EHCI_PS_PR);
849 850 851 852 853 854 855 856
				/*
				 * A host controller must terminate the reset
				 * and stabilize the state of the port within
				 * 2 milliseconds
				 */
				ret = handshake(status_reg, EHCI_PS_PR, 0,
						2 * 1000);
				if (!ret)
857
					ctrl->portreset |= 1 << port;
858 859
				else
					printf("port(%d) reset error\n",
860
					       port - 1);
Michael Trimarchi's avatar
Michael Trimarchi committed
861 862
			}
			break;
863
		case USB_PORT_FEAT_TEST:
864
			ehci_shutdown(ctrl);
865 866 867 868
			reg &= ~(0xf << 16);
			reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16;
			ehci_writel(status_reg, reg);
			break;
Michael Trimarchi's avatar
Michael Trimarchi committed
869
		default:
870
			debug("unknown feature %x\n", le16_to_cpu(req->value));
Michael Trimarchi's avatar
Michael Trimarchi committed
871 872
			goto unknown;
		}
Remy Böhmer's avatar
Remy Böhmer committed
873
		/* unblock posted writes */
874
		(void) ehci_readl(&ctrl->hcor->or_usbcmd);
Michael Trimarchi's avatar
Michael Trimarchi committed
875
		break;
876
	case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
Remy Böhmer's avatar
Remy Böhmer committed
877
		reg = ehci_readl(status_reg);
878
		reg &= ~EHCI_PS_CLEAR;
Michael Trimarchi's avatar
Michael Trimarchi committed
879 880 881 882
		switch (le16_to_cpu(req->value)) {
		case USB_PORT_FEAT_ENABLE:
			reg &= ~EHCI_PS_PE;
			break;
Remy Böhmer's avatar
Remy Böhmer committed
883
		case USB_PORT_FEAT_C_ENABLE:
884
			reg |= EHCI_PS_PE;
Remy Böhmer's avatar
Remy Böhmer committed
885 886
			break;
		case USB_PORT_FEAT_POWER:
887
			if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams)))
888 889
				reg &= ~EHCI_PS_PP;
			break;
Michael Trimarchi's avatar
Michael Trimarchi committed
890
		case USB_PORT_FEAT_C_CONNECTION:
891
			reg |= EHCI_PS_CSC;
Michael Trimarchi's avatar
Michael Trimarchi committed
892
			break;
893
		case USB_PORT_FEAT_OVER_CURRENT:
894
			reg |= EHCI_PS_OCC;
895
			break;
Michael Trimarchi's avatar
Michael Trimarchi committed
896
		case USB_PORT_FEAT_C_RESET:
897
			ctrl->portreset &= ~(1 << port);
Michael Trimarchi's avatar
Michael Trimarchi committed
898 899
			break;
		default:
900
			debug("unknown feature %x\n", le16_to_cpu(req->value));
Michael Trimarchi's avatar
Michael Trimarchi committed
901 902
			goto unknown;
		}
Remy Böhmer's avatar
Remy Böhmer committed
903 904
		ehci_writel(status_reg, reg);
		/* unblock posted write */
905
		(void) ehci_readl(&ctrl->hcor->or_usbcmd);
Michael Trimarchi's avatar
Michael Trimarchi committed
906 907
		break;
	default: