Merge branch 'master' of git://git.denx.de/u-boot-usb
* 'master' of git://git.denx.de/u-boot-usb: usb_storage: fix ehci driver max transfer size smsc95xx: align buffers to cache line size ehci-hcd: change debug() to printf() in case of errors usb: check return value of submit_{control, bulk}_msg usb: pass cache-aligned buffer to usb_get_descriptor() ehci-hcd: fix external buffer cache handling ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment ehci-hcd: program asynclistaddr before every transfer common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER ehci-omap: Do not call dcache_off from omap_ehci_hcd_init Signed-off-by: Wolfgang Denk <wd@denx.de>
This commit is contained in:
commit
3ec81d758c
12
common/usb.c
12
common/usb.c
@ -188,7 +188,8 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
|
|||||||
request, requesttype, value, index, size);
|
request, requesttype, value, index, size);
|
||||||
dev->status = USB_ST_NOT_PROC; /*not yet processed */
|
dev->status = USB_ST_NOT_PROC; /*not yet processed */
|
||||||
|
|
||||||
submit_control_msg(dev, pipe, data, size, setup_packet);
|
if (submit_control_msg(dev, pipe, data, size, setup_packet) < 0)
|
||||||
|
return -1;
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
return (int)size;
|
return (int)size;
|
||||||
|
|
||||||
@ -220,7 +221,8 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
|
|||||||
if (len < 0)
|
if (len < 0)
|
||||||
return -1;
|
return -1;
|
||||||
dev->status = USB_ST_NOT_PROC; /*not yet processed */
|
dev->status = USB_ST_NOT_PROC; /*not yet processed */
|
||||||
submit_bulk_msg(dev, pipe, data, len);
|
if (submit_bulk_msg(dev, pipe, data, len) < 0)
|
||||||
|
return -1;
|
||||||
while (timeout--) {
|
while (timeout--) {
|
||||||
if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
|
if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
|
||||||
break;
|
break;
|
||||||
@ -799,12 +801,13 @@ int usb_new_device(struct usb_device *dev)
|
|||||||
dev->epmaxpacketin[0] = 8;
|
dev->epmaxpacketin[0] = 8;
|
||||||
dev->epmaxpacketout[0] = 8;
|
dev->epmaxpacketout[0] = 8;
|
||||||
|
|
||||||
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
|
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, tmpbuf, 8);
|
||||||
if (err < 8) {
|
if (err < 8) {
|
||||||
printf("\n USB device not responding, " \
|
printf("\n USB device not responding, " \
|
||||||
"giving up (status=%lX)\n", dev->status);
|
"giving up (status=%lX)\n", dev->status);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
memcpy(&dev->descriptor, tmpbuf, 8);
|
||||||
#else
|
#else
|
||||||
/* This is a Windows scheme of initialization sequence, with double
|
/* This is a Windows scheme of initialization sequence, with double
|
||||||
* reset of the device (Linux uses the same sequence)
|
* reset of the device (Linux uses the same sequence)
|
||||||
@ -893,7 +896,7 @@ int usb_new_device(struct usb_device *dev)
|
|||||||
tmp = sizeof(dev->descriptor);
|
tmp = sizeof(dev->descriptor);
|
||||||
|
|
||||||
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
|
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
|
||||||
&dev->descriptor, sizeof(dev->descriptor));
|
tmpbuf, sizeof(dev->descriptor));
|
||||||
if (err < tmp) {
|
if (err < tmp) {
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
printf("unable to get device descriptor (error=%d)\n",
|
printf("unable to get device descriptor (error=%d)\n",
|
||||||
@ -903,6 +906,7 @@ int usb_new_device(struct usb_device *dev)
|
|||||||
"(expected %i, got %i)\n", tmp, err);
|
"(expected %i, got %i)\n", tmp, err);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor));
|
||||||
/* correct le values */
|
/* correct le values */
|
||||||
le16_to_cpus(&dev->descriptor.bcdUSB);
|
le16_to_cpus(&dev->descriptor.bcdUSB);
|
||||||
le16_to_cpus(&dev->descriptor.idVendor);
|
le16_to_cpus(&dev->descriptor.idVendor);
|
||||||
|
@ -150,12 +150,17 @@ struct us_data {
|
|||||||
unsigned int irqpipe; /* pipe for release_irq */
|
unsigned int irqpipe; /* pipe for release_irq */
|
||||||
unsigned char irqmaxp; /* max packed for irq Pipe */
|
unsigned char irqmaxp; /* max packed for irq Pipe */
|
||||||
unsigned char irqinterval; /* Intervall for IRQ Pipe */
|
unsigned char irqinterval; /* Intervall for IRQ Pipe */
|
||||||
unsigned long max_xfer_blk; /* Max blocks per xfer */
|
|
||||||
ccb *srb; /* current srb */
|
ccb *srb; /* current srb */
|
||||||
trans_reset transport_reset; /* reset routine */
|
trans_reset transport_reset; /* reset routine */
|
||||||
trans_cmnd transport; /* transport routine */
|
trans_cmnd transport; /* transport routine */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The U-Boot EHCI driver cannot handle more than 5 page aligned buffers
|
||||||
|
* of 4096 bytes in a transfer without running itself out of qt_buffers
|
||||||
|
*/
|
||||||
|
#define USB_MAX_XFER_BLK(start, blksz) (((4096 * 5) - (start % 4096)) / blksz)
|
||||||
|
|
||||||
static struct us_data usb_stor[USB_MAX_STOR_DEV];
|
static struct us_data usb_stor[USB_MAX_STOR_DEV];
|
||||||
|
|
||||||
|
|
||||||
@ -1041,7 +1046,7 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor,
|
|||||||
unsigned long usb_stor_read(int device, unsigned long blknr,
|
unsigned long usb_stor_read(int device, unsigned long blknr,
|
||||||
unsigned long blkcnt, void *buffer)
|
unsigned long blkcnt, void *buffer)
|
||||||
{
|
{
|
||||||
unsigned long start, blks, buf_addr;
|
unsigned long start, blks, buf_addr, max_xfer_blk;
|
||||||
unsigned short smallblks;
|
unsigned short smallblks;
|
||||||
struct usb_device *dev;
|
struct usb_device *dev;
|
||||||
struct us_data *ss;
|
struct us_data *ss;
|
||||||
@ -1083,12 +1088,14 @@ unsigned long usb_stor_read(int device, unsigned long blknr,
|
|||||||
/* XXX need some comment here */
|
/* XXX need some comment here */
|
||||||
retry = 2;
|
retry = 2;
|
||||||
srb->pdata = (unsigned char *)buf_addr;
|
srb->pdata = (unsigned char *)buf_addr;
|
||||||
if (blks > ss->max_xfer_blk)
|
max_xfer_blk = USB_MAX_XFER_BLK(buf_addr,
|
||||||
smallblks = ss->max_xfer_blk;
|
usb_dev_desc[device].blksz);
|
||||||
|
if (blks > max_xfer_blk)
|
||||||
|
smallblks = (unsigned short) max_xfer_blk;
|
||||||
else
|
else
|
||||||
smallblks = (unsigned short) blks;
|
smallblks = (unsigned short) blks;
|
||||||
retry_it:
|
retry_it:
|
||||||
if (smallblks == ss->max_xfer_blk)
|
if (smallblks == max_xfer_blk)
|
||||||
usb_show_progress();
|
usb_show_progress();
|
||||||
srb->datalen = usb_dev_desc[device].blksz * smallblks;
|
srb->datalen = usb_dev_desc[device].blksz * smallblks;
|
||||||
srb->pdata = (unsigned char *)buf_addr;
|
srb->pdata = (unsigned char *)buf_addr;
|
||||||
@ -1109,7 +1116,7 @@ retry_it:
|
|||||||
start, smallblks, buf_addr);
|
start, smallblks, buf_addr);
|
||||||
|
|
||||||
usb_disable_asynch(0); /* asynch transfer allowed */
|
usb_disable_asynch(0); /* asynch transfer allowed */
|
||||||
if (blkcnt >= ss->max_xfer_blk)
|
if (blkcnt >= max_xfer_blk)
|
||||||
debug("\n");
|
debug("\n");
|
||||||
return blkcnt;
|
return blkcnt;
|
||||||
}
|
}
|
||||||
@ -1117,7 +1124,7 @@ retry_it:
|
|||||||
unsigned long usb_stor_write(int device, unsigned long blknr,
|
unsigned long usb_stor_write(int device, unsigned long blknr,
|
||||||
unsigned long blkcnt, const void *buffer)
|
unsigned long blkcnt, const void *buffer)
|
||||||
{
|
{
|
||||||
unsigned long start, blks, buf_addr;
|
unsigned long start, blks, buf_addr, max_xfer_blk;
|
||||||
unsigned short smallblks;
|
unsigned short smallblks;
|
||||||
struct usb_device *dev;
|
struct usb_device *dev;
|
||||||
struct us_data *ss;
|
struct us_data *ss;
|
||||||
@ -1162,12 +1169,14 @@ unsigned long usb_stor_write(int device, unsigned long blknr,
|
|||||||
*/
|
*/
|
||||||
retry = 2;
|
retry = 2;
|
||||||
srb->pdata = (unsigned char *)buf_addr;
|
srb->pdata = (unsigned char *)buf_addr;
|
||||||
if (blks > ss->max_xfer_blk)
|
max_xfer_blk = USB_MAX_XFER_BLK(buf_addr,
|
||||||
smallblks = ss->max_xfer_blk;
|
usb_dev_desc[device].blksz);
|
||||||
|
if (blks > max_xfer_blk)
|
||||||
|
smallblks = (unsigned short) max_xfer_blk;
|
||||||
else
|
else
|
||||||
smallblks = (unsigned short) blks;
|
smallblks = (unsigned short) blks;
|
||||||
retry_it:
|
retry_it:
|
||||||
if (smallblks == ss->max_xfer_blk)
|
if (smallblks == max_xfer_blk)
|
||||||
usb_show_progress();
|
usb_show_progress();
|
||||||
srb->datalen = usb_dev_desc[device].blksz * smallblks;
|
srb->datalen = usb_dev_desc[device].blksz * smallblks;
|
||||||
srb->pdata = (unsigned char *)buf_addr;
|
srb->pdata = (unsigned char *)buf_addr;
|
||||||
@ -1188,7 +1197,7 @@ retry_it:
|
|||||||
start, smallblks, buf_addr);
|
start, smallblks, buf_addr);
|
||||||
|
|
||||||
usb_disable_asynch(0); /* asynch transfer allowed */
|
usb_disable_asynch(0); /* asynch transfer allowed */
|
||||||
if (blkcnt >= ss->max_xfer_blk)
|
if (blkcnt >= max_xfer_blk)
|
||||||
debug("\n");
|
debug("\n");
|
||||||
return blkcnt;
|
return blkcnt;
|
||||||
|
|
||||||
@ -1415,12 +1424,6 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
|
|||||||
USB_STOR_PRINTF(" address %d\n", dev_desc->target);
|
USB_STOR_PRINTF(" address %d\n", dev_desc->target);
|
||||||
USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
|
USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
|
||||||
|
|
||||||
/*
|
|
||||||
* The U-Boot EHCI driver cannot handle more than 4096 * 5 bytes in a
|
|
||||||
* transfer without running itself out of qt_buffers.
|
|
||||||
*/
|
|
||||||
ss->max_xfer_blk = (4096 * 5) / dev_desc->blksz;
|
|
||||||
|
|
||||||
init_part(dev_desc);
|
init_part(dev_desc);
|
||||||
|
|
||||||
USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
|
USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
|
||||||
|
@ -153,13 +153,15 @@ static int curr_eth_dev; /* index for name of next device detected */
|
|||||||
static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data)
|
static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
|
||||||
|
|
||||||
cpu_to_le32s(&data);
|
cpu_to_le32s(&data);
|
||||||
|
tmpbuf[0] = data;
|
||||||
|
|
||||||
len = usb_control_msg(dev->pusb_dev, usb_sndctrlpipe(dev->pusb_dev, 0),
|
len = usb_control_msg(dev->pusb_dev, usb_sndctrlpipe(dev->pusb_dev, 0),
|
||||||
USB_VENDOR_REQUEST_WRITE_REGISTER,
|
USB_VENDOR_REQUEST_WRITE_REGISTER,
|
||||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||||
00, index, &data, sizeof(data), USB_CTRL_SET_TIMEOUT);
|
00, index, tmpbuf, sizeof(data), USB_CTRL_SET_TIMEOUT);
|
||||||
if (len != sizeof(data)) {
|
if (len != sizeof(data)) {
|
||||||
debug("smsc95xx_write_reg failed: index=%d, data=%d, len=%d",
|
debug("smsc95xx_write_reg failed: index=%d, data=%d, len=%d",
|
||||||
index, data, len);
|
index, data, len);
|
||||||
@ -171,11 +173,13 @@ static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data)
|
|||||||
static int smsc95xx_read_reg(struct ueth_data *dev, u32 index, u32 *data)
|
static int smsc95xx_read_reg(struct ueth_data *dev, u32 index, u32 *data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
|
||||||
|
|
||||||
len = usb_control_msg(dev->pusb_dev, usb_rcvctrlpipe(dev->pusb_dev, 0),
|
len = usb_control_msg(dev->pusb_dev, usb_rcvctrlpipe(dev->pusb_dev, 0),
|
||||||
USB_VENDOR_REQUEST_READ_REGISTER,
|
USB_VENDOR_REQUEST_READ_REGISTER,
|
||||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||||
00, index, data, sizeof(data), USB_CTRL_GET_TIMEOUT);
|
00, index, tmpbuf, sizeof(data), USB_CTRL_GET_TIMEOUT);
|
||||||
|
*data = tmpbuf[0];
|
||||||
if (len != sizeof(data)) {
|
if (len != sizeof(data)) {
|
||||||
debug("smsc95xx_read_reg failed: index=%d, len=%d",
|
debug("smsc95xx_read_reg failed: index=%d, len=%d",
|
||||||
index, len);
|
index, len);
|
||||||
@ -664,7 +668,8 @@ static int smsc95xx_send(struct eth_device *eth, void* packet, int length)
|
|||||||
int actual_len;
|
int actual_len;
|
||||||
u32 tx_cmd_a;
|
u32 tx_cmd_a;
|
||||||
u32 tx_cmd_b;
|
u32 tx_cmd_b;
|
||||||
unsigned char msg[PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b)];
|
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
|
||||||
|
PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b));
|
||||||
|
|
||||||
debug("** %s(), len %d, buf %#x\n", __func__, length, (int)msg);
|
debug("** %s(), len %d, buf %#x\n", __func__, length, (int)msg);
|
||||||
if (length > PKTSIZE)
|
if (length > PKTSIZE)
|
||||||
@ -695,7 +700,7 @@ static int smsc95xx_send(struct eth_device *eth, void* packet, int length)
|
|||||||
static int smsc95xx_recv(struct eth_device *eth)
|
static int smsc95xx_recv(struct eth_device *eth)
|
||||||
{
|
{
|
||||||
struct ueth_data *dev = (struct ueth_data *)eth->priv;
|
struct ueth_data *dev = (struct ueth_data *)eth->priv;
|
||||||
static unsigned char recv_buf[AX_RX_URB_SIZE];
|
DEFINE_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE);
|
||||||
unsigned char *buf_ptr;
|
unsigned char *buf_ptr;
|
||||||
int err;
|
int err;
|
||||||
int actual_len;
|
int actual_len;
|
||||||
|
@ -34,7 +34,10 @@ struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
|
|||||||
volatile struct ehci_hcor *hcor;
|
volatile struct ehci_hcor *hcor;
|
||||||
|
|
||||||
static uint16_t portreset;
|
static uint16_t portreset;
|
||||||
static struct QH qh_list __attribute__((aligned(32)));
|
DEFINE_ALIGN_BUFFER(struct QH, qh_list, 1, USB_DMA_MINALIGN);
|
||||||
|
|
||||||
|
#define ALIGN_END_ADDR(type, ptr, size) \
|
||||||
|
((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
|
||||||
|
|
||||||
static struct descriptor {
|
static struct descriptor {
|
||||||
struct usb_hub_descriptor hub;
|
struct usb_hub_descriptor hub;
|
||||||
@ -172,18 +175,15 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
|
|||||||
{
|
{
|
||||||
uint32_t delta, next;
|
uint32_t delta, next;
|
||||||
uint32_t addr = (uint32_t)buf;
|
uint32_t addr = (uint32_t)buf;
|
||||||
size_t rsz = roundup(sz, 32);
|
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
if (sz != rsz)
|
if (addr != ALIGN(addr, ARCH_DMA_MINALIGN))
|
||||||
debug("EHCI-HCD: Misaligned buffer size (%08x)\n", sz);
|
|
||||||
|
|
||||||
if (addr & 31)
|
|
||||||
debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf);
|
debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf);
|
||||||
|
|
||||||
|
flush_dcache_range(addr, ALIGN(addr + sz, ARCH_DMA_MINALIGN));
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
while (idx < 5) {
|
while (idx < 5) {
|
||||||
flush_dcache_range(addr, addr + rsz);
|
|
||||||
td->qt_buffer[idx] = cpu_to_hc32(addr);
|
td->qt_buffer[idx] = cpu_to_hc32(addr);
|
||||||
td->qt_buffer_hi[idx] = 0;
|
td->qt_buffer_hi[idx] = 0;
|
||||||
next = (addr + 4096) & ~4095;
|
next = (addr + 4096) & ~4095;
|
||||||
@ -196,7 +196,7 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (idx == 5) {
|
if (idx == 5) {
|
||||||
debug("out of buffer pointers (%u bytes left)\n", sz);
|
printf("out of buffer pointers (%u bytes left)\n", sz);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,8 +207,8 @@ static int
|
|||||||
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
||||||
int length, struct devrequest *req)
|
int length, struct devrequest *req)
|
||||||
{
|
{
|
||||||
static struct QH qh __attribute__((aligned(32)));
|
ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN);
|
||||||
static struct qTD qtd[3] __attribute__((aligned (32)));
|
ALLOC_ALIGN_BUFFER(struct qTD, qtd, 3, USB_DMA_MINALIGN);
|
||||||
int qtd_counter = 0;
|
int qtd_counter = 0;
|
||||||
|
|
||||||
volatile struct qTD *vtd;
|
volatile struct qTD *vtd;
|
||||||
@ -229,8 +229,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
le16_to_cpu(req->value), le16_to_cpu(req->value),
|
le16_to_cpu(req->value), le16_to_cpu(req->value),
|
||||||
le16_to_cpu(req->index));
|
le16_to_cpu(req->index));
|
||||||
|
|
||||||
memset(&qh, 0, sizeof(struct QH));
|
memset(qh, 0, sizeof(struct QH));
|
||||||
memset(qtd, 0, sizeof(qtd));
|
memset(qtd, 0, 3 * sizeof(*qtd));
|
||||||
|
|
||||||
toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
|
toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
* qh_overlay.qt_next ...... 13-10 H
|
* qh_overlay.qt_next ...... 13-10 H
|
||||||
* - qh_overlay.qt_altnext
|
* - qh_overlay.qt_altnext
|
||||||
*/
|
*/
|
||||||
qh.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
|
qh->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
|
||||||
c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
|
c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
|
||||||
usb_pipeendpoint(pipe) == 0) ? 1 : 0;
|
usb_pipeendpoint(pipe) == 0) ? 1 : 0;
|
||||||
endpt = (8 << 28) |
|
endpt = (8 << 28) |
|
||||||
@ -255,14 +255,14 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
(usb_pipespeed(pipe) << 12) |
|
(usb_pipespeed(pipe) << 12) |
|
||||||
(usb_pipeendpoint(pipe) << 8) |
|
(usb_pipeendpoint(pipe) << 8) |
|
||||||
(0 << 7) | (usb_pipedevice(pipe) << 0);
|
(0 << 7) | (usb_pipedevice(pipe) << 0);
|
||||||
qh.qh_endpt1 = cpu_to_hc32(endpt);
|
qh->qh_endpt1 = cpu_to_hc32(endpt);
|
||||||
endpt = (1 << 30) |
|
endpt = (1 << 30) |
|
||||||
(dev->portnr << 23) |
|
(dev->portnr << 23) |
|
||||||
(dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
|
(dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
|
||||||
qh.qh_endpt2 = cpu_to_hc32(endpt);
|
qh->qh_endpt2 = cpu_to_hc32(endpt);
|
||||||
qh.qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
|
qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
|
||||||
|
|
||||||
tdp = &qh.qh_overlay.qt_next;
|
tdp = &qh->qh_overlay.qt_next;
|
||||||
|
|
||||||
if (req != NULL) {
|
if (req != NULL) {
|
||||||
/*
|
/*
|
||||||
@ -281,7 +281,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
(0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
|
(0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
|
||||||
qtd[qtd_counter].qt_token = cpu_to_hc32(token);
|
qtd[qtd_counter].qt_token = cpu_to_hc32(token);
|
||||||
if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req)) != 0) {
|
if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req)) != 0) {
|
||||||
debug("unable construct SETUP td\n");
|
printf("unable construct SETUP td\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Update previous qTD! */
|
/* Update previous qTD! */
|
||||||
@ -310,7 +310,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
|
((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
|
||||||
qtd[qtd_counter].qt_token = cpu_to_hc32(token);
|
qtd[qtd_counter].qt_token = cpu_to_hc32(token);
|
||||||
if (ehci_td_buffer(&qtd[qtd_counter], buffer, length) != 0) {
|
if (ehci_td_buffer(&qtd[qtd_counter], buffer, length) != 0) {
|
||||||
debug("unable construct DATA td\n");
|
printf("unable construct DATA td\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Update previous qTD! */
|
/* Update previous qTD! */
|
||||||
@ -340,13 +340,16 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
tdp = &qtd[qtd_counter++].qt_next;
|
tdp = &qtd[qtd_counter++].qt_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
qh_list.qh_link = cpu_to_hc32((uint32_t)&qh | QH_LINK_TYPE_QH);
|
qh_list->qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);
|
||||||
|
|
||||||
/* Flush dcache */
|
/* Flush dcache */
|
||||||
flush_dcache_range((uint32_t)&qh_list,
|
flush_dcache_range((uint32_t)qh_list,
|
||||||
(uint32_t)&qh_list + sizeof(struct QH));
|
ALIGN_END_ADDR(struct QH, qh_list, 1));
|
||||||
flush_dcache_range((uint32_t)&qh, (uint32_t)&qh + sizeof(struct QH));
|
flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1));
|
||||||
flush_dcache_range((uint32_t)qtd, (uint32_t)qtd + sizeof(qtd));
|
flush_dcache_range((uint32_t)qtd, ALIGN_END_ADDR(struct qTD, qtd, 3));
|
||||||
|
|
||||||
|
/* Set async. queue head pointer. */
|
||||||
|
ehci_writel(&hcor->or_asynclistaddr, (uint32_t)qh_list);
|
||||||
|
|
||||||
usbsts = ehci_readl(&hcor->or_usbsts);
|
usbsts = ehci_readl(&hcor->or_usbsts);
|
||||||
ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
|
ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
|
||||||
@ -369,12 +372,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
timeout = USB_TIMEOUT_MS(pipe);
|
timeout = USB_TIMEOUT_MS(pipe);
|
||||||
do {
|
do {
|
||||||
/* Invalidate dcache */
|
/* Invalidate dcache */
|
||||||
invalidate_dcache_range((uint32_t)&qh_list,
|
invalidate_dcache_range((uint32_t)qh_list,
|
||||||
(uint32_t)&qh_list + sizeof(struct QH));
|
ALIGN_END_ADDR(struct QH, qh_list, 1));
|
||||||
invalidate_dcache_range((uint32_t)&qh,
|
invalidate_dcache_range((uint32_t)qh,
|
||||||
(uint32_t)&qh + sizeof(struct QH));
|
ALIGN_END_ADDR(struct QH, qh, 1));
|
||||||
invalidate_dcache_range((uint32_t)qtd,
|
invalidate_dcache_range((uint32_t)qtd,
|
||||||
(uint32_t)qtd + sizeof(qtd));
|
ALIGN_END_ADDR(struct qTD, qtd, 3));
|
||||||
|
|
||||||
token = hc32_to_cpu(vtd->qt_token);
|
token = hc32_to_cpu(vtd->qt_token);
|
||||||
if (!(token & 0x80))
|
if (!(token & 0x80))
|
||||||
@ -382,9 +385,17 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
WATCHDOG_RESET();
|
WATCHDOG_RESET();
|
||||||
} while (get_timer(ts) < timeout);
|
} while (get_timer(ts) < timeout);
|
||||||
|
|
||||||
/* Invalidate the memory area occupied by buffer */
|
/*
|
||||||
invalidate_dcache_range(((uint32_t)buffer & ~31),
|
* Invalidate the memory area occupied by buffer
|
||||||
((uint32_t)buffer & ~31) + roundup(length, 32));
|
* Don't try to fix the buffer alignment, if it isn't properly
|
||||||
|
* aligned it's upper layer's fault so let invalidate_dcache_range()
|
||||||
|
* vow about it. But we have to fix the length as it's actual
|
||||||
|
* transfer length and can be unaligned. This is potentially
|
||||||
|
* dangerous operation, it's responsibility of the calling
|
||||||
|
* code to make sure enough space is reserved.
|
||||||
|
*/
|
||||||
|
invalidate_dcache_range((uint32_t)buffer,
|
||||||
|
ALIGN((uint32_t)buffer + length, ARCH_DMA_MINALIGN));
|
||||||
|
|
||||||
/* Check that the TD processing happened */
|
/* Check that the TD processing happened */
|
||||||
if (token & 0x80) {
|
if (token & 0x80) {
|
||||||
@ -403,9 +414,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
|
token = hc32_to_cpu(qh->qh_overlay.qt_token);
|
||||||
|
|
||||||
token = hc32_to_cpu(qh.qh_overlay.qt_token);
|
|
||||||
if (!(token & 0x80)) {
|
if (!(token & 0x80)) {
|
||||||
debug("TOKEN=%#x\n", token);
|
debug("TOKEN=%#x\n", token);
|
||||||
switch (token & 0xfc) {
|
switch (token & 0xfc) {
|
||||||
@ -733,16 +742,13 @@ int usb_lowlevel_init(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set head of reclaim list */
|
/* Set head of reclaim list */
|
||||||
memset(&qh_list, 0, sizeof(qh_list));
|
memset(qh_list, 0, sizeof(*qh_list));
|
||||||
qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
|
qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
|
||||||
qh_list.qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
|
qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
|
||||||
qh_list.qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
|
qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
|
||||||
qh_list.qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
|
qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
|
||||||
qh_list.qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
|
qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
|
||||||
qh_list.qh_overlay.qt_token = cpu_to_hc32(0x40);
|
qh_list->qh_overlay.qt_token = cpu_to_hc32(0x40);
|
||||||
|
|
||||||
/* Set async. queue head pointer. */
|
|
||||||
ehci_writel(&hcor->or_asynclistaddr, (uint32_t)&qh_list);
|
|
||||||
|
|
||||||
reg = ehci_readl(&hccr->cr_hcsparams);
|
reg = ehci_readl(&hccr->cr_hcsparams);
|
||||||
descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
|
descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
|
||||||
|
@ -246,7 +246,6 @@ int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata)
|
|||||||
if (is_ehci_phy_mode(usbhs_pdata->port_mode[i]))
|
if (is_ehci_phy_mode(usbhs_pdata->port_mode[i]))
|
||||||
omap_ehci_soft_phy_reset(i);
|
omap_ehci_soft_phy_reset(i);
|
||||||
|
|
||||||
dcache_disable();
|
|
||||||
hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
|
hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
|
||||||
hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
|
hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ struct musb_regs {
|
|||||||
struct musb_epN_regs epN;
|
struct musb_epN_regs epN;
|
||||||
} ep[16];
|
} ep[16];
|
||||||
|
|
||||||
} __attribute__((packed, aligned(32)));
|
} __attribute__((packed, aligned(USB_DMA_MINALIGN)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -39,6 +39,7 @@ typedef volatile unsigned char vu_char;
|
|||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/compiler.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000))
|
#if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000))
|
||||||
@ -944,11 +945,25 @@ int cpu_release(int nr, int argc, char * const argv[]);
|
|||||||
* of a function scoped static buffer. It can not be used to create a cache
|
* of a function scoped static buffer. It can not be used to create a cache
|
||||||
* line aligned global buffer.
|
* line aligned global buffer.
|
||||||
*/
|
*/
|
||||||
#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \
|
#define ALLOC_ALIGN_BUFFER(type, name, size, align) \
|
||||||
char __##name[ROUND(size * sizeof(type), ARCH_DMA_MINALIGN) + \
|
char __##name[ROUND(size * sizeof(type), align) + (align - 1)]; \
|
||||||
ARCH_DMA_MINALIGN - 1]; \
|
|
||||||
\
|
\
|
||||||
type *name = (type *) ALIGN((uintptr_t)__##name, ARCH_DMA_MINALIGN)
|
type *name = (type *) ALIGN((uintptr_t)__##name, align)
|
||||||
|
#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \
|
||||||
|
ALLOC_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DEFINE_CACHE_ALIGN_BUFFER() is similar to ALLOC_CACHE_ALIGN_BUFFER, but it's
|
||||||
|
* purpose is to allow allocating aligned buffers outside of function scope.
|
||||||
|
* Usage of this macro shall be avoided or used with extreme care!
|
||||||
|
*/
|
||||||
|
#define DEFINE_ALIGN_BUFFER(type, name, size, align) \
|
||||||
|
static char __##name[roundup(size * sizeof(type), align)] \
|
||||||
|
__aligned(align); \
|
||||||
|
\
|
||||||
|
static type *name = (type *)__##name
|
||||||
|
#define DEFINE_CACHE_ALIGN_BUFFER(type, name, size) \
|
||||||
|
DEFINE_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN)
|
||||||
|
|
||||||
/* Pull in stuff for the build system */
|
/* Pull in stuff for the build system */
|
||||||
#ifdef DO_DEPS_ONLY
|
#ifdef DO_DEPS_ONLY
|
||||||
|
@ -29,6 +29,16 @@
|
|||||||
#include <usb_defs.h>
|
#include <usb_defs.h>
|
||||||
#include <usbdescriptors.h>
|
#include <usbdescriptors.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The EHCI spec says that we must align to at least 32 bytes. However,
|
||||||
|
* some platforms require larger alignment.
|
||||||
|
*/
|
||||||
|
#if ARCH_DMA_MINALIGN > 32
|
||||||
|
#define USB_DMA_MINALIGN ARCH_DMA_MINALIGN
|
||||||
|
#else
|
||||||
|
#define USB_DMA_MINALIGN 32
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Everything is aribtrary */
|
/* Everything is aribtrary */
|
||||||
#define USB_ALTSETTINGALLOC 4
|
#define USB_ALTSETTINGALLOC 4
|
||||||
#define USB_MAXALTSETTING 128 /* Hard limit */
|
#define USB_MAXALTSETTING 128 /* Hard limit */
|
||||||
|
Loading…
Reference in New Issue
Block a user