Merge branch 'master' of git://git.denx.de/u-boot-usb

This commit is contained in:
Wolfgang Denk 2009-12-21 21:01:56 +01:00
commit f7767c7541
29 changed files with 2245 additions and 132 deletions

View File

@ -241,6 +241,7 @@ LIBS += drivers/twserial/libtws.a
LIBS += drivers/usb/gadget/libusb_gadget.a
LIBS += drivers/usb/host/libusb_host.a
LIBS += drivers/usb/musb/libusb_musb.a
LIBS += drivers/usb/phy/libusb_phy.a
LIBS += drivers/video/libvideo.a
LIBS += drivers/watchdog/libwatchdog.a
LIBS += common/libcommon.a

View File

@ -86,6 +86,8 @@ void quad_putc_dev (unsigned long base, const char c)
quad_putc_dev (base, '\r');
NS16550_putc ((NS16550_t) base, c);
} else {
usbtty_putc(c);
}
}
@ -94,6 +96,8 @@ void quad_puts_dev (unsigned long base, const char *s)
if (zoom2_debug_board_connected ()) {
while ((s != NULL) && (*s != '\0'))
quad_putc_dev (base, *s++);
} else {
usbtty_puts(s);
}
}
@ -101,16 +105,16 @@ int quad_getc_dev (unsigned long base)
{
if (zoom2_debug_board_connected ())
return NS16550_getc ((NS16550_t) base);
else
return 0;
return usbtty_getc();
}
int quad_tstc_dev (unsigned long base)
{
if (zoom2_debug_board_connected ())
return NS16550_tstc ((NS16550_t) base);
else
return 0;
return usbtty_tstc();
}
void quad_setbrg_dev (unsigned long base)

View File

