diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/bios_emulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/dm9000x.c | 2 | ||||
-rw-r--r-- | drivers/net/e1000.c | 1 | ||||
-rw-r--r-- | drivers/net/fec_mxc.c | 1 | ||||
-rw-r--r-- | drivers/net/lan91c96.c | 452 | ||||
-rw-r--r-- | drivers/net/lan91c96.h | 110 | ||||
-rw-r--r-- | drivers/serial/usbtty.h | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/musb/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.c | 8 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 40 | ||||
-rw-r--r-- | drivers/usb/musb/musb_debug.h | 205 | ||||
-rw-r--r-- | drivers/usb/musb/musb_hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/musb/musb_udc.c | 963 | ||||
-rw-r--r-- | drivers/usb/musb/omap3.c | 134 | ||||
-rw-r--r-- | drivers/usb/musb/omap3.h | 48 | ||||
-rw-r--r-- | drivers/usb/phy/Makefile | 44 | ||||
-rw-r--r-- | drivers/usb/phy/twl4030.c | 189 | ||||
-rw-r--r-- | drivers/video/cfb_console.c | 2 |
20 files changed, 1874 insertions, 336 deletions
diff --git a/drivers/bios_emulator/Makefile b/drivers/bios_emulator/Makefile index dd9c102ba..feba4da75 100644 --- a/drivers/bios_emulator/Makefile +++ b/drivers/bios_emulator/Makefile @@ -23,6 +23,7 @@ EXTRA_CFLAGS += -I. -I./include -I$(TOPDIR)/include \ CFLAGS += $(EXTRA_CFLAGS) HOSTCFLAGS += $(EXTRA_CFLAGS) +CPPFLAGS += $(EXTRA_CFLAGS) all: $(LIB) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index fc9887b51..904727e1b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -44,7 +44,7 @@ COBJS-$(CONFIG_GRETH) += greth.o COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o COBJS-$(CONFIG_KIRKWOOD_EGIGA) += kirkwood_egiga.o COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o -COBJS-$(CONFIG_DRIVER_LAN91C96) += lan91c96.o +COBJS-$(CONFIG_LAN91C96) += lan91c96.o COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 73dd33572..a7fef5603 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -75,7 +75,7 @@ TODO: external MII is not functional, only internal at the moment. #define DM9000_DMP_PACKET(func,packet,length) \ do { \ int i; \ - printf(func ": length: %d\n", length); \ + printf("%s: length: %d\n", func, length); \ for (i = 0; i < length; i++) { \ if (i % 8 == 0) \ printf("\n%s: %02x: ", func, i); \ diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 7f9f783c4..2825342ff 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -79,6 +79,7 @@ static struct pci_device_id supported[] = { {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_COPPER}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_FIBER}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_FIBER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546GB_COPPER}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM_LOM}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541ER}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541GI_LF}, diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index ad073077c..19116f253 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -450,6 +450,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd) */ if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) { free(fec->base_ptr); + fec->base_ptr = NULL; return -ENOMEM; } fec_tbd_init(fec); diff --git a/drivers/net/lan91c96.c b/drivers/net/lan91c96.c index 65565bcb0..90e400249 100644 --- a/drivers/net/lan91c96.c +++ b/drivers/net/lan91c96.c @@ -60,6 +60,7 @@ #include <common.h> #include <command.h> +#include <malloc.h> #include "lan91c96.h" #include <net.h> @@ -108,11 +109,7 @@ * *------------------------------------------------------------------------ */ -#define CARDNAME "LAN91C96" - -#define SMC_BASE_ADDRESS CONFIG_LAN91C96_BASE - -#define SMC_DEV_NAME "LAN91C96" +#define DRIVER_NAME "LAN91C96" #define SMC_ALLOC_MAX_TRY 5 #define SMC_TX_TIMEOUT 30 @@ -124,64 +121,12 @@ #undef USE_32_BIT #endif -/*----------------------------------------------------------------- - * - * The driver can be entered at any of the following entry points. - * - *----------------------------------------------------------------- - */ - -extern int eth_init (bd_t * bd); -extern void eth_halt (void); -extern int eth_rx (void); -extern int eth_send (volatile void *packet, int length); -#if 0 -static int smc_hw_init (void); -#endif - -/* - * This is called by register_netdev(). It is responsible for - * checking the portlist for the SMC9000 series chipset. If it finds - * one, then it will initialize the device, find the hardware information, - * and sets up the appropriate device parameters. - * NOTE: Interrupts are *OFF* when this procedure is called. - * - * NB:This shouldn't be static since it is referred to externally. - */ -int smc_init (void); - -/* - * This is called by unregister_netdev(). It is responsible for - * cleaning up before the driver is finally unregistered and discarded. - */ -void smc_destructor (void); - -/* - * The kernel calls this function when someone wants to use the device, - * typically 'ifconfig ethX up'. - */ -static int smc_open (bd_t *bd); - - -/* - * This is called by the kernel in response to 'ifconfig ethX down'. It - * is responsible for cleaning up everything that the open routine - * does, and maybe putting the card into a powerdown state. - */ -static int smc_close (void); - -/* - * This is a separate procedure to handle the receipt of a packet, to - * leave the interrupt code looking slightly cleaner - */ -static int smc_rcv (void); - /* See if a MAC address is defined in the current environment. If so use it. If not . print a warning and set the environment and other globals with the default. . If an EEPROM is present it really should be consulted. */ -int smc_get_ethaddr(bd_t *bd); -int get_rom_mac(unsigned char *v_rom_mac); +static int smc_get_ethaddr(bd_t *bd, struct eth_device *dev); +static int get_rom_mac(struct eth_device *dev, unsigned char *v_rom_mac); /* ------------------------------------------------------------ * Internal routines @@ -195,7 +140,7 @@ static unsigned char smc_mac_addr[] = { 0xc0, 0x00, 0x00, 0x1b, 0x62, 0x9c }; * the default mac address. */ -void smc_set_mac_addr (const unsigned char *addr) +static void smc_set_mac_addr(const unsigned char *addr) { int i; @@ -204,45 +149,21 @@ void smc_set_mac_addr (const unsigned char *addr) } } -/* - * smc_get_macaddr is no longer used. If you want to override the default - * mac address, call smc_get_mac_addr as a part of the board initialisation. - */ - -#if 0 -void smc_get_macaddr (byte * addr) -{ - /* MAC ADDRESS AT FLASHBLOCK 1 / OFFSET 0x10 */ - unsigned char *dnp1110_mac = (unsigned char *) (0xE8000000 + 0x20010); - int i; - - - for (i = 0; i < 6; i++) { - addr[0] = *(dnp1110_mac + 0); - addr[1] = *(dnp1110_mac + 1); - addr[2] = *(dnp1110_mac + 2); - addr[3] = *(dnp1110_mac + 3); - addr[4] = *(dnp1110_mac + 4); - addr[5] = *(dnp1110_mac + 5); - } -} -#endif /* 0 */ - /*********************************************** * Show available memory * ***********************************************/ -void dump_memory_info (void) +void dump_memory_info(struct eth_device *dev) { word mem_info; word old_bank; - old_bank = SMC_inw (LAN91C96_BANK_SELECT) & 0xF; + old_bank = SMC_inw(dev, LAN91C96_BANK_SELECT) & 0xF; - SMC_SELECT_BANK (0); - mem_info = SMC_inw (LAN91C96_MIR); + SMC_SELECT_BANK(dev, 0); + mem_info = SMC_inw(dev, LAN91C96_MIR); PRINTK2 ("Memory: %4d available\n", (mem_info >> 8) * 2048); - SMC_SELECT_BANK (old_bank); + SMC_SELECT_BANK(dev, old_bank); } /* @@ -252,28 +173,15 @@ void dump_memory_info (void) static void print_packet (byte *, int); #endif -/* #define tx_done(dev) 1 */ - - -/* this does a soft reset on the device */ -static void smc_reset (void); - -/* Enable Interrupts, Receive, and Transmit */ -static void smc_enable (void); - -/* this puts the device in an inactive state */ -static void smc_shutdown (void); - - -static int poll4int (byte mask, int timeout) +static int poll4int (struct eth_device *dev, byte mask, int timeout) { int tmo = get_timer (0) + timeout * CONFIG_SYS_HZ; int is_timeout = 0; - word old_bank = SMC_inw (LAN91C96_BANK_SELECT); + word old_bank = SMC_inw(dev, LAN91C96_BANK_SELECT); PRINTK2 ("Polling...\n"); - SMC_SELECT_BANK (2); - while ((SMC_inw (LAN91C96_INT_STATS) & mask) == 0) { + SMC_SELECT_BANK(dev, 2); + while ((SMC_inw(dev, LAN91C96_INT_STATS) & mask) == 0) { if (get_timer (0) >= tmo) { is_timeout = 1; break; @@ -281,7 +189,7 @@ static int poll4int (byte mask, int timeout) } /* restore old bank selection */ - SMC_SELECT_BANK (old_bank); + SMC_SELECT_BANK(dev, old_bank); if (is_timeout) return 1; @@ -290,7 +198,7 @@ static int poll4int (byte mask, int timeout) } /* - * Function: smc_reset( void ) + * Function: smc_reset * Purpose: * This sets the SMC91111 chip to its normal state, hopefully from whatever * mess that any other DOS driver has put it in. @@ -306,28 +214,28 @@ static int poll4int (byte mask, int timeout) * 5. clear all interrupts * */ -static void smc_reset (void) +static void smc_reset(struct eth_device *dev) { - PRINTK2 ("%s:smc_reset\n", SMC_DEV_NAME); + PRINTK2("%s:smc_reset\n", dev->name); /* This resets the registers mostly to defaults, but doesn't affect EEPROM. That seems unnecessary */ - SMC_SELECT_BANK (0); - SMC_outw (LAN91C96_RCR_SOFT_RST, LAN91C96_RCR); + SMC_SELECT_BANK(dev, 0); + SMC_outw(dev, LAN91C96_RCR_SOFT_RST, LAN91C96_RCR); udelay (10); /* Disable transmit and receive functionality */ - SMC_outw (0, LAN91C96_RCR); - SMC_outw (0, LAN91C96_TCR); + SMC_outw(dev, 0, LAN91C96_RCR); + SMC_outw(dev, 0, LAN91C96_TCR); /* set the control register */ - SMC_SELECT_BANK (1); - SMC_outw (SMC_inw (LAN91C96_CONTROL) | LAN91C96_CTR_BIT_8, + SMC_SELECT_BANK(dev, 1); + SMC_outw(dev, SMC_inw(dev, LAN91C96_CONTROL) | LAN91C96_CTR_BIT_8, LAN91C96_CONTROL); /* Disable all interrupts */ - SMC_outb (0, LAN91C96_INT_MASK); + SMC_outb(dev, 0, LAN91C96_INT_MASK); } /* @@ -338,24 +246,24 @@ static void smc_reset (void) * 2. Enable the transmitter * 3. Enable the receiver */ -static void smc_enable () +static void smc_enable(struct eth_device *dev) { - PRINTK2 ("%s:smc_enable\n", SMC_DEV_NAME); - SMC_SELECT_BANK (0); + PRINTK2("%s:smc_enable\n", dev->name); + SMC_SELECT_BANK(dev, 0); /* Initialize the Memory Configuration Register. See page 49 of the LAN91C96 data sheet for details. */ - SMC_outw (LAN91C96_MCR_TRANSMIT_PAGES, LAN91C96_MCR); + SMC_outw(dev, LAN91C96_MCR_TRANSMIT_PAGES, LAN91C96_MCR); /* Initialize the Transmit Control Register */ - SMC_outw (LAN91C96_TCR_TXENA, LAN91C96_TCR); + SMC_outw(dev, LAN91C96_TCR_TXENA, LAN91C96_TCR); /* Initialize the Receive Control Register * FIXME: * The promiscuous bit set because I could not receive ARP reply * packets from the server when I send a ARP request. It only works * when I set the promiscuous bit */ - SMC_outw (LAN91C96_RCR_RXEN | LAN91C96_RCR_PRMS, LAN91C96_RCR); + SMC_outw(dev, LAN91C96_RCR_RXEN | LAN91C96_RCR_PRMS, LAN91C96_RCR); } /* @@ -372,18 +280,18 @@ static void smc_enable () * the manual says that it will wake up in response to any I/O requests * in the register space. Empirical results do not show this working. */ -static void smc_shutdown () +static void smc_shutdown(struct eth_device *dev) { - PRINTK2 (CARDNAME ":smc_shutdown\n"); + PRINTK2("%s:smc_shutdown\n", dev->name); /* no more interrupts for me */ - SMC_SELECT_BANK (2); - SMC_outb (0, LAN91C96_INT_MASK); + SMC_SELECT_BANK(dev, 2); + SMC_outb(dev, 0, LAN91C96_INT_MASK); /* and tell the card to stay away from that nasty outside world */ - SMC_SELECT_BANK (0); - SMC_outb (0, LAN91C96_RCR); - SMC_outb (0, LAN91C96_TCR); + SMC_SELECT_BANK(dev, 0); + SMC_outb(dev, 0, LAN91C96_RCR); + SMC_outb(dev, 0, LAN91C96_TCR); } @@ -405,7 +313,8 @@ static void smc_shutdown () * Enable the transmit interrupt, so I know if it failed * Free the kernel data if I actually sent it. */ -static int smc_send_packet (volatile void *packet, int packet_length) +static int smc_send_packet(struct eth_device *dev, volatile void *packet, + int packet_length) { byte packet_no; unsigned long ioaddr; @@ -417,7 +326,7 @@ static int smc_send_packet (volatile void *packet, int packet_length) byte status; - PRINTK3 ("%s:smc_hardware_send_packet\n", SMC_DEV_NAME); + PRINTK3("%s:smc_hardware_send_packet\n", dev->name); length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN; @@ -437,30 +346,31 @@ static int smc_send_packet (volatile void *packet, int packet_length) numPages >>= 8; /* Divide by 256 */ if (numPages > 7) { - printf ("%s: Far too big packet error. \n", SMC_DEV_NAME); + printf("%s: Far too big packet error. \n", dev->name); return 0; } /* now, try to allocate the memory */ - SMC_SELECT_BANK (2); - SMC_outw (LAN91C96_MMUCR_ALLOC_TX | numPages, LAN91C96_MMU); + SMC_SELECT_BANK(dev, 2); + SMC_outw(dev, LAN91C96_MMUCR_ALLOC_TX | numPages, LAN91C96_MMU); again: try++; time_out = MEMORY_WAIT_TIME; do { - status = SMC_inb (LAN91C96_INT_STATS); + status = SMC_inb(dev, LAN91C96_INT_STATS); if (status & LAN91C96_IST_ALLOC_INT) { - SMC_outb (LAN91C96_IST_ALLOC_INT, LAN91C96_INT_STATS); + SMC_outb(dev, LAN91C96_IST_ALLOC_INT, + LAN91C96_INT_STATS); break; } } while (--time_out); if (!time_out) { PRINTK2 ("%s: memory allocation, try %d failed ...\n", - SMC_DEV_NAME, try); + dev->name, try); if (try < SMC_ALLOC_MAX_TRY) goto again; else @@ -468,30 +378,30 @@ static int smc_send_packet (volatile void *packet, int packet_length) } PRINTK2 ("%s: memory allocation, try %d succeeded ...\n", - SMC_DEV_NAME, try); + dev->name, try); /* I can send the packet now.. */ - ioaddr = SMC_BASE_ADDRESS; + ioaddr = dev->iobase; buf = (byte *) packet; /* If I get here, I _know_ there is a packet slot waiting for me */ - packet_no = SMC_inb (LAN91C96_ARR); + packet_no = SMC_inb(dev, LAN91C96_ARR); if (packet_no & LAN91C96_ARR_FAILED) { /* or isn't there? BAD CHIP! */ - printf ("%s: Memory allocation failed. \n", SMC_DEV_NAME); + printf("%s: Memory allocation failed. \n", dev->name); return 0; } /* we have a packet address, so tell the card to use it */ - SMC_outb (packet_no, LAN91C96_PNR); + SMC_outb(dev, packet_no, LAN91C96_PNR); /* point to the beginning of the packet */ - SMC_outw (LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER); + SMC_outw(dev, LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER); - PRINTK3 ("%s: Trying to xmit packet of length %x\n", - SMC_DEV_NAME, length); + PRINTK3("%s: Trying to xmit packet of length %x\n", + dev->name, length); #if SMC_DEBUG > 2 printf ("Transmitting Packet\n"); @@ -501,11 +411,11 @@ static int smc_send_packet (volatile void *packet, int packet_length) /* send the packet length ( +6 for status, length and ctl byte ) and the status word ( set to zeros ) */ #ifdef USE_32_BIT - SMC_outl ((length + 6) << 16, LAN91C96_DATA_HIGH); + SMC_outl(dev, (length + 6) << 16, LAN91C96_DATA_HIGH); #else - SMC_outw (0, LAN91C96_DATA_HIGH); + SMC_outw(dev, 0, LAN91C96_DATA_HIGH); /* send the packet length ( +6 for status words, length, and ctl */ - SMC_outw ((length + 6), LAN91C96_DATA_HIGH); + SMC_outw(dev, (length + 6), LAN91C96_DATA_HIGH); #endif /* USE_32_BIT */ /* send the actual data @@ -516,54 +426,52 @@ static int smc_send_packet (volatile void *packet, int packet_length) * almost as much time as is saved? */ #ifdef USE_32_BIT - SMC_outsl (LAN91C96_DATA_HIGH, buf, length >> 2); + SMC_outsl(dev, LAN91C96_DATA_HIGH, buf, length >> 2); if (length & 0x2) - SMC_outw (*((word *) (buf + (length & 0xFFFFFFFC))), + SMC_outw(dev, *((word *) (buf + (length & 0xFFFFFFFC))), LAN91C96_DATA_HIGH); #else - SMC_outsw (LAN91C96_DATA_HIGH, buf, (length) >> 1); + SMC_outsw(dev, LAN91C96_DATA_HIGH, buf, (length) >> 1); #endif /* USE_32_BIT */ /* Send the last byte, if there is one. */ if ((length & 1) == 0) { - SMC_outw (0, LAN91C96_DATA_HIGH); + SMC_outw(dev, 0, LAN91C96_DATA_HIGH); } else { - SMC_outw (buf[length - 1] | 0x2000, LAN91C96_DATA_HIGH); + SMC_outw(dev, buf[length - 1] | 0x2000, LAN91C96_DATA_HIGH); } /* and let the chipset deal with it */ - SMC_outw (LAN91C96_MMUCR_ENQUEUE, LAN91C96_MMU); + SMC_outw(dev, LAN91C96_MMUCR_ENQUEUE, LAN91C96_MMU); /* poll for TX INT */ - if (poll4int (LAN91C96_MSK_TX_INT, SMC_TX_TIMEOUT)) { + if (poll4int (dev, LAN91C96_MSK_TX_INT, SMC_TX_TIMEOUT)) { /* sending failed */ - PRINTK2 ("%s: TX timeout, sending failed...\n", SMC_DEV_NAME); + PRINTK2("%s: TX timeout, sending failed...\n", dev->name); /* release packet */ - SMC_outw (LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU); + SMC_outw(dev, LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU); /* wait for MMU getting ready (low) */ - while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) { + while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) udelay (10); - } - PRINTK2 ("MMU ready\n"); + PRINTK2("MMU ready\n"); return 0; } else { /* ack. int */ - SMC_outw (LAN91C96_IST_TX_INT, LAN91C96_INT_STATS); + SMC_outw(dev, LAN91C96_IST_TX_INT, LAN91C96_INT_STATS); - PRINTK2 ("%s: Sent packet of length %d \n", SMC_DEV_NAME, length); + PRINTK2("%s: Sent packet of length %d \n", dev->name, length); /* release packet */ - SMC_outw (LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU); + SMC_outw(dev, LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU); /* wait for MMU getting ready (low) */ - while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) { + while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) udelay (10); - } PRINTK2 ("MMU ready\n"); } @@ -571,20 +479,6 @@ static int smc_send_packet (volatile void *packet, int packet_length) return length; } -/*------------------------------------------------------------------------- - * smc_destructor( struct net_device * dev ) - * Input parameters: - * dev, pointer to the device structure - * - * Output: - * None. - *-------------------------------------------------------------------------- - */ -void smc_destructor () -{ - PRINTK2 (CARDNAME ":smc_destructor\n"); -} - /* * Open and Initialize the board @@ -592,20 +486,20 @@ void smc_destructor () * Set up everything, reset the card, etc .. * */ -static int smc_open (bd_t *bd) +static int smc_open(bd_t *bd, struct eth_device *dev) { int i, err; /* used to set hw ethernet address */ - PRINTK2 ("%s:smc_open\n", SMC_DEV_NAME); + PRINTK2("%s:smc_open\n", dev->name); /* reset the hardware */ - smc_reset (); - smc_enable (); - - SMC_SELECT_BANK (1); + smc_reset(dev); + smc_enable(dev); - err = smc_get_ethaddr (bd); /* set smc_mac_addr, and sync it with u-boot globals */ + SMC_SELECT_BANK(dev, 1); + /* set smc_mac_addr, and sync it with u-boot globals */ + err = smc_get_ethaddr(bd, dev); if (err < 0) return -1; #ifdef USE_32_BIT @@ -614,11 +508,11 @@ static int smc_open (bd_t *bd) address = smc_mac_addr[i + 1] << 8; address |= smc_mac_addr[i]; - SMC_outw (address, LAN91C96_IA0 + i); + SMC_outw(dev, address, LAN91C96_IA0 + i); } #else for (i = 0; i < 6; i++) - SMC_outb (smc_mac_addr[i], LAN91C96_IA0 + i); + SMC_outb(dev, smc_mac_addr[i], LAN91C96_IA0 + i); #endif return 0; } @@ -635,7 +529,7 @@ static int smc_open (bd_t *bd) * o otherwise, read in the packet *------------------------------------------------------------- */ -static int smc_rcv () +static int smc_rcv(struct eth_device *dev) { int packet_number; word status; @@ -647,26 +541,26 @@ static int smc_rcv () #endif - SMC_SELECT_BANK (2); - packet_number = SMC_inw (LAN91C96_FIFO); + SMC_SELECT_BANK(dev, 2); + packet_number = SMC_inw(dev, LAN91C96_FIFO); if (packet_number & LAN91C96_FIFO_RXEMPTY) { return 0; } - PRINTK3 ("%s:smc_rcv\n", SMC_DEV_NAME); + PRINTK3("%s:smc_rcv\n", dev->name); /* start reading from the start of the packet */ - SMC_outw (LAN91C96_PTR_READ | LAN91C96_PTR_RCV | + SMC_outw(dev, LAN91C96_PTR_READ | LAN91C96_PTR_RCV | LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER); /* First two words are status and packet_length */ #ifdef USE_32_BIT - stat_len = SMC_inl (LAN91C96_DATA_HIGH); + stat_len = SMC_inl(dev, LAN91C96_DATA_HIGH); status = stat_len & 0xffff; packet_length = stat_len >> 16; #else - status = SMC_inw (LAN91C96_DATA_HIGH); - packet_length = SMC_inw (LAN91C96_DATA_HIGH); + status = SMC_inw(dev, LAN91C96_DATA_HIGH); + packet_length = SMC_inw(dev, LAN91C96_DATA_HIGH); #endif packet_length &= 0x07ff; /* mask off top bits */ @@ -690,13 +584,14 @@ static int smc_rcv () to send the DWORDs or the bytes first, or some mixture. A mixture might improve already slow PIO performance */ - SMC_insl (LAN91C96_DATA_HIGH, NetRxPackets[0], packet_length >> 2); + SMC_insl(dev, LAN91C96_DATA_HIGH, NetRxPackets[0], + packet_length >> 2); /* read the left over bytes */ if (packet_length & 3) { int i; byte *tail = (byte *) (NetRxPackets[0] + (packet_length & ~3)); - dword leftover = SMC_inl (LAN91C96_DATA_HIGH); + dword leftover = SMC_inl(dev, LAN91C96_DATA_HIGH); for (i = 0; i < (packet_length & 3); i++) *tail++ = (byte) (leftover >> (8 * i)) & 0xff; @@ -704,13 +599,14 @@ static int smc_rcv () #else PRINTK3 (" Reading %d words and %d byte(s) \n", (packet_length >> 1), packet_length & 1); - SMC_insw (LAN91C96_DATA_HIGH, NetRxPackets[0], packet_length >> 1); + SMC_insw(dev, LAN91C96_DATA_HIGH, NetRxPackets[0], + packet_length >> 1); #endif /* USE_32_BIT */ #if SMC_DEBUG > 2 printf ("Receiving Packet\n"); - print_packet (NetRxPackets[0], packet_length); + print_packet((byte *)NetRxPackets[0], packet_length); #endif } else { /* error ... */ @@ -718,13 +614,13 @@ static int smc_rcv () is_error = 1; } - while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) + while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) udelay (1); /* Wait until not busy */ /* error or good, tell the card to get rid of this packet */ - SMC_outw (LAN91C96_MMUCR_RELEASE_RX, LAN91C96_MMU); + SMC_outw(dev, LAN91C96_MMUCR_RELEASE_RX, LAN91C96_MMU); - while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) + while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) udelay (1); /* Wait until not busy */ if (!is_error) { @@ -745,18 +641,18 @@ static int smc_rcv () * an 'ifconfig ethX down' * -----------------------------------------------------*/ -static int smc_close () +static int smc_close(struct eth_device *dev) { - PRINTK2 ("%s:smc_close\n", SMC_DEV_NAME); + PRINTK2("%s:smc_close\n", dev->name); /* clear everything */ - smc_shutdown (); + smc_shutdown(dev); return 0; } #if SMC_DEBUG > 2 -static void print_packet (byte * buf, int length) +static void print_packet(byte *buf, int length) { #if 0 int i; @@ -792,86 +688,40 @@ static void print_packet (byte * buf, int length) } #endif /* SMC_DEBUG > 2 */ -int eth_init (bd_t * bd) -{ - return (smc_open(bd)); -} - -void eth_halt () +static int lan91c96_init(struct eth_device *dev, bd_t *bd) { - smc_close (); + return smc_open(bd, dev); } -int eth_rx () +static void lan91c96_halt(struct eth_device *dev) { - return smc_rcv (); + smc_close(dev); } -int eth_send (volatile void *packet, int length) +static int lan91c96_recv(struct eth_device *dev) { - return smc_send_packet (packet, length); + return smc_rcv(dev); } - -#if 0 -/*------------------------------------------------------------------------- - * smc_hw_init() - * - * Function: - * Reset and enable the device, check if the I/O space location - * is correct - * - * Input parameters: - * None - * - * Output: - * 0 --> success - * 1 --> error - *-------------------------------------------------------------------------- - */ -static int smc_hw_init () +static int lan91c96_send(struct eth_device *dev, volatile void *packet, + int length) { - unsigned short status_test; - - /* The attribute register of the LAN91C96 is located at address - 0x0e000000 on the lubbock platform */ - volatile unsigned *attaddr = (unsigned *) (0x0e000000); - - /* first reset, then enable the device. Sequence is critical */ - attaddr[LAN91C96_ECOR] |= LAN91C96_ECOR_SRESET; - udelay (100); - attaddr[LAN91C96_ECOR] &= ~LAN91C96_ECOR_SRESET; - attaddr[LAN91C96_ECOR] |= LAN91C96_ECOR_ENABLE; - - /* force 16-bit mode */ - attaddr[LAN91C96_ECSR] &= ~LAN91C96_ECSR_IOIS8; - udelay (100); - - /* check if the I/O address is correct, the upper byte of the - bank select register should read 0x33 */ - - status_test = SMC_inw (LAN91C96_BANK_SELECT); - if ((status_test & 0xFF00) != 0x3300) { - printf ("Failed to initialize ethernetchip\n"); - return 1; - } - return 0; + return smc_send_packet(dev, packet, length); } -#endif /* 0 */ -/* smc_get_ethaddr (bd_t * bd) +/* smc_get_ethaddr * * This checks both the environment and the ROM for an ethernet address. If * found, the environment takes precedence. */ -int smc_get_ethaddr (bd_t * bd) +static int smc_get_ethaddr(bd_t *bd, struct eth_device *dev) { uchar v_mac[6]; if (!eth_getenv_enetaddr("ethaddr", v_mac)) { /* get ROM mac value if any */ - if (!get_rom_mac(v_mac)) { + if (!get_rom_mac(dev, v_mac)) { printf("\n*** ERROR: ethaddr is NOT set !!\n"); return -1; } @@ -888,7 +738,7 @@ int smc_get_ethaddr (bd_t * bd) * Note, this has omly been tested for the OMAP730 P2. */ -int get_rom_mac (unsigned char *v_rom_mac) +static int get_rom_mac(struct eth_device *dev, unsigned char *v_rom_mac) { #ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; @@ -897,11 +747,75 @@ int get_rom_mac (unsigned char *v_rom_mac) return (1); #else int i; - SMC_SELECT_BANK (1); + SMC_SELECT_BANK(dev, 1); for (i=0; i<6; i++) { - v_rom_mac[i] = SMC_inb (LAN91C96_IA0 + i); + v_rom_mac[i] = SMC_inb(dev, LAN91C96_IA0 + i); } return (1); #endif } + +/* Structure to detect the device IDs */ +struct id_type { + u8 id; + char *name; +}; +static struct id_type supported_chips[] = { + {0, ""}, /* Dummy entry to prevent id check failure */ + {9, "LAN91C110"}, + {8, "LAN91C100FD"}, + {7, "LAN91C100"}, + {5, "LAN91C95"}, + {4, "LAN91C94/LAN91C96"}, + {3, "LAN91C90/LAN91C92"}, +}; +/* lan91c96_detect_chip + * See: + * http://www.embeddedsys.com/subpages/resources/images/documents/LAN91C96_datasheet.pdf + * page 71 - that is the closest we get to detect this device + */ +static int lan91c96_detect_chip(struct eth_device *dev) +{ + u8 chip_id; + int r; + SMC_SELECT_BANK(dev, 3); + chip_id = SMC_inw(dev, 0xA) & LAN91C96_REV_REVID; + SMC_SELECT_BANK(dev, 0); + for (r = 0; r < sizeof(supported_chips) / sizeof(struct id_type); r++) + if (chip_id == supported_chips[r].id) + return r; + return 0; +} + +int lan91c96_initialize(u8 dev_num, int base_addr) +{ + struct eth_device *dev; + int r = 0; + + dev = malloc(sizeof(*dev)); + if (!dev) { + free(dev); + return 0; + } + memset(dev, 0, sizeof(*dev)); + + dev->iobase = base_addr; + + /* Try to detect chip. Will fail if not present. */ + r = lan91c96_detect_chip(dev); + if (!r) { + free(dev); + return 0; + } + get_rom_mac(dev, dev->enetaddr); + + dev->init = lan91c96_init; + dev->halt = lan91c96_halt; + dev->send = lan91c96_send; + dev->recv = lan91c96_recv; + sprintf(dev->name, "%s-%hu", supported_chips[r].name, dev_num); + + eth_register(dev); + return 0; +} diff --git a/drivers/net/lan91c96.h b/drivers/net/lan91c96.h index 5beddda04..6fbb0e3cb 100644 --- a/drivers/net/lan91c96.h +++ b/drivers/net/lan91c96.h @@ -46,14 +46,6 @@ #include <asm/io.h> #include <config.h> -/* - * This function may be called by the board specific initialisation code - * in order to override the default mac address. - */ - -void smc_set_mac_addr(const unsigned char *addr); - - /* I want some simple types */ typedef unsigned char byte; @@ -86,66 +78,71 @@ typedef unsigned long int dword; #define SMC_IO_SHIFT 0 #endif -#define SMCREG(r) (SMC_BASE_ADDRESS+((r)<<SMC_IO_SHIFT)) +#define SMCREG(edev, r) ((edev)->iobase+((r)<<SMC_IO_SHIFT)) -#define SMC_inl(r) (*((volatile dword *)SMCREG(r))) -#define SMC_inw(r) (*((volatile word *)SMCREG(r))) -#define SMC_inb(p) ({ \ +#define SMC_inl(edev, r) (*((volatile dword *)SMCREG(edev, r))) +#define SMC_inw(edev, r) (*((volatile word *)SMCREG(edev, r))) +#define SMC_inb(edev, p) ({ \ unsigned int __p = p; \ - unsigned int __v = SMC_inw(__p & ~1); \ + unsigned int __v = SMC_inw(edev, __p & ~1); \ if (__p & 1) __v >>= 8; \ else __v &= 0xff; \ __v; }) -#define SMC_outl(d,r) (*((volatile dword *)SMCREG(r)) = d) -#define SMC_outw(d,r) (*((volatile word *)SMCREG(r)) = d) -#define SMC_outb(d,r) ({ word __d = (byte)(d); \ - word __w = SMC_inw((r)&~1); \ +#define SMC_outl(edev, d, r) (*((volatile dword *)SMCREG(edev, r)) = d) +#define SMC_outw(edev, d, r) (*((volatile word *)SMCREG(edev, r)) = d) +#define SMC_outb(edev, d, r) ({ word __d = (byte)(d); \ + word __w = SMC_inw(edev, (r)&~1); \ __w &= ((r)&1) ? 0x00FF : 0xFF00; \ __w |= ((r)&1) ? __d<<8 : __d; \ - SMC_outw(__w,(r)&~1); \ + SMC_outw(edev, __w, (r)&~1); \ }) -#define SMC_outsl(r,b,l) ({ int __i; \ +#define SMC_outsl(edev, r, b, l) ({ int __i; \ dword *__b2; \ __b2 = (dword *) b; \ for (__i = 0; __i < l; __i++) { \ - SMC_outl( *(__b2 + __i), r ); \ + SMC_outl(edev, *(__b2 + __i),\ + r); \ } \ }) -#define SMC_outsw(r,b,l) ({ int __i; \ +#define SMC_outsw(edev, r, b, l) ({ int __i; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ - SMC_outw( *(__b2 + __i), r ); \ + SMC_outw(edev, *(__b2 + __i),\ + r); \ } \ }) -#define SMC_insl(r,b,l) ({ int __i ; \ +#define SMC_insl(edev, r, b, l) ({ int __i ; \ dword *__b2; \ __b2 = (dword *) b; \ for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inl(r); \ - SMC_inl(0); \ + *(__b2 + __i) = SMC_inl(edev,\ + r); \ + SMC_inl(edev, 0); \ }; \ }) -#define SMC_insw(r,b,l) ({ int __i ; \ +#define SMC_insw(edev, r, b, l) ({ int __i ; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inw(r); \ - SMC_inw(0); \ + *(__b2 + __i) = SMC_inw(edev,\ + r); \ + SMC_inw(edev, 0); \ }; \ }) -#define SMC_insb(r,b,l) ({ int __i ; \ +#define SMC_insb(edev, r, b, l) ({ int __i ; \ byte *__b2; \ __b2 = (byte *) b; \ for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inb(r); \ - SMC_inb(0); \ + *(__b2 + __i) = SMC_inb(edev,\ + r); \ + SMC_inb(edev, 0); \ }; \ }) @@ -155,40 +152,35 @@ typedef unsigned long int dword; * We have only 16 Bit PCMCIA access on Socket 0 */ -#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r)))) -#define SMC_inb(r) (((r)&1) ? SMC_inw((r)&~1)>>8 : SMC_inw(r)&0xFF) +#define SMC_inw(edev, r) (*((volatile word *)((edev)->iobase+(r)))) +#define SMC_inb(edev, r) (((r)&1) ? SMC_inw(edev, (r)&~1)>>8 :\ + SMC_inw(edev, r)&0xFF) -#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d) -#define SMC_outb(d,r) ({ word __d = (byte)(d); \ - word __w = SMC_inw((r)&~1); \ +#define SMC_outw(edev, d, r) (*((volatile word *)((edev)->iobase+(r))) = d) +#define SMC_outb(edev, d, r) ({ word __d = (byte)(d); \ + word __w = SMC_inw(edev, (r)&~1); \ __w &= ((r)&1) ? 0x00FF : 0xFF00; \ __w |= ((r)&1) ? __d<<8 : __d; \ - SMC_outw(__w,(r)&~1); \ + SMC_outw(edev, __w, (r)&~1); \ }) -#if 0 -#define SMC_outsw(r,b,l) outsw(SMC_BASE_ADDRESS+(r), (b), (l)) -#else -#define SMC_outsw(r,b,l) ({ int __i; \ +#define SMC_outsw(edev, r, b, l) ({ int __i; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ - SMC_outw( *(__b2 + __i), r); \ + SMC_outw(edev, *(__b2 + __i),\ + r); \ } \ }) -#endif -#if 0 -#define SMC_insw(r,b,l) insw(SMC_BASE_ADDRESS+(r), (b), (l)) -#else -#define SMC_insw(r,b,l) ({ int __i ; \ +#define SMC_insw(edev, r, b, l) ({ int __i ; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inw(r); \ - SMC_inw(0); \ + *(__b2 + __i) = SMC_inw(edev,\ + r); \ + SMC_inw(edev, 0); \ }; \ }) -#endif #endif @@ -608,25 +600,25 @@ typedef unsigned long int dword; /* select a register bank, 0 to 3 */ -#define SMC_SELECT_BANK(x) { SMC_outw( x, LAN91C96_BANK_SELECT ); } +#define SMC_SELECT_BANK(edev, x) { SMC_outw(edev, x, LAN91C96_BANK_SELECT); } /* this enables an interrupt in the interrupt mask register */ -#define SMC_ENABLE_INT(x) {\ +#define SMC_ENABLE_INT(edev, x) {\ unsigned char mask;\ - SMC_SELECT_BANK(2);\ - mask = SMC_inb( LAN91C96_INT_MASK );\ + SMC_SELECT_BANK(edev, 2);\ + mask = SMC_inb(edev, LAN91C96_INT_MASK);\ mask |= (x);\ - SMC_outb( mask, LAN91C96_INT_MASK ); \ + SMC_outb(edev, mask, LAN91C96_INT_MASK); \ } /* this disables an interrupt from the interrupt mask register */ -#define SMC_DISABLE_INT(x) {\ +#define SMC_DISABLE_INT(edev, x) {\ unsigned char mask;\ - SMC_SELECT_BANK(2);\ - mask = SMC_inb( LAN91C96_INT_MASK );\ + SMC_SELECT_BANK(edev, 2);\ + mask = SMC_inb(edev, LAN91C96_INT_MASK);\ mask &= ~(x);\ - SMC_outb( mask, LAN91C96_INT_MASK ); \ + SMC_outb(edev, mask, LAN91C96_INT_MASK); \ } /*---------------------------------------------------------------------- diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h index f746d6317..6b6c4a162 100644 --- a/drivers/serial/usbtty.h +++ b/drivers/serial/usbtty.h @@ -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 diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 324c308f4..ba85991e8 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -96,7 +96,7 @@ static struct descriptor { * UE_DIR_IN | EHCI_INTR_ENDPT */ 3, /* bmAttributes: UE_INTERRUPT */ - 8, 0, /* wMaxPacketSize */ + 8, /* wMaxPacketSize */ 255 /* bInterval */ }, }; diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 09e0a5f32..f2ccd9fe0 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -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) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index ec57fc811..22f3dba0c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -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 */ diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index f9da3f0b2..15c7f49a3 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -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))); /* diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h new file mode 100644 index 000000000..62380ffc6 --- /dev/null +++ b/drivers/usb/musb/musb_debug.h @@ -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 */ diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c index 4ca94cb31..555d2dc1b 100644 --- a/drivers/usb/musb/musb_hcd.c +++ b/drivers/usb/musb/musb_hcd.c @@ -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; diff --git a/drivers/usb/musb/musb_udc.c b/drivers/usb/musb/musb_udc.c new file mode 100644 index 000000000..fc43cf4f0 --- /dev/null +++ b/drivers/usb/musb/musb_udc.c @@ -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; +} diff --git a/drivers/usb/musb/omap3.c b/drivers/usb/musb/omap3.c new file mode 100644 index 000000000..ea98c3cac --- /dev/null +++ b/drivers/usb/musb/omap3.c @@ -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 */ +} diff --git a/drivers/usb/musb/omap3.h b/drivers/usb/musb/omap3.h new file mode 100644 index 000000000..20fc9d294 --- /dev/null +++ b/drivers/usb/musb/omap3.h @@ -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 */ + diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile new file mode 100644 index 000000000..200b907d9 --- /dev/null +++ b/drivers/usb/phy/Makefile @@ -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 + +######################################################################### diff --git a/drivers/usb/phy/twl4030.c b/drivers/usb/phy/twl4030.c new file mode 100644 index 000000000..54d2e615c --- /dev/null +++ b/drivers/usb/phy/twl4030.c @@ -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; +} diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 16d6689f2..c07a26e3c 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -403,8 +403,6 @@ static const int video_font_draw_table32[16][4] = { { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } }; -int gunzip(void *, int, unsigned char *, unsigned long *); - /******************************************************************************/ static void video_drawchars (int xx, int yy, unsigned char *s, int count) |