Merge tag 'efi-2020-07-rc6' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
[oweals/u-boot.git] / drivers / usb / musb / musb_core.c
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 #include <linux/bitops.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_USB_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_USB_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_USB_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_USB_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 */