@ -157,7 +157,7 @@ void usb_display_desc(struct usb_device *dev)
{
if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) {
printf("%d: %s, USB Revision %x.%x\n", dev->devnum,
usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass),
usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass),
(dev->descriptor.bcdUSB>>8) & 0xff,
dev->descriptor.bcdUSB & 0xff);
@ -174,7 +174,7 @@ void usb_display_desc(struct usb_device *dev)
} else {
printf(" - Class: (from Interface) %s\n",
usb_get_class_desc(
dev->config.if_desc[0].bInterfaceClass));
dev->config.if_desc[0].desc.bInterfaceClass));
}
printf(" - PacketSize: %d Configurations: %d\n",
dev->descriptor.bMaxPacketSize0,
@ -187,14 +187,14 @@ void usb_display_desc(struct usb_device *dev)
}
void usb_display_conf_desc(struct usb_config_descriptor *config,
void usb_display_conf_desc(struct usb_configuration_descriptor *config,
struct usb_device *dev)
{
printf(" Configuration: %d\n", config->bConfigurationValue);
printf(" - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces,
(config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
(config->bmAttributes & 0x20) ? "Remote Wakeup " : "",
config->MaxPower*2);
config->bMaxPower*2);
if (config->iConfiguration) {
printf(" - ");
usb_display_string(dev, config->iConfiguration);
@ -246,16 +246,16 @@ void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
/* main routine to diasplay the configs, interfaces and endpoints */
void usb_display_config(struct usb_device *dev)
{
struct usb_config_descriptor *config;
struct usb_interface_descriptor *ifdesc;
struct usb_config *config;
struct usb_interface *ifdesc;
struct usb_endpoint_descriptor *epdesc;
int i, ii;
config = &dev->config;
usb_display_conf_desc(config, dev);
usb_display_conf_desc(&config->desc, dev);
for (i = 0; i < config->no_of_if; i++) {
ifdesc = &config->if_desc[i];
usb_display_if_desc(ifdesc, dev);
usb_display_if_desc(&ifdesc->desc, dev);
for (ii = 0; ii < ifdesc->no_of_ep; ii++) {
epdesc = &ifdesc->ep_desc[ii];
usb_display_ep_desc(epdesc);
@ -319,9 +319,9 @@ void usb_show_tree_graph(struct usb_device *dev, char *pre)
pre[index++] = has_child ? '|' : ' ';
pre[index] = 0;
printf(" %s (%s, %dmA)\n", usb_get_class_desc(
dev->config.if_desc[0].bInterfaceClass),
dev->config.if_desc[0].desc.bInterfaceClass),
portspeed(dev->speed),
dev->config.MaxPower * 2);
dev->config.desc.bMaxPower * 2);
if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
printf(" %s\n", pre);
@ -642,6 +642,28 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return 1;
}
}
if (strcmp(argv[1], "write") == 0) {
if (usb_stor_curr_dev < 0) {
printf("no current device selected\n");
return 1;
}
if (argc == 5) {
unsigned long addr = simple_strtoul(argv[2], NULL, 16);
unsigned long blk = simple_strtoul(argv[3], NULL, 16);
unsigned long cnt = simple_strtoul(argv[4], NULL, 16);
unsigned long n;
printf("\nUSB write: device %d block # %ld, count %ld"
" ... ", usb_stor_curr_dev, blk, cnt);
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
n = stor_dev->block_write(usb_stor_curr_dev, blk, cnt,
(ulong *)addr);
printf("%ld blocks write: %s\n", n,
(n == cnt) ? "OK" : "ERROR");
if (n == cnt)
return 0;
return 1;
}
}
if (strncmp(argv[1], "dev", 3) == 0) {
if (argc == 3) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
@ -687,6 +709,8 @@ U_BOOT_CMD(
" devices\n"
"usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
" to memory address `addr'"
"usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n"
" from memory address `addr'"
);

View File

@ -299,8 +299,8 @@ int usb_set_maxpacket(struct usb_device *dev)
{
int i, ii;
for (i = 0; i < dev->config.bNumInterfaces; i++)
for (ii = 0; ii < dev->config.if_desc[i].bNumEndpoints; ii++)
for (i = 0; i < dev->config.desc.bNumInterfaces; i++)
for (ii = 0; ii < dev->config.if_desc[i].desc.bNumEndpoints; ii++)
usb_set_maxpacket_ep(dev,
&dev->config.if_desc[i].ep_desc[ii]);
@ -330,14 +330,14 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
return -1;
}
memcpy(&dev->config, buffer, buffer[0]);
le16_to_cpus(&(dev->config.wTotalLength));
le16_to_cpus(&(dev->config.desc.wTotalLength));
dev->config.no_of_if = 0;
index = dev->config.bLength;
index = dev->config.desc.bLength;
/* Ok the first entry must be a configuration entry,
* now process the others */
head = (struct usb_descriptor_header *) &buffer[index];
while (index + 1 < dev->config.wTotalLength) {
while (index + 1 < dev->config.desc.wTotalLength) {
switch (head->bDescriptorType) {
case USB_DT_INTERFACE:
if (((struct usb_interface_descriptor *) \
@ -350,7 +350,7 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
dev->config.if_desc[ifno].no_of_ep = 0;
dev->config.if_desc[ifno].num_altsetting = 1;
curr_if_num =
dev->config.if_desc[ifno].bInterfaceNumber;
dev->config.if_desc[ifno].desc.bInterfaceNumber;
} else {
/* found alternate setting for the interface */
dev->config.if_desc[ifno].num_altsetting++;
@ -440,10 +440,9 @@ int usb_get_configuration_no(struct usb_device *dev,
{
int result;
unsigned int tmp;
struct usb_config_descriptor *config;
struct usb_configuration_descriptor *config;
config = (struct usb_config_descriptor *)&buffer[0];
config = (struct usb_configuration_descriptor *)&buffer[0];
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9);
if (result < 9) {
if (result < 0)
@ -489,11 +488,11 @@ int usb_set_address(struct usb_device *dev)
*/
int usb_set_interface(struct usb_device *dev, int interface, int alternate)
{
struct usb_interface_descriptor *if_face = NULL;
struct usb_interface *if_face = NULL;
int ret, i;
for (i = 0; i < dev->config.bNumInterfaces; i++) {
if (dev->config.if_desc[i].bInterfaceNumber == interface) {
for (i = 0; i < dev->config.desc.bNumInterfaces; i++) {
if (dev->config.if_desc[i].desc.bInterfaceNumber == interface) {
if_face = &dev->config.if_desc[i];
break;
}
@ -897,7 +896,7 @@ int usb_new_device(struct usb_device *dev)
usb_parse_config(dev, &tmpbuf[0], 0);
usb_set_maxpacket(dev);
/* we set the default configuration here */
if (usb_set_configuration(dev, dev->config.bConfigurationValue)) {
if (usb_set_configuration(dev, dev->config.desc.bConfigurationValue)) {
printf("failed to set default configuration " \
"len %d, status %lX\n", dev->act_len, dev->status);
return -1;
@ -1347,21 +1346,21 @@ int usb_hub_configure(struct usb_device *dev)
int usb_hub_probe(struct usb_device *dev, int ifnum)
{
struct usb_interface_descriptor *iface;
struct usb_interface *iface;
struct usb_endpoint_descriptor *ep;
int ret;
iface = &dev->config.if_desc[ifnum];
/* Is it a hub? */
if (iface->bInterfaceClass != USB_CLASS_HUB)
if (iface->desc.bInterfaceClass != USB_CLASS_HUB)
return 0;
/* Some hubs have a subclass of 1, which AFAICT according to the */
/* specs is not defined, but it works */
if ((iface->bInterfaceSubClass != 0) &&
(iface->bInterfaceSubClass != 1))
if ((iface->desc.bInterfaceSubClass != 0) &&
(iface->desc.bInterfaceSubClass != 1))
return 0;
/* Multiple endpoints? What kind of mutant ninja-hub is this? */
if (iface->bNumEndpoints != 1)
if (iface->desc.bNumEndpoints != 1)
return 0;
ep = &iface->ep_desc[0];
/* Output endpoint? Curiousier and curiousier.. */

View File

@ -229,7 +229,7 @@ int usb_kbd_deregister(void)
static void usb_kbd_setled(struct usb_device *dev)
{
struct usb_interface_descriptor *iface;
struct usb_interface *iface;
iface = &dev->config.if_desc[0];
leds=0;
if(scroll_lock!=0)
@ -242,7 +242,7 @@ static void usb_kbd_setled(struct usb_device *dev)
leds|=1;
usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0x200, iface->bInterfaceNumber,(void *)&leds, 1, 0);
0x200, iface->desc.bInterfaceNumber, (void *)&leds, 1, 0);
}
@ -348,17 +348,21 @@ static int usb_kbd_irq(struct usb_device *dev)
/* probes the USB device dev for keyboard type */
static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
{
struct usb_interface_descriptor *iface;
struct usb_interface *iface;
struct usb_endpoint_descriptor *ep;
int pipe,maxp;
if (dev->descriptor.bNumConfigurations != 1) return 0;
iface = &dev->config.if_desc[ifnum];
if (iface->bInterfaceClass != 3) return 0;
if (iface->bInterfaceSubClass != 1) return 0;
if (iface->bInterfaceProtocol != 1) return 0;
if (iface->bNumEndpoints != 1) return 0;
if (iface->desc.bInterfaceClass != 3)
return 0;
if (iface->desc.bInterfaceSubClass != 1)
return 0;
if (iface->desc.bInterfaceProtocol != 1)
return 0;
if (iface->desc.bNumEndpoints != 1)
return 0;
ep = &iface->ep_desc[0];
@ -367,9 +371,9 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
USB_KBD_PRINTF("USB KBD found set protocol...\n");
/* ok, we found a USB Keyboard, install it */
/* usb_kbd_get_hid_desc(dev); */
usb_set_protocol(dev, iface->bInterfaceNumber, 0);
usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0);
USB_KBD_PRINTF("USB KBD found set idle...\n");
usb_set_idle(dev, iface->bInterfaceNumber, REPEAT_RATE, 0);
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0);
memset(&new[0], 0, 8);
memset(&old[0], 0, 8);
repeat_delay=0;

View File

@ -168,6 +168,8 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
struct us_data *ss);
unsigned long usb_stor_read(int device, unsigned long blknr,
unsigned long blkcnt, void *buffer);
unsigned long usb_stor_write(int device, unsigned long blknr,
unsigned long blkcnt, const void *buffer);
struct usb_device * usb_get_dev_index(int index);
void uhci_show_temp_int_td(void);
@ -227,6 +229,7 @@ int usb_stor_scan(int mode)
usb_dev_desc[i].dev = i;
usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
usb_dev_desc[i].block_read = usb_stor_read;
usb_dev_desc[i].block_write = usb_stor_write;
}
usb_max_devs = 0;
@ -964,6 +967,22 @@ static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
return ss->transport(srb, ss);
}
static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
unsigned short blocks)
{
memset(&srb->cmd[0], 0, 12);
srb->cmd[0] = SCSI_WRITE10;
srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
srb->cmd[5] = ((unsigned char) (start)) & 0xff;
srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
srb->cmd[8] = (unsigned char) blocks & 0xff;
srb->cmdlen = 12;
USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
return ss->transport(srb, ss);
}
#ifdef CONFIG_USB_BIN_FIXUP
/*
@ -1065,12 +1084,92 @@ retry_it:
return blkcnt;
}
#define USB_MAX_WRITE_BLK 20
unsigned long usb_stor_write(int device, unsigned long blknr,
unsigned long blkcnt, const void *buffer)
{
unsigned long start, blks, buf_addr;
unsigned short smallblks;
struct usb_device *dev;
int retry, i;
ccb *srb = &usb_ccb;
if (blkcnt == 0)
return 0;
device &= 0xff;
/* Setup device */
USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
dev = NULL;
for (i = 0; i < USB_MAX_DEVICE; i++) {
dev = usb_get_dev_index(i);
if (dev == NULL)
return 0;
if (dev->devnum == usb_dev_desc[device].target)
break;
}
usb_disable_asynch(1); /* asynch transfer not allowed */
srb->lun = usb_dev_desc[device].lun;
buf_addr = (unsigned long)buffer;
start = blknr;
blks = blkcnt;
if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
printf("Device NOT ready\n Request Sense returned %02X %02X"
" %02X\n", srb->sense_buf[2], srb->sense_buf[12],
srb->sense_buf[13]);
return 0;
}
USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx"
" buffer %lx\n", device, start, blks, buf_addr);
do {
/* If write fails retry for max retry count else
* return with number of blocks written successfully.
*/
retry = 2;
srb->pdata = (unsigned char *)buf_addr;
if (blks > USB_MAX_WRITE_BLK)
smallblks = USB_MAX_WRITE_BLK;
else
smallblks = (unsigned short) blks;
retry_it:
if (smallblks == USB_MAX_WRITE_BLK)
usb_show_progress();
srb->datalen = usb_dev_desc[device].blksz * smallblks;
srb->pdata = (unsigned char *)buf_addr;
if (usb_write_10(srb, (struct us_data *)dev->privptr, start,
smallblks)) {
USB_STOR_PRINTF("Write ERROR\n");
usb_request_sense(srb, (struct us_data *)dev->privptr);
if (retry--)
goto retry_it;
blkcnt -= blks;
break;
}
start += smallblks;
blks -= smallblks;
buf_addr += srb->datalen;
} while (blks != 0);
USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n",
start, smallblks, buf_addr);
usb_disable_asynch(0); /* asynch transfer allowed */
if (blkcnt >= USB_MAX_WRITE_BLK)
printf("\n");
return blkcnt;
}
/* Probe to see if a new device is actually a Storage device */
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
struct us_data *ss)
{
struct usb_interface_descriptor *iface;
struct usb_interface *iface;
int i;
unsigned int flags = 0;
@ -1094,9 +1193,9 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
#endif
if (dev->descriptor.bDeviceClass != 0 ||
iface->bInterfaceClass != USB_CLASS_MASS_STORAGE ||
iface->bInterfaceSubClass < US_SC_MIN ||
iface->bInterfaceSubClass > US_SC_MAX) {
iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
iface->desc.bInterfaceSubClass < US_SC_MIN ||
iface->desc.bInterfaceSubClass > US_SC_MAX) {
/* if it's not a mass storage, we go no further */
return 0;
}
@ -1119,8 +1218,8 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
ss->subclass = subclass;
ss->protocol = protocol;
} else {
ss->subclass = iface->bInterfaceSubClass;
ss->protocol = iface->bInterfaceProtocol;
ss->subclass = iface->desc.bInterfaceSubClass;
ss->protocol = iface->desc.bInterfaceProtocol;
}
/* set the handler pointers based on the protocol */
@ -1153,7 +1252,7 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
* An optional interrupt is OK (necessary for CBI protocol).
* We will ignore any others.
*/
for (i = 0; i < iface->bNumEndpoints; i++) {
for (i = 0; i < iface->desc.bNumEndpoints; i++) {
/* is it an BULK endpoint? */
if ((iface->ep_desc[i].bmAttributes &
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
@ -1178,7 +1277,7 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
ss->ep_in, ss->ep_out, ss->ep_int);
/* Do some basic sanity checks, and bail if we find a problem */
if (usb_set_interface(dev, iface->bInterfaceNumber, 0) ||
if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
!ss->ep_in || !ss->ep_out ||
(ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
USB_STOR_PRINTF("Problems with device\n");

View File

@ -21,7 +21,7 @@ void process_endpoints(unsigned short usb2d0_intrin)
{
/*will hold the packet received */
struct usb_device_descriptor usb_device_packet;
struct usb_config_descriptor usb_config_packet;
struct usb_configuration_descriptor usb_config_packet;
struct usb_string_descriptor usb_string_packet;
struct devrequest setup_packet;
unsigned int *setup_packet_pt;
@ -99,7 +99,7 @@ void process_endpoints(unsigned short usb2d0_intrin)
usb_config_packet.bConfigurationValue = 1;
usb_config_packet.iConfiguration = 0;
usb_config_packet.bmAttributes = 0x40;
usb_config_packet.MaxPower = 0;
usb_config_packet.bMaxPower = 0;
/*put packet in fifo */
packet_pt = (unsigned char *)&usb_config_packet;

View File

@ -29,6 +29,8 @@
#include <usb/mpc8xx_udc.h>
#elif defined(CONFIG_OMAP1510)
#include <usb/omap1510_udc.h>
#elif defined(CONFIG_MUSB_UDC)
#include <usb/musb_udc.h>
#elif defined(CONFIG_PXA27X)
#include <usb/pxa27x_udc.h>
#endif

View File

@ -96,7 +96,7 @@ static struct descriptor {
* UE_DIR_IN | EHCI_INTR_ENDPT
*/
3, /* bmAttributes: UE_INTERRUPT */
8, 0, /* wMaxPacketSize */
8, /* wMaxPacketSize */
255 /* bInterval */
},
};

View File

@ -26,7 +26,9 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libusb_musb.a
COBJS-$(CONFIG_MUSB_HCD) += musb_hcd.o musb_core.o
COBJS-$(CONFIG_MUSB_UDC) += musb_udc.o musb_core.o
COBJS-$(CONFIG_USB_DAVINCI) += davinci.o
COBJS-$(CONFIG_USB_OMAP3) += omap3.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)

View File

@ -32,7 +32,9 @@ struct musb_regs *musbr;
*/
void musb_start(void)
{
#if defined(CONFIG_MUSB_HCD)
u8 devctl;
#endif
/* disable all interrupts */
writew(0, &musbr->intrtxe);
@ -74,9 +76,10 @@ void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt)
/* Configure fifo size and fifo base address */
writeb(idx, &musbr->txfifosz);
writew(fifoaddr >> 3, &musbr->txfifoadd);
csr = readw(&musbr->txcsr);
#if defined(CONFIG_MUSB_HCD)
/* clear the data toggle bit */
csr = readw(&musbr->txcsr);
writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
#endif
/* Flush fifo if required */
@ -87,9 +90,10 @@ void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt)
/* Configure fifo size and fifo base address */
writeb(idx, &musbr->rxfifosz);
writew(fifoaddr >> 3, &musbr->rxfifoadd);
csr = readw(&musbr->rxcsr);
#if defined(CONFIG_MUSB_HCD)
/* clear the data toggle bit */
csr = readw(&musbr->rxcsr);
writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
#endif
/* Flush fifo if required */

View File

@ -40,6 +40,36 @@
#define MUSB_EP0_FIFOSIZE 64 /* This is non-configurable */
/* EP0 */
struct musb_ep0_regs {
u16 reserved4;
u16 csr0;
u16 reserved5;
u16 reserved6;
u16 count0;
u8 host_type0;
u8 host_naklimit0;
u8 reserved7;
u8 reserved8;
u8 reserved9;
u8 configdata;
};
/* EP 1-15 */
struct musb_epN_regs {
u16 txmaxp;
u16 txcsr;
u16 rxmaxp;
u16 rxcsr;
u16 rxcount;
u8 txtype;
u8 txinterval;
u8 rxtype;
u8 rxinterval;
u8 reserved0;
u8 fifosize;
};
/* Mentor USB core register overlay structure */
struct musb_regs {
/* common registers */
@ -97,6 +127,16 @@ struct musb_regs {
u8 rxhubaddr;
u8 rxhubport;
} tar[16];
/*
* end point registers
* ep0 elements are valid when array index is 0
* otherwise epN is valid
*/
union musb_ep_regs {
struct musb_ep0_regs ep0;
struct musb_epN_regs epN;
} ep[16];
} __attribute__((aligned(32)));
/*

View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2009 Wind River Systems, Inc.
* Tom Rix <Tom.Rix@windriver.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; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* Define MUSB_DEBUG before including this file to get debug macros */
#ifdef MUSB_DEBUG
#define MUSB_FLAGS_PRINT(v, x, y) \
if (((v) & MUSB_##x##_##y)) \
serial_printf("\t\t"#y"\n")
static inline void musb_print_pwr(u8 b)
{
serial_printf("\tpower 0x%2.2x\n", b);
MUSB_FLAGS_PRINT(b, POWER, ISOUPDATE);
MUSB_FLAGS_PRINT(b, POWER, SOFTCONN);
MUSB_FLAGS_PRINT(b, POWER, HSENAB);
MUSB_FLAGS_PRINT(b, POWER, HSMODE);
MUSB_FLAGS_PRINT(b, POWER, RESET);
MUSB_FLAGS_PRINT(b, POWER, RESUME);
MUSB_FLAGS_PRINT(b, POWER, SUSPENDM);
MUSB_FLAGS_PRINT(b, POWER, ENSUSPEND);
}
static inline void musb_print_csr0(u16 w)
{
serial_printf("\tcsr0 0x%4.4x\n", w);
MUSB_FLAGS_PRINT(w, CSR0, FLUSHFIFO);
MUSB_FLAGS_PRINT(w, CSR0_P, SVDSETUPEND);
MUSB_FLAGS_PRINT(w, CSR0_P, SVDRXPKTRDY);
MUSB_FLAGS_PRINT(w, CSR0_P, SENDSTALL);
MUSB_FLAGS_PRINT(w, CSR0_P, SETUPEND);
MUSB_FLAGS_PRINT(w, CSR0_P, DATAEND);
MUSB_FLAGS_PRINT(w, CSR0_P, SENTSTALL);
MUSB_FLAGS_PRINT(w, CSR0, TXPKTRDY);
MUSB_FLAGS_PRINT(w, CSR0, RXPKTRDY);
}
static inline void musb_print_intrusb(u8 b)
{
serial_printf("\tintrusb 0x%2.2x\n", b);
MUSB_FLAGS_PRINT(b, INTR, VBUSERROR);
MUSB_FLAGS_PRINT(b, INTR, SESSREQ);
MUSB_FLAGS_PRINT(b, INTR, DISCONNECT);
MUSB_FLAGS_PRINT(b, INTR, CONNECT);
MUSB_FLAGS_PRINT(b, INTR, SOF);
MUSB_FLAGS_PRINT(b, INTR, RESUME);
MUSB_FLAGS_PRINT(b, INTR, SUSPEND);
if (b & MUSB_INTR_BABBLE)
serial_printf("\t\tMUSB_INTR_RESET or MUSB_INTR_BABBLE\n");
}
static inline void musb_print_intrtx(u16 w)
{
serial_printf("\tintrtx 0x%4.4x\n", w);
}
static inline void musb_print_intrrx(u16 w)
{
serial_printf("\tintrx 0x%4.4x\n", w);
}
static inline void musb_print_devctl(u8 b)
{
serial_printf("\tdevctl 0x%2.2x\n", b);
if (b & MUSB_DEVCTL_BDEVICE)
serial_printf("\t\tB device\n");
else
serial_printf("\t\tA device\n");
if (b & MUSB_DEVCTL_FSDEV)
serial_printf("\t\tFast Device -(host mode)\n");
if (b & MUSB_DEVCTL_LSDEV)
serial_printf("\t\tSlow Device -(host mode)\n");
if (b & MUSB_DEVCTL_HM)
serial_printf("\t\tHost mode\n");
else
serial_printf("\t\tPeripherial mode\n");
if (b & MUSB_DEVCTL_HR)
serial_printf("\t\tHost request started(B device)\n");
else
serial_printf("\t\tHost request finished(B device)\n");
if (b & MUSB_DEVCTL_BDEVICE) {
if (b & MUSB_DEVCTL_SESSION)
serial_printf("\t\tStart of session(B device)\n");
else
serial_printf("\t\tEnd of session(B device)\n");
} else {
if (b & MUSB_DEVCTL_SESSION)
serial_printf("\t\tStart of session(A device)\n");
else
serial_printf("\t\tEnd of session(A device)\n");
}
}
static inline void musb_print_config(u8 b)
{
serial_printf("\tconfig 0x%2.2x\n", b);
if (b & MUSB_CONFIGDATA_MPRXE)
serial_printf("\t\tAuto combine rx bulk packets\n");
if (b & MUSB_CONFIGDATA_MPTXE)
serial_printf("\t\tAuto split tx bulk packets\n");
if (b & MUSB_CONFIGDATA_BIGENDIAN)
serial_printf("\t\tBig Endian ordering\n");
else
serial_printf("\t\tLittle Endian ordering\n");
if (b & MUSB_CONFIGDATA_HBRXE)
serial_printf("\t\tHigh speed rx iso endpoint\n");
if (b & MUSB_CONFIGDATA_HBTXE)
serial_printf("\t\tHigh speed tx iso endpoint\n");
if (b & MUSB_CONFIGDATA_DYNFIFO)
serial_printf("\t\tDynamic fifo sizing\n");
if (b & MUSB_CONFIGDATA_SOFTCONE)
serial_printf("\t\tSoft Connect\n");
if (b & MUSB_CONFIGDATA_UTMIDW)
serial_printf("\t\t16 bit data width\n");
else
serial_printf("\t\t8 bit data width\n");
}
static inline void musb_print_rxmaxp(u16 w)
{
serial_printf("\trxmaxp 0x%4.4x\n", w);
}
static inline void musb_print_rxcsr(u16 w)
{
serial_printf("\trxcsr 0x%4.4x\n", w);
MUSB_FLAGS_PRINT(w, RXCSR, AUTOCLEAR);
MUSB_FLAGS_PRINT(w, RXCSR, DMAENAB);
MUSB_FLAGS_PRINT(w, RXCSR, DISNYET);
MUSB_FLAGS_PRINT(w, RXCSR, PID_ERR);
MUSB_FLAGS_PRINT(w, RXCSR, DMAMODE);
MUSB_FLAGS_PRINT(w, RXCSR, CLRDATATOG);
MUSB_FLAGS_PRINT(w, RXCSR, FLUSHFIFO);
MUSB_FLAGS_PRINT(w, RXCSR, DATAERROR);
MUSB_FLAGS_PRINT(w, RXCSR, FIFOFULL);
MUSB_FLAGS_PRINT(w, RXCSR, RXPKTRDY);
MUSB_FLAGS_PRINT(w, RXCSR_P, SENTSTALL);
MUSB_FLAGS_PRINT(w, RXCSR_P, SENDSTALL);
MUSB_FLAGS_PRINT(w, RXCSR_P, OVERRUN);
if (w & MUSB_RXCSR_P_ISO)
serial_printf("\t\tiso mode\n");
else
serial_printf("\t\tbulk mode\n");
}
static inline void musb_print_txmaxp(u16 w)
{
serial_printf("\ttxmaxp 0x%4.4x\n", w);
}
static inline void musb_print_txcsr(u16 w)
{
serial_printf("\ttxcsr 0x%4.4x\n", w);
MUSB_FLAGS_PRINT(w, TXCSR, TXPKTRDY);
MUSB_FLAGS_PRINT(w, TXCSR, FIFONOTEMPTY);
MUSB_FLAGS_PRINT(w, TXCSR, FLUSHFIFO);
MUSB_FLAGS_PRINT(w, TXCSR, CLRDATATOG);
MUSB_FLAGS_PRINT(w, TXCSR_P, UNDERRUN);
MUSB_FLAGS_PRINT(w, TXCSR_P, SENTSTALL);
MUSB_FLAGS_PRINT(w, TXCSR_P, SENDSTALL);
if (w & MUSB_TXCSR_MODE)
serial_printf("\t\tTX mode\n");
else
serial_printf("\t\tRX mode\n");
}
#else
/* stubs */
#define musb_print_pwr(b)
#define musb_print_csr0(w)
#define musb_print_intrusb(b)
#define musb_print_intrtx(w)
#define musb_print_intrrx(w)
#define musb_print_devctl(b)
#define musb_print_config(b)
#define musb_print_rxmaxp(w)
#define musb_print_rxcsr(w)
#define musb_print_txmaxp(w)
#define musb_print_txcsr(w)
#endif /* MUSB_DEBUG */

View File

@ -803,7 +803,7 @@ void usb_event_poll()
{
struct stdio_dev *dev;
struct usb_device *usb_kbd_dev;
struct usb_interface_descriptor *iface;
struct usb_interface *iface;
struct usb_endpoint_descriptor *ep;
int pipe;
int maxp;

963
drivers/usb/musb/musb_udc.c Normal file
View File

@ -0,0 +1,963 @@
/*
* Copyright (c) 2009 Wind River Systems, Inc.
* Tom Rix <Tom.Rix@windriver.com>
*
* This file is a rewrite of the usb device part of
* repository git.omapzoom.org/repo/u-boot.git, branch master,
* file cpu/omap3/fastboot.c
*
* This is the unique part of its copyright :
*
* -------------------------------------------------------------------------
*
* (C) Copyright 2008 - 2009
* Windriver, <www.windriver.com>
* Tom Rix <Tom.Rix@windriver.com>
*
* -------------------------------------------------------------------------
*
* The details of connecting the device to the uboot usb device subsystem
* came from the old omap3 repository www.sakoman.net/u-boot-omap3.git,
* branch omap3-dev-usb, file drivers/usb/usbdcore_musb.c
*
* This is the unique part of its copyright :
*
* -------------------------------------------------------------------------
*
* (C) Copyright 2008 Texas Instruments Incorporated.
*
* Based on
* u-boot OMAP1510 USB drivers (drivers/usbdcore_omap1510.c)
* twl4030 init based on linux (drivers/i2c/chips/twl4030_usb.c)
*
* Author: Diego Dompe (diego.dompe@ridgerun.com)
* Atin Malaviya (atin.malaviya@gmail.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; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <usb/musb_udc.h>
#include "../gadget/ep0.h"
#include "musb_core.h"
#if defined(CONFIG_USB_OMAP3)
#include "omap3.h"
#elif defined(CONFIG_USB_DAVINCI)
#include "davinci.h"
#endif
/* Define MUSB_DEBUG for debugging */
/* #define MUSB_DEBUG */
#include "musb_debug.h"
#define MAX_ENDPOINT 15
#define GET_ENDPOINT(dev,ep) \
(((struct usb_device_instance *)(dev))->bus->endpoint_array + ep)
#define SET_EP0_STATE(s) \
do { \
if ((0 <= (s)) && (SET_ADDRESS >= (s))) { \
if ((s) != ep0_state) { \
if ((debug_setup) && (debug_level > 1)) \
serial_printf("INFO : Changing state " \
"from %s to %s in %s at " \
"line %d\n", \
ep0_state_strings[ep0_state],\
ep0_state_strings[s], \
__PRETTY_FUNCTION__, \
__LINE__); \
ep0_state = s; \
} \
} else { \
if (debug_level > 0) \
serial_printf("Error at %s %d with setting " \
"state %d is invalid\n", \
__PRETTY_FUNCTION__, __LINE__, s); \
} \
} while (0)
/* static implies these initialized to 0 or NULL */
static int debug_setup;
static int debug_level;
static struct musb_epinfo epinfo[MAX_ENDPOINT * 2];
static enum ep0_state_enum {
IDLE = 0,
TX,
RX,
SET_ADDRESS
} ep0_state = IDLE;
static char *ep0_state_strings[4] = {
"IDLE",
"TX",
"RX",
"SET_ADDRESS",
};
static struct urb *ep0_urb;
struct usb_endpoint_instance *ep0_endpoint;
static struct usb_device_instance *udc_device;
static int enabled;
#ifdef MUSB_DEBUG
static void musb_db_regs(void)
{
u8 b;
u16 w;
b = readb(&musbr->faddr);
serial_printf("\tfaddr 0x%2.2x\n", b);
b = readb(&musbr->power);
musb_print_pwr(b);
w = readw(&musbr->ep[0].ep0.csr0);
musb_print_csr0(w);
b = readb(&musbr->devctl);
musb_print_devctl(b);
b = readb(&musbr->ep[0].ep0.configdata);
musb_print_config(b);
w = readw(&musbr->frame);
serial_printf("\tframe 0x%4.4x\n", w);
b = readb(&musbr->index);
serial_printf("\tindex 0x%2.2x\n", b);
w = readw(&musbr->ep[1].epN.rxmaxp);
musb_print_rxmaxp(w);
w = readw(&musbr->ep[1].epN.rxcsr);
musb_print_rxcsr(w);
w = readw(&musbr->ep[1].epN.txmaxp);
musb_print_txmaxp(w);
w = readw(&musbr->ep[1].epN.txcsr);
musb_print_txcsr(w);
}
#else
#define musb_db_regs()
#endif /* DEBUG_MUSB */
static void musb_peri_softconnect(void)
{
u8 power, devctl;
u8 intrusb;
u16 intrrx, intrtx;
/* Power off MUSB */
power = readb(&musbr->power);
power &= ~MUSB_POWER_SOFTCONN;
writeb(power, &musbr->power);
/* Read intr to clear */
intrusb = readb(&musbr->intrusb);
intrrx = readw(&musbr->intrrx);
intrtx = readw(&musbr->intrtx);
udelay(1000 * 1000); /* 1 sec */
/* Power on MUSB */
power = readb(&musbr->power);
power |= MUSB_POWER_SOFTCONN;
/*
* The usb device interface is usb 1.1
* Disable 2.0 high speed by clearring the hsenable bit.
*/
power &= ~MUSB_POWER_HSENAB;
writeb(power, &musbr->power);
/* Check if device is in b-peripheral mode */
devctl = readb(&musbr->devctl);
if (!(devctl & MUSB_DEVCTL_BDEVICE) ||
(devctl & MUSB_DEVCTL_HM)) {
serial_printf("ERROR : Unsupport USB mode\n");
serial_printf("Check that mini-B USB cable is attached "
"to the device\n");
}
if (debug_setup && (debug_level > 1))
musb_db_regs();
}
static void musb_peri_reset(void)
{
if ((debug_setup) && (debug_level > 1))
serial_printf("INFO : %s reset\n", __PRETTY_FUNCTION__);
if (ep0_endpoint)
ep0_endpoint->endpoint_address = 0xff;
/* Sync sw and hw addresses */
writeb(udc_device->address, &musbr->faddr);
SET_EP0_STATE(IDLE);
}
static void musb_peri_resume(void)
{
/* noop */
}
static void musb_peri_ep0_stall(void)
{
u16 csr0;
csr0 = readw(&musbr->ep[0].ep0.csr0);
csr0 |= MUSB_CSR0_P_SENDSTALL;
writew(csr0, &musbr->ep[0].ep0.csr0);
if ((debug_setup) && (debug_level > 1))
serial_printf("INFO : %s stall\n", __PRETTY_FUNCTION__);
}
static void musb_peri_ep0_ack_req(void)
{
u16 csr0;
csr0 = readw(&musbr->ep[0].ep0.csr0);
csr0 |= MUSB_CSR0_P_SVDRXPKTRDY;
writew(csr0, &musbr->ep[0].ep0.csr0);
}
static void musb_ep0_tx_ready(void)
{
u16 csr0;
csr0 = readw(&musbr->ep[0].ep0.csr0);
csr0 |= MUSB_CSR0_TXPKTRDY;
writew(csr0, &musbr->ep[0].ep0.csr0);
}
static void musb_ep0_tx_ready_and_last(void)
{
u16 csr0;
csr0 = readw(&musbr->ep[0].ep0.csr0);
csr0 |= (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_P_DATAEND);
writew(csr0, &musbr->ep[0].ep0.csr0);
}
static void musb_peri_ep0_last(void)
{
u16 csr0;
csr0 = readw(&musbr->ep[0].ep0.csr0);
csr0 |= MUSB_CSR0_P_DATAEND;
writew(csr0, &musbr->ep[0].ep0.csr0);
}
static void musb_peri_ep0_set_address(void)
{
u8 faddr;
writeb(udc_device->address, &musbr->faddr);
/* Verify */
faddr = readb(&musbr->faddr);
if (udc_device->address == faddr) {
SET_EP0_STATE(IDLE);
usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
if ((debug_setup) && (debug_level > 1))
serial_printf("INFO : %s Address set to %d\n",
__PRETTY_FUNCTION__, udc_device->address);
} else {
if (debug_level > 0)
serial_printf("ERROR : %s Address missmatch "
"sw %d vs hw %d\n",
__PRETTY_FUNCTION__,
udc_device->address, faddr);
}
}
static void musb_peri_rx_ack(unsigned int ep)
{
u16 peri_rxcsr;
peri_rxcsr = readw(&musbr->ep[ep].epN.rxcsr);
peri_rxcsr &= ~MUSB_RXCSR_RXPKTRDY;
writew(peri_rxcsr, &musbr->ep[ep].epN.rxcsr);
}
static void musb_peri_tx_ready(unsigned int ep)
{
u16 peri_txcsr;
peri_txcsr = readw(&musbr->ep[ep].epN.txcsr);
peri_txcsr |= MUSB_TXCSR_TXPKTRDY;
writew(peri_txcsr, &musbr->ep[ep].epN.txcsr);
}
static void musb_peri_ep0_zero_data_request(int err)
{
musb_peri_ep0_ack_req();
if (err) {
musb_peri_ep0_stall();
SET_EP0_STATE(IDLE);
} else {
musb_peri_ep0_last();
/* USBD state */
switch (ep0_urb->device_request.bRequest) {
case USB_REQ_SET_ADDRESS:
if ((debug_setup) && (debug_level > 1))
serial_printf("INFO : %s received set "
"address\n", __PRETTY_FUNCTION__);
break;
case USB_REQ_SET_CONFIGURATION:
if ((debug_setup) && (debug_level > 1))
serial_printf("INFO : %s Configured\n",
__PRETTY_FUNCTION__);
usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
break;
}
/* EP0 state */
if (USB_REQ_SET_ADDRESS == ep0_urb->device_request.bRequest) {
SET_EP0_STATE(SET_ADDRESS);
} else {
SET_EP0_STATE(IDLE);
}
}
}
static void musb_peri_ep0_rx_data_request(void)
{
/*
* This is the completion of the data OUT / RX
*
* Host is sending data to ep0 that is not
* part of setup. This comes from the cdc_recv_setup
* op that is device specific.
*
*/
musb_peri_ep0_ack_req();
ep0_endpoint->rcv_urb = ep0_urb;
ep0_urb->actual_length = 0;
SET_EP0_STATE(RX);
}
static void musb_peri_ep0_tx_data_request(int err)
{
if (err) {
musb_peri_ep0_stall();
SET_EP0_STATE(IDLE);
} else {
musb_peri_ep0_ack_req();
ep0_endpoint->tx_urb = ep0_urb;
ep0_endpoint->sent = 0;
SET_EP0_STATE(TX);
}
}
static void musb_peri_ep0_idle(void)
{
u16 count0;
int err;
u16 csr0;
/*
* Verify addresses
* A lot of confusion can be caused if the address
* in software, udc layer, does not agree with the
* hardware. Since the setting of the hardware address
* must be set after the set address request, the
* usb state machine is out of sync for a few frame.
* It is a good idea to run this check when changes
* are made to the state machine.
*/
if ((debug_level > 0) &&
(ep0_state != SET_ADDRESS)) {
u8 faddr;
faddr = readb(&musbr->faddr);
if (udc_device->address != faddr) {
serial_printf("ERROR : %s addresses do not"
"match sw %d vs hw %d\n",
__PRETTY_FUNCTION__,
udc_device->address, faddr);
udelay(1000 * 1000);
hang();
}
}
csr0 = readw(&musbr->ep[0].ep0.csr0);
if (!(MUSB_CSR0_RXPKTRDY & csr0))
goto end;
count0 = readw(&musbr->ep[0].ep0.count0);
if (count0 == 0)
goto end;
if (count0 != 8) {
if ((debug_setup) && (debug_level > 1))
serial_printf("WARN : %s SETUP incorrect size %d\n",
__PRETTY_FUNCTION__, count0);
musb_peri_ep0_stall();
goto end;
}
read_fifo(0, count0, &ep0_urb->device_request);
if (debug_level > 2)
print_usb_device_request(&ep0_urb->device_request);
if (ep0_urb->device_request.wLength == 0) {
err = ep0_recv_setup(ep0_urb);
/* Zero data request */
musb_peri_ep0_zero_data_request(err);
} else {
/* Is data coming or going ? */
u8 reqType = ep0_urb->device_request.bmRequestType;
if (USB_REQ_DEVICE2HOST == (reqType & USB_REQ_DIRECTION_MASK)) {
err = ep0_recv_setup(ep0_urb);
/* Device to host */
musb_peri_ep0_tx_data_request(err);
} else {
/*
* Host to device
*
* The RX routine will call ep0_recv_setup
* when the data packet has arrived.
*/
musb_peri_ep0_rx_data_request();
}
}
end:
return;
}
static void musb_peri_ep0_rx(void)
{
/*
* This is the completion of the data OUT / RX
*
* Host is sending data to ep0 that is not
* part of setup. This comes from the cdc_recv_setup
* op that is device specific.
*
* Pass the data back to driver ep0_recv_setup which
* should give the cdc_recv_setup the chance to handle
* the rx
*/
u16 csr0;
u16 count0;
if (debug_level > 3) {
if (0 != ep0_urb->actual_length) {
serial_printf("%s finished ? %d of %d\n",
__PRETTY_FUNCTION__,
ep0_urb->actual_length,
ep0_urb->device_request.wLength);
}
}
if (ep0_urb->device_request.wLength == ep0_urb->actual_length) {
musb_peri_ep0_last();
SET_EP0_STATE(IDLE);
ep0_recv_setup(ep0_urb);
return;
}
csr0 = readw(&musbr->ep[0].ep0.csr0);
if (!(MUSB_CSR0_RXPKTRDY & csr0))
return;
count0 = readw(&musbr->ep[0].ep0.count0);
if (count0) {
struct usb_endpoint_instance *endpoint;
u32 length;
u8 *data;
endpoint = ep0_endpoint;
if (endpoint && endpoint->rcv_urb) {
struct urb *urb = endpoint->rcv_urb;
unsigned int remaining_space = urb->buffer_length -
urb->actual_length;
if (remaining_space) {
int urb_bad = 0; /* urb is good */
if (count0 > remaining_space)
length = remaining_space;
else
length = count0;
data = (u8 *) urb->buffer_data;
data += urb->actual_length;
/* The common musb fifo reader */
read_fifo(0, length, data);
musb_peri_ep0_ack_req();
/*
* urb's actual_length is updated in
* usbd_rcv_complete
*/
usbd_rcv_complete(endpoint, length, urb_bad);
} else {
if (debug_level > 0)
serial_printf("ERROR : %s no space in "
"rcv buffer\n",
__PRETTY_FUNCTION__);
}
} else {
if (debug_level > 0)
serial_printf("ERROR : %s problem with "
"endpoint\n",
__PRETTY_FUNCTION__);
}
} else {
if (debug_level > 0)
serial_printf("ERROR : %s with nothing to do\n",
__PRETTY_FUNCTION__);
}
}
static void musb_peri_ep0_tx(void)
{
u16 csr0;
int transfer_size = 0;
unsigned int p, pm;
csr0 = readw(&musbr->ep[0].ep0.csr0);
/* Check for pending tx */
if (csr0 & MUSB_CSR0_TXPKTRDY)
goto end;
/* Check if this is the last packet sent */
if (ep0_endpoint->sent >= ep0_urb->actual_length) {
SET_EP0_STATE(IDLE);
goto end;
}
transfer_size = ep0_urb->actual_length - ep0_endpoint->sent;
/* Is the transfer size negative ? */
if (transfer_size <= 0) {
if (debug_level > 0)
serial_printf("ERROR : %s problem with the"
" transfer size %d\n",
__PRETTY_FUNCTION__,
transfer_size);
SET_EP0_STATE(IDLE);
goto end;
}
/* Truncate large transfers to the fifo size */
if (transfer_size > ep0_endpoint->tx_packetSize)
transfer_size = ep0_endpoint->tx_packetSize;
write_fifo(0, transfer_size, &ep0_urb->buffer[ep0_endpoint->sent]);
ep0_endpoint->sent += transfer_size;
/* Done or more to send ? */
if (ep0_endpoint->sent >= ep0_urb->actual_length)
musb_ep0_tx_ready_and_last();
else
musb_ep0_tx_ready();
/* Wait a bit */
pm = 10;
for (p = 0; p < pm; p++) {
csr0 = readw(&musbr->ep[0].ep0.csr0);
if (!(csr0 & MUSB_CSR0_TXPKTRDY))
break;
/* Double the delay. */
udelay(1 << pm);
}
if ((ep0_endpoint->sent >= ep0_urb->actual_length) && (p < pm))
SET_EP0_STATE(IDLE);
end:
return;
}
static void musb_peri_ep0(void)
{
u16 csr0;
if (SET_ADDRESS == ep0_state)
return;
csr0 = readw(&musbr->ep[0].ep0.csr0);
/* Error conditions */
if (MUSB_CSR0_P_SENTSTALL & csr0) {
csr0 &= ~MUSB_CSR0_P_SENTSTALL;
writew(csr0, &musbr->ep[0].ep0.csr0);
SET_EP0_STATE(IDLE);
}
if (MUSB_CSR0_P_SETUPEND & csr0) {
csr0 |= MUSB_CSR0_P_SVDSETUPEND;
writew(csr0, &musbr->ep[0].ep0.csr0);
SET_EP0_STATE(IDLE);
if ((debug_setup) && (debug_level > 1))
serial_printf("WARN: %s SETUPEND\n",
__PRETTY_FUNCTION__);
}
/* Normal states */
if (IDLE == ep0_state)
musb_peri_ep0_idle();
if (TX == ep0_state)
musb_peri_ep0_tx();
if (RX == ep0_state)
musb_peri_ep0_rx();
}
static void musb_peri_rx_ep(unsigned int ep)
{
u16 peri_rxcount = readw(&musbr->ep[ep].epN.rxcount);
if (peri_rxcount) {
struct usb_endpoint_instance *endpoint;
u32 length;
u8 *data;
endpoint = GET_ENDPOINT(udc_device, ep);
if (endpoint && endpoint->rcv_urb) {
struct urb *urb = endpoint->rcv_urb;
unsigned int remaining_space = urb->buffer_length -
urb->actual_length;
if (remaining_space) {
int urb_bad = 0; /* urb is good */
if (peri_rxcount > remaining_space)
length = remaining_space;
else
length = peri_rxcount;
data = (u8 *) urb->buffer_data;
data += urb->actual_length;
/* The common musb fifo reader */
read_fifo(ep, length, data);
musb_peri_rx_ack(ep);
/*
* urb's actual_length is updated in
* usbd_rcv_complete
*/
usbd_rcv_complete(endpoint, length, urb_bad);
} else {
if (debug_level > 0)
serial_printf("ERROR : %s %d no space "
"in rcv buffer\n",
__PRETTY_FUNCTION__, ep);
}
} else {
if (debug_level > 0)
serial_printf("ERROR : %s %d problem with "
"endpoint\n",
__PRETTY_FUNCTION__, ep);
}
} else {
if (debug_level > 0)
serial_printf("ERROR : %s %d with nothing to do\n",
__PRETTY_FUNCTION__, ep);
}
}
static void musb_peri_rx(u16 intr)
{
unsigned int ep;
/* Check for EP0 */
if (0x01 & intr)
musb_peri_ep0();
for (ep = 1; ep < 16; ep++) {
if ((1 << ep) & intr)
musb_peri_rx_ep(ep);
}
}
static void musb_peri_tx(u16 intr)
{
/* Check for EP0 */
if (0x01 & intr)
musb_peri_ep0_tx();
/*
* Use this in the future when handling epN tx
*
* u8 ep;
*
* for (ep = 1; ep < 16; ep++) {
* if ((1 << ep) & intr) {
* / * handle tx for this endpoint * /
* }
* }
*/
}
void udc_irq(void)
{
/* This is a high freq called function */
if (enabled) {
u8 intrusb;
intrusb = readb(&musbr->intrusb);
/*
* See drivers/usb/gadget/mpc8xx_udc.c for
* state diagram going from detached through
* configuration.
*/
if (MUSB_INTR_RESUME & intrusb) {
usbd_device_event_irq(udc_device,
DEVICE_BUS_ACTIVITY, 0);
musb_peri_resume();
}
musb_peri_ep0();
if (MUSB_INTR_RESET & intrusb) {
usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
musb_peri_reset();
}
if (MUSB_INTR_DISCONNECT & intrusb) {
/* cable unplugged from hub/host */
usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
musb_peri_reset();
usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0);
}
if (MUSB_INTR_SOF & intrusb) {
usbd_device_event_irq(udc_device,
DEVICE_BUS_ACTIVITY, 0);
musb_peri_resume();
}
if (MUSB_INTR_SUSPEND & intrusb) {
usbd_device_event_irq(udc_device,
DEVICE_BUS_INACTIVE, 0);
}
if (ep0_state != SET_ADDRESS) {
u16 intrrx, intrtx;
intrrx = readw(&musbr->intrrx);
intrtx = readw(&musbr->intrtx);
if (intrrx)
musb_peri_rx(intrrx);
if (intrtx)
musb_peri_tx(intrtx);
} else {
if (MUSB_INTR_SOF & intrusb) {
u8 faddr;
faddr = readb(&musbr->faddr);
/*
* Setting of the address can fail.
* Normally it succeeds the second time.
*/
if (udc_device->address != faddr)
musb_peri_ep0_set_address();
}
}
}
}
void udc_set_nak(int ep_num)
{
/* noop */
}
void udc_unset_nak(int ep_num)
{
/* noop */
}
int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
{
int ret = 0;
/* Transmit only if the hardware is available */
if (endpoint->tx_urb && endpoint->state == 0) {
unsigned int ep = endpoint->endpoint_address &
USB_ENDPOINT_NUMBER_MASK;
u16 peri_txcsr = readw(&musbr->ep[ep].epN.txcsr);
/* Error conditions */
if (peri_txcsr & MUSB_TXCSR_P_UNDERRUN) {
peri_txcsr &= ~MUSB_TXCSR_P_UNDERRUN;
writew(peri_txcsr, &musbr->ep[ep].epN.txcsr);
}
if (debug_level > 1)
musb_print_txcsr(peri_txcsr);
/* Check if a packet is waiting to be sent */
if (!(peri_txcsr & MUSB_TXCSR_TXPKTRDY)) {
u32 length;
u8 *data;
struct urb *urb = endpoint->tx_urb;
unsigned int remaining_packet = urb->actual_length -
endpoint->sent;
if (endpoint->tx_packetSize < remaining_packet)
length = endpoint->tx_packetSize;
else
length = remaining_packet;
data = (u8 *) urb->buffer;
data += endpoint->sent;
/* common musb fifo function */
write_fifo(ep, length, data);
musb_peri_tx_ready(ep);
endpoint->last = length;
/* usbd_tx_complete will take care of updating 'sent' */
usbd_tx_complete(endpoint);
}
} else {
if (debug_level > 0)
serial_printf("ERROR : %s Problem with urb %p "
"or ep state %d\n",
__PRETTY_FUNCTION__,
endpoint->tx_urb, endpoint->state);
}
return ret;
}
void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
struct usb_endpoint_instance *endpoint)
{
if (0 == id) {
/* EP0 */
ep0_endpoint = endpoint;
ep0_endpoint->endpoint_address = 0xff;
ep0_urb = usbd_alloc_urb(device, endpoint);
} else if (MAX_ENDPOINT >= id) {
int ep_addr;
/* Check the direction */
ep_addr = endpoint->endpoint_address;
if (USB_DIR_IN == (ep_addr & USB_ENDPOINT_DIR_MASK)) {
/* IN */
epinfo[(id * 2) + 1].epsize = endpoint->tx_packetSize;
} else {
/* OUT */
epinfo[id * 2].epsize = endpoint->rcv_packetSize;
}
musb_configure_ep(&epinfo[0],
sizeof(epinfo) / sizeof(struct musb_epinfo));
} else {
if (debug_level > 0)
serial_printf("ERROR : %s endpoint request %d "
"exceeds maximum %d\n",
__PRETTY_FUNCTION__, id, MAX_ENDPOINT);
}
}
void udc_connect(void)
{
/* noop */
}
void udc_disconnect(void)
{
/* noop */
}
void udc_enable(struct usb_device_instance *device)
{
/* Save the device structure pointer */
udc_device = device;
enabled = 1;
}
void udc_disable(void)
{
enabled = 0;
}
void udc_startup_events(struct usb_device_instance *device)
{
/* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
usbd_device_event_irq(device, DEVICE_INIT, 0);
/*
* The DEVICE_CREATE event puts the USB device in the state
* STATE_ATTACHED.
*/
usbd_device_event_irq(device, DEVICE_CREATE, 0);
/* Resets the address to 0 */
usbd_device_event_irq(device, DEVICE_RESET, 0);
udc_enable(device);
}
int udc_init(void)
{
int ret;
int ep_loop;
ret = musb_platform_init();
if (ret < 0)
goto end;
/* Configure all the endpoint FIFO's and start usb controller */
musbr = musb_cfg.regs;
/* Initialize the endpoints */
for (ep_loop = 0; ep_loop < MAX_ENDPOINT * 2; ep_loop++) {
epinfo[ep_loop].epnum = (ep_loop / 2) + 1;
epinfo[ep_loop].epdir = ep_loop % 2; /* OUT, IN */
epinfo[ep_loop].epsize = 0;
}
musb_peri_softconnect();
ret = 0;
end:
return ret;
}

134
drivers/usb/musb/omap3.c Normal file
View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2009 Wind River Systems, Inc.
* Tom Rix <Tom.Rix@windriver.com>
*
* This is file is based on
* repository git.gitorious.org/u-boot-omap3/mainline.git,
* branch omap3-dev-usb, file drivers/usb/host/omap3530_usb.c
*
* This is the unique part of its copyright :
*
* ------------------------------------------------------------------------
*
* Copyright (c) 2009 Texas Instruments
*
* ------------------------------------------------------------------------
*
* 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; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <twl4030.h>
#include "omap3.h"
static int platform_needs_initialization = 1;
struct musb_config musb_cfg = {
(struct musb_regs *)MENTOR_USB0_BASE,
OMAP3_USB_TIMEOUT,
0
};
/*
* OMAP3 USB OTG registers.
*/
struct omap3_otg_regs {
u32 revision;
u32 sysconfig;
u32 sysstatus;
u32 interfsel;
u32 simenable;
u32 forcestdby;
};
static struct omap3_otg_regs *otg;
#define OMAP3_OTG_SYSCONFIG_SMART_STANDBY_MODE 0x2000
#define OMAP3_OTG_SYSCONFIG_NO_STANDBY_MODE 0x1000
#define OMAP3_OTG_SYSCONFIG_SMART_IDLE_MODE 0x0010
#define OMAP3_OTG_SYSCONFIG_NO_IDLE_MODE 0x0008
#define OMAP3_OTG_SYSCONFIG_ENABLEWAKEUP 0x0004
#define OMAP3_OTG_SYSCONFIG_SOFTRESET 0x0002
#define OMAP3_OTG_SYSCONFIG_AUTOIDLE 0x0001
#define OMAP3_OTG_SYSSTATUS_RESETDONE 0x0001
#define OMAP3_OTG_INTERFSEL_OMAP 0x0001
#define OMAP3_OTG_FORCESTDBY_STANDBY 0x0001
#ifdef DEBUG_MUSB_OMAP3
static void musb_db_otg_regs(void)
{
u32 l;
l = readl(&otg->revision);
serial_printf("OTG_REVISION 0x%x\n", l);
l = readl(&otg->sysconfig);
serial_printf("OTG_SYSCONFIG 0x%x\n", l);
l = readl(&otg->sysstatus);
serial_printf("OTG_SYSSTATUS 0x%x\n", l);
l = readl(&otg->interfsel);
serial_printf("OTG_INTERFSEL 0x%x\n", l);
l = readl(&otg->forcestdby);
serial_printf("OTG_FORCESTDBY 0x%x\n", l);
}
#endif
int musb_platform_init(void)
{
int ret = -1;
if (platform_needs_initialization) {
u32 stdby;
/*
* OMAP3EVM uses ISP1504 phy and so
* twl4030 related init is not required.
*/
#ifdef CONFIG_TWL4030_USB
if (twl4030_usb_ulpi_init()) {
serial_printf("ERROR: %s Could not initialize PHY\n",
__PRETTY_FUNCTION__);
goto end;
}
#endif
otg = (struct omap3_otg_regs *)OMAP3_OTG_BASE;
/* Set OTG to always be on */
writel(OMAP3_OTG_SYSCONFIG_NO_STANDBY_MODE |
OMAP3_OTG_SYSCONFIG_NO_IDLE_MODE, &otg->sysconfig);
/* Set the interface */
writel(OMAP3_OTG_INTERFSEL_OMAP, &otg->interfsel);
/* Clear force standby */
stdby = readl(&otg->forcestdby);
stdby &= ~OMAP3_OTG_FORCESTDBY_STANDBY;
writel(stdby, &otg->forcestdby);
platform_needs_initialization = 0;
}
ret = platform_needs_initialization;
end:
return ret;
}
void musb_platform_deinit(void)
{
/* noop */
}

48
drivers/usb/musb/omap3.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2009 Wind River Systems, Inc.
* Tom Rix <Tom.Rix@windriver.com>
*
* This file is based on the file drivers/usb/musb/davinci.h
*
* This is the unique part of its copyright:
*
* --------------------------------------------------------------------
*
* Copyright (c) 2008 Texas Instruments
* Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
*
* --------------------------------------------------------------------
*
* 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; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef _MUSB_OMAP3_H_
#define _MUSB_OMAP3_H_
#include "musb_core.h"
/* Base address of MUSB registers */
#define MENTOR_USB0_BASE (OMAP34XX_CORE_L4_IO_BASE + 0xAB000)
/* Base address of OTG registers */
#define OMAP3_OTG_BASE (MENTOR_USB0_BASE + 0x400)
/* Timeout for USB module */
#define OMAP3_USB_TIMEOUT 0x3FFFFFF
int musb_platform_init(void);
#endif /* _MUSB_OMAP3_H */

44
drivers/usb/phy/Makefile Normal file
View File

@ -0,0 +1,44 @@
#
# Copyright (c) 2009 Wind River Systems, Inc.
# Tom Rix <Tom.Rix@windriver.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; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
include $(TOPDIR)/config.mk
LIB := $(obj)libusb_phy.a
COBJS-$(CONFIG_TWL4030_USB) += twl4030.o
COBJS-y := twl4030.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
all: $(LIB)
$(LIB): $(obj).depend $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

189
drivers/usb/phy/twl4030.c Normal file
View File

@ -0,0 +1,189 @@
/*
* Copyright (c) 2009 Wind River Systems, Inc.
* Tom Rix <Tom.Rix@windriver.com>
*
* This is file is based on
* repository git.gitorious.org/u-boot-omap3/mainline.git,
* branch omap3-dev-usb, file drivers/usb/gadget/twl4030_usb.c
*
* This is the unique part of its copyright :
*
* ------------------------------------------------------------------------
*
* * (C) Copyright 2009 Atin Malaviya (atin.malaviya@gmail.com)
*
* Based on: twl4030_usb.c in linux 2.6 (drivers/i2c/chips/twl4030_usb.c)
* Copyright (C) 2004-2007 Texas Instruments
* Copyright (C) 2008 Nokia Corporation
* Contact: Felipe Balbi <felipe.balbi@nokia.com>
*
* Author: Atin Malaviya (atin.malaviya@gmail.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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <twl4030.h>
/* Defines for bits in registers */
#define OPMODE_MASK (3 << 3)
#define XCVRSELECT_MASK (3 << 0)
#define CARKITMODE (1 << 2)
#define OTG_ENAB (1 << 5)
#define PHYPWD (1 << 0)
#define CLOCKGATING_EN (1 << 2)
#define CLK32K_EN (1 << 1)
#define REQ_PHY_DPLL_CLK (1 << 0)
#define PHY_DPLL_CLK (1 << 0)
static int twl4030_usb_write(u8 address, u8 data)
{
int ret;
ret = twl4030_i2c_write_u8(TWL4030_CHIP_USB, data, address);
if (ret != 0)
printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
return ret;
}
static int twl4030_usb_read(u8 address)
{
u8 data;
int ret;
ret = twl4030_i2c_read_u8(TWL4030_CHIP_USB, &data, address);
if (ret == 0)
ret = data;
else
printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
return ret;
}
static void twl4030_usb_ldo_init(void)
{
/* Enable writing to power configuration registers */
twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0xC0,
TWL4030_PM_MASTER_PROTECT_KEY);
twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x0C,
TWL4030_PM_MASTER_PROTECT_KEY);
/* put VUSB3V1 LDO in active state */
twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
TWL4030_PM_RECEIVER_VUSB_DEDICATED2);
/* input to VUSB3V1 LDO is from VBAT, not VBUS */
twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x14,
TWL4030_PM_RECEIVER_VUSB_DEDICATED1);
/* turn on 3.1V regulator */
twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
TWL4030_PM_RECEIVER_VUSB3V1_DEV_GRP);
twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
TWL4030_PM_RECEIVER_VUSB3V1_TYPE);
/* turn on 1.5V regulator */
twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
TWL4030_PM_RECEIVER_VUSB1V5_DEV_GRP);
twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
TWL4030_PM_RECEIVER_VUSB1V5_TYPE);
/* turn on 1.8V regulator */
twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
TWL4030_PM_RECEIVER_VUSB1V8_DEV_GRP);
twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
TWL4030_PM_RECEIVER_VUSB1V8_TYPE);
/* disable access to power configuration registers */
twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x00,
TWL4030_PM_MASTER_PROTECT_KEY);
}
static void twl4030_phy_power(void)
{
u8 pwr, clk;
/* Power the PHY */
pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL);
pwr &= ~PHYPWD;
twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr);
/* Enable clocks */
clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
clk |= CLOCKGATING_EN | CLK32K_EN;
twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
}
/*
* Initiaze the ULPI interface
* ULPI : Universal Transceiver Macrocell Low Pin Interface
* An interface between the USB link controller like musb and the
* the PHY or transceiver that drives the actual bus.
*/
int twl4030_usb_ulpi_init(void)
{
long timeout = 1000 * 1000; /* 1 sec */;
u8 clk, sts, pwr;
/* twl4030 ldo init */
twl4030_usb_ldo_init();
/* Enable the twl4030 phy */
twl4030_phy_power();
/* Enable DPLL to access PHY registers over I2C */
clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
clk |= REQ_PHY_DPLL_CLK;
twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
/* Check if the PHY DPLL is locked */
sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
udelay(10);
sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
timeout -= 10;
}
/* Final check */
sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
if (!(sts & PHY_DPLL_CLK)) {
printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n");
return -1;
}
/*
* There are two circuit blocks attached to the PHY,
* Carkit and USB OTG. Disable Carkit and enable USB OTG
*/
twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE);
pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL);
pwr |= OTG_ENAB;
twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr);
/* Clear the opmode bits to ensure normal encode */
twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK);
/* Clear the xcvrselect bits to enable the high speed transeiver */
twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK);
/* Let ULPI control the DPLL clock */
clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
clk &= ~REQ_PHY_DPLL_CLK;
twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
return 0;
}

