Tom Rini | 83d290c | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 2 | /* |
| 3 | * Mentor USB OTG Core functionality common for both Host and Device |
| 4 | * functionality. |
| 5 | * |
| 6 | * Copyright (c) 2008 Texas Instruments |
| 7 | * |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 8 | * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments |
| 9 | */ |
| 10 | |
| 11 | #include <common.h> |
Simon Glass | cd93d62 | 2020-05-10 11:40:13 -0600 | [diff] [blame] | 12 | #include <linux/bitops.h> |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 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 | { |
Paul Kocialkowski | 95de1e2 | 2015-08-04 17:04:06 +0200 | [diff] [blame] | 22 | #if defined(CONFIG_USB_MUSB_HCD) |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 23 | u8 devctl; |
Ajay Kumar Gupta | 9bb47ab | 2010-06-10 11:20:48 +0530 | [diff] [blame] | 24 | u8 busctl; |
Tom Rix | f298e4b | 2009-10-31 12:37:41 -0500 | [diff] [blame] | 25 | #endif |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 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); |
Paul Kocialkowski | 95de1e2 | 2015-08-04 17:04:06 +0200 | [diff] [blame] | 35 | #if defined(CONFIG_USB_MUSB_HCD) |
Ajay Kumar Gupta | 9bb47ab | 2010-06-10 11:20:48 +0530 | [diff] [blame] | 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 | |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 42 | devctl = readb(&musbr->devctl); |
| 43 | writeb(devctl | MUSB_DEVCTL_SESSION, &musbr->devctl); |
| 44 | #endif |
| 45 | } |
| 46 | |
Bryan Wu | df402ba | 2009-12-16 22:03:59 -0500 | [diff] [blame] | 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); \ |
Pali Rohár | 10bc132 | 2021-02-07 14:50:05 +0100 | [diff] [blame] | 53 | writew(addr, &musbr->dir##fifoadd); \ |
Bryan Wu | df402ba | 2009-12-16 22:03:59 -0500 | [diff] [blame] | 54 | } while (0) |
| 55 | #endif |
| 56 | |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 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 | */ |
Mike Frysinger | 0228348 | 2010-10-20 07:15:35 -0400 | [diff] [blame] | 66 | void musb_configure_ep(const struct musb_epinfo *epinfo, u8 cnt) |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 67 | { |
| 68 | u16 csr; |
Pali Rohár | 10bc132 | 2021-02-07 14:50:05 +0100 | [diff] [blame] | 69 | u16 fifoaddr = 64 >> 3; /* First 64 bytes of FIFO reserved for EP0 */ |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 70 | u32 fifosize; |
| 71 | u8 idx; |
| 72 | |
| 73 | while (cnt--) { |
| 74 | /* prepare fifosize to write to register */ |
| 75 | fifosize = epinfo->epsize >> 3; |
Pali Rohár | 10bc132 | 2021-02-07 14:50:05 +0100 | [diff] [blame] | 76 | idx = fifosize ? ((ffs(fifosize) - 1) & 0xF) : 0; |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 77 | |
| 78 | writeb(epinfo->epnum, &musbr->index); |
| 79 | if (epinfo->epdir) { |
| 80 | /* Configure fifo size and fifo base address */ |
Bryan Wu | df402ba | 2009-12-16 22:03:59 -0500 | [diff] [blame] | 81 | config_fifo(tx, idx, fifoaddr); |
Tom Rix | f298e4b | 2009-10-31 12:37:41 -0500 | [diff] [blame] | 82 | |
| 83 | csr = readw(&musbr->txcsr); |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 84 | /* clear the data toggle bit */ |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 85 | writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr); |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 86 | /* Flush fifo if required */ |
| 87 | if (csr & MUSB_TXCSR_TXPKTRDY) |
| 88 | writew(csr | MUSB_TXCSR_FLUSHFIFO, |
| 89 | &musbr->txcsr); |
| 90 | } else { |
| 91 | /* Configure fifo size and fifo base address */ |
Bryan Wu | df402ba | 2009-12-16 22:03:59 -0500 | [diff] [blame] | 92 | config_fifo(rx, idx, fifoaddr); |
Tom Rix | f298e4b | 2009-10-31 12:37:41 -0500 | [diff] [blame] | 93 | |
| 94 | csr = readw(&musbr->rxcsr); |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 95 | /* clear the data toggle bit */ |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 96 | writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr); |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 97 | /* Flush fifo if required */ |
| 98 | if (csr & MUSB_RXCSR_RXPKTRDY) |
| 99 | writew(csr | MUSB_RXCSR_FLUSHFIFO, |
| 100 | &musbr->rxcsr); |
| 101 | } |
Pali Rohár | 10bc132 | 2021-02-07 14:50:05 +0100 | [diff] [blame] | 102 | fifoaddr += 1 << idx; |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 103 | epinfo++; |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | /* |
| 108 | * This function writes data to endpoint fifo |
| 109 | * |
| 110 | * ep - endpoint number |
| 111 | * length - number of bytes to write to FIFO |
| 112 | * fifo_data - Pointer to data buffer that contains the data to write |
| 113 | */ |
Bryan Wu | df402ba | 2009-12-16 22:03:59 -0500 | [diff] [blame] | 114 | __attribute__((weak)) |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 115 | void write_fifo(u8 ep, u32 length, void *fifo_data) |
| 116 | { |
| 117 | u8 *data = (u8 *)fifo_data; |
| 118 | |
| 119 | /* select the endpoint index */ |
| 120 | writeb(ep, &musbr->index); |
| 121 | |
| 122 | /* write the data to the fifo */ |
| 123 | while (length--) |
| 124 | writeb(*data++, &musbr->fifox[ep]); |
| 125 | } |
| 126 | |
| 127 | /* |
Ajay Kumar Gupta | 5689f4b | 2010-07-09 11:43:49 +0530 | [diff] [blame] | 128 | * AM35x supports only 32bit read operations so |
| 129 | * use seperate read_fifo() function for it. |
| 130 | */ |
| 131 | #ifndef CONFIG_USB_AM35X |
| 132 | /* |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 133 | * This function reads data from endpoint fifo |
| 134 | * |
| 135 | * ep - endpoint number |
| 136 | * length - number of bytes to read from FIFO |
| 137 | * fifo_data - pointer to data buffer into which data is read |
| 138 | */ |
Bryan Wu | df402ba | 2009-12-16 22:03:59 -0500 | [diff] [blame] | 139 | __attribute__((weak)) |
Thomas Abraham | a142896 | 2009-01-04 09:41:03 +0530 | [diff] [blame] | 140 | void read_fifo(u8 ep, u32 length, void *fifo_data) |
| 141 | { |
| 142 | u8 *data = (u8 *)fifo_data; |
| 143 | |
| 144 | /* select the endpoint index */ |
| 145 | writeb(ep, &musbr->index); |
| 146 | |
| 147 | /* read the data to the fifo */ |
| 148 | while (length--) |
| 149 | *data++ = readb(&musbr->fifox[ep]); |
| 150 | } |
Ajay Kumar Gupta | 5689f4b | 2010-07-09 11:43:49 +0530 | [diff] [blame] | 151 | #endif /* CONFIG_USB_AM35X */ |