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  */
musb_start(void)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(addr, &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  */
musb_configure_ep(const struct musb_epinfo * epinfo,u8 cnt)66 void musb_configure_ep(const struct musb_epinfo *epinfo, u8 cnt)
67 {
68 	u16 csr;
69 	u16 fifoaddr = 64 >> 3; /* 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 = fifosize ? ((ffs(fifosize) - 1) & 0xF) : 0;
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 			/* clear the data toggle bit */
85 			writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
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 */
92 			config_fifo(rx, idx, fifoaddr);
93 
94 			csr = readw(&musbr->rxcsr);
95 			/* clear the data toggle bit */
96 			writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
97 			/* Flush fifo if required */
98 			if (csr & MUSB_RXCSR_RXPKTRDY)
99 				writew(csr | MUSB_RXCSR_FLUSHFIFO,
100 					&musbr->rxcsr);
101 		}
102 		fifoaddr += 1 << idx;
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  */
114 __attribute__((weak))
write_fifo(u8 ep,u32 length,void * fifo_data)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 /*
128  * AM35x supports only 32bit read operations so
129  * use seperate read_fifo() function for it.
130  */
131 #ifndef CONFIG_USB_AM35X
132 /*
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  */
139 __attribute__((weak))
read_fifo(u8 ep,u32 length,void * fifo_data)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 }
151 #endif /* CONFIG_USB_AM35X */
152