View File

@ -100,6 +100,21 @@
/* DDR - I use Micron DDR */
#define CONFIG_OMAP3_MICRON_DDR 1
/* USB */
#define CONFIG_MUSB_UDC 1
#define CONFIG_USB_OMAP3 1
#define CONFIG_TWL4030_USB 1
/* USB device configuration */
#define CONFIG_USB_DEVICE 1
#define CONFIG_USB_TTY 1
#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1
/* Change these to suit your needs */
#define CONFIG_USBD_VENDORID 0x0451
#define CONFIG_USBD_PRODUCTID 0x5678
#define CONFIG_USBD_MANUFACTURER "Texas Instruments"
#define CONFIG_USBD_PRODUCT_NAME "Beagle"
/* commands to include */
#include <config_cmd_default.h>
@ -164,6 +179,7 @@
#define CONFIG_EXTRA_ENV_SETTINGS \
"loadaddr=0x82000000\0" \
"usbtty=cdc_acm\0" \
"console=ttyS2,115200n8\0" \
"vram=12M\0" \
"dvimode=1024x768MR-16@60\0" \

View File

@ -104,6 +104,44 @@
/* DDR - I use Micron DDR */
#define CONFIG_OMAP3_MICRON_DDR 1
/* USB
* Enable CONFIG_MUSB_HCD for Host functionalities MSC, keyboard
* Enable CONFIG_MUSB_UDD for Device functionalities.
*/
#define CONFIG_USB_OMAP3 1
#define CONFIG_MUSB_HCD 1
/* #define CONFIG_MUSB_UDC 1 */
#ifdef CONFIG_USB_OMAP3
#ifdef CONFIG_MUSB_HCD
#define CONFIG_CMD_USB
#define CONFIG_USB_STORAGE
#define CONGIG_CMD_STORAGE
#define CONFIG_CMD_FAT
#ifdef CONFIG_USB_KEYBOARD
#define CONFIG_SYS_USB_EVENT_POLL
#define CONFIG_PREBOOT "usb start"
#endif /* CONFIG_USB_KEYBOARD */
#endif /* CONFIG_MUSB_HCD */
#ifdef CONFIG_MUSB_UDC
/* USB device configuration */
#define CONFIG_USB_DEVICE 1
#define CONFIG_USB_TTY 1
#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1
/* Change these to suit your needs */
#define CONFIG_USBD_VENDORID 0x0451
#define CONFIG_USBD_PRODUCTID 0x5678
#define CONFIG_USBD_MANUFACTURER "Texas Instruments"
#define CONFIG_USBD_PRODUCT_NAME "EVM"
#endif /* CONFIG_MUSB_UDC */
#endif /* CONFIG_USB_OMAP3 */
/* commands to include */
#include <config_cmd_default.h>
@ -160,6 +198,7 @@
#define CONFIG_EXTRA_ENV_SETTINGS \
"loadaddr=0x82000000\0" \
"usbtty=cdc_acm\0" \
"console=ttyS2,115200n8\0" \
"mmcargs=setenv bootargs console=${console} " \
"root=/dev/mmcblk0p2 rw " \

