diff options
author | Darius Augulis <augulis.darius@gmail.com> | 2008-11-12 16:38:31 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-07 13:00:11 -0500 |
commit | 2a4f136fbdcd89d44d83ed54df2c492a89f5ba9c (patch) | |
tree | 5e51cdbbe6024ba35e4fef3809a761f30d272942 /drivers/usb/gadget/imx_udc.h | |
parent | 856395d6e137b4e7194972cb7765f3de6a72ba61 (diff) |
USB: add imx udc gadget driver
Implementation of USB device driver integrated in Freescale's i.MXL
processor.
Adds USB device driver for i.MXL.
Signed-off-by: Darius Augulis <augulis.darius@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/imx_udc.h')
-rw-r--r-- | drivers/usb/gadget/imx_udc.h | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h new file mode 100644 index 000000000000..850076937d8d --- /dev/null +++ b/drivers/usb/gadget/imx_udc.h | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Mike Lee(eemike@gmail.com) | ||
3 | * | ||
4 | * This udc driver is now under testing and code is based on pxa2xx_udc.h | ||
5 | * Please use it with your own risk! | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #ifndef __LINUX_USB_GADGET_IMX_H | ||
19 | #define __LINUX_USB_GADGET_IMX_H | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | |||
23 | /* Helper macros */ | ||
24 | #define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */ | ||
25 | #define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0) | ||
26 | #define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ | ||
27 | #define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0) | ||
28 | #define IMX_USB_NB_EP 6 | ||
29 | |||
30 | /* Driver structures */ | ||
31 | struct imx_request { | ||
32 | struct usb_request req; | ||
33 | struct list_head queue; | ||
34 | unsigned int in_use; | ||
35 | }; | ||
36 | |||
37 | enum ep0_state { | ||
38 | EP0_IDLE, | ||
39 | EP0_IN_DATA_PHASE, | ||
40 | EP0_OUT_DATA_PHASE, | ||
41 | EP0_CONFIG, | ||
42 | EP0_STALL, | ||
43 | }; | ||
44 | |||
45 | struct imx_ep_struct { | ||
46 | struct usb_ep ep; | ||
47 | struct imx_udc_struct *imx_usb; | ||
48 | struct list_head queue; | ||
49 | unsigned char stopped; | ||
50 | unsigned char fifosize; | ||
51 | unsigned char bEndpointAddress; | ||
52 | unsigned char bmAttributes; | ||
53 | }; | ||
54 | |||
55 | struct imx_udc_struct { | ||
56 | struct usb_gadget gadget; | ||
57 | struct usb_gadget_driver *driver; | ||
58 | struct device *dev; | ||
59 | struct imx_ep_struct imx_ep[IMX_USB_NB_EP]; | ||
60 | struct clk *clk; | ||
61 | enum ep0_state ep0state; | ||
62 | struct resource *res; | ||
63 | void __iomem *base; | ||
64 | unsigned char set_config; | ||
65 | int cfg, | ||
66 | intf, | ||
67 | alt, | ||
68 | usbd_int[7]; | ||
69 | }; | ||
70 | |||
71 | /* USB registers */ | ||
72 | #define USB_FRAME (0x00) /* USB frame */ | ||
73 | #define USB_SPEC (0x04) /* USB Spec */ | ||
74 | #define USB_STAT (0x08) /* USB Status */ | ||
75 | #define USB_CTRL (0x0C) /* USB Control */ | ||
76 | #define USB_DADR (0x10) /* USB Desc RAM addr */ | ||
77 | #define USB_DDAT (0x14) /* USB Desc RAM/EP buffer data */ | ||
78 | #define USB_INTR (0x18) /* USB interrupt */ | ||
79 | #define USB_MASK (0x1C) /* USB Mask */ | ||
80 | #define USB_ENAB (0x24) /* USB Enable */ | ||
81 | #define USB_EP_STAT(x) (0x30 + (x*0x30)) /* USB status/control */ | ||
82 | #define USB_EP_INTR(x) (0x34 + (x*0x30)) /* USB interrupt */ | ||
83 | #define USB_EP_MASK(x) (0x38 + (x*0x30)) /* USB mask */ | ||
84 | #define USB_EP_FDAT(x) (0x3C + (x*0x30)) /* USB FIFO data */ | ||
85 | #define USB_EP_FDAT0(x) (0x3C + (x*0x30)) /* USB FIFO data */ | ||
86 | #define USB_EP_FDAT1(x) (0x3D + (x*0x30)) /* USB FIFO data */ | ||
87 | #define USB_EP_FDAT2(x) (0x3E + (x*0x30)) /* USB FIFO data */ | ||
88 | #define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */ | ||
89 | #define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */ | ||
90 | #define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */ | ||
91 | #define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */ | ||
92 | #define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */ | ||
93 | #define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */ | ||
94 | #define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */ | ||
95 | #define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */ | ||
96 | /* USB Control Register Bit Fields.*/ | ||
97 | #define CTRL_CMDOVER (1<<6) /* UDC status */ | ||
98 | #define CTRL_CMDERROR (1<<5) /* UDC status */ | ||
99 | #define CTRL_FE_ENA (1<<3) /* Enable Font End logic */ | ||
100 | #define CTRL_UDC_RST (1<<2) /* UDC reset */ | ||
101 | #define CTRL_AFE_ENA (1<<1) /* Analog Font end enable */ | ||
102 | #define CTRL_RESUME (1<<0) /* UDC resume */ | ||
103 | /* USB Status Register Bit Fields.*/ | ||
104 | #define STAT_RST (1<<8) | ||
105 | #define STAT_SUSP (1<<7) | ||
106 | #define STAT_CFG (3<<5) | ||
107 | #define STAT_INTF (3<<3) | ||
108 | #define STAT_ALTSET (7<<0) | ||
109 | /* USB Interrupt Status/Mask Registers Bit fields */ | ||
110 | #define INTR_WAKEUP (1<<31) /* Wake up Interrupt */ | ||
111 | #define INTR_MSOF (1<<7) /* Missed Start of Frame */ | ||
112 | #define INTR_SOF (1<<6) /* Start of Frame */ | ||
113 | #define INTR_RESET_STOP (1<<5) /* Reset Signaling stop */ | ||
114 | #define INTR_RESET_START (1<<4) /* Reset Signaling start */ | ||
115 | #define INTR_RESUME (1<<3) /* Suspend to resume */ | ||
116 | #define INTR_SUSPEND (1<<2) /* Active to suspend */ | ||
117 | #define INTR_FRAME_MATCH (1<<1) /* Frame matched */ | ||
118 | #define INTR_CFG_CHG (1<<0) /* Configuration change occurred */ | ||
119 | /* USB Enable Register Bit Fields.*/ | ||
120 | #define ENAB_RST (1<<31) /* Reset USB modules */ | ||
121 | #define ENAB_ENAB (1<<30) /* Enable USB modules*/ | ||
122 | #define ENAB_SUSPEND (1<<29) /* Suspend USB modules */ | ||
123 | #define ENAB_ENDIAN (1<<28) /* Endian of USB modules */ | ||
124 | #define ENAB_PWRMD (1<<0) /* Power mode of USB modules */ | ||
125 | /* USB Descriptor Ram Address Register bit fields */ | ||
126 | #define DADR_CFG (1<<31) /* Configuration */ | ||
127 | #define DADR_BSY (1<<30) /* Busy status */ | ||
128 | #define DADR_DADR (0x1FF) /* Descriptor Ram Address */ | ||
129 | /* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */ | ||
130 | #define DDAT_DDAT (0xFF) /* Descriptor Endpoint Buffer */ | ||
131 | /* USB Endpoint Status Register bit fields */ | ||
132 | #define EPSTAT_BCOUNT (0x7F<<16) /* Endpoint FIFO byte count */ | ||
133 | #define EPSTAT_SIP (1<<8) /* Endpoint setup in progress */ | ||
134 | #define EPSTAT_DIR (1<<7) /* Endpoint transfer direction */ | ||
135 | #define EPSTAT_MAX (3<<5) /* Endpoint Max packet size */ | ||
136 | #define EPSTAT_TYP (3<<3) /* Endpoint type */ | ||
137 | #define EPSTAT_ZLPS (1<<2) /* Send zero length packet */ | ||
138 | #define EPSTAT_FLUSH (1<<1) /* Endpoint FIFO Flush */ | ||
139 | #define EPSTAT_STALL (1<<0) /* Force stall */ | ||
140 | /* USB Endpoint FIFO Status Register bit fields */ | ||
141 | #define FSTAT_FRAME_STAT (0xF<<24) /* Frame status bit [0-3] */ | ||
142 | #define FSTAT_ERR (1<<22) /* FIFO error */ | ||
143 | #define FSTAT_UF (1<<21) /* FIFO underflow */ | ||
144 | #define FSTAT_OF (1<<20) /* FIFO overflow */ | ||
145 | #define FSTAT_FR (1<<19) /* FIFO frame ready */ | ||
146 | #define FSTAT_FULL (1<<18) /* FIFO full */ | ||
147 | #define FSTAT_ALRM (1<<17) /* FIFO alarm */ | ||
148 | #define FSTAT_EMPTY (1<<16) /* FIFO empty */ | ||
149 | /* USB Endpoint FIFO Control Register bit fields */ | ||
150 | #define FCTRL_WFR (1<<29) /* Write frame end */ | ||
151 | /* USB Endpoint Interrupt Status Regsiter bit fields */ | ||
152 | #define EPINTR_FIFO_FULL (1<<8) /* fifo full */ | ||
153 | #define EPINTR_FIFO_EMPTY (1<<7) /* fifo empty */ | ||
154 | #define EPINTR_FIFO_ERROR (1<<6) /* fifo error */ | ||
155 | #define EPINTR_FIFO_HIGH (1<<5) /* fifo high */ | ||
156 | #define EPINTR_FIFO_LOW (1<<4) /* fifo low */ | ||
157 | #define EPINTR_MDEVREQ (1<<3) /* multi Device request */ | ||
158 | #define EPINTR_EOT (1<<2) /* fifo end of transfer */ | ||
159 | #define EPINTR_DEVREQ (1<<1) /* Device request */ | ||
160 | #define EPINTR_EOF (1<<0) /* fifo end of frame */ | ||
161 | |||
162 | /* Debug macros */ | ||
163 | #ifdef DEBUG | ||
164 | |||
165 | /* #define DEBUG_REQ */ | ||
166 | /* #define DEBUG_TRX */ | ||
167 | /* #define DEBUG_INIT */ | ||
168 | /* #define DEBUG_EP0 */ | ||
169 | /* #define DEBUG_EPX */ | ||
170 | /* #define DEBUG_IRQ */ | ||
171 | /* #define DEBUG_EPIRQ */ | ||
172 | /* #define DEBUG_DUMP */ | ||
173 | #define DEBUG_ERR | ||
174 | |||
175 | #ifdef DEBUG_REQ | ||
176 | #define D_REQ(dev, args...) dev_dbg(dev, ## args) | ||
177 | #else | ||
178 | #define D_REQ(dev, args...) do {} while (0) | ||
179 | #endif /* DEBUG_REQ */ | ||
180 | |||
181 | #ifdef DEBUG_TRX | ||
182 | #define D_TRX(dev, args...) dev_dbg(dev, ## args) | ||
183 | #else | ||
184 | #define D_TRX(dev, args...) do {} while (0) | ||
185 | #endif /* DEBUG_TRX */ | ||
186 | |||
187 | #ifdef DEBUG_INIT | ||
188 | #define D_INI(dev, args...) dev_dbg(dev, ## args) | ||
189 | #else | ||
190 | #define D_INI(dev, args...) do {} while (0) | ||
191 | #endif /* DEBUG_INIT */ | ||
192 | |||
193 | #ifdef DEBUG_EP0 | ||
194 | static const char *state_name[] = { | ||
195 | "EP0_IDLE", | ||
196 | "EP0_IN_DATA_PHASE", | ||
197 | "EP0_OUT_DATA_PHASE", | ||
198 | "EP0_CONFIG", | ||
199 | "EP0_STALL" | ||
200 | }; | ||
201 | #define D_EP0(dev, args...) dev_dbg(dev, ## args) | ||
202 | #else | ||
203 | #define D_EP0(dev, args...) do {} while (0) | ||
204 | #endif /* DEBUG_EP0 */ | ||
205 | |||
206 | #ifdef DEBUG_EPX | ||
207 | #define D_EPX(dev, args...) dev_dbg(dev, ## args) | ||
208 | #else | ||
209 | #define D_EPX(dev, args...) do {} while (0) | ||
210 | #endif /* DEBUG_EP0 */ | ||
211 | |||
212 | #ifdef DEBUG_IRQ | ||
213 | static void dump_intr(const char *label, int irqreg, struct device *dev) | ||
214 | { | ||
215 | dev_dbg(dev, "<%s> USB_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, | ||
216 | (irqreg & INTR_WAKEUP) ? " wake" : "", | ||
217 | (irqreg & INTR_MSOF) ? " msof" : "", | ||
218 | (irqreg & INTR_SOF) ? " sof" : "", | ||
219 | (irqreg & INTR_RESUME) ? " resume" : "", | ||
220 | (irqreg & INTR_SUSPEND) ? " suspend" : "", | ||
221 | (irqreg & INTR_RESET_STOP) ? " noreset" : "", | ||
222 | (irqreg & INTR_RESET_START) ? " reset" : "", | ||
223 | (irqreg & INTR_FRAME_MATCH) ? " fmatch" : "", | ||
224 | (irqreg & INTR_CFG_CHG) ? " config" : ""); | ||
225 | } | ||
226 | #else | ||
227 | #define dump_intr(x, y, z) do {} while (0) | ||
228 | #endif /* DEBUG_IRQ */ | ||
229 | |||
230 | #ifdef DEBUG_EPIRQ | ||
231 | static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev) | ||
232 | { | ||
233 | dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr, | ||
234 | (irqreg & EPINTR_FIFO_FULL) ? " full" : "", | ||
235 | (irqreg & EPINTR_FIFO_EMPTY) ? " fempty" : "", | ||
236 | (irqreg & EPINTR_FIFO_ERROR) ? " ferr" : "", | ||
237 | (irqreg & EPINTR_FIFO_HIGH) ? " fhigh" : "", | ||
238 | (irqreg & EPINTR_FIFO_LOW) ? " flow" : "", | ||
239 | (irqreg & EPINTR_MDEVREQ) ? " mreq" : "", | ||
240 | (irqreg & EPINTR_EOF) ? " eof" : "", | ||
241 | (irqreg & EPINTR_DEVREQ) ? " devreq" : "", | ||
242 | (irqreg & EPINTR_EOT) ? " eot" : ""); | ||
243 | } | ||
244 | #else | ||
245 | #define dump_ep_intr(x, y, z, i) do {} while (0) | ||
246 | #endif /* DEBUG_IRQ */ | ||
247 | |||
248 | #ifdef DEBUG_DUMP | ||
249 | static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb) | ||
250 | { | ||
251 | int temp = __raw_readl(imx_usb->base + USB_STAT); | ||
252 | |||
253 | dev_dbg(imx_usb->dev, | ||
254 | "<%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d]\n", label, | ||
255 | (temp & STAT_RST) ? " reset" : "", | ||
256 | (temp & STAT_SUSP) ? " suspend" : "", | ||
257 | (temp & STAT_CFG) >> 5, | ||
258 | (temp & STAT_INTF) >> 3, | ||
259 | (temp & STAT_ALTSET)); | ||
260 | } | ||
261 | |||
262 | static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep) | ||
263 | { | ||
264 | int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); | ||
265 | |||
266 | dev_dbg(imx_ep->imx_usb->dev, | ||
267 | "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), | ||
268 | (temp & EPINTR_FIFO_FULL) ? " full" : "", | ||
269 | (temp & EPINTR_FIFO_EMPTY) ? " fempty" : "", | ||
270 | (temp & EPINTR_FIFO_ERROR) ? " ferr" : "", | ||
271 | (temp & EPINTR_FIFO_HIGH) ? " fhigh" : "", | ||
272 | (temp & EPINTR_FIFO_LOW) ? " flow" : "", | ||
273 | (temp & EPINTR_MDEVREQ) ? " mreq" : "", | ||
274 | (temp & EPINTR_EOF) ? " eof" : "", | ||
275 | (temp & EPINTR_DEVREQ) ? " devreq" : "", | ||
276 | (temp & EPINTR_EOT) ? " eot" : ""); | ||
277 | |||
278 | temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | ||
279 | |||
280 | dev_dbg(imx_ep->imx_usb->dev, | ||
281 | "<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep), | ||
282 | (temp & EPSTAT_SIP) ? " sip" : "", | ||
283 | (temp & EPSTAT_STALL) ? " stall" : "", | ||
284 | (temp & EPSTAT_BCOUNT) >> 16); | ||
285 | |||
286 | temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))); | ||
287 | |||
288 | dev_dbg(imx_ep->imx_usb->dev, | ||
289 | "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), | ||
290 | (temp & FSTAT_ERR) ? " ferr" : "", | ||
291 | (temp & FSTAT_UF) ? " funder" : "", | ||
292 | (temp & FSTAT_OF) ? " fover" : "", | ||
293 | (temp & FSTAT_FR) ? " fready" : "", | ||
294 | (temp & FSTAT_FULL) ? " ffull" : "", | ||
295 | (temp & FSTAT_ALRM) ? " falarm" : "", | ||
296 | (temp & FSTAT_EMPTY) ? " fempty" : ""); | ||
297 | } | ||
298 | |||
299 | static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req) | ||
300 | { | ||
301 | int i; | ||
302 | |||
303 | if (!req || !req->buf) { | ||
304 | dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label); | ||
305 | return; | ||
306 | } | ||
307 | |||
308 | if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) | ||
309 | || (EP_NO(imx_ep) && EP_DIR(imx_ep))) { | ||
310 | |||
311 | dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label); | ||
312 | for (i = 0; i < req->length; i++) | ||
313 | printk("%02x-", *((u8 *)req->buf + i)); | ||
314 | printk(">\n"); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | #else | ||
319 | #define dump_ep_stat(x, y) do {} while (0) | ||
320 | #define dump_usb_stat(x, y) do {} while (0) | ||
321 | #define dump_req(x, y, z) do {} while (0) | ||
322 | #endif /* DEBUG_DUMP */ | ||
323 | |||
324 | #ifdef DEBUG_ERR | ||
325 | #define D_ERR(dev, args...) dev_dbg(dev, ## args) | ||
326 | #else | ||
327 | #define D_ERR(dev, args...) do {} while (0) | ||
328 | #endif | ||
329 | |||
330 | #else | ||
331 | #define D_REQ(dev, args...) do {} while (0) | ||
332 | #define D_TRX(dev, args...) do {} while (0) | ||
333 | #define D_INI(dev, args...) do {} while (0) | ||
334 | #define D_EP0(dev, args...) do {} while (0) | ||
335 | #define D_EPX(dev, args...) do {} while (0) | ||
336 | #define dump_ep_intr(x, y, z, i) do {} while (0) | ||
337 | #define dump_intr(x, y, z) do {} while (0) | ||
338 | #define dump_ep_stat(x, y) do {} while (0) | ||
339 | #define dump_usb_stat(x, y) do {} while (0) | ||
340 | #define dump_req(x, y, z) do {} while (0) | ||
341 | #define D_ERR(dev, args...) do {} while (0) | ||
342 | #endif /* DEBUG */ | ||
343 | |||
344 | #endif /* __LINUX_USB_GADGET_IMX_H */ | ||