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