View File

@ -101,6 +101,21 @@
/* DDR - I use Micron DDR */
#define CONFIG_OMAP3_MICRON_DDR 1
/* USB */
#define CONFIG_MUSB_UDC 1
#define CONFIG_USB_OMAP3 1
#define CONFIG_TWL4030_USB 1
/* USB device configuration */
#define CONFIG_USB_DEVICE 1
#define CONFIG_USB_TTY 1
#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1
/* Change these to suit your needs */
#define CONFIG_USBD_VENDORID 0x0451
#define CONFIG_USBD_PRODUCTID 0x5678
#define CONFIG_USBD_MANUFACTURER "Texas Instruments"
#define CONFIG_USBD_PRODUCT_NAME "Zoom1"
/* commands to include */
#include <config_cmd_default.h>
@ -160,6 +175,7 @@
#define CONFIG_EXTRA_ENV_SETTINGS \
"loadaddr=0x82000000\0" \
"usbtty=cdc_acm\0" \
"console=ttyS2,115200n8\0" \
"videomode=1024x768@60,vxres=1024,vyres=768\0" \
"videospec=omapfb:vram:2M,vram:4M\0" \

View File

@ -125,6 +125,20 @@
#define CONFIG_OMAP3_GPIO_3 /* board revision */
#define CONFIG_OMAP3_GPIO_5 /* debug board detection, ZOOM2_LED_BLUE */
/* USB */
#define CONFIG_MUSB_UDC 1
#define CONFIG_USB_OMAP3 1
#define CONFIG_TWL4030_USB 1
/* USB device configuration */
#define CONFIG_USB_DEVICE 1
#define CONFIG_USB_TTY 1
/* Change these to suit your needs */
#define CONFIG_USBD_VENDORID 0x0451
#define CONFIG_USBD_PRODUCTID 0x5678
#define CONFIG_USBD_MANUFACTURER "Texas Instruments"
#define CONFIG_USBD_PRODUCT_NAME "Zoom2"
/* commands to include */
#include <config_cmd_default.h>
@ -170,6 +184,9 @@
/* Environment information */
#define CONFIG_BOOTDELAY 10
#define CONFIG_EXTRA_ENV_SETTINGS \
"usbtty=cdc_acm\0" \
/*
* Miscellaneous configurable options
*/

