add support for Renesas R8A66597 usb controller. This patch supports USB Host mode. Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> Signed-off-by: Markus Klotzbuecher <mk@denx.de>master
parent
1d10dcd041
commit
fd0f2f3796
@ -0,0 +1,924 @@ |
||||
/*
|
||||
* R8A66597 HCD (Host Controller Driver) for u-boot |
||||
* |
||||
* Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@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 */ |
||||
|
@ -0,0 +1,663 @@ |
||||
/*
|
||||
* R8A66597 HCD (Host Controller Driver) for u-boot |
||||
* |
||||
* Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@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__ */ |
||||
|
Loading…
Reference in new issue