[U-Boot-Users] [PATCH] usb: add support for R8A66597 usb controller

Yoshihiro Shimoda shimoda.yoshihiro at renesas.com
Wed Jul 9 14:07:38 CEST 2008


add support for Renesas R8A66597 usb controller.
This patch supports USB Host mode.

Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro at renesas.com>
---
 drivers/usb/Makefile       |    1 +
 drivers/usb/r8a66597-hcd.c |  924 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/r8a66597.h     |  663 +++++++++++++++++++++++++++++++
 include/usb.h              |    2 +-
 4 files changed, 1589 insertions(+), 1 deletions(-)
 create mode 100644 drivers/usb/r8a66597-hcd.c
 create mode 100644 drivers/usb/r8a66597.h

diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 252b00e..2bdbb59 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -28,6 +28,7 @@ LIB	:= $(obj)libusb.a
 COBJS-y += isp116x-hcd.o
 COBJS-y += sl811_usb.o
 COBJS-y += usb_ohci.o
+COBJS-y += r8a66597-hcd.o
 COBJS-y += usbdcore.o
 COBJS-y += usbdcore_ep0.o
 COBJS-y += usbdcore_mpc8xx.o
diff --git a/drivers/usb/r8a66597-hcd.c b/drivers/usb/r8a66597-hcd.c
new file mode 100644
index 0000000..3eb4cb0
--- /dev/null
+++ b/drivers/usb/r8a66597-hcd.c
@@ -0,0 +1,924 @@
+/*
+ * R8A66597 HCD (Host Controller Driver) for u-boot
+ *
+ * Copyright (C) 2008  Yoshihiro Shimoda <shimoda.yoshihiro at renesas.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <common.h>
+#include <usb.h>
+#include <asm/io.h>
+
+#include "r8a66597.h"
+
+#if defined(CONFIG_USB_R8A66597_HCD)
+
+#ifdef R8A66597_DEBUG
+#define R8A66597_DPRINT		printf
+#else
+#define R8A66597_DPRINT(...)
+#endif
+
+static const char hcd_name[] = "r8a66597_hcd";
+static unsigned short clock = CONFIG_R8A66597_XTAL;
+static unsigned short vif = CONFIG_R8A66597_LDRV;
+static unsigned short endian = CONFIG_R8A66597_ENDIAN;
+static struct r8a66597 gr8a66597;
+
+static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address,
+			   u16 usbspd, u8 upphub, u8 hubport, int port)
+{
+	u16 val;
+	unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
+
+	val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001);
+	r8a66597_write(r8a66597, val, devadd_reg);
+}
+
+static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
+{
+	u16 tmp;
+	int i = 0;
+
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+	do {
+		r8a66597_write(r8a66597, SCKE, SYSCFG0);
+		tmp = r8a66597_read(r8a66597, SYSCFG0);
+		if (i++ > 1000) {
+			printf("register access fail.\n");
+			return -1;
+		}
+	} while ((tmp & SCKE) != SCKE);
+	r8a66597_write(r8a66597, 0x04, 0x02);
+#else
+	do {
+		r8a66597_write(r8a66597, USBE, SYSCFG0);
+		tmp = r8a66597_read(r8a66597, SYSCFG0);
+		if (i++ > 1000) {
+			printf("register access fail.\n");
+			return -1;
+		}
+	} while ((tmp & USBE) != USBE);
+	r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+	r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0);
+
+	i = 0;
+	r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+	do {
+		udelay(1000);
+		tmp = r8a66597_read(r8a66597, SYSCFG0);
+		if (i++ > 500) {
+			printf("register access fail.\n");
+			return -1;
+		}
+	} while ((tmp & SCKE) != SCKE);
+#endif	/* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
+
+	return 0;
+}
+
+static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
+{
+	r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+	udelay(1);
+#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+	r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+	r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+	r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+#endif
+}
+
+static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
+{
+	u16 val;
+
+	val = port ? DRPD : DCFM | DRPD;
+	r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
+	r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+
+	r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port));
+}
+
+static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
+{
+	u16 val, tmp;
+
+	r8a66597_write(r8a66597, 0, get_intenb_reg(port));
+	r8a66597_write(r8a66597, 0, get_intsts_reg(port));
+
+	r8a66597_port_power(r8a66597, port, 0);
+
+	do {
+		tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+		udelay(640);
+	} while (tmp == EDGESTS);
+
+	val = port ? DRPD : DCFM | DRPD;
+	r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
+	r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+}
+
+static int enable_controller(struct r8a66597 *r8a66597)
+{
+	int ret, port;
+
+	ret = r8a66597_clock_enable(r8a66597);
+	if (ret < 0)
+		return ret;
+
+	r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+	r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+	r8a66597_bset(r8a66597, INTL, SOFCFG);
+	r8a66597_write(r8a66597, 0, INTENB0);
+	r8a66597_write(r8a66597, 0, INTENB1);
+	r8a66597_write(r8a66597, 0, INTENB2);
+
+	r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
+	r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
+	r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+	r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
+
+	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+		r8a66597_enable_port(r8a66597, port);
+
+	return 0;
+}
+
+static void disable_controller(struct r8a66597 *r8a66597)
+{
+	int i;
+
+	if (!(r8a66597_read(r8a66597, SYSCFG0) & USBE))
+		return;
+
+	r8a66597_write(r8a66597, 0, INTENB0);
+	r8a66597_write(r8a66597, 0, INTSTS0);
+
+	r8a66597_write(r8a66597, 0, D0FIFOSEL);
+	r8a66597_write(r8a66597, 0, D1FIFOSEL);
+	r8a66597_write(r8a66597, 0, DCPCFG);
+	r8a66597_write(r8a66597, 0x40, DCPMAXP);
+	r8a66597_write(r8a66597, 0, DCPCTR);
+
+	for (i = 0; i <= 10; i++)
+		r8a66597_write(r8a66597, 0, get_devadd_addr(i));
+	for (i = 1; i <= 5; i++) {
+		r8a66597_write(r8a66597, 0, get_pipetre_addr(i));
+		r8a66597_write(r8a66597, 0, get_pipetrn_addr(i));
+	}
+	for (i = 1; i < R8A66597_MAX_NUM_PIPE; i++) {
+		r8a66597_write(r8a66597, 0, get_pipectr_addr(i));
+		r8a66597_write(r8a66597, i, PIPESEL);
+		r8a66597_write(r8a66597, 0, PIPECFG);
+		r8a66597_write(r8a66597, 0, PIPEBUF);
+		r8a66597_write(r8a66597, 0, PIPEMAXP);
+		r8a66597_write(r8a66597, 0, PIPEPERI);
+	}
+
+	for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++)
+		r8a66597_disable_port(r8a66597, i);
+
+	r8a66597_clock_disable(r8a66597);
+}
+
+static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
+			      u16 mask, u16 loop)
+{
+	u16 tmp;
+	int i = 0;
+
+	do {
+		tmp = r8a66597_read(r8a66597, reg);
+		if (i++ > 1000000) {
+			printf("register%lx, loop %x is timeout\n", reg, loop);
+			break;
+		}
+	} while ((tmp & mask) != loop);
+}
+
+static void pipe_buffer_setting(struct r8a66597 *r8a66597,
+				struct usb_device *dev, unsigned long pipe)
+{
+	u16 val = 0;
+	u16 pipenum, bufnum, maxpacket;
+
+	if (usb_pipein(pipe)) {
+		pipenum = BULK_IN_PIPENUM;
+		bufnum = BULK_IN_BUFNUM;
+		maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
+	} else {
+		pipenum = BULK_OUT_PIPENUM;
+		bufnum = BULK_OUT_BUFNUM;
+		maxpacket = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
+	}
+
+	if (r8a66597->pipe_config & (1 << pipenum))
+		return;
+	r8a66597->pipe_config |= (1 << pipenum);
+
+	r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(pipenum));
+	r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(pipenum));
+	r8a66597_write(r8a66597, pipenum, PIPESEL);
+
+	/* FIXME: This driver support bulk transfer only. */
+	if (!usb_pipein(pipe))
+		val |= R8A66597_DIR;
+	else
+		val |= R8A66597_SHTNAK;
+	val |= R8A66597_BULK | R8A66597_DBLB | usb_pipeendpoint(pipe);
+	r8a66597_write(r8a66597, val, PIPECFG);
+
+	r8a66597_write(r8a66597, (8 << 10) | bufnum, PIPEBUF);
+	r8a66597_write(r8a66597, make_devsel(usb_pipedevice(pipe)) |
+				 maxpacket, PIPEMAXP);
+	r8a66597_write(r8a66597, 0, PIPEPERI);
+	r8a66597_write(r8a66597, SQCLR, get_pipectr_addr(pipenum));
+}
+
+static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
+			     struct devrequest *setup)
+{
+	int i;
+	unsigned short *p = (unsigned short *)setup;
+	unsigned long setup_addr = USBREQ;
+	u16 intsts1;
+	int timeout = 3000;
+	u16 devsel = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum;
+
+	r8a66597_write(r8a66597, make_devsel(devsel) |
+				 (8 << dev->maxpacketsize), DCPMAXP);
+	r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1);
+
+	for (i = 0; i < 4; i++) {
+		r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr);
+		setup_addr += 2;
+	}
+	r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
+	r8a66597_write(r8a66597, SUREQ, DCPCTR);
+
+	while (1) {
+		intsts1 = r8a66597_read(r8a66597, INTSTS1);
+		if (intsts1 & SACK)
+			break;
+		if (intsts1 & SIGN) {
+			printf("setup packet send error\n");
+			return -1;
+		}
+		if (timeout-- < 0) {
+			printf("setup packet timeout\n");
+			return -1;
+		}
+		udelay(500);
+	}
+
+	return 0;
+}
+
+static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
+			    unsigned long pipe, void *buffer, int transfer_len)
+{
+	u16 tmp, bufsize;
+	u16 *buf;
+	size_t size;
+
+	R8A66597_DPRINT("%s\n", __func__);
+
+	r8a66597_mdfy(r8a66597, MBW | BULK_OUT_PIPENUM,
+			MBW | CURPIPE, CFIFOSEL);
+	r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, BULK_OUT_PIPENUM);
+	tmp = r8a66597_read(r8a66597, CFIFOCTR);
+	if ((tmp & FRDY) == 0) {
+		printf("%s FRDY is not set (%x)\n", __func__, tmp);
+		return -1;
+	}
+
+	/* prepare parameters */
+	bufsize = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
+	buf = (u16 *)(buffer + dev->act_len);
+	size = min((int)bufsize, transfer_len - dev->act_len);
+
+	/* write fifo */
+	r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
+	if (buffer) {
+		r8a66597_write_fifo(r8a66597, CFIFO, buf, size);
+		r8a66597_write(r8a66597, BVAL, CFIFOCTR);
+	}
+
+	/* update parameters */
+	dev->act_len += size;
+
+	r8a66597_mdfy(r8a66597, PID_BUF, PID,
+			get_pipectr_addr(BULK_OUT_PIPENUM));
+
+	while (!(r8a66597_read(r8a66597, BEMPSTS) & (1 << BULK_OUT_PIPENUM)))
+		if (ctrlc())
+			return -1;
+	r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
+
+	if (dev->act_len >= transfer_len)
+		r8a66597_mdfy(r8a66597, PID_NAK, PID,
+				get_pipectr_addr(BULK_OUT_PIPENUM));
+
+	return 0;
+}
+
+static int receive_bulk_packet(struct r8a66597 *r8a66597,
+			       struct usb_device *dev,
+			       unsigned long pipe,
+			       void *buffer, int transfer_len)
+{
+	u16 tmp;
+	u16 *buf;
+	const u16 pipenum = BULK_IN_PIPENUM;
+	int rcv_len;
+	int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
+
+	R8A66597_DPRINT("%s\n", __func__);
+
+	/* prepare */
+	if (dev->act_len == 0) {
+		r8a66597_mdfy(r8a66597, PID_NAK, PID,
+				get_pipectr_addr(pipenum));
+		r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
+
+		r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum));
+		r8a66597_write(r8a66597,
+				(transfer_len + maxpacket - 1) / maxpacket,
+				get_pipetrn_addr(pipenum));
+		r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum));
+
+		r8a66597_mdfy(r8a66597, PID_BUF, PID,
+				get_pipectr_addr(pipenum));
+	}
+
+	r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
+	r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
+
+	while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum)))
+		if (ctrlc())
+			return -1;
+	r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
+
+	tmp = r8a66597_read(r8a66597, CFIFOCTR);
+	if ((tmp & FRDY) == 0) {
+		printf("%s FRDY is not set. (%x)\n", __func__, tmp);
+		return -1;
+	}
+
+	buf = (u16 *)(buffer + dev->act_len);
+	rcv_len = tmp & DTLN;
+	dev->act_len += rcv_len;
+
+	if (buffer) {
+		if (rcv_len == 0)
+			r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+		else
+			r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len);
+	}
+
+	return 0;
+}
+
+static int receive_control_packet(struct r8a66597 *r8a66597,
+				  struct usb_device *dev,
+				  void *buffer, int transfer_len)
+{
+	u16 tmp;
+	int rcv_len;
+
+	/* FIXME: limit transfer size : 64byte or less */
+
+	r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+	r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+	r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+	r8a66597_bset(r8a66597, SQSET, DCPCTR);
+	r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+	r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
+
+	while (!(r8a66597_read(r8a66597, BRDYSTS) & 0x0001))
+		if (ctrlc())
+			return -1;
+	r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
+
+	r8a66597_mdfy(r8a66597, MBW, MBW | CURPIPE, CFIFOSEL);
+	r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+
+	tmp = r8a66597_read(r8a66597, CFIFOCTR);
+	if ((tmp & FRDY) == 0) {
+		printf("%s FRDY is not set. (%x)\n", __func__, tmp);
+		return -1;
+	}
+
+	rcv_len = tmp & DTLN;
+	dev->act_len += rcv_len;
+
+	r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
+
+	if (buffer) {
+		if (rcv_len == 0)
+			r8a66597_write(r8a66597, BCLR, DCPCTR);
+		else
+			r8a66597_read_fifo(r8a66597, CFIFO, buffer, rcv_len);
+	}
+
+	return 0;
+}
+
+static int send_status_packet(struct r8a66597 *r8a66597,
+			       unsigned long pipe)
+{
+	r8a66597_bset(r8a66597, SQSET, DCPCTR);
+	r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
+
+	if (usb_pipein(pipe)) {
+		r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+		r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+		r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+		r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+		r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR);
+	} else {
+		r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+		r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+		r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+		r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+	}
+	r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
+
+	while (!(r8a66597_read(r8a66597, BEMPSTS) & 0x0001))
+		if (ctrlc())
+			return -1;
+
+	return 0;
+}
+
+static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port)
+{
+	int count = R8A66597_MAX_SAMPLING;
+	unsigned short syssts, old_syssts;
+
+	R8A66597_DPRINT("%s\n", __func__);
+
+	old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
+	while (count > 0) {
+		wait_ms(R8A66597_RH_POLL_TIME);
+
+		syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
+		if (syssts == old_syssts) {
+			count--;
+		} else {
+			count = R8A66597_MAX_SAMPLING;
+			old_syssts = syssts;
+		}
+	}
+}
+
+static void r8a66597_bus_reset(struct r8a66597 *r8a66597, int port)
+{
+	wait_ms(10);
+	r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port));
+	wait_ms(50);
+	r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port));
+	wait_ms(50);
+}
+
+static int check_usb_device_connecting(struct r8a66597 *r8a66597)
+{
+	int timeout = 10000;	/* 100usec * 10000 = 1sec */
+	int i;
+
+	for (i = 0; i < 5; i++) {
+		/* check a usb cable connect */
+		while (!(r8a66597_read(r8a66597, INTSTS1) & ATTCH)) {
+			if (timeout-- < 0) {
+				printf("%s timeout.\n", __func__);
+				return -1;
+			}
+			udelay(100);
+		}
+
+		/* check a data line */
+		r8a66597_check_syssts(r8a66597, 0);
+
+		r8a66597_bus_reset(r8a66597, 0);
+		r8a66597->speed = get_rh_usb_speed(r8a66597, 0);
+
+		if (!(r8a66597_read(r8a66597, INTSTS1) & DTCH)) {
+			r8a66597->port_change = USB_PORT_STAT_C_CONNECTION;
+			r8a66597->port_status = USB_PORT_STAT_CONNECTION |
+						USB_PORT_STAT_ENABLE;
+			return 0;	/* success */
+		}
+
+		R8A66597_DPRINT("USB device has detached. retry = %d\n", i);
+		r8a66597_write(r8a66597, ~DTCH, INTSTS1);
+	}
+
+	return -1;	/* fail */
+}
+
+/* based on usb_ohci.c */
+#define min_t(type, x, y) \
+		({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+	0x12,	    /*	__u8  bLength; */
+	0x01,	    /*	__u8  bDescriptorType; Device */
+	0x10,	    /*	__u16 bcdUSB; v1.1 */
+	0x01,
+	0x09,	    /*	__u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,	    /*	__u8  bDeviceSubClass; */
+	0x00,	    /*	__u8  bDeviceProtocol; */
+	0x08,	    /*	__u8  bMaxPacketSize0; 8 Bytes */
+	0x00,	    /*	__u16 idVendor; */
+	0x00,
+	0x00,	    /*	__u16 idProduct; */
+	0x00,
+	0x00,	    /*	__u16 bcdDevice; */
+	0x00,
+	0x00,	    /*	__u8  iManufacturer; */
+	0x01,	    /*	__u8  iProduct; */
+	0x00,	    /*	__u8  iSerialNumber; */
+	0x01	    /*	__u8  bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+	0x09,	    /*	__u8  bLength; */
+	0x02,	    /*	__u8  bDescriptorType; Configuration */
+	0x19,	    /*	__u16 wTotalLength; */
+	0x00,
+	0x01,	    /*	__u8  bNumInterfaces; */
+	0x01,	    /*	__u8  bConfigurationValue; */
+	0x00,	    /*	__u8  iConfiguration; */
+	0x40,	    /*	__u8  bmAttributes; */
+
+	0x00,	    /*	__u8  MaxPower; */
+
+	/* interface */
+	0x09,	    /*	__u8  if_bLength; */
+	0x04,	    /*	__u8  if_bDescriptorType; Interface */
+	0x00,	    /*	__u8  if_bInterfaceNumber; */
+	0x00,	    /*	__u8  if_bAlternateSetting; */
+	0x01,	    /*	__u8  if_bNumEndpoints; */
+	0x09,	    /*	__u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,	    /*	__u8  if_bInterfaceSubClass; */
+	0x00,	    /*	__u8  if_bInterfaceProtocol; */
+	0x00,	    /*	__u8  if_iInterface; */
+
+	/* endpoint */
+	0x07,	    /*	__u8  ep_bLength; */
+	0x05,	    /*	__u8  ep_bDescriptorType; Endpoint */
+	0x81,	    /*	__u8  ep_bEndpointAddress; IN Endpoint 1 */
+	0x03,	    /*	__u8  ep_bmAttributes; Interrupt */
+	0x02,	    /*	__u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+	0x00,
+	0xff	    /*	__u8  ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+	0x04,			/*  __u8  bLength; */
+	0x03,			/*  __u8  bDescriptorType; String-descriptor */
+	0x09,			/*  __u8  lang ID */
+	0x04,			/*  __u8  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+	34,			/*  __u8  bLength; */
+	0x03,			/*  __u8  bDescriptorType; String-descriptor */
+	'R',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'8',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'A',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'6',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'6',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'5',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'9',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'7',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	' ',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'R',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'o',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'o',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	't',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'H',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'u',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'b',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+};
+
+static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+			void *buffer, int transfer_len, struct devrequest *cmd)
+{
+	struct r8a66597 *r8a66597 = &gr8a66597;
+	int leni = transfer_len;
+	int len = 0;
+	int stat = 0;
+	__u16 bmRType_bReq;
+	__u16 wValue;
+	__u16 wIndex;
+	__u16 wLength;
+	unsigned char data[32];
+
+	R8A66597_DPRINT("%s\n", __func__);
+
+	if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
+		printf("Root-Hub submit IRQ: NOT implemented");
+		return 0;
+	}
+
+	bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
+	wValue	      = cpu_to_le16 (cmd->value);
+	wIndex	      = cpu_to_le16 (cmd->index);
+	wLength	      = cpu_to_le16 (cmd->length);
+
+	switch (bmRType_bReq) {
+	case RH_GET_STATUS:
+		*(__u16 *)buffer = cpu_to_le16(1);
+		len = 2;
+		break;
+	case RH_GET_STATUS | RH_INTERFACE:
+		*(__u16 *)buffer = cpu_to_le16(0);
+		len = 2;
+		break;
+	case RH_GET_STATUS | RH_ENDPOINT:
+		*(__u16 *)buffer = cpu_to_le16(0);
+		len = 2;
+		break;
+	case RH_GET_STATUS | RH_CLASS:
+		*(__u32 *)buffer = cpu_to_le32(0);
+		len = 4;
+		break;
+	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+		*(__u32 *)buffer = cpu_to_le32(r8a66597->port_status |
+						(r8a66597->port_change << 16));
+		len = 4;
+		break;
+	case RH_CLEAR_FEATURE | RH_ENDPOINT:
+	case RH_CLEAR_FEATURE | RH_CLASS:
+		break;
+
+	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+		case RH_C_PORT_CONNECTION:
+			r8a66597->port_change &= ~USB_PORT_STAT_C_CONNECTION;
+			break;
+		}
+		break;
+
+	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+		case (RH_PORT_SUSPEND):
+			break;
+		case (RH_PORT_RESET):
+			r8a66597_bus_reset(r8a66597, 0);
+			break;
+		case (RH_PORT_POWER):
+			break;
+		case (RH_PORT_ENABLE):
+			break;
+		}
+		break;
+	case RH_SET_ADDRESS:
+		gr8a66597.rh_devnum = wValue;
+		break;
+	case RH_GET_DESCRIPTOR:
+		switch ((wValue & 0xff00) >> 8) {
+		case (0x01): /* device descriptor */
+			len = min_t(unsigned int,
+				  leni,
+				  min_t(unsigned int,
+				      sizeof(root_hub_dev_des),
+				      wLength));
+			memcpy(buffer, root_hub_dev_des, len);
+			break;
+		case (0x02): /* configuration descriptor */
+			len = min_t(unsigned int,
+				  leni,
+				  min_t(unsigned int,
+				      sizeof(root_hub_config_des),
+				      wLength));
+			memcpy(buffer, root_hub_config_des, len);
+			break;
+		case (0x03): /* string descriptors */
+			if (wValue == 0x0300) {
+				len = min_t(unsigned int,
+					  leni,
+					  min_t(unsigned int,
+					      sizeof(root_hub_str_index0),
+					      wLength));
+				memcpy(buffer, root_hub_str_index0, len);
+			}
+			if (wValue == 0x0301) {
+				len = min_t(unsigned int,
+					  leni,
+					  min_t(unsigned int,
+					      sizeof(root_hub_str_index1),
+					      wLength));
+				memcpy(buffer, root_hub_str_index1, len);
+			}
+			break;
+		default:
+			stat = USB_ST_STALLED;
+		}
+		break;
+
+	case RH_GET_DESCRIPTOR | RH_CLASS:
+	{
+		__u32 temp = 0x00000001;
+
+		data[0] = 9;		/* min length; */
+		data[1] = 0x29;
+		data[2] = temp & RH_A_NDP;
+		data[3] = 0;
+		if (temp & RH_A_PSM)
+			data[3] |= 0x1;
+		if (temp & RH_A_NOCP)
+			data[3] |= 0x10;
+		else if (temp & RH_A_OCPM)
+			data[3] |= 0x8;
+
+		/* corresponds to data[4-7] */
+		data[5] = (temp & RH_A_POTPGT) >> 24;
+		data[7] = temp & RH_B_DR;
+		if (data[2] < 7) {
+			data[8] = 0xff;
+		} else {
+			data[0] += 2;
+			data[8] = (temp & RH_B_DR) >> 8;
+			data[10] = data[9] = 0xff;
+		}
+
+		len = min_t(unsigned int, leni,
+			    min_t(unsigned int, data[0], wLength));
+		memcpy(buffer, data, len);
+		break;
+	}
+
+	case RH_GET_CONFIGURATION:
+		*(__u8 *) buffer = 0x01;
+		len = 1;
+		break;
+	case RH_SET_CONFIGURATION:
+		break;
+	default:
+		dbg("unsupported root hub command");
+		stat = USB_ST_STALLED;
+	}
+
+	wait_ms(1);
+
+	len = min_t(int, len, leni);
+
+	dev->act_len = len;
+	dev->status = stat;
+
+	return stat;
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		    int transfer_len)
+{
+	struct r8a66597 *r8a66597 = &gr8a66597;
+	int ret = 0;
+
+	R8A66597_DPRINT("%s\n", __func__);
+	R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n",
+			pipe, buffer, transfer_len, dev->devnum);
+
+	set_devadd_reg(r8a66597, dev->devnum, r8a66597->speed, 0, 0, 0);
+
+	pipe_buffer_setting(r8a66597, dev, pipe);
+
+	dev->act_len = 0;
+	while (dev->act_len < transfer_len && ret == 0) {
+		if (ctrlc())
+			return -1;
+
+		if (usb_pipein(pipe))
+			ret = receive_bulk_packet(r8a66597, dev, pipe, buffer,
+							transfer_len);
+		else
+			ret = send_bulk_packet(r8a66597, dev, pipe, buffer,
+							transfer_len);
+	}
+
+	if (ret == 0)
+		dev->status = 0;
+
+	return ret;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe,
+		       void *buffer, int transfer_len, struct devrequest *setup)
+{
+	struct r8a66597 *r8a66597 = &gr8a66597;
+	u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ?
+					0 : dev->devnum;
+
+	R8A66597_DPRINT("%s\n", __func__);
+	if (usb_pipedevice(pipe) == r8a66597->rh_devnum)
+		return r8a66597_submit_rh_msg(dev, pipe, buffer, transfer_len,
+						setup);
+
+	R8A66597_DPRINT("%s: setup\n", __func__);
+	set_devadd_reg(r8a66597, r8a66597_address, r8a66597->speed, 0, 0, 0);
+
+	if (send_setup_packet(r8a66597, dev, setup) < 0) {
+		printf("setup packet send error\n");
+		return -1;
+	}
+
+	if (usb_pipein(pipe))
+		if (receive_control_packet(r8a66597, dev, buffer,
+						transfer_len) < 0)
+			return -1;
+
+	if (send_status_packet(r8a66597, pipe) < 0)
+		return -1;
+
+	dev->status = 0;
+
+	return 0;
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+			int transfer_len, int interval)
+{
+	/* no implement */
+	R8A66597_DPRINT("%s\n", __func__);
+	return 0;
+}
+
+void usb_event_poll(void)
+{
+	/* no implement */
+	R8A66597_DPRINT("%s\n", __func__);
+}
+
+int usb_lowlevel_init(void)
+{
+	struct r8a66597 *r8a66597 = &gr8a66597;
+
+	R8A66597_DPRINT("%s\n", __func__);
+
+	memset(r8a66597, 0, sizeof(r8a66597));
+	r8a66597->reg = CONFIG_R8A66597_BASE_ADDR;
+
+	disable_controller(r8a66597);
+	wait_ms(100);
+
+	enable_controller(r8a66597);
+	r8a66597_port_power(r8a66597, 0 , 1);
+
+	/* check usb device */
+	check_usb_device_connecting(r8a66597);
+
+	wait_ms(50);
+
+	return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+	disable_controller(&gr8a66597);
+
+	return 0;
+}
+
+#endif	/* CONFIG_USB_R8A66597_HCD */
+
diff --git a/drivers/usb/r8a66597.h b/drivers/usb/r8a66597.h
new file mode 100644
index 0000000..54a1f26
--- /dev/null
+++ b/drivers/usb/r8a66597.h
@@ -0,0 +1,663 @@
+/*
+ * R8A66597 HCD (Host Controller Driver) for u-boot
+ *
+ * Copyright (C) 2008  Yoshihiro Shimoda <shimoda.yoshihiro at renesas.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __R8A66597_H__
+#define __R8A66597_H__
+
+#define SYSCFG0		0x00
+#define SYSCFG1		0x02
+#define SYSSTS0		0x04
+#define SYSSTS1		0x06
+#define DVSTCTR0	0x08
+#define DVSTCTR1	0x0A
+#define TESTMODE	0x0C
+#define PINCFG		0x0E
+#define DMA0CFG		0x10
+#define DMA1CFG		0x12
+#define CFIFO		0x14
+#define D0FIFO		0x18
+#define D1FIFO		0x1C
+#define CFIFOSEL	0x20
+#define CFIFOCTR	0x22
+#define CFIFOSIE	0x24
+#define D0FIFOSEL	0x28
+#define D0FIFOCTR	0x2A
+#define D1FIFOSEL	0x2C
+#define D1FIFOCTR	0x2E
+#define INTENB0		0x30
+#define INTENB1		0x32
+#define INTENB2		0x34
+#define BRDYENB		0x36
+#define NRDYENB		0x38
+#define BEMPENB		0x3A
+#define SOFCFG		0x3C
+#define INTSTS0		0x40
+#define INTSTS1		0x42
+#define INTSTS2		0x44
+#define BRDYSTS		0x46
+#define NRDYSTS		0x48
+#define BEMPSTS		0x4A
+#define FRMNUM		0x4C
+#define UFRMNUM		0x4E
+#define USBADDR		0x50
+#define USBREQ		0x54
+#define USBVAL		0x56
+#define USBINDX		0x58
+#define USBLENG		0x5A
+#define DCPCFG		0x5C
+#define DCPMAXP		0x5E
+#define DCPCTR		0x60
+#define PIPESEL		0x64
+#define PIPECFG		0x68
+#define PIPEBUF		0x6A
+#define PIPEMAXP	0x6C
+#define PIPEPERI	0x6E
+#define PIPE1CTR	0x70
+#define PIPE2CTR	0x72
+#define PIPE3CTR	0x74
+#define PIPE4CTR	0x76
+#define PIPE5CTR	0x78
+#define PIPE6CTR	0x7A
+#define PIPE7CTR	0x7C
+#define PIPE8CTR	0x7E
+#define PIPE9CTR	0x80
+#define PIPE1TRE	0x90
+#define PIPE1TRN	0x92
+#define PIPE2TRE	0x94
+#define PIPE2TRN	0x96
+#define PIPE3TRE	0x98
+#define PIPE3TRN	0x9A
+#define PIPE4TRE	0x9C
+#define	PIPE4TRN	0x9E
+#define	PIPE5TRE	0xA0
+#define	PIPE5TRN	0xA2
+#define DEVADD0		0xD0
+#define DEVADD1		0xD2
+#define DEVADD2		0xD4
+#define DEVADD3		0xD6
+#define DEVADD4		0xD8
+#define DEVADD5		0xDA
+#define DEVADD6		0xDC
+#define DEVADD7		0xDE
+#define DEVADD8		0xE0
+#define DEVADD9		0xE2
+#define DEVADDA		0xE4
+
+/* System Configuration Control Register */
+#define	XTAL		0xC000	/* b15-14: Crystal selection */
+#define	  XTAL48	 0x8000	  /* 48MHz */
+#define	  XTAL24	 0x4000	  /* 24MHz */
+#define	  XTAL12	 0x0000	  /* 12MHz */
+#define	XCKE		0x2000	/* b13: External clock enable */
+#define	PLLC		0x0800	/* b11: PLL control */
+#define	SCKE		0x0400	/* b10: USB clock enable */
+#define	PCSDIS		0x0200	/* b9: not CS wakeup */
+#define	LPSME		0x0100	/* b8: Low power sleep mode */
+#define	HSE		0x0080	/* b7: Hi-speed enable */
+#define	DCFM		0x0040	/* b6: Controller function select  */
+#define	DRPD		0x0020	/* b5: D+/- pull down control */
+#define	DPRPU		0x0010	/* b4: D+ pull up control */
+#define	USBE		0x0001	/* b0: USB module operation enable */
+
+/* System Configuration Status Register */
+#define	OVCBIT		0x8000	/* b15-14: Over-current bit */
+#define	OVCMON		0xC000	/* b15-14: Over-current monitor */
+#define	SOFEA		0x0020	/* b5: SOF monitor */
+#define	IDMON		0x0004	/* b3: ID-pin monitor */
+#define	LNST		0x0003	/* b1-0: D+, D- line status */
+#define	  SE1		 0x0003	  /* SE1 */
+#define	  FS_KSTS	 0x0002	  /* Full-Speed K State */
+#define	  FS_JSTS	 0x0001	  /* Full-Speed J State */
+#define	  LS_JSTS	 0x0002	  /* Low-Speed J State */
+#define	  LS_KSTS	 0x0001	  /* Low-Speed K State */
+#define	  SE0		 0x0000	  /* SE0 */
+
+/* Device State Control Register */
+#define	EXTLP0		0x0400	/* b10: External port */
+#define	VBOUT		0x0200	/* b9: VBUS output */
+#define	WKUP		0x0100	/* b8: Remote wakeup */
+#define	RWUPE		0x0080	/* b7: Remote wakeup sense */
+#define	USBRST		0x0040	/* b6: USB reset enable */
+#define	RESUME		0x0020	/* b5: Resume enable */
+#define	UACT		0x0010	/* b4: USB bus enable */
+#define	RHST		0x0007	/* b1-0: Reset handshake status */
+#define	  HSPROC	 0x0004	  /* HS handshake is processing */
+#define	  HSMODE	 0x0003	  /* Hi-Speed mode */
+#define	  FSMODE	 0x0002	  /* Full-Speed mode */
+#define	  LSMODE	 0x0001	  /* Low-Speed mode */
+#define	  UNDECID	 0x0000	  /* Undecided */
+
+/* Test Mode Register */
+#define	UTST			0x000F	/* b3-0: Test select */
+#define	  H_TST_PACKET		 0x000C	  /* HOST TEST Packet */
+#define	  H_TST_SE0_NAK		 0x000B	  /* HOST TEST SE0 NAK */
+#define	  H_TST_K		 0x000A	  /* HOST TEST K */
+#define	  H_TST_J		 0x0009	  /* HOST TEST J */
+#define	  H_TST_NORMAL		 0x0000	  /* HOST Normal Mode */
+#define	  P_TST_PACKET		 0x0004	  /* PERI TEST Packet */
+#define	  P_TST_SE0_NAK		 0x0003	  /* PERI TEST SE0 NAK */
+#define	  P_TST_K		 0x0002	  /* PERI TEST K */
+#define	  P_TST_J		 0x0001	  /* PERI TEST J */
+#define	  P_TST_NORMAL		 0x0000	  /* PERI Normal Mode */
+
+/* Data Pin Configuration Register */
+#define	LDRV			0x8000	/* b15: Drive Current Adjust */
+#define	  VIF1			  0x0000		/* VIF = 1.8V */
+#define	  VIF3			  0x8000		/* VIF = 3.3V */
+#define	INTA			0x0001	/* b1: USB INT-pin active */
+
+/* DMAx Pin Configuration Register */
+#define	DREQA			0x4000	/* b14: Dreq active select */
+#define	BURST			0x2000	/* b13: Burst mode */
+#define	DACKA			0x0400	/* b10: Dack active select */
+#define	DFORM			0x0380	/* b9-7: DMA mode select */
+#define	  CPU_ADR_RD_WR		 0x0000	  /* Address + RD/WR mode (CPU bus) */
+#define	  CPU_DACK_RD_WR	 0x0100	  /* DACK + RD/WR mode (CPU bus) */
+#define	  CPU_DACK_ONLY		 0x0180	  /* DACK only mode (CPU bus) */
+#define	  SPLIT_DACK_ONLY	 0x0200	  /* DACK only mode (SPLIT bus) */
+#define	DENDA			0x0040	/* b6: Dend active select */
+#define	PKTM			0x0020	/* b5: Packet mode */
+#define	DENDE			0x0010	/* b4: Dend enable */
+#define	OBUS			0x0004	/* b2: OUTbus mode */
+
+/* CFIFO/DxFIFO Port Select Register */
+#define	RCNT		0x8000	/* b15: Read count mode */
+#define	REW		0x4000	/* b14: Buffer rewind */
+#define	DCLRM		0x2000	/* b13: DMA buffer clear mode */
+#define	DREQE		0x1000	/* b12: DREQ output enable */
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+#define	MBW		0x0800
+#else
+#define	MBW		0x0400	/* b10: Maximum bit width for FIFO access */
+#endif
+#define	  MBW_8		 0x0000	  /*  8bit */
+#define	  MBW_16	 0x0400	  /* 16bit */
+#define	BIGEND		0x0100	/* b8: Big endian mode */
+#define	  BYTE_LITTLE	 0x0000		/* little dendian */
+#define	  BYTE_BIG	 0x0100		/* big endifan */
+#define	ISEL		0x0020	/* b5: DCP FIFO port direction select */
+#define	CURPIPE		0x000F	/* b2-0: PIPE select */
+
+/* CFIFO/DxFIFO Port Control Register */
+#define	BVAL		0x8000	/* b15: Buffer valid flag */
+#define	BCLR		0x4000	/* b14: Buffer clear */
+#define	FRDY		0x2000	/* b13: FIFO ready */
+#define	DTLN		0x0FFF	/* b11-0: FIFO received data length */
+
+/* Interrupt Enable Register 0 */
+#define	VBSE	0x8000	/* b15: VBUS interrupt */
+#define	RSME	0x4000	/* b14: Resume interrupt */
+#define	SOFE	0x2000	/* b13: Frame update interrupt */
+#define	DVSE	0x1000	/* b12: Device state transition interrupt */
+#define	CTRE	0x0800	/* b11: Control transfer stage transition interrupt */
+#define	BEMPE	0x0400	/* b10: Buffer empty interrupt */
+#define	NRDYE	0x0200	/* b9: Buffer not ready interrupt */
+#define	BRDYE	0x0100	/* b8: Buffer ready interrupt */
+
+/* Interrupt Enable Register 1 */
+#define	OVRCRE		0x8000	/* b15: Over-current interrupt */
+#define	BCHGE		0x4000	/* b14: USB us chenge interrupt */
+#define	DTCHE		0x1000	/* b12: Detach sense interrupt */
+#define	ATTCHE		0x0800	/* b11: Attach sense interrupt */
+#define	EOFERRE		0x0040	/* b6: EOF error interrupt */
+#define	SIGNE		0x0020	/* b5: SETUP IGNORE interrupt */
+#define	SACKE		0x0010	/* b4: SETUP ACK interrupt */
+
+/* BRDY Interrupt Enable/Status Register */
+#define	BRDY9		0x0200	/* b9: PIPE9 */
+#define	BRDY8		0x0100	/* b8: PIPE8 */
+#define	BRDY7		0x0080	/* b7: PIPE7 */
+#define	BRDY6		0x0040	/* b6: PIPE6 */
+#define	BRDY5		0x0020	/* b5: PIPE5 */
+#define	BRDY4		0x0010	/* b4: PIPE4 */
+#define	BRDY3		0x0008	/* b3: PIPE3 */
+#define	BRDY2		0x0004	/* b2: PIPE2 */
+#define	BRDY1		0x0002	/* b1: PIPE1 */
+#define	BRDY0		0x0001	/* b1: PIPE0 */
+
+/* NRDY Interrupt Enable/Status Register */
+#define	NRDY9		0x0200	/* b9: PIPE9 */
+#define	NRDY8		0x0100	/* b8: PIPE8 */
+#define	NRDY7		0x0080	/* b7: PIPE7 */
+#define	NRDY6		0x0040	/* b6: PIPE6 */
+#define	NRDY5		0x0020	/* b5: PIPE5 */
+#define	NRDY4		0x0010	/* b4: PIPE4 */
+#define	NRDY3		0x0008	/* b3: PIPE3 */
+#define	NRDY2		0x0004	/* b2: PIPE2 */
+#define	NRDY1		0x0002	/* b1: PIPE1 */
+#define	NRDY0		0x0001	/* b1: PIPE0 */
+
+/* BEMP Interrupt Enable/Status Register */
+#define	BEMP9		0x0200	/* b9: PIPE9 */
+#define	BEMP8		0x0100	/* b8: PIPE8 */
+#define	BEMP7		0x0080	/* b7: PIPE7 */
+#define	BEMP6		0x0040	/* b6: PIPE6 */
+#define	BEMP5		0x0020	/* b5: PIPE5 */
+#define	BEMP4		0x0010	/* b4: PIPE4 */
+#define	BEMP3		0x0008	/* b3: PIPE3 */
+#define	BEMP2		0x0004	/* b2: PIPE2 */
+#define	BEMP1		0x0002	/* b1: PIPE1 */
+#define	BEMP0		0x0001	/* b0: PIPE0 */
+
+/* SOF Pin Configuration Register */
+#define	TRNENSEL	0x0100	/* b8: Select transaction enable period */
+#define	BRDYM		0x0040	/* b6: BRDY clear timing */
+#define	INTL		0x0020	/* b5: Interrupt sense select */
+#define	EDGESTS		0x0010	/* b4:  */
+#define	SOFMODE		0x000C	/* b3-2: SOF pin select */
+#define	  SOF_125US	 0x0008	  /* SOF OUT 125us Frame Signal */
+#define	  SOF_1MS	 0x0004	  /* SOF OUT 1ms Frame Signal */
+#define	  SOF_DISABLE	 0x0000	  /* SOF OUT Disable */
+
+/* Interrupt Status Register 0 */
+#define	VBINT	0x8000	/* b15: VBUS interrupt */
+#define	RESM	0x4000	/* b14: Resume interrupt */
+#define	SOFR	0x2000	/* b13: SOF frame update interrupt */
+#define	DVST	0x1000	/* b12: Device state transition interrupt */
+#define	CTRT	0x0800	/* b11: Control transfer stage transition interrupt */
+#define	BEMP	0x0400	/* b10: Buffer empty interrupt */
+#define	NRDY	0x0200	/* b9: Buffer not ready interrupt */
+#define	BRDY	0x0100	/* b8: Buffer ready interrupt */
+#define	VBSTS	0x0080	/* b7: VBUS input port */
+#define	DVSQ	0x0070	/* b6-4: Device state */
+#define	  DS_SPD_CNFG	 0x0070	  /* Suspend Configured */
+#define	  DS_SPD_ADDR	 0x0060	  /* Suspend Address */
+#define	  DS_SPD_DFLT	 0x0050	  /* Suspend Default */
+#define	  DS_SPD_POWR	 0x0040	  /* Suspend Powered */
+#define	  DS_SUSP	 0x0040	  /* Suspend */
+#define	  DS_CNFG	 0x0030	  /* Configured */
+#define	  DS_ADDS	 0x0020	  /* Address */
+#define	  DS_DFLT	 0x0010	  /* Default */
+#define	  DS_POWR	 0x0000	  /* Powered */
+#define	DVSQS		0x0030	/* b5-4: Device state */
+#define	VALID		0x0008	/* b3: Setup packet detected flag */
+#define	CTSQ		0x0007	/* b2-0: Control transfer stage */
+#define	  CS_SQER	 0x0006	  /* Sequence error */
+#define	  CS_WRND	 0x0005	  /* Control write nodata status stage */
+#define	  CS_WRSS	 0x0004	  /* Control write status stage */
+#define	  CS_WRDS	 0x0003	  /* Control write data stage */
+#define	  CS_RDSS	 0x0002	  /* Control read status stage */
+#define	  CS_RDDS	 0x0001	  /* Control read data stage */
+#define	  CS_IDST	 0x0000	  /* Idle or setup stage */
+
+/* Interrupt Status Register 1 */
+#define	OVRCR		0x8000	/* b15: Over-current interrupt */
+#define	BCHG		0x4000	/* b14: USB bus chenge interrupt */
+#define	DTCH		0x1000	/* b12: Detach sense interrupt */
+#define	ATTCH		0x0800	/* b11: Attach sense interrupt */
+#define	EOFERR		0x0040	/* b6: EOF-error interrupt */
+#define	SIGN		0x0020	/* b5: Setup ignore interrupt */
+#define	SACK		0x0010	/* b4: Setup acknowledge interrupt */
+
+/* Frame Number Register */
+#define	OVRN		0x8000	/* b15: Overrun error */
+#define	CRCE		0x4000	/* b14: Received data error */
+#define	FRNM		0x07FF	/* b10-0: Frame number */
+
+/* Micro Frame Number Register */
+#define	UFRNM		0x0007	/* b2-0: Micro frame number */
+
+/* Default Control Pipe Maxpacket Size Register */
+/* Pipe Maxpacket Size Register */
+#define	DEVSEL	0xF000	/* b15-14: Device address select */
+#define	MAXP	0x007F	/* b6-0: Maxpacket size of default control pipe */
+
+/* Default Control Pipe Control Register */
+#define	BSTS		0x8000	/* b15: Buffer status */
+#define	SUREQ		0x4000	/* b14: Send USB request  */
+#define	CSCLR		0x2000	/* b13: complete-split status clear */
+#define	CSSTS		0x1000	/* b12: complete-split status */
+#define	SUREQCLR	0x0800	/* b11: stop setup request */
+#define	SQCLR		0x0100	/* b8: Sequence toggle bit clear */
+#define	SQSET		0x0080	/* b7: Sequence toggle bit set */
+#define	SQMON		0x0040	/* b6: Sequence toggle bit monitor */
+#define	PBUSY		0x0020	/* b5: pipe busy */
+#define	PINGE		0x0010	/* b4: ping enable */
+#define	CCPL		0x0004	/* b2: Enable control transfer complete */
+#define	PID		0x0003	/* b1-0: Response PID */
+#define	  PID_STALL11	 0x0003	  /* STALL */
+#define	  PID_STALL	 0x0002	  /* STALL */
+#define	  PID_BUF	 0x0001	  /* BUF */
+#define	  PID_NAK	 0x0000	  /* NAK */
+
+/* Pipe Window Select Register */
+#define	PIPENM		0x0007	/* b2-0: Pipe select */
+
+/* Pipe Configuration Register */
+#define	R8A66597_TYP	0xC000	/* b15-14: Transfer type */
+#define	  R8A66597_ISO	 0xC000		  /* Isochronous */
+#define	  R8A66597_INT	 0x8000		  /* Interrupt */
+#define	  R8A66597_BULK	 0x4000		  /* Bulk */
+#define	R8A66597_BFRE	0x0400	/* b10: Buffer ready interrupt mode select */
+#define	R8A66597_DBLB	0x0200	/* b9: Double buffer mode select */
+#define	R8A66597_CNTMD	0x0100	/* b8: Continuous transfer mode select */
+#define	R8A66597_SHTNAK	0x0080	/* b7: Transfer end NAK */
+#define	R8A66597_DIR	0x0010	/* b4: Transfer direction select */
+#define	R8A66597_EPNUM	0x000F	/* b3-0: Eendpoint number select */
+
+/* Pipe Buffer Configuration Register */
+#define	BUFSIZE		0x7C00	/* b14-10: Pipe buffer size */
+#define	BUFNMB		0x007F	/* b6-0: Pipe buffer number */
+#define	PIPE0BUF	256
+#define	PIPExBUF	64
+
+/* Pipe Maxpacket Size Register */
+#define	MXPS		0x07FF	/* b10-0: Maxpacket size */
+
+/* Pipe Cycle Configuration Register */
+#define	IFIS	0x1000	/* b12: Isochronous in-buffer flush mode select */
+#define	IITV	0x0007	/* b2-0: Isochronous interval */
+
+/* Pipex Control Register */
+#define	BSTS	0x8000	/* b15: Buffer status */
+#define	INBUFM	0x4000	/* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define	CSCLR	0x2000	/* b13: complete-split status clear */
+#define	CSSTS	0x1000	/* b12: complete-split status */
+#define	ATREPM	0x0400	/* b10: Auto repeat mode */
+#define	ACLRM	0x0200	/* b9: Out buffer auto clear mode */
+#define	SQCLR	0x0100	/* b8: Sequence toggle bit clear */
+#define	SQSET	0x0080	/* b7: Sequence toggle bit set */
+#define	SQMON	0x0040	/* b6: Sequence toggle bit monitor */
+#define	PBUSY	0x0020	/* b5: pipe busy */
+#define	PID	0x0003	/* b1-0: Response PID */
+
+/* PIPExTRE */
+#define	TRENB		0x0200	/* b9: Transaction counter enable */
+#define	TRCLR		0x0100	/* b8: Transaction counter clear */
+
+/* PIPExTRN */
+#define	TRNCNT		0xFFFF	/* b15-0: Transaction counter */
+
+/* DEVADDx */
+#define	UPPHUB		0x7800
+#define	HUBPORT		0x0700
+#define	USBSPD		0x00C0
+#define	RTPORT		0x0001
+
+#define R8A66597_MAX_NUM_PIPE		10
+#define R8A66597_BUF_BSIZE		8
+#define R8A66597_MAX_DEVICE		10
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+#define R8A66597_MAX_ROOT_HUB		1
+#else
+#define R8A66597_MAX_ROOT_HUB		2
+#endif
+#define R8A66597_MAX_SAMPLING		5
+#define R8A66597_RH_POLL_TIME		10
+
+#define BULK_IN_PIPENUM		3
+#define BULK_IN_BUFNUM		8
+
+#define BULK_OUT_PIPENUM	4
+#define BULK_OUT_BUFNUM		40
+
+#define check_bulk_or_isoc(pipenum)	((pipenum >= 1 && pipenum <= 5))
+#define check_interrupt(pipenum)	((pipenum >= 6 && pipenum <= 9))
+#define make_devsel(addr)		(addr << 12)
+
+struct r8a66597 {
+	unsigned long reg;
+	unsigned short pipe_config;	/* bit field */
+	unsigned short port_status;
+	unsigned short port_change;
+	u16 speed;	/* HSMODE or FSMODE or LSMODE */
+	unsigned char rh_devnum;
+};
+
+static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
+{
+	return inw(r8a66597->reg + offset);
+}
+
+static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+				      unsigned long offset, void *buf,
+				      int len)
+{
+	int i;
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+	unsigned long fifoaddr = r8a66597->reg + offset;
+	unsigned long count;
+	unsigned long *p = buf;
+
+	count = len / 4;
+	for (i = 0; i < count; i++)
+		inl(p[i], r8a66597->reg + offset);
+
+	if (len & 0x00000003) {
+		unsigned long tmp = inl(fifoaddr);
+		memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
+	}
+#else
+	unsigned short *p = buf;
+
+	len = (len + 1) / 2;
+	for (i = 0; i < len; i++)
+		p[i] = inw(r8a66597->reg + offset);
+#endif
+}
+
+static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+				  unsigned long offset)
+{
+	outw(val, r8a66597->reg + offset);
+}
+
+static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+				       unsigned long offset, void *buf,
+				       int len)
+{
+	int i;
+	unsigned long fifoaddr = r8a66597->reg + offset;
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+	unsigned long count;
+	unsigned char *pb;
+	unsigned long *p = buf;
+
+	count = len / 4;
+	for (i = 0; i < count; i++)
+		outl(p[i], fifoaddr);
+
+	if (len & 0x00000003) {
+		pb = (unsigned char *)buf + count * 4;
+		for (i = 0; i < (len & 0x00000003); i++) {
+			if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
+				outb(pb[i], fifoaddr + i);
+			else
+				outb(pb[i], fifoaddr + 3 - i);
+		}
+	}
+#else
+	int odd = len & 0x0001;
+	unsigned short *p = buf;
+
+	len = len / 2;
+	for (i = 0; i < len; i++)
+		outw(p[i], fifoaddr);
+
+	if (odd) {
+		unsigned char *pb = (unsigned char *)(buf + len);
+		outb(*pb, fifoaddr);
+	}
+#endif
+}
+
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+				 u16 val, u16 pat, unsigned long offset)
+{
+	u16 tmp;
+	tmp = r8a66597_read(r8a66597, offset);
+	tmp = tmp & (~pat);
+	tmp = tmp | val;
+	r8a66597_write(r8a66597, tmp, offset);
+}
+
+#define r8a66597_bclr(r8a66597, val, offset)	\
+			r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset)	\
+			r8a66597_mdfy(r8a66597, val, 0, offset)
+
+static inline unsigned long get_syscfg_reg(int port)
+{
+	return port == 0 ? SYSCFG0 : SYSCFG1;
+}
+
+static inline unsigned long get_syssts_reg(int port)
+{
+	return port == 0 ? SYSSTS0 : SYSSTS1;
+}
+
+static inline unsigned long get_dvstctr_reg(int port)
+{
+	return port == 0 ? DVSTCTR0 : DVSTCTR1;
+}
+
+static inline unsigned long get_dmacfg_reg(int port)
+{
+	return port == 0 ? DMA0CFG : DMA1CFG;
+}
+
+static inline unsigned long get_intenb_reg(int port)
+{
+	return port == 0 ? INTENB1 : INTENB2;
+}
+
+static inline unsigned long get_intsts_reg(int port)
+{
+	return port == 0 ? INTSTS1 : INTSTS2;
+}
+
+static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port)
+{
+	unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+	return r8a66597_read(r8a66597, dvstctr_reg) & RHST;
+}
+
+static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port,
+				       int power)
+{
+	unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+	if (power)
+		r8a66597_bset(r8a66597, VBOUT, dvstctr_reg);
+	else
+		r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg);
+}
+
+#define get_pipectr_addr(pipenum)	(PIPE1CTR + (pipenum - 1) * 2)
+#define get_pipetre_addr(pipenum)	(PIPE1TRE + (pipenum - 1) * 4)
+#define get_pipetrn_addr(pipenum)	(PIPE1TRN + (pipenum - 1) * 4)
+#define get_devadd_addr(address)	(DEVADD0 + address * 2)
+
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h, based on usb_ohci.h) */
+
+/* destination of request */
+#define RH_INTERFACE		   0x01
+#define RH_ENDPOINT		   0x02
+#define RH_OTHER		   0x03
+
+#define RH_CLASS		   0x20
+#define RH_VENDOR		   0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS		0x0080
+#define RH_CLEAR_FEATURE	0x0100
+#define RH_SET_FEATURE		0x0300
+#define RH_SET_ADDRESS		0x0500
+#define RH_GET_DESCRIPTOR	0x0680
+#define RH_SET_DESCRIPTOR	0x0700
+#define RH_GET_CONFIGURATION	0x0880
+#define RH_SET_CONFIGURATION	0x0900
+#define RH_GET_STATE		0x0280
+#define RH_GET_INTERFACE	0x0A80
+#define RH_SET_INTERFACE	0x0B00
+#define RH_SYNC_FRAME		0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP		0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION	   0x00
+#define RH_PORT_ENABLE		   0x01
+#define RH_PORT_SUSPEND		   0x02
+#define RH_PORT_OVER_CURRENT	   0x03
+#define RH_PORT_RESET		   0x04
+#define RH_PORT_POWER		   0x08
+#define RH_PORT_LOW_SPEED	   0x09
+
+#define RH_C_PORT_CONNECTION	   0x10
+#define RH_C_PORT_ENABLE	   0x11
+#define RH_C_PORT_SUSPEND	   0x12
+#define RH_C_PORT_OVER_CURRENT	   0x13
+#define RH_C_PORT_RESET		   0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER	   0x00
+#define RH_C_HUB_OVER_CURRENT	   0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP	   0x00
+#define RH_ENDPOINT_STALL	   0x01
+
+#define RH_ACK			   0x01
+#define RH_REQ_ERR		   -1
+#define RH_NACK			   0x00
+
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS	0x00000001	/* current connect status */
+#define RH_PS_PES	0x00000002	/* port enable status*/
+#define RH_PS_PSS	0x00000004	/* port suspend status */
+#define RH_PS_POCI	0x00000008	/* port over current indicator */
+#define RH_PS_PRS	0x00000010	/* port reset status */
+#define RH_PS_PPS	0x00000100	/* port power status */
+#define RH_PS_LSDA	0x00000200	/* low speed device attached */
+#define RH_PS_CSC	0x00010000	/* connect status change */
+#define RH_PS_PESC	0x00020000	/* port enable status change */
+#define RH_PS_PSSC	0x00040000	/* port suspend status change */
+#define RH_PS_OCIC	0x00080000	/* over current indicator change */
+#define RH_PS_PRSC	0x00100000	/* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS	0x00000001	/* local power status */
+#define RH_HS_OCI	0x00000002	/* over current indicator */
+#define RH_HS_DRWE	0x00008000	/* device remote wakeup enable */
+#define RH_HS_LPSC	0x00010000	/* local power status change */
+#define RH_HS_OCIC	0x00020000	/* over current indicator change */
+#define RH_HS_CRWE	0x80000000	/* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR		0x0000ffff	/* device removable flags */
+#define RH_B_PPCM	0xffff0000	/* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP	(0xff << 0)	/* number of downstream ports */
+#define RH_A_PSM	(1 << 8)	/* power switching mode */
+#define RH_A_NPS	(1 << 9)	/* no power switching */
+#define RH_A_DT		(1 << 10)	/* device type (mbz) */
+#define RH_A_OCPM	(1 << 11)	/* over current protection mode */
+#define RH_A_NOCP	(1 << 12)	/* no over current protection */
+#define RH_A_POTPGT	(0xff << 24)	/* power on to power good time */
+
+
+#endif	/* __R8A66597_H__ */
+
diff --git a/include/usb.h b/include/usb.h
index 5a6ffdd..e68e98e 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -171,7 +171,7 @@ struct usb_device {

 #if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \
 	defined(CONFIG_USB_OHCI_NEW) || defined (CONFIG_USB_SL811HS) || \
-	defined(CONFIG_USB_ISP116X_HCD)
+	defined(CONFIG_USB_ISP116X_HCD) || defined(CONFIG_USB_R8A66597_HCD)

 int usb_lowlevel_init(void);
 int usb_lowlevel_stop(void);





More information about the U-Boot mailing list