1 /* 2 * Mentor USB OTG Core functionality common for both Host and Device 3 * functionality. 4 * 5 * Copyright (c) 2008 Texas Instruments 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * MA 02111-1307 USA 21 * 22 * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments 23 */ 24 25 #include <common.h> 26 27 #include "musb_core.h" 28 struct musb_regs *musbr; 29 30 /* 31 * program the mentor core to start (enable interrupts, dma, etc.) 32 */ 33 void musb_start(void) 34 { 35 #if defined(CONFIG_MUSB_HCD) 36 u8 devctl; 37 u8 busctl; 38 #endif 39 40 /* disable all interrupts */ 41 writew(0, &musbr->intrtxe); 42 writew(0, &musbr->intrrxe); 43 writeb(0, &musbr->intrusbe); 44 writeb(0, &musbr->testmode); 45 46 /* put into basic highspeed mode and start session */ 47 writeb(MUSB_POWER_HSENAB, &musbr->power); 48 #if defined(CONFIG_MUSB_HCD) 49 /* Program PHY to use EXT VBUS if required */ 50 if (musb_cfg.extvbus == 1) { 51 busctl = musb_read_ulpi_buscontrol(musbr); 52 musb_write_ulpi_buscontrol(musbr, busctl | ULPI_USE_EXTVBUS); 53 } 54 55 devctl = readb(&musbr->devctl); 56 writeb(devctl | MUSB_DEVCTL_SESSION, &musbr->devctl); 57 #endif 58 } 59 60 #ifdef MUSB_NO_DYNAMIC_FIFO 61 # define config_fifo(dir, idx, addr) 62 #else 63 # define config_fifo(dir, idx, addr) \ 64 do { \ 65 writeb(idx, &musbr->dir##fifosz); \ 66 writew(fifoaddr >> 3, &musbr->dir##fifoadd); \ 67 } while (0) 68 #endif 69 70 /* 71 * This function configures the endpoint configuration. The musb hcd or musb 72 * device implementation can use this function to configure the endpoints 73 * and set the FIFO sizes. Note: The summation of FIFO sizes of all endpoints 74 * should not be more than the available FIFO size. 75 * 76 * epinfo - Pointer to EP configuration table 77 * cnt - Number of entries in the EP conf table. 78 */ 79 void musb_configure_ep(const struct musb_epinfo *epinfo, u8 cnt) 80 { 81 u16 csr; 82 u16 fifoaddr = 64; /* First 64 bytes of FIFO reserved for EP0 */ 83 u32 fifosize; 84 u8 idx; 85 86 while (cnt--) { 87 /* prepare fifosize to write to register */ 88 fifosize = epinfo->epsize >> 3; 89 idx = ffs(fifosize) - 1; 90 91 writeb(epinfo->epnum, &musbr->index); 92 if (epinfo->epdir) { 93 /* Configure fifo size and fifo base address */ 94 config_fifo(tx, idx, fifoaddr); 95 96 csr = readw(&musbr->txcsr); 97 #if defined(CONFIG_MUSB_HCD) 98 /* clear the data toggle bit */ 99 writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr); 100 #endif 101 /* Flush fifo if required */ 102 if (csr & MUSB_TXCSR_TXPKTRDY) 103 writew(csr | MUSB_TXCSR_FLUSHFIFO, 104 &musbr->txcsr); 105 } else { 106 /* Configure fifo size and fifo base address */ 107 config_fifo(rx, idx, fifoaddr); 108 109 csr = readw(&musbr->rxcsr); 110 #if defined(CONFIG_MUSB_HCD) 111 /* clear the data toggle bit */ 112 writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr); 113 #endif 114 /* Flush fifo if required */ 115 if (csr & MUSB_RXCSR_RXPKTRDY) 116 writew(csr | MUSB_RXCSR_FLUSHFIFO, 117 &musbr->rxcsr); 118 } 119 fifoaddr += epinfo->epsize; 120 epinfo++; 121 } 122 } 123 124 /* 125 * This function writes data to endpoint fifo 126 * 127 * ep - endpoint number 128 * length - number of bytes to write to FIFO 129 * fifo_data - Pointer to data buffer that contains the data to write 130 */ 131 __attribute__((weak)) 132 void write_fifo(u8 ep, u32 length, void *fifo_data) 133 { 134 u8 *data = (u8 *)fifo_data; 135 136 /* select the endpoint index */ 137 writeb(ep, &musbr->index); 138 139 /* write the data to the fifo */ 140 while (length--) 141 writeb(*data++, &musbr->fifox[ep]); 142 } 143 144 /* 145 * AM35x supports only 32bit read operations so 146 * use seperate read_fifo() function for it. 147 */ 148 #ifndef CONFIG_USB_AM35X 149 /* 150 * This function reads data from endpoint fifo 151 * 152 * ep - endpoint number 153 * length - number of bytes to read from FIFO 154 * fifo_data - pointer to data buffer into which data is read 155 */ 156 __attribute__((weak)) 157 void read_fifo(u8 ep, u32 length, void *fifo_data) 158 { 159 u8 *data = (u8 *)fifo_data; 160 161 /* select the endpoint index */ 162 writeb(ep, &musbr->index); 163 164 /* read the data to the fifo */ 165 while (length--) 166 *data++ = readb(&musbr->fifox[ep]); 167 } 168 #endif /* CONFIG_USB_AM35X */ 169