View File

@ -66,4 +66,22 @@ extern void serial_stdio_init(void);
extern int serial_assign(char * name);
extern void serial_reinit_all(void);
/* For usbtty */
#ifdef CONFIG_USB_TTY
extern int usbtty_getc(void);
extern void usbtty_putc(const char c);
extern void usbtty_puts(const char *str);
extern int usbtty_tstc(void);
#else
/* stubs */
#define usbtty_getc() 0
#define usbtty_putc(a)
#define usbtty_puts(a)
#define usbtty_tstc() 0
#endif /* CONFIG_USB_TTY */
#endif

View File

@ -342,21 +342,129 @@
#define TWL4030_KEYPAD_CTRL_SOFT_NRST (1 << 0)
/* USB */
#define TWL4030_USB_FUNC_CTRL (0x04)
#define TWL4030_USB_OPMODE_MASK (3 << 3)
#define TWL4030_USB_XCVRSELECT_MASK (3 << 0)
#define TWL4030_USB_IFC_CTRL (0x07)
#define TWL4030_USB_CARKITMODE (1 << 2)
#define TWL4030_USB_POWER_CTRL (0xAC)
#define TWL4030_USB_OTG_ENAB (1 << 5)
#define TWL4030_USB_PHY_PWR_CTRL (0xFD)
#define TWL4030_USB_PHYPWD (1 << 0)
#define TWL4030_USB_PHY_CLK_CTRL (0xFE)
#define TWL4030_USB_CLOCKGATING_EN (1 << 2)
#define TWL4030_USB_CLK32K_EN (1 << 1)
#define TWL4030_USB_REQ_PHY_DPLL_CLK (1 << 0)
#define TWL4030_USB_PHY_CLK_CTRL_STS (0xFF)
#define TWL4030_USB_PHY_DPLL_CLK (1 << 0)
#define TWL4030_USB_VENDOR_ID_LO 0x00
#define TWL4030_USB_VENDOR_ID_HI 0x01
#define TWL4030_USB_PRODUCT_ID_LO 0x02
#define TWL4030_USB_PRODUCT_ID_HI 0x03
#define TWL4030_USB_FUNC_CTRL 0x04
#define TWL4030_USB_FUNC_CTRL_SET 0x05
#define TWL4030_USB_FUNC_CTRL_CLR 0x06
#define TWL4030_USB_IFC_CTRL 0x07
#define TWL4030_USB_IFC_CTRL_SET 0x08
#define TWL4030_USB_IFC_CTRL_CLR 0x09
#define TWL4030_USB_OTG_CTRL 0x0A
#define TWL4030_USB_OTG_CTRL_SET 0x0B
#define TWL4030_USB_OTG_CTRL_CLR 0x0C
#define TWL4030_USB_USB_INT_EN_RISE 0x0D
#define TWL4030_USB_USB_INT_EN_RISE_SET 0x0E
#define TWL4030_USB_USB_INT_EN_RISE_CLR 0x0F
#define TWL4030_USB_USB_INT_EN_FALL 0x10
#define TWL4030_USB_USB_INT_EN_FALL_SET 0x11
#define TWL4030_USB_USB_INT_EN_FALL_CLR 0x12
#define TWL4030_USB_USB_INT_STS 0x13
#define TWL4030_USB_USB_INT_LATCH 0x14
#define TWL4030_USB_DEBUG 0x15
#define TWL4030_USB_SCRATCH_REG 0x16
#define TWL4030_USB_SCRATCH_REG_SET 0x17
#define TWL4030_USB_SCRATCH_REG_CLR 0x18
#define TWL4030_USB_CARKIT_CTRL 0x19
#define TWL4030_USB_CARKIT_CTRL_SET 0x1A
#define TWL4030_USB_CARKIT_CTRL_CLR 0x1B
#define TWL4030_USB_CARKIT_INT_DELAY 0x1C
#define TWL4030_USB_CARKIT_INT_EN 0x1D
#define TWL4030_USB_CARKIT_INT_EN_SET 0x1E
#define TWL4030_USB_CARKIT_INT_EN_CLR 0x1F
#define TWL4030_USB_CARKIT_INT_STS 0x20
#define TWL4030_USB_CARKIT_INT_LATCH 0x21
#define TWL4030_USB_CARKIT_PLS_CTRL 0x22
#define TWL4030_USB_CARKIT_PLS_CTRL_SET 0x23
#define TWL4030_USB_CARKIT_PLS_CTRL_CLR 0x24
#define TWL4030_USB_TRANS_POS_WIDTH 0x25
#define TWL4030_USB_TRANS_NEG_WIDTH 0x26
#define TWL4030_USB_RCV_PLTY_RECOVERY 0x27
#define TWL4030_USB_MCPC_CTRL 0x30
#define TWL4030_USB_MCPC_CTRL_SET 0x31
#define TWL4030_USB_MCPC_CTRL_CLR 0x32
#define TWL4030_USB_MCPC_IO_CTRL 0x33
#define TWL4030_USB_MCPC_IO_CTRL_SET 0x34
#define TWL4030_USB_MCPC_IO_CTRL_CLR 0x35
#define TWL4030_USB_MCPC_CTRL2 0x36
#define TWL4030_USB_MCPC_CTRL2_SET 0x37
#define TWL4030_USB_MCPC_CTRL2_CLR 0x38
#define TWL4030_USB_OTHER_FUNC_CTRL 0x80
#define TWL4030_USB_OTHER_FUNC_CTRL_SET 0x81
#define TWL4030_USB_OTHER_FUNC_CTRL_CLR 0x82
#define TWL4030_USB_OTHER_IFC_CTRL 0x83
#define TWL4030_USB_OTHER_IFC_CTRL_SET 0x84
#define TWL4030_USB_OTHER_IFC_CTRL_CLR 0x85
#define TWL4030_USB_OTHER_INT_EN_RISE_SET 0x87
#define TWL4030_USB_OTHER_INT_EN_RISE_CLR 0x88
#define TWL4030_USB_OTHER_INT_EN_FALL 0x89
#define TWL4030_USB_OTHER_INT_EN_FALL_SET 0x8A
#define TWL4030_USB_OTHER_INT_EN_FALL_CLR 0x8B
#define TWL4030_USB_OTHER_INT_STS 0x8C
#define TWL4030_USB_OTHER_INT_LATCH 0x8D
#define TWL4030_USB_ID_STATUS 0x96
#define TWL4030_USB_CARKIT_SM_1_INT_EN 0x97
#define TWL4030_USB_CARKIT_SM_1_INT_EN_SET 0x98
#define TWL4030_USB_CARKIT_SM_1_INT_EN_CLR 0x99
#define TWL4030_USB_CARKIT_SM_1_INT_STS 0x9A
#define TWL4030_USB_CARKIT_SM_1_INT_LATCH 0x9B
#define TWL4030_USB_CARKIT_SM_2_INT_EN 0x9C
#define TWL4030_USB_CARKIT_SM_2_INT_EN_SET 0x9D
#define TWL4030_USB_CARKIT_SM_2_INT_EN_CLR 0x9E
#define TWL4030_USB_CARKIT_SM_2_INT_STS 0x9F
#define TWL4030_USB_CARKIT_SM_2_INT_LATCH 0xA0
#define TWL4030_USB_CARKIT_SM_CTRL 0xA1
#define TWL4030_USB_CARKIT_SM_CTRL_SET 0xA2
#define TWL4030_USB_CARKIT_SM_CTRL_CLR 0xA3
#define TWL4030_USB_CARKIT_SM_CMD 0xA4
#define TWL4030_USB_CARKIT_SM_CMD_SET 0xA5
#define TWL4030_USB_CARKIT_SM_CMD_CLR 0xA6
#define TWL4030_USB_CARKIT_SM_CMD_STS 0xA7
#define TWL4030_USB_CARKIT_SM_STATUS 0xA8
#define TWL4030_USB_CARKIT_SM_ERR_STATUS 0xAA
#define TWL4030_USB_CARKIT_SM_CTRL_STATE 0xAB
#define TWL4030_USB_POWER_CTRL 0xAC
#define TWL4030_USB_POWER_CTRL_SET 0xAD
#define TWL4030_USB_POWER_CTRL_CLR 0xAE
#define TWL4030_USB_OTHER_IFC_CTRL2 0xAF
#define TWL4030_USB_OTHER_IFC_CTRL2_SET 0xB0
#define TWL4030_USB_OTHER_IFC_CTRL2_CLR 0xB1
#define TWL4030_USB_REG_CTRL_EN 0xB2
#define TWL4030_USB_REG_CTRL_EN_SET 0xB3
#define TWL4030_USB_REG_CTRL_EN_CLR 0xB4
#define TWL4030_USB_REG_CTRL_ERROR 0xB5
#define TWL4030_USB_OTHER_FUNC_CTRL2 0xB8
#define TWL4030_USB_OTHER_FUNC_CTRL2_SET 0xB9
#define TWL4030_USB_OTHER_FUNC_CTRL2_CLR 0xBA
#define TWL4030_USB_CARKIT_ANA_CTRL 0xBB
#define TWL4030_USB_CARKIT_ANA_CTRL_SET 0xBC
#define TWL4030_USB_CARKIT_ANA_CTRL_CLR 0xBD
#define TWL4030_USB_VBUS_DEBOUNCE 0xC0
#define TWL4030_USB_ID_DEBOUNCE 0xC1
#define TWL4030_USB_TPH_DP_CON_MIN 0xC2
#define TWL4030_USB_TPH_DP_CON_MAX 0xC3
#define TWL4030_USB_TCR_DP_CON_MIN 0xC4
#define TWL4030_USB_TCR_DP_CON_MAX 0xC5
#define TWL4030_USB_TPH_DP_PD_SHORT 0xC6
#define TWL4030_USB_TPH_CMD_DLY 0xC7
#define TWL4030_USB_TPH_DET_RST 0xC8
#define TWL4030_USB_TPH_AUD_BIAS 0xC9
#define TWL4030_USB_TCR_UART_DET_MIN 0xCA
#define TWL4030_USB_TCR_UART_DET_MAX 0xCB
#define TWL4030_USB_TPH_ID_INT_PW 0xCD
#define TWL4030_USB_TACC_ID_INT_WAIT 0xCE
#define TWL4030_USB_TACC_ID_INT_PW 0xCF
#define TWL4030_USB_TPH_CMD_WAIT 0xD0
#define TWL4030_USB_TPH_ACK_WAIT 0xD1
#define TWL4030_USB_TPH_DP_DISC_DET 0xD2
#define TWL4030_USB_VBAT_TIMER 0xD3
#define TWL4030_USB_CARKIT_4W_DEBUG 0xE0
#define TWL4030_USB_CARKIT_5W_DEBUG 0xE1
#define TWL4030_USB_PHY_PWR_CTRL 0xFD
#define TWL4030_USB_PHY_CLK_CTRL 0xFE
#define TWL4030_USB_PHY_CLK_CTRL_STS 0xFF
/*
* Convience functions to read and write from TWL4030
@ -398,4 +506,9 @@ void twl4030_power_mmc_init(void);
*/
void twl4030_led_init(void);
/*
* USB
*/
int twl4030_usb_ulpi_init(void);
#endif /* TWL4030_H */

