xref: /openbmc/u-boot/drivers/usb/musb/musb_core.c (revision 87a62bce)
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