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