View File

@ -27,6 +27,7 @@
#define _USB_H_
#include <usb_defs.h>
#include <usbdescriptors.h>
/* Everything is aribtrary */
#define USB_ALTSETTINGALLOC 4
@ -41,13 +42,6 @@
#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */
/* String descriptor */
struct usb_string_descriptor {
unsigned char bLength;
unsigned char bDescriptorType;
unsigned short wData[1];
} __attribute__ ((packed));
/* device request (setup) */
struct devrequest {
unsigned char requesttype;
@ -63,47 +57,9 @@ struct usb_descriptor_header {
unsigned char bDescriptorType;
} __attribute__ ((packed));
/* Device descriptor */
struct usb_device_descriptor {
unsigned char bLength;
unsigned char bDescriptorType;
unsigned short bcdUSB;
unsigned char bDeviceClass;
unsigned char bDeviceSubClass;
unsigned char bDeviceProtocol;
unsigned char bMaxPacketSize0;
unsigned short idVendor;
unsigned short idProduct;
unsigned short bcdDevice;
unsigned char iManufacturer;
unsigned char iProduct;
unsigned char iSerialNumber;
unsigned char bNumConfigurations;
} __attribute__ ((packed));
/* Endpoint descriptor */
struct usb_endpoint_descriptor {
unsigned char bLength;
unsigned char bDescriptorType;
unsigned char bEndpointAddress;
unsigned char bmAttributes;
unsigned short wMaxPacketSize;
unsigned char bInterval;
unsigned char bRefresh;
unsigned char bSynchAddress;
} __attribute__ ((packed)) __attribute__ ((aligned(2)));
/* Interface descriptor */
struct usb_interface_descriptor {
unsigned char bLength;
unsigned char bDescriptorType;
unsigned char bInterfaceNumber;
unsigned char bAlternateSetting;
unsigned char bNumEndpoints;
unsigned char bInterfaceClass;
unsigned char bInterfaceSubClass;
unsigned char bInterfaceProtocol;
unsigned char iInterface;
/* Interface */
struct usb_interface {
struct usb_interface_descriptor desc;
unsigned char no_of_ep;
unsigned char num_altsetting;
@ -112,20 +68,12 @@ struct usb_interface_descriptor {
struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
} __attribute__ ((packed));
/* Configuration descriptor information.. */
struct usb_config_descriptor {
unsigned char bLength;
unsigned char bDescriptorType;
unsigned short wTotalLength;
unsigned char bNumInterfaces;
unsigned char bConfigurationValue;
unsigned char iConfiguration;
unsigned char bmAttributes;
unsigned char MaxPower;
/* Configuration information.. */
struct usb_config {
struct usb_configuration_descriptor desc;
unsigned char no_of_if; /* number of interfaces */
struct usb_interface_descriptor if_desc[USB_MAXINTERFACES];
struct usb_interface if_desc[USB_MAXINTERFACES];
} __attribute__ ((packed));
enum {
@ -156,7 +104,7 @@ struct usb_device {
int configno; /* selected config number */
struct usb_device_descriptor descriptor; /* Device Descriptor */
struct usb_config_descriptor config; /* config descriptor */
struct usb_config config; /* config descriptor */
int have_langid; /* whether string_langid is valid yet */
int string_langid; /* language ID for strings */
@ -183,7 +131,8 @@ struct usb_device {
#if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \
defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_OHCI_NEW) || \
defined(CONFIG_USB_SL811HS) || defined(CONFIG_USB_ISP116X_HCD) || \
defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI)
defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI) || \
defined(CONFIG_USB_OMAP3)
int usb_lowlevel_init(void);
int usb_lowlevel_stop(void);

54
include/usb/musb_udc.h Normal file
View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2009 Wind River Systems, Inc.
* Tom Rix <Tom.Rix@windriver.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; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef __MUSB_UDC_H__
#define __MUSB_UDC_H__
#include <usbdevice.h>
/* UDC level routines */
void udc_irq(void);
void udc_set_nak(int ep_num);
void udc_unset_nak(int ep_num);
int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
struct usb_endpoint_instance *endpoint);
void udc_connect(void);
void udc_disconnect(void);
void udc_enable(struct usb_device_instance *device);
void udc_disable(void);
void udc_startup_events(struct usb_device_instance *device);
int udc_init(void);
/* usbtty */
#ifdef CONFIG_USB_TTY
#define EP0_MAX_PACKET_SIZE 64 /* MUSB_EP0_FIFOSIZE */
#define UDC_INT_ENDPOINT 1
#define UDC_INT_PACKET_SIZE 64
#define UDC_OUT_ENDPOINT 2
#define UDC_OUT_PACKET_SIZE 64
#define UDC_IN_ENDPOINT 3
#define UDC_IN_PACKET_SIZE 64
#define UDC_BULK_PACKET_SIZE 64
#endif /* CONFIG_USB_TTY */
#endif /* __MUSB_UDC_H__ */

View File

@ -504,4 +504,30 @@ struct usb_class_descriptor {
} __attribute__ ((packed));
#ifdef DEBUG
static inline void print_device_descriptor(struct usb_device_descriptor *d)
{
serial_printf("usb device descriptor \n");
serial_printf("\tbLength %2.2x\n", d->bLength);
serial_printf("\tbDescriptorType %2.2x\n", d->bDescriptorType);
serial_printf("\tbcdUSB %4.4x\n", d->bcdUSB);
serial_printf("\tbDeviceClass %2.2x\n", d->bDeviceClass);
serial_printf("\tbDeviceSubClass %2.2x\n", d->bDeviceSubClass);
serial_printf("\tbDeviceProtocol %2.2x\n", d->bDeviceProtocol);
serial_printf("\tbMaxPacketSize0 %2.2x\n", d->bMaxPacketSize0);
serial_printf("\tidVendor %4.4x\n", d->idVendor);
serial_printf("\tidProduct %4.4x\n", d->idProduct);
serial_printf("\tbcdDevice %4.4x\n", d->bcdDevice);
serial_printf("\tiManufacturer %2.2x\n", d->iManufacturer);
serial_printf("\tiProduct %2.2x\n", d->iProduct);
serial_printf("\tiSerialNumber %2.2x\n", d->iSerialNumber);
serial_printf("\tbNumConfigurations %2.2x\n", d->bNumConfigurations);
}
#else
/* stubs */
#define print_device_descriptor(d)
#endif /* DEBUG */
#endif

View File

@ -663,4 +663,107 @@ int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint);
void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad);
void usbd_tx_complete (struct usb_endpoint_instance *endpoint);
/* These are macros used in debugging */
#ifdef DEBUG
static inline void print_urb(struct urb *u)
{
serial_printf("urb %p\n", (u));
serial_printf("\tendpoint %p\n", u->endpoint);
serial_printf("\tdevice %p\n", u->device);
serial_printf("\tbuffer %p\n", u->buffer);
serial_printf("\tbuffer_length %d\n", u->buffer_length);
serial_printf("\tactual_length %d\n", u->actual_length);
serial_printf("\tstatus %d\n", u->status);
serial_printf("\tdata %d\n", u->data);
}
static inline void print_usb_device_request(struct usb_device_request *r)
{
serial_printf("usb request\n");
serial_printf("\tbmRequestType 0x%2.2x\n", r->bmRequestType);
if ((r->bmRequestType & USB_REQ_DIRECTION_MASK) == 0)
serial_printf("\t\tDirection : To device\n");
else
serial_printf("\t\tDirection : To host\n");
if ((r->bmRequestType & USB_TYPE_STANDARD) == USB_TYPE_STANDARD)
serial_printf("\t\tType : Standard\n");
if ((r->bmRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS)
serial_printf("\t\tType : Standard\n");
if ((r->bmRequestType & USB_TYPE_VENDOR) == USB_TYPE_VENDOR)
serial_printf("\t\tType : Standard\n");
if ((r->bmRequestType & USB_TYPE_RESERVED) == USB_TYPE_RESERVED)
serial_printf("\t\tType : Standard\n");
if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
USB_REQ_RECIPIENT_DEVICE)
serial_printf("\t\tRecipient : Device\n");
if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
USB_REQ_RECIPIENT_INTERFACE)
serial_printf("\t\tRecipient : Interface\n");
if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
USB_REQ_RECIPIENT_ENDPOINT)
serial_printf("\t\tRecipient : Endpoint\n");
if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
USB_REQ_RECIPIENT_OTHER)
serial_printf("\t\tRecipient : Other\n");
serial_printf("\tbRequest 0x%2.2x\n", r->bRequest);
if (r->bRequest == USB_REQ_GET_STATUS)
serial_printf("\t\tGET_STATUS\n");
else if (r->bRequest == USB_REQ_SET_ADDRESS)
serial_printf("\t\tSET_ADDRESS\n");
else if (r->bRequest == USB_REQ_SET_FEATURE)
serial_printf("\t\tSET_FEATURE\n");
else if (r->bRequest == USB_REQ_GET_DESCRIPTOR)
serial_printf("\t\tGET_DESCRIPTOR\n");
else if (r->bRequest == USB_REQ_SET_CONFIGURATION)
serial_printf("\t\tSET_CONFIGURATION\n");
else if (r->bRequest == USB_REQ_SET_INTERFACE)
serial_printf("\t\tUSB_REQ_SET_INTERFACE\n");
else
serial_printf("\tUNKNOWN %d\n", r->bRequest);
serial_printf("\twValue 0x%4.4x\n", r->wValue);
if (r->bRequest == USB_REQ_GET_DESCRIPTOR) {
switch (r->wValue >> 8) {
case USB_DESCRIPTOR_TYPE_DEVICE:
serial_printf("\tDEVICE\n");
break;
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
serial_printf("\tCONFIGURATION\n");
break;
case USB_DESCRIPTOR_TYPE_STRING:
serial_printf("\tSTRING\n");
break;
case USB_DESCRIPTOR_TYPE_INTERFACE:
serial_printf("\tINTERFACE\n");
break;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
serial_printf("\tENDPOINT\n");
break;
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
serial_printf("\tDEVICE_QUALIFIER\n");
break;
case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
serial_printf("\tOTHER_SPEED_CONFIGURATION\n");
break;
case USB_DESCRIPTOR_TYPE_INTERFACE_POWER:
serial_printf("\tINTERFACE_POWER\n");
break;
case USB_DESCRIPTOR_TYPE_HID:
serial_printf("\tHID\n");
break;
case USB_DESCRIPTOR_TYPE_REPORT:
serial_printf("\tREPORT\n");
break;
default:
serial_printf("\tUNKNOWN TYPE\n");
break;
}
}
serial_printf("\twIndex 0x%4.4x\n", r->wIndex);
serial_printf("\twLength 0x%4.4x\n", r->wLength);
}
#else
/* stubs */
#define print_urb(u)
#define print_usb_device_request(r)
#endif /* DEBUG */
#endif