1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Intel PXA25x on-chip full speed USB device controller |
4 | * |
5 | * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix |
6 | * Copyright (C) 2003 David Brownell |
7 | */ |
8 | |
9 | #ifndef __LINUX_USB_GADGET_PXA25X_H |
10 | #define __LINUX_USB_GADGET_PXA25X_H |
11 | |
12 | #include <linux/types.h> |
13 | |
14 | /*-------------------------------------------------------------------------*/ |
15 | |
16 | /* pxa25x has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */ |
17 | #define UFNRH_SIR (1 << 7) /* SOF interrupt request */ |
18 | #define UFNRH_SIM (1 << 6) /* SOF interrupt mask */ |
19 | #define UFNRH_IPE14 (1 << 5) /* ISO packet error, ep14 */ |
20 | #define UFNRH_IPE9 (1 << 4) /* ISO packet error, ep9 */ |
21 | #define UFNRH_IPE4 (1 << 3) /* ISO packet error, ep4 */ |
22 | |
23 | /* pxa255 has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */ |
24 | #define UDCCFR UDC_RES2 /* UDC Control Function Register */ |
25 | #define UDCCFR_AREN (1 << 7) /* ACK response enable (now) */ |
26 | #define UDCCFR_ACM (1 << 2) /* ACK control mode (wait for AREN) */ |
27 | |
28 | /* latest pxa255 errata define new "must be one" bits in UDCCFR */ |
29 | #define UDCCFR_MB1 (0xff & ~(UDCCFR_AREN|UDCCFR_ACM)) |
30 | |
31 | /*-------------------------------------------------------------------------*/ |
32 | |
33 | struct pxa25x_udc; |
34 | |
35 | struct pxa25x_ep { |
36 | struct usb_ep ep; |
37 | struct pxa25x_udc *dev; |
38 | |
39 | struct list_head queue; |
40 | unsigned long pio_irqs; |
41 | |
42 | unsigned short fifo_size; |
43 | u8 bEndpointAddress; |
44 | u8 bmAttributes; |
45 | |
46 | unsigned stopped : 1; |
47 | unsigned dma_fixup : 1; |
48 | |
49 | /* UDCCS = UDC Control/Status for this EP |
50 | * UBCR = UDC Byte Count Remaining (contents of OUT fifo) |
51 | * UDDR = UDC Endpoint Data Register (the fifo) |
52 | * DRCM = DMA Request Channel Map |
53 | */ |
54 | u32 regoff_udccs; |
55 | u32 regoff_ubcr; |
56 | u32 regoff_uddr; |
57 | }; |
58 | |
59 | struct pxa25x_request { |
60 | struct usb_request req; |
61 | struct list_head queue; |
62 | }; |
63 | |
64 | enum ep0_state { |
65 | EP0_IDLE, |
66 | EP0_IN_DATA_PHASE, |
67 | EP0_OUT_DATA_PHASE, |
68 | EP0_END_XFER, |
69 | EP0_STALL, |
70 | }; |
71 | |
72 | #define EP0_FIFO_SIZE ((unsigned)16) |
73 | #define BULK_FIFO_SIZE ((unsigned)64) |
74 | #define ISO_FIFO_SIZE ((unsigned)256) |
75 | #define INT_FIFO_SIZE ((unsigned)8) |
76 | |
77 | struct udc_stats { |
78 | struct ep0stats { |
79 | unsigned long ops; |
80 | unsigned long bytes; |
81 | } read, write; |
82 | unsigned long irqs; |
83 | }; |
84 | |
85 | #ifdef CONFIG_USB_PXA25X_SMALL |
86 | /* when memory's tight, SMALL config saves code+data. */ |
87 | #define PXA_UDC_NUM_ENDPOINTS 3 |
88 | #endif |
89 | |
90 | #ifndef PXA_UDC_NUM_ENDPOINTS |
91 | #define PXA_UDC_NUM_ENDPOINTS 16 |
92 | #endif |
93 | |
94 | struct pxa25x_udc { |
95 | struct usb_gadget gadget; |
96 | struct usb_gadget_driver *driver; |
97 | |
98 | enum ep0_state ep0state; |
99 | struct udc_stats stats; |
100 | unsigned got_irq : 1, |
101 | vbus : 1, |
102 | pullup : 1, |
103 | has_cfr : 1, |
104 | req_pending : 1, |
105 | req_std : 1, |
106 | req_config : 1, |
107 | suspended : 1, |
108 | active : 1; |
109 | |
110 | #define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200)) |
111 | struct timer_list timer; |
112 | |
113 | struct device *dev; |
114 | struct clk *clk; |
115 | struct pxa2xx_udc_mach_info *mach; |
116 | struct usb_phy *transceiver; |
117 | u64 dma_mask; |
118 | struct pxa25x_ep ep [PXA_UDC_NUM_ENDPOINTS]; |
119 | void __iomem *regs; |
120 | int usb_irq; |
121 | int usb_disc_irq; |
122 | }; |
123 | #define to_pxa25x(g) (container_of((g), struct pxa25x_udc, gadget)) |
124 | |
125 | /*-------------------------------------------------------------------------*/ |
126 | |
127 | static struct pxa25x_udc *the_controller; |
128 | |
129 | /*-------------------------------------------------------------------------*/ |
130 | |
131 | /* |
132 | * Debugging support vanishes in non-debug builds. DBG_NORMAL should be |
133 | * mostly silent during normal use/testing, with no timing side-effects. |
134 | */ |
135 | #define DBG_NORMAL 1 /* error paths, device state transitions */ |
136 | #define DBG_VERBOSE 2 /* add some success path trace info */ |
137 | #define DBG_NOISY 3 /* ... even more: request level */ |
138 | #define DBG_VERY_NOISY 4 /* ... even more: packet level */ |
139 | |
140 | #define DMSG(stuff...) pr_debug("udc: " stuff) |
141 | |
142 | #ifdef DEBUG |
143 | |
144 | static const char *state_name[] = { |
145 | "EP0_IDLE" , |
146 | "EP0_IN_DATA_PHASE" , "EP0_OUT_DATA_PHASE" , |
147 | "EP0_END_XFER" , "EP0_STALL" |
148 | }; |
149 | |
150 | #ifdef VERBOSE_DEBUG |
151 | # define UDC_DEBUG DBG_VERBOSE |
152 | #else |
153 | # define UDC_DEBUG DBG_NORMAL |
154 | #endif |
155 | |
156 | static void __maybe_unused |
157 | dump_udccr(const char *label) |
158 | { |
159 | u32 udccr = UDCCR; |
160 | DMSG("%s %02X =%s%s%s%s%s%s%s%s\n" , |
161 | label, udccr, |
162 | (udccr & UDCCR_REM) ? " rem" : "" , |
163 | (udccr & UDCCR_RSTIR) ? " rstir" : "" , |
164 | (udccr & UDCCR_SRM) ? " srm" : "" , |
165 | (udccr & UDCCR_SUSIR) ? " susir" : "" , |
166 | (udccr & UDCCR_RESIR) ? " resir" : "" , |
167 | (udccr & UDCCR_RSM) ? " rsm" : "" , |
168 | (udccr & UDCCR_UDA) ? " uda" : "" , |
169 | (udccr & UDCCR_UDE) ? " ude" : "" ); |
170 | } |
171 | |
172 | static void __maybe_unused |
173 | dump_udccs0(const char *label) |
174 | { |
175 | u32 udccs0 = UDCCS0; |
176 | |
177 | DMSG("%s %s %02X =%s%s%s%s%s%s%s%s\n" , |
178 | label, state_name[the_controller->ep0state], udccs0, |
179 | (udccs0 & UDCCS0_SA) ? " sa" : "" , |
180 | (udccs0 & UDCCS0_RNE) ? " rne" : "" , |
181 | (udccs0 & UDCCS0_FST) ? " fst" : "" , |
182 | (udccs0 & UDCCS0_SST) ? " sst" : "" , |
183 | (udccs0 & UDCCS0_DRWF) ? " dwrf" : "" , |
184 | (udccs0 & UDCCS0_FTF) ? " ftf" : "" , |
185 | (udccs0 & UDCCS0_IPR) ? " ipr" : "" , |
186 | (udccs0 & UDCCS0_OPR) ? " opr" : "" ); |
187 | } |
188 | |
189 | static inline u32 udc_ep_get_UDCCS(struct pxa25x_ep *); |
190 | |
191 | static void __maybe_unused |
192 | dump_state(struct pxa25x_udc *dev) |
193 | { |
194 | u32 tmp; |
195 | unsigned i; |
196 | |
197 | DMSG("%s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n" , |
198 | state_name[dev->ep0state], |
199 | UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL); |
200 | dump_udccr(label: "udccr" ); |
201 | if (dev->has_cfr) { |
202 | tmp = UDCCFR; |
203 | DMSG("udccfr %02X =%s%s\n" , tmp, |
204 | (tmp & UDCCFR_AREN) ? " aren" : "" , |
205 | (tmp & UDCCFR_ACM) ? " acm" : "" ); |
206 | } |
207 | |
208 | if (!dev->driver) { |
209 | DMSG("no gadget driver bound\n" ); |
210 | return; |
211 | } else |
212 | DMSG("ep0 driver '%s'\n" , dev->driver->driver.name); |
213 | |
214 | dump_udccs0 (label: "udccs0" ); |
215 | DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n" , |
216 | dev->stats.write.bytes, dev->stats.write.ops, |
217 | dev->stats.read.bytes, dev->stats.read.ops); |
218 | |
219 | for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) { |
220 | if (dev->ep[i].ep.desc == NULL) |
221 | continue; |
222 | DMSG ("udccs%d = %02x\n" , i, udc_ep_get_UDCCS(&dev->ep[i])); |
223 | } |
224 | } |
225 | |
226 | #else |
227 | |
228 | #define dump_udccr(x) do{}while(0) |
229 | #define dump_udccs0(x) do{}while(0) |
230 | #define dump_state(x) do{}while(0) |
231 | |
232 | #define UDC_DEBUG ((unsigned)0) |
233 | |
234 | #endif |
235 | |
236 | #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0) |
237 | |
238 | #define ERR(stuff...) pr_err("udc: " stuff) |
239 | #define WARNING(stuff...) pr_warn("udc: " stuff) |
240 | #define INFO(stuff...) pr_info("udc: " stuff) |
241 | |
242 | |
243 | #endif /* __LINUX_USB_GADGET_PXA25X_H */ |
244 | |