diff options
Diffstat (limited to 'drivers/usb/musb/musb_core.h')
-rw-r--r-- | drivers/usb/musb/musb_core.h | 488 |
1 files changed, 488 insertions, 0 deletions
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h new file mode 100644 index 000000000000..82227251931b --- /dev/null +++ b/drivers/usb/musb/musb_core.h | |||
@@ -0,0 +1,488 @@ | |||
1 | /* | ||
2 | * MUSB OTG driver defines | ||
3 | * | ||
4 | * Copyright 2005 Mentor Graphics Corporation | ||
5 | * Copyright (C) 2005-2006 by Texas Instruments | ||
6 | * Copyright (C) 2006-2007 Nokia Corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED | ||
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
25 | * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
28 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
29 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | #ifndef __MUSB_CORE_H__ | ||
36 | #define __MUSB_CORE_H__ | ||
37 | |||
38 | #include <linux/slab.h> | ||
39 | #include <linux/list.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/smp_lock.h> | ||
42 | #include <linux/errno.h> | ||
43 | #include <linux/clk.h> | ||
44 | #include <linux/device.h> | ||
45 | #include <linux/usb/ch9.h> | ||
46 | #include <linux/usb/gadget.h> | ||
47 | #include <linux/usb.h> | ||
48 | #include <linux/usb/otg.h> | ||
49 | #include <linux/usb/musb.h> | ||
50 | |||
51 | struct musb; | ||
52 | struct musb_hw_ep; | ||
53 | struct musb_ep; | ||
54 | |||
55 | |||
56 | #include "musb_debug.h" | ||
57 | #include "musb_dma.h" | ||
58 | |||
59 | #include "musb_io.h" | ||
60 | #include "musb_regs.h" | ||
61 | |||
62 | #include "musb_gadget.h" | ||
63 | #include "../core/hcd.h" | ||
64 | #include "musb_host.h" | ||
65 | |||
66 | |||
67 | |||
68 | #ifdef CONFIG_USB_MUSB_OTG | ||
69 | |||
70 | #define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST) | ||
71 | #define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL) | ||
72 | #define is_otg_enabled(musb) ((musb)->board_mode == MUSB_OTG) | ||
73 | |||
74 | /* NOTE: otg and peripheral-only state machines start at B_IDLE. | ||
75 | * OTG or host-only go to A_IDLE when ID is sensed. | ||
76 | */ | ||
77 | #define is_peripheral_active(m) (!(m)->is_host) | ||
78 | #define is_host_active(m) ((m)->is_host) | ||
79 | |||
80 | #else | ||
81 | #define is_peripheral_enabled(musb) is_peripheral_capable() | ||
82 | #define is_host_enabled(musb) is_host_capable() | ||
83 | #define is_otg_enabled(musb) 0 | ||
84 | |||
85 | #define is_peripheral_active(musb) is_peripheral_capable() | ||
86 | #define is_host_active(musb) is_host_capable() | ||
87 | #endif | ||
88 | |||
89 | #if defined(CONFIG_USB_MUSB_OTG) || defined(CONFIG_USB_MUSB_PERIPHERAL) | ||
90 | /* for some reason, the "select USB_GADGET_MUSB_HDRC" doesn't always | ||
91 | * override that choice selection (often USB_GADGET_DUMMY_HCD). | ||
92 | */ | ||
93 | #ifndef CONFIG_USB_GADGET_MUSB_HDRC | ||
94 | #error bogus Kconfig output ... select CONFIG_USB_GADGET_MUSB_HDRC | ||
95 | #endif | ||
96 | #endif /* need MUSB gadget selection */ | ||
97 | |||
98 | |||
99 | #ifdef CONFIG_PROC_FS | ||
100 | #include <linux/fs.h> | ||
101 | #define MUSB_CONFIG_PROC_FS | ||
102 | #endif | ||
103 | |||
104 | /****************************** PERIPHERAL ROLE *****************************/ | ||
105 | |||
106 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
107 | |||
108 | #define is_peripheral_capable() (1) | ||
109 | |||
110 | extern irqreturn_t musb_g_ep0_irq(struct musb *); | ||
111 | extern void musb_g_tx(struct musb *, u8); | ||
112 | extern void musb_g_rx(struct musb *, u8); | ||
113 | extern void musb_g_reset(struct musb *); | ||
114 | extern void musb_g_suspend(struct musb *); | ||
115 | extern void musb_g_resume(struct musb *); | ||
116 | extern void musb_g_wakeup(struct musb *); | ||
117 | extern void musb_g_disconnect(struct musb *); | ||
118 | |||
119 | #else | ||
120 | |||
121 | #define is_peripheral_capable() (0) | ||
122 | |||
123 | static inline irqreturn_t musb_g_ep0_irq(struct musb *m) { return IRQ_NONE; } | ||
124 | static inline void musb_g_reset(struct musb *m) {} | ||
125 | static inline void musb_g_suspend(struct musb *m) {} | ||
126 | static inline void musb_g_resume(struct musb *m) {} | ||
127 | static inline void musb_g_wakeup(struct musb *m) {} | ||
128 | static inline void musb_g_disconnect(struct musb *m) {} | ||
129 | |||
130 | #endif | ||
131 | |||
132 | /****************************** HOST ROLE ***********************************/ | ||
133 | |||
134 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
135 | |||
136 | #define is_host_capable() (1) | ||
137 | |||
138 | extern irqreturn_t musb_h_ep0_irq(struct musb *); | ||
139 | extern void musb_host_tx(struct musb *, u8); | ||
140 | extern void musb_host_rx(struct musb *, u8); | ||
141 | |||
142 | #else | ||
143 | |||
144 | #define is_host_capable() (0) | ||
145 | |||
146 | static inline irqreturn_t musb_h_ep0_irq(struct musb *m) { return IRQ_NONE; } | ||
147 | static inline void musb_host_tx(struct musb *m, u8 e) {} | ||
148 | static inline void musb_host_rx(struct musb *m, u8 e) {} | ||
149 | |||
150 | #endif | ||
151 | |||
152 | |||
153 | /****************************** CONSTANTS ********************************/ | ||
154 | |||
155 | #ifndef MUSB_C_NUM_EPS | ||
156 | #define MUSB_C_NUM_EPS ((u8)16) | ||
157 | #endif | ||
158 | |||
159 | #ifndef MUSB_MAX_END0_PACKET | ||
160 | #define MUSB_MAX_END0_PACKET ((u16)MUSB_EP0_FIFOSIZE) | ||
161 | #endif | ||
162 | |||
163 | /* host side ep0 states */ | ||
164 | enum musb_h_ep0_state { | ||
165 | MUSB_EP0_IDLE, | ||
166 | MUSB_EP0_START, /* expect ack of setup */ | ||
167 | MUSB_EP0_IN, /* expect IN DATA */ | ||
168 | MUSB_EP0_OUT, /* expect ack of OUT DATA */ | ||
169 | MUSB_EP0_STATUS, /* expect ack of STATUS */ | ||
170 | } __attribute__ ((packed)); | ||
171 | |||
172 | /* peripheral side ep0 states */ | ||
173 | enum musb_g_ep0_state { | ||
174 | MUSB_EP0_STAGE_SETUP, /* idle, waiting for setup */ | ||
175 | MUSB_EP0_STAGE_TX, /* IN data */ | ||
176 | MUSB_EP0_STAGE_RX, /* OUT data */ | ||
177 | MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */ | ||
178 | MUSB_EP0_STAGE_STATUSOUT, /* (after IN data) */ | ||
179 | MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */ | ||
180 | } __attribute__ ((packed)); | ||
181 | |||
182 | /* OTG protocol constants */ | ||
183 | #define OTG_TIME_A_WAIT_VRISE 100 /* msec (max) */ | ||
184 | #define OTG_TIME_A_WAIT_BCON 0 /* 0=infinite; min 1000 msec */ | ||
185 | #define OTG_TIME_A_IDLE_BDIS 200 /* msec (min) */ | ||
186 | |||
187 | /*************************** REGISTER ACCESS ********************************/ | ||
188 | |||
189 | /* Endpoint registers (other than dynfifo setup) can be accessed either | ||
190 | * directly with the "flat" model, or after setting up an index register. | ||
191 | */ | ||
192 | |||
193 | #if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430) \ | ||
194 | || defined(CONFIG_ARCH_OMAP3430) | ||
195 | /* REVISIT indexed access seemed to | ||
196 | * misbehave (on DaVinci) for at least peripheral IN ... | ||
197 | */ | ||
198 | #define MUSB_FLAT_REG | ||
199 | #endif | ||
200 | |||
201 | /* TUSB mapping: "flat" plus ep0 special cases */ | ||
202 | #if defined(CONFIG_USB_TUSB6010) | ||
203 | #define musb_ep_select(_mbase, _epnum) \ | ||
204 | musb_writeb((_mbase), MUSB_INDEX, (_epnum)) | ||
205 | #define MUSB_EP_OFFSET MUSB_TUSB_OFFSET | ||
206 | |||
207 | /* "flat" mapping: each endpoint has its own i/o address */ | ||
208 | #elif defined(MUSB_FLAT_REG) | ||
209 | #define musb_ep_select(_mbase, _epnum) (((void)(_mbase)), ((void)(_epnum))) | ||
210 | #define MUSB_EP_OFFSET MUSB_FLAT_OFFSET | ||
211 | |||
212 | /* "indexed" mapping: INDEX register controls register bank select */ | ||
213 | #else | ||
214 | #define musb_ep_select(_mbase, _epnum) \ | ||
215 | musb_writeb((_mbase), MUSB_INDEX, (_epnum)) | ||
216 | #define MUSB_EP_OFFSET MUSB_INDEXED_OFFSET | ||
217 | #endif | ||
218 | |||
219 | /****************************** FUNCTIONS ********************************/ | ||
220 | |||
221 | #define MUSB_HST_MODE(_musb)\ | ||
222 | { (_musb)->is_host = true; } | ||
223 | #define MUSB_DEV_MODE(_musb) \ | ||
224 | { (_musb)->is_host = false; } | ||
225 | |||
226 | #define test_devctl_hst_mode(_x) \ | ||
227 | (musb_readb((_x)->mregs, MUSB_DEVCTL)&MUSB_DEVCTL_HM) | ||
228 | |||
229 | #define MUSB_MODE(musb) ((musb)->is_host ? "Host" : "Peripheral") | ||
230 | |||
231 | /******************************** TYPES *************************************/ | ||
232 | |||
233 | /* | ||
234 | * struct musb_hw_ep - endpoint hardware (bidirectional) | ||
235 | * | ||
236 | * Ordered slightly for better cacheline locality. | ||
237 | */ | ||
238 | struct musb_hw_ep { | ||
239 | struct musb *musb; | ||
240 | void __iomem *fifo; | ||
241 | void __iomem *regs; | ||
242 | |||
243 | #ifdef CONFIG_USB_TUSB6010 | ||
244 | void __iomem *conf; | ||
245 | #endif | ||
246 | |||
247 | /* index in musb->endpoints[] */ | ||
248 | u8 epnum; | ||
249 | |||
250 | /* hardware configuration, possibly dynamic */ | ||
251 | bool is_shared_fifo; | ||
252 | bool tx_double_buffered; | ||
253 | bool rx_double_buffered; | ||
254 | u16 max_packet_sz_tx; | ||
255 | u16 max_packet_sz_rx; | ||
256 | |||
257 | struct dma_channel *tx_channel; | ||
258 | struct dma_channel *rx_channel; | ||
259 | |||
260 | #ifdef CONFIG_USB_TUSB6010 | ||
261 | /* TUSB has "asynchronous" and "synchronous" dma modes */ | ||
262 | dma_addr_t fifo_async; | ||
263 | dma_addr_t fifo_sync; | ||
264 | void __iomem *fifo_sync_va; | ||
265 | #endif | ||
266 | |||
267 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
268 | void __iomem *target_regs; | ||
269 | |||
270 | /* currently scheduled peripheral endpoint */ | ||
271 | struct musb_qh *in_qh; | ||
272 | struct musb_qh *out_qh; | ||
273 | |||
274 | u8 rx_reinit; | ||
275 | u8 tx_reinit; | ||
276 | #endif | ||
277 | |||
278 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
279 | /* peripheral side */ | ||
280 | struct musb_ep ep_in; /* TX */ | ||
281 | struct musb_ep ep_out; /* RX */ | ||
282 | #endif | ||
283 | }; | ||
284 | |||
285 | static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep) | ||
286 | { | ||
287 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
288 | return next_request(&hw_ep->ep_in); | ||
289 | #else | ||
290 | return NULL; | ||
291 | #endif | ||
292 | } | ||
293 | |||
294 | static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep) | ||
295 | { | ||
296 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
297 | return next_request(&hw_ep->ep_out); | ||
298 | #else | ||
299 | return NULL; | ||
300 | #endif | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * struct musb - Driver instance data. | ||
305 | */ | ||
306 | struct musb { | ||
307 | /* device lock */ | ||
308 | spinlock_t lock; | ||
309 | struct clk *clock; | ||
310 | irqreturn_t (*isr)(int, void *); | ||
311 | struct work_struct irq_work; | ||
312 | |||
313 | /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ | ||
314 | #define MUSB_PORT_STAT_RESUME (1 << 31) | ||
315 | |||
316 | u32 port1_status; | ||
317 | |||
318 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
319 | unsigned long rh_timer; | ||
320 | |||
321 | enum musb_h_ep0_state ep0_stage; | ||
322 | |||
323 | /* bulk traffic normally dedicates endpoint hardware, and each | ||
324 | * direction has its own ring of host side endpoints. | ||
325 | * we try to progress the transfer at the head of each endpoint's | ||
326 | * queue until it completes or NAKs too much; then we try the next | ||
327 | * endpoint. | ||
328 | */ | ||
329 | struct musb_hw_ep *bulk_ep; | ||
330 | |||
331 | struct list_head control; /* of musb_qh */ | ||
332 | struct list_head in_bulk; /* of musb_qh */ | ||
333 | struct list_head out_bulk; /* of musb_qh */ | ||
334 | struct musb_qh *periodic[32]; /* tree of interrupt+iso */ | ||
335 | #endif | ||
336 | |||
337 | /* called with IRQs blocked; ON/nonzero implies starting a session, | ||
338 | * and waiting at least a_wait_vrise_tmout. | ||
339 | */ | ||
340 | void (*board_set_vbus)(struct musb *, int is_on); | ||
341 | |||
342 | struct dma_controller *dma_controller; | ||
343 | |||
344 | struct device *controller; | ||
345 | void __iomem *ctrl_base; | ||
346 | void __iomem *mregs; | ||
347 | |||
348 | #ifdef CONFIG_USB_TUSB6010 | ||
349 | dma_addr_t async; | ||
350 | dma_addr_t sync; | ||
351 | void __iomem *sync_va; | ||
352 | #endif | ||
353 | |||
354 | /* passed down from chip/board specific irq handlers */ | ||
355 | u8 int_usb; | ||
356 | u16 int_rx; | ||
357 | u16 int_tx; | ||
358 | |||
359 | struct otg_transceiver xceiv; | ||
360 | |||
361 | int nIrq; | ||
362 | |||
363 | struct musb_hw_ep endpoints[MUSB_C_NUM_EPS]; | ||
364 | #define control_ep endpoints | ||
365 | |||
366 | #define VBUSERR_RETRY_COUNT 3 | ||
367 | u16 vbuserr_retry; | ||
368 | u16 epmask; | ||
369 | u8 nr_endpoints; | ||
370 | |||
371 | u8 board_mode; /* enum musb_mode */ | ||
372 | int (*board_set_power)(int state); | ||
373 | |||
374 | int (*set_clock)(struct clk *clk, int is_active); | ||
375 | |||
376 | u8 min_power; /* vbus for periph, in mA/2 */ | ||
377 | |||
378 | bool is_host; | ||
379 | |||
380 | int a_wait_bcon; /* VBUS timeout in msecs */ | ||
381 | unsigned long idle_timeout; /* Next timeout in jiffies */ | ||
382 | |||
383 | /* active means connected and not suspended */ | ||
384 | unsigned is_active:1; | ||
385 | |||
386 | unsigned is_multipoint:1; | ||
387 | unsigned ignore_disconnect:1; /* during bus resets */ | ||
388 | |||
389 | #ifdef C_MP_TX | ||
390 | unsigned bulk_split:1; | ||
391 | #define can_bulk_split(musb,type) \ | ||
392 | (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split) | ||
393 | #else | ||
394 | #define can_bulk_split(musb, type) 0 | ||
395 | #endif | ||
396 | |||
397 | #ifdef C_MP_RX | ||
398 | unsigned bulk_combine:1; | ||
399 | #define can_bulk_combine(musb,type) \ | ||
400 | (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine) | ||
401 | #else | ||
402 | #define can_bulk_combine(musb, type) 0 | ||
403 | #endif | ||
404 | |||
405 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
406 | /* is_suspended means USB B_PERIPHERAL suspend */ | ||
407 | unsigned is_suspended:1; | ||
408 | |||
409 | /* may_wakeup means remote wakeup is enabled */ | ||
410 | unsigned may_wakeup:1; | ||
411 | |||
412 | /* is_self_powered is reported in device status and the | ||
413 | * config descriptor. is_bus_powered means B_PERIPHERAL | ||
414 | * draws some VBUS current; both can be true. | ||
415 | */ | ||
416 | unsigned is_self_powered:1; | ||
417 | unsigned is_bus_powered:1; | ||
418 | |||
419 | unsigned set_address:1; | ||
420 | unsigned test_mode:1; | ||
421 | unsigned softconnect:1; | ||
422 | |||
423 | u8 address; | ||
424 | u8 test_mode_nr; | ||
425 | u16 ackpend; /* ep0 */ | ||
426 | enum musb_g_ep0_state ep0_state; | ||
427 | struct usb_gadget g; /* the gadget */ | ||
428 | struct usb_gadget_driver *gadget_driver; /* its driver */ | ||
429 | #endif | ||
430 | |||
431 | struct musb_hdrc_config *config; | ||
432 | |||
433 | #ifdef MUSB_CONFIG_PROC_FS | ||
434 | struct proc_dir_entry *proc_entry; | ||
435 | #endif | ||
436 | }; | ||
437 | |||
438 | static inline void musb_set_vbus(struct musb *musb, int is_on) | ||
439 | { | ||
440 | musb->board_set_vbus(musb, is_on); | ||
441 | } | ||
442 | |||
443 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
444 | static inline struct musb *gadget_to_musb(struct usb_gadget *g) | ||
445 | { | ||
446 | return container_of(g, struct musb, g); | ||
447 | } | ||
448 | #endif | ||
449 | |||
450 | |||
451 | /***************************** Glue it together *****************************/ | ||
452 | |||
453 | extern const char musb_driver_name[]; | ||
454 | |||
455 | extern void musb_start(struct musb *musb); | ||
456 | extern void musb_stop(struct musb *musb); | ||
457 | |||
458 | extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); | ||
459 | extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); | ||
460 | |||
461 | extern void musb_load_testpacket(struct musb *); | ||
462 | |||
463 | extern irqreturn_t musb_interrupt(struct musb *); | ||
464 | |||
465 | extern void musb_platform_enable(struct musb *musb); | ||
466 | extern void musb_platform_disable(struct musb *musb); | ||
467 | |||
468 | extern void musb_hnp_stop(struct musb *musb); | ||
469 | |||
470 | extern void musb_platform_set_mode(struct musb *musb, u8 musb_mode); | ||
471 | |||
472 | #if defined(CONFIG_USB_TUSB6010) || \ | ||
473 | defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) | ||
474 | extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout); | ||
475 | #else | ||
476 | #define musb_platform_try_idle(x, y) do {} while (0) | ||
477 | #endif | ||
478 | |||
479 | #ifdef CONFIG_USB_TUSB6010 | ||
480 | extern int musb_platform_get_vbus_status(struct musb *musb); | ||
481 | #else | ||
482 | #define musb_platform_get_vbus_status(x) 0 | ||
483 | #endif | ||
484 | |||
485 | extern int __init musb_platform_init(struct musb *musb); | ||
486 | extern int musb_platform_exit(struct musb *musb); | ||
487 | |||
488 | #endif /* __MUSB_CORE_H__ */ | ||