Branch data Line data Source code
1 : : /* ==========================================================================
2 : : * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
3 : : * $Revision: #58 $
4 : : * $Date: 2011/09/15 $
5 : : * $Change: 1846647 $
6 : : *
7 : : * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8 : : * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9 : : * otherwise expressly agreed to in writing between Synopsys and you.
10 : : *
11 : : * The Software IS NOT an item of Licensed Software or Licensed Product under
12 : : * any End User Software License Agreement or Agreement for Licensed Product
13 : : * with Synopsys or any supplement thereto. You are permitted to use and
14 : : * redistribute this Software in source and binary forms, with or without
15 : : * modification, provided that redistributions of source code must retain this
16 : : * notice. You may not view, use, disclose, copy or distribute this file or
17 : : * any information contained herein except pursuant to this license grant from
18 : : * Synopsys. If you do not agree with this notice, including the disclaimer
19 : : * below, then you are not authorized to use the Software.
20 : : *
21 : : * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22 : : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : : * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25 : : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 : : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 : : * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 : : * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 : : * DAMAGE.
32 : : * ========================================================================== */
33 : : #ifndef DWC_DEVICE_ONLY
34 : : #ifndef __DWC_HCD_H__
35 : : #define __DWC_HCD_H__
36 : :
37 : : #include "dwc_otg_os_dep.h"
38 : : #include "usb.h"
39 : : #include "dwc_otg_hcd_if.h"
40 : : #include "dwc_otg_core_if.h"
41 : : #include "dwc_list.h"
42 : : #include "dwc_otg_cil.h"
43 : : #include "dwc_otg_fiq_fsm.h"
44 : : #include "dwc_otg_driver.h"
45 : :
46 : :
47 : : /**
48 : : * @file
49 : : *
50 : : * This file contains the structures, constants, and interfaces for
51 : : * the Host Contoller Driver (HCD).
52 : : *
53 : : * The Host Controller Driver (HCD) is responsible for translating requests
54 : : * from the USB Driver into the appropriate actions on the DWC_otg controller.
55 : : * It isolates the USBD from the specifics of the controller by providing an
56 : : * API to the USBD.
57 : : */
58 : :
59 : : struct dwc_otg_hcd_pipe_info {
60 : : uint8_t dev_addr;
61 : : uint8_t ep_num;
62 : : uint8_t pipe_type;
63 : : uint8_t pipe_dir;
64 : : uint16_t mps;
65 : : };
66 : :
67 : : struct dwc_otg_hcd_iso_packet_desc {
68 : : uint32_t offset;
69 : : uint32_t length;
70 : : uint32_t actual_length;
71 : : uint32_t status;
72 : : };
73 : :
74 : : struct dwc_otg_qtd;
75 : :
76 : : struct dwc_otg_hcd_urb {
77 : : void *priv;
78 : : struct dwc_otg_qtd *qtd;
79 : : void *buf;
80 : : dwc_dma_t dma;
81 : : void *setup_packet;
82 : : dwc_dma_t setup_dma;
83 : : uint32_t length;
84 : : uint32_t actual_length;
85 : : uint32_t status;
86 : : uint32_t error_count;
87 : : uint32_t packet_count;
88 : : uint32_t flags;
89 : : uint16_t interval;
90 : : struct dwc_otg_hcd_pipe_info pipe_info;
91 : : struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
92 : : };
93 : :
94 : : static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
95 : : {
96 : 227670956 : return pipe->ep_num;
97 : : }
98 : :
99 : : static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
100 : : *pipe)
101 : : {
102 [ # # ]: 683355352 : return pipe->pipe_type;
103 : : }
104 : :
105 : : static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
106 : : {
107 : 5408 : return pipe->mps;
108 : : }
109 : :
110 : : static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
111 : : *pipe)
112 : : {
113 : 227670956 : return pipe->dev_addr;
114 : : }
115 : :
116 : : static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
117 : : *pipe)
118 : : {
119 : : return (pipe->pipe_type == UE_ISOCHRONOUS);
120 : : }
121 : :
122 : : static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
123 : : *pipe)
124 : : {
125 : : return (pipe->pipe_type == UE_INTERRUPT);
126 : : }
127 : :
128 : : static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
129 : : *pipe)
130 : : {
131 : : return (pipe->pipe_type == UE_BULK);
132 : : }
133 : :
134 : : static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
135 : : *pipe)
136 : : {
137 : : return (pipe->pipe_type == UE_CONTROL);
138 : : }
139 : :
140 : : static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
141 : : {
142 : 227704618 : return (pipe->pipe_dir == UE_DIR_IN);
143 : : }
144 : :
145 : : static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
146 : : *pipe)
147 : : {
148 : 28254 : return (!dwc_otg_hcd_is_pipe_in(pipe));
149 : : }
150 : :
151 : : static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
152 : : uint8_t devaddr, uint8_t ep_num,
153 : : uint8_t pipe_type, uint8_t pipe_dir,
154 : : uint16_t mps)
155 : : {
156 : 185636 : pipe->dev_addr = devaddr;
157 : 185636 : pipe->ep_num = ep_num;
158 : 185636 : pipe->pipe_type = pipe_type;
159 : 185636 : pipe->pipe_dir = pipe_dir;
160 : 185636 : pipe->mps = mps;
161 : : }
162 : :
163 : : /**
164 : : * Phases for control transfers.
165 : : */
166 : : typedef enum dwc_otg_control_phase {
167 : : DWC_OTG_CONTROL_SETUP,
168 : : DWC_OTG_CONTROL_DATA,
169 : : DWC_OTG_CONTROL_STATUS
170 : : } dwc_otg_control_phase_e;
171 : :
172 : : /** Transaction types. */
173 : : typedef enum dwc_otg_transaction_type {
174 : : DWC_OTG_TRANSACTION_NONE = 0,
175 : : DWC_OTG_TRANSACTION_PERIODIC = 1,
176 : : DWC_OTG_TRANSACTION_NON_PERIODIC = 2,
177 : : DWC_OTG_TRANSACTION_ALL = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC
178 : : } dwc_otg_transaction_type_e;
179 : :
180 : : struct dwc_otg_qh;
181 : :
182 : : /**
183 : : * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
184 : : * interrupt, or isochronous transfer. A single QTD is created for each URB
185 : : * (of one of these types) submitted to the HCD. The transfer associated with
186 : : * a QTD may require one or multiple transactions.
187 : : *
188 : : * A QTD is linked to a Queue Head, which is entered in either the
189 : : * non-periodic or periodic schedule for execution. When a QTD is chosen for
190 : : * execution, some or all of its transactions may be executed. After
191 : : * execution, the state of the QTD is updated. The QTD may be retired if all
192 : : * its transactions are complete or if an error occurred. Otherwise, it
193 : : * remains in the schedule so more transactions can be executed later.
194 : : */
195 : : typedef struct dwc_otg_qtd {
196 : : /**
197 : : * Determines the PID of the next data packet for the data phase of
198 : : * control transfers. Ignored for other transfer types.<br>
199 : : * One of the following values:
200 : : * - DWC_OTG_HC_PID_DATA0
201 : : * - DWC_OTG_HC_PID_DATA1
202 : : */
203 : : uint8_t data_toggle;
204 : :
205 : : /** Current phase for control transfers (Setup, Data, or Status). */
206 : : dwc_otg_control_phase_e control_phase;
207 : :
208 : : /** Keep track of the current split type
209 : : * for FS/LS endpoints on a HS Hub */
210 : : uint8_t complete_split;
211 : :
212 : : /** How many bytes transferred during SSPLIT OUT */
213 : : uint32_t ssplit_out_xfer_count;
214 : :
215 : : /**
216 : : * Holds the number of bus errors that have occurred for a transaction
217 : : * within this transfer.
218 : : */
219 : : uint8_t error_count;
220 : :
221 : : /**
222 : : * Index of the next frame descriptor for an isochronous transfer. A
223 : : * frame descriptor describes the buffer position and length of the
224 : : * data to be transferred in the next scheduled (micro)frame of an
225 : : * isochronous transfer. It also holds status for that transaction.
226 : : * The frame index starts at 0.
227 : : */
228 : : uint16_t isoc_frame_index;
229 : :
230 : : /** Position of the ISOC split on full/low speed */
231 : : uint8_t isoc_split_pos;
232 : :
233 : : /** Position of the ISOC split in the buffer for the current frame */
234 : : uint16_t isoc_split_offset;
235 : :
236 : : /** URB for this transfer */
237 : : struct dwc_otg_hcd_urb *urb;
238 : :
239 : : struct dwc_otg_qh *qh;
240 : :
241 : : /** This list of QTDs */
242 : : DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
243 : :
244 : : /** Indicates if this QTD is currently processed by HW. */
245 : : uint8_t in_process;
246 : :
247 : : /** Number of DMA descriptors for this QTD */
248 : : uint8_t n_desc;
249 : :
250 : : /**
251 : : * Last activated frame(packet) index.
252 : : * Used in Descriptor DMA mode only.
253 : : */
254 : : uint16_t isoc_frame_index_last;
255 : :
256 : : } dwc_otg_qtd_t;
257 : :
258 : : DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
259 : :
260 : : /**
261 : : * A Queue Head (QH) holds the static characteristics of an endpoint and
262 : : * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
263 : : * be entered in either the non-periodic or periodic schedule.
264 : : */
265 : : typedef struct dwc_otg_qh {
266 : : /**
267 : : * Endpoint type.
268 : : * One of the following values:
269 : : * - UE_CONTROL
270 : : * - UE_BULK
271 : : * - UE_INTERRUPT
272 : : * - UE_ISOCHRONOUS
273 : : */
274 : : uint8_t ep_type;
275 : : uint8_t ep_is_in;
276 : :
277 : : /** wMaxPacketSize Field of Endpoint Descriptor. */
278 : : uint16_t maxp;
279 : :
280 : : /**
281 : : * Device speed.
282 : : * One of the following values:
283 : : * - DWC_OTG_EP_SPEED_LOW
284 : : * - DWC_OTG_EP_SPEED_FULL
285 : : * - DWC_OTG_EP_SPEED_HIGH
286 : : */
287 : : uint8_t dev_speed;
288 : :
289 : : /**
290 : : * Determines the PID of the next data packet for non-control
291 : : * transfers. Ignored for control transfers.<br>
292 : : * One of the following values:
293 : : * - DWC_OTG_HC_PID_DATA0
294 : : * - DWC_OTG_HC_PID_DATA1
295 : : */
296 : : uint8_t data_toggle;
297 : :
298 : : /** Ping state if 1. */
299 : : uint8_t ping_state;
300 : :
301 : : /**
302 : : * List of QTDs for this QH.
303 : : */
304 : : struct dwc_otg_qtd_list qtd_list;
305 : :
306 : : /** Host channel currently processing transfers for this QH. */
307 : : struct dwc_hc *channel;
308 : :
309 : : /** Full/low speed endpoint on high-speed hub requires split. */
310 : : uint8_t do_split;
311 : :
312 : : /** @name Periodic schedule information */
313 : : /** @{ */
314 : :
315 : : /** Bandwidth in microseconds per (micro)frame. */
316 : : uint16_t usecs;
317 : :
318 : : /** Interval between transfers in (micro)frames. */
319 : : uint16_t interval;
320 : :
321 : : /**
322 : : * (micro)frame to initialize a periodic transfer. The transfer
323 : : * executes in the following (micro)frame.
324 : : */
325 : : uint16_t sched_frame;
326 : :
327 : : /*
328 : : ** Frame a NAK was received on this queue head, used to minimise NAK retransmission
329 : : */
330 : : uint16_t nak_frame;
331 : :
332 : : /** (micro)frame at which last start split was initialized. */
333 : : uint16_t start_split_frame;
334 : :
335 : : /** @} */
336 : :
337 : : /**
338 : : * Used instead of original buffer if
339 : : * it(physical address) is not dword-aligned.
340 : : */
341 : : uint8_t *dw_align_buf;
342 : : dwc_dma_t dw_align_buf_dma;
343 : :
344 : : /** Entry for QH in either the periodic or non-periodic schedule. */
345 : : dwc_list_link_t qh_list_entry;
346 : :
347 : : /** @name Descriptor DMA support */
348 : : /** @{ */
349 : :
350 : : /** Descriptor List. */
351 : : dwc_otg_host_dma_desc_t *desc_list;
352 : :
353 : : /** Descriptor List physical address. */
354 : : dwc_dma_t desc_list_dma;
355 : :
356 : : /**
357 : : * Xfer Bytes array.
358 : : * Each element corresponds to a descriptor and indicates
359 : : * original XferSize size value for the descriptor.
360 : : */
361 : : uint32_t *n_bytes;
362 : :
363 : : /** Actual number of transfer descriptors in a list. */
364 : : uint16_t ntd;
365 : :
366 : : /** First activated isochronous transfer descriptor index. */
367 : : uint8_t td_first;
368 : : /** Last activated isochronous transfer descriptor index. */
369 : : uint8_t td_last;
370 : :
371 : : /** @} */
372 : :
373 : :
374 : : uint16_t speed;
375 : : uint16_t frame_usecs[8];
376 : :
377 : : uint32_t skip_count;
378 : : } dwc_otg_qh_t;
379 : :
380 : : DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
381 : :
382 : : typedef struct urb_tq_entry {
383 : : struct urb *urb;
384 : : DWC_TAILQ_ENTRY(urb_tq_entry) urb_tq_entries;
385 : : } urb_tq_entry_t;
386 : :
387 : : DWC_TAILQ_HEAD(urb_list, urb_tq_entry);
388 : :
389 : : /**
390 : : * This structure holds the state of the HCD, including the non-periodic and
391 : : * periodic schedules.
392 : : */
393 : : struct dwc_otg_hcd {
394 : : /** The DWC otg device pointer */
395 : : struct dwc_otg_device *otg_dev;
396 : : /** DWC OTG Core Interface Layer */
397 : : dwc_otg_core_if_t *core_if;
398 : :
399 : : /** Function HCD driver callbacks */
400 : : struct dwc_otg_hcd_function_ops *fops;
401 : :
402 : : /** Internal DWC HCD Flags */
403 : : volatile union dwc_otg_hcd_internal_flags {
404 : : uint32_t d32;
405 : : struct {
406 : : unsigned port_connect_status_change:1;
407 : : unsigned port_connect_status:1;
408 : : unsigned port_reset_change:1;
409 : : unsigned port_enable_change:1;
410 : : unsigned port_suspend_change:1;
411 : : unsigned port_over_current_change:1;
412 : : unsigned port_l1_change:1;
413 : : unsigned port_speed:2;
414 : : unsigned reserved:24;
415 : : } b;
416 : : } flags;
417 : :
418 : : /**
419 : : * Inactive items in the non-periodic schedule. This is a list of
420 : : * Queue Heads. Transfers associated with these Queue Heads are not
421 : : * currently assigned to a host channel.
422 : : */
423 : : dwc_list_link_t non_periodic_sched_inactive;
424 : :
425 : : /**
426 : : * Active items in the non-periodic schedule. This is a list of
427 : : * Queue Heads. Transfers associated with these Queue Heads are
428 : : * currently assigned to a host channel.
429 : : */
430 : : dwc_list_link_t non_periodic_sched_active;
431 : :
432 : : /**
433 : : * Pointer to the next Queue Head to process in the active
434 : : * non-periodic schedule.
435 : : */
436 : : dwc_list_link_t *non_periodic_qh_ptr;
437 : :
438 : : /**
439 : : * Inactive items in the periodic schedule. This is a list of QHs for
440 : : * periodic transfers that are _not_ scheduled for the next frame.
441 : : * Each QH in the list has an interval counter that determines when it
442 : : * needs to be scheduled for execution. This scheduling mechanism
443 : : * allows only a simple calculation for periodic bandwidth used (i.e.
444 : : * must assume that all periodic transfers may need to execute in the
445 : : * same frame). However, it greatly simplifies scheduling and should
446 : : * be sufficient for the vast majority of OTG hosts, which need to
447 : : * connect to a small number of peripherals at one time.
448 : : *
449 : : * Items move from this list to periodic_sched_ready when the QH
450 : : * interval counter is 0 at SOF.
451 : : */
452 : : dwc_list_link_t periodic_sched_inactive;
453 : :
454 : : /**
455 : : * List of periodic QHs that are ready for execution in the next
456 : : * frame, but have not yet been assigned to host channels.
457 : : *
458 : : * Items move from this list to periodic_sched_assigned as host
459 : : * channels become available during the current frame.
460 : : */
461 : : dwc_list_link_t periodic_sched_ready;
462 : :
463 : : /**
464 : : * List of periodic QHs to be executed in the next frame that are
465 : : * assigned to host channels.
466 : : *
467 : : * Items move from this list to periodic_sched_queued as the
468 : : * transactions for the QH are queued to the DWC_otg controller.
469 : : */
470 : : dwc_list_link_t periodic_sched_assigned;
471 : :
472 : : /**
473 : : * List of periodic QHs that have been queued for execution.
474 : : *
475 : : * Items move from this list to either periodic_sched_inactive or
476 : : * periodic_sched_ready when the channel associated with the transfer
477 : : * is released. If the interval for the QH is 1, the item moves to
478 : : * periodic_sched_ready because it must be rescheduled for the next
479 : : * frame. Otherwise, the item moves to periodic_sched_inactive.
480 : : */
481 : : dwc_list_link_t periodic_sched_queued;
482 : :
483 : : /**
484 : : * Total bandwidth claimed so far for periodic transfers. This value
485 : : * is in microseconds per (micro)frame. The assumption is that all
486 : : * periodic transfers may occur in the same (micro)frame.
487 : : */
488 : : uint16_t periodic_usecs;
489 : :
490 : : /**
491 : : * Total bandwidth claimed so far for all periodic transfers
492 : : * in a frame.
493 : : * This will include a mixture of HS and FS transfers.
494 : : * Units are microseconds per (micro)frame.
495 : : * We have a budget per frame and have to schedule
496 : : * transactions accordingly.
497 : : * Watch out for the fact that things are actually scheduled for the
498 : : * "next frame".
499 : : */
500 : : uint16_t frame_usecs[8];
501 : :
502 : :
503 : : /**
504 : : * Frame number read from the core at SOF. The value ranges from 0 to
505 : : * DWC_HFNUM_MAX_FRNUM.
506 : : */
507 : : uint16_t frame_number;
508 : :
509 : : /**
510 : : * Count of periodic QHs, if using several eps. For SOF enable/disable.
511 : : */
512 : : uint16_t periodic_qh_count;
513 : :
514 : : /**
515 : : * Free host channels in the controller. This is a list of
516 : : * dwc_hc_t items.
517 : : */
518 : : struct hc_list free_hc_list;
519 : : /**
520 : : * Number of host channels assigned to periodic transfers. Currently
521 : : * assuming that there is a dedicated host channel for each periodic
522 : : * transaction and at least one host channel available for
523 : : * non-periodic transactions.
524 : : */
525 : : int periodic_channels; /* microframe_schedule==0 */
526 : :
527 : : /**
528 : : * Number of host channels assigned to non-periodic transfers.
529 : : */
530 : : int non_periodic_channels; /* microframe_schedule==0 */
531 : :
532 : : /**
533 : : * Number of host channels assigned to non-periodic transfers.
534 : : */
535 : : int available_host_channels;
536 : :
537 : : /**
538 : : * Array of pointers to the host channel descriptors. Allows accessing
539 : : * a host channel descriptor given the host channel number. This is
540 : : * useful in interrupt handlers.
541 : : */
542 : : struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
543 : :
544 : : /**
545 : : * Buffer to use for any data received during the status phase of a
546 : : * control transfer. Normally no data is transferred during the status
547 : : * phase. This buffer is used as a bit bucket.
548 : : */
549 : : uint8_t *status_buf;
550 : :
551 : : /**
552 : : * DMA address for status_buf.
553 : : */
554 : : dma_addr_t status_buf_dma;
555 : : #define DWC_OTG_HCD_STATUS_BUF_SIZE 64
556 : :
557 : : /**
558 : : * Connection timer. An OTG host must display a message if the device
559 : : * does not connect. Started when the VBus power is turned on via
560 : : * sysfs attribute "buspower".
561 : : */
562 : : dwc_timer_t *conn_timer;
563 : :
564 : : /* Tasket to do a reset */
565 : : dwc_tasklet_t *reset_tasklet;
566 : :
567 : : dwc_tasklet_t *completion_tasklet;
568 : : struct urb_list completed_urb_list;
569 : :
570 : : /* */
571 : : dwc_spinlock_t *lock;
572 : : /**
573 : : * Private data that could be used by OS wrapper.
574 : : */
575 : : void *priv;
576 : :
577 : : uint8_t otg_port;
578 : :
579 : : /** Frame List */
580 : : uint32_t *frame_list;
581 : :
582 : : /** Hub - Port assignment */
583 : : int hub_port[128];
584 : : #ifdef FIQ_DEBUG
585 : : int hub_port_alloc[2048];
586 : : #endif
587 : :
588 : : /** Frame List DMA address */
589 : : dma_addr_t frame_list_dma;
590 : :
591 : : struct fiq_stack *fiq_stack;
592 : : struct fiq_state *fiq_state;
593 : :
594 : : /** Virtual address for split transaction DMA bounce buffers */
595 : : struct fiq_dma_blob *fiq_dmab;
596 : :
597 : : #ifdef DEBUG
598 : : uint32_t frrem_samples;
599 : : uint64_t frrem_accum;
600 : :
601 : : uint32_t hfnum_7_samples_a;
602 : : uint64_t hfnum_7_frrem_accum_a;
603 : : uint32_t hfnum_0_samples_a;
604 : : uint64_t hfnum_0_frrem_accum_a;
605 : : uint32_t hfnum_other_samples_a;
606 : : uint64_t hfnum_other_frrem_accum_a;
607 : :
608 : : uint32_t hfnum_7_samples_b;
609 : : uint64_t hfnum_7_frrem_accum_b;
610 : : uint32_t hfnum_0_samples_b;
611 : : uint64_t hfnum_0_frrem_accum_b;
612 : : uint32_t hfnum_other_samples_b;
613 : : uint64_t hfnum_other_frrem_accum_b;
614 : : #endif
615 : : };
616 : :
617 : : static inline struct device *dwc_otg_hcd_to_dev(struct dwc_otg_hcd *hcd)
618 : : {
619 : 227672976 : return &hcd->otg_dev->os_dep.platformdev->dev;
620 : : }
621 : :
622 : : /** @name Transaction Execution Functions */
623 : : /** @{ */
624 : : extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
625 : : * hcd);
626 : : extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
627 : : dwc_otg_transaction_type_e tr_type);
628 : :
629 : : int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh);
630 : : void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);
631 : :
632 : : extern int fiq_fsm_queue_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
633 : : extern int fiq_fsm_transaction_suitable(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
634 : : extern void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num);
635 : :
636 : : /** @} */
637 : :
638 : : /** @name Interrupt Handler Functions */
639 : : /** @{ */
640 : : extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
641 : : extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
642 : : extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
643 : : dwc_otg_hcd);
644 : : extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
645 : : dwc_otg_hcd);
646 : : extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
647 : : dwc_otg_hcd);
648 : : extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
649 : : dwc_otg_hcd);
650 : : extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
651 : : extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
652 : : dwc_otg_hcd);
653 : : extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
654 : : extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
655 : : extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
656 : : uint32_t num);
657 : : extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
658 : : extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
659 : : dwc_otg_hcd);
660 : : /** @} */
661 : :
662 : : /** @name Schedule Queue Functions */
663 : : /** @{ */
664 : :
665 : : /* Implemented in dwc_otg_hcd_queue.c */
666 : : extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
667 : : dwc_otg_hcd_urb_t * urb, int atomic_alloc);
668 : : extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
669 : : extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
670 : : extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
671 : : extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
672 : : int sched_csplit);
673 : :
674 : : /** Remove and free a QH */
675 : 0 : static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
676 : : dwc_otg_qh_t * qh)
677 : : {
678 : : dwc_irqflags_t flags;
679 : 0 : DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
680 : 0 : dwc_otg_hcd_qh_remove(hcd, qh);
681 : 0 : DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
682 : 0 : dwc_otg_hcd_qh_free(hcd, qh);
683 : 0 : }
684 : :
685 : : /** Allocates memory for a QH structure.
686 : : * @return Returns the memory allocate or NULL on error. */
687 : 5408 : static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
688 : : {
689 [ + - ]: 5408 : if (atomic_alloc)
690 : 5408 : return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
691 : : else
692 : 0 : return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
693 : : }
694 : :
695 : : extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
696 : : int atomic_alloc);
697 : : extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
698 : : extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
699 : : dwc_otg_qh_t ** qh, int atomic_alloc);
700 : :
701 : : /** Allocates memory for a QTD structure.
702 : : * @return Returns the memory allocate or NULL on error. */
703 : 185644 : static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
704 : : {
705 [ + - ]: 185644 : if (atomic_alloc)
706 : 185644 : return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
707 : : else
708 : 0 : return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
709 : : }
710 : :
711 : : /** Frees the memory for a QTD structure. QTD should already be removed from
712 : : * list.
713 : : * @param qtd QTD to free.*/
714 : : static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
715 : : {
716 : 182656 : DWC_FREE(qtd);
717 : : }
718 : :
719 : : /** Removes a QTD from list.
720 : : * @param hcd HCD instance.
721 : : * @param qtd QTD to remove from list.
722 : : * @param qh QTD belongs to.
723 : : */
724 : : static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
725 : : dwc_otg_qtd_t * qtd,
726 : : dwc_otg_qh_t * qh)
727 : : {
728 [ + + + - ]: 182656 : DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
729 : : }
730 : :
731 : : /** Remove and free a QTD
732 : : * Need to disable IRQ and hold hcd lock while calling this function out of
733 : : * interrupt servicing chain */
734 : 182656 : static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
735 : : dwc_otg_qtd_t * qtd,
736 : : dwc_otg_qh_t * qh)
737 : : {
738 : : dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
739 : : dwc_otg_hcd_qtd_free(qtd);
740 : 182656 : }
741 : :
742 : : /** @} */
743 : :
744 : : /** @name Descriptor DMA Supporting Functions */
745 : : /** @{ */
746 : :
747 : : extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
748 : : extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
749 : : dwc_hc_t * hc,
750 : : dwc_otg_hc_regs_t * hc_regs,
751 : : dwc_otg_halt_status_e halt_status);
752 : :
753 : : extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
754 : : extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
755 : :
756 : : /** @} */
757 : :
758 : : /** @name Internal Functions */
759 : : /** @{ */
760 : : dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
761 : : /** @} */
762 : :
763 : : #ifdef CONFIG_USB_DWC_OTG_LPM
764 : : extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
765 : : uint8_t devaddr);
766 : : extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
767 : : #endif
768 : :
769 : : /** Gets the QH that contains the list_head */
770 : : #define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
771 : :
772 : : /** Gets the QTD that contains the list_head */
773 : : #define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
774 : :
775 : : /** Check if QH is non-periodic */
776 : : #define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
777 : : (_qh_ptr_->ep_type == UE_CONTROL))
778 : :
779 : : /** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
780 : : #define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
781 : :
782 : : /** Packet size for any kind of endpoint descriptor */
783 : : #define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
784 : :
785 : : /**
786 : : * Returns true if _frame1 is less than or equal to _frame2. The comparison is
787 : : * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
788 : : * frame number when the max frame number is reached.
789 : : */
790 : : static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
791 : : {
792 : 714613080 : return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
793 : : (DWC_HFNUM_MAX_FRNUM >> 1);
794 : : }
795 : :
796 : : /**
797 : : * Returns true if _frame1 is greater than _frame2. The comparison is done
798 : : * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
799 : : * number when the max frame number is reached.
800 : : */
801 : : static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
802 : : {
803 [ + + + + ]: 123267826 : return (frame1 != frame2) &&
804 : 61632022 : (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
805 : : (DWC_HFNUM_MAX_FRNUM >> 1));
806 : : }
807 : :
808 : : /**
809 : : * Increments _frame by the amount specified by _inc. The addition is done
810 : : * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
811 : : */
812 : : static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
813 : : {
814 : 227829374 : return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
815 : : }
816 : :
817 : : static inline uint16_t dwc_full_frame_num(uint16_t frame)
818 : : {
819 : 0 : return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
820 : : }
821 : :
822 : : static inline uint16_t dwc_micro_frame_num(uint16_t frame)
823 : : {
824 : 0 : return frame & 0x7;
825 : : }
826 : :
827 : : extern void init_hcd_usecs(dwc_otg_hcd_t *_hcd);
828 : :
829 : : void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
830 : : dwc_otg_hc_regs_t * hc_regs,
831 : : dwc_otg_qtd_t * qtd);
832 : :
833 : : #ifdef DEBUG
834 : : /**
835 : : * Macro to sample the remaining PHY clocks left in the current frame. This
836 : : * may be used during debugging to determine the average time it takes to
837 : : * execute sections of code. There are two possible sample points, "a" and
838 : : * "b", so the _letter argument must be one of these values.
839 : : *
840 : : * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
841 : : * example, "cat /sys/devices/lm0/hcd_frrem".
842 : : */
843 : : #define dwc_sample_frrem(_hcd, _qh, _letter) \
844 : : { \
845 : : hfnum_data_t hfnum; \
846 : : dwc_otg_qtd_t *qtd; \
847 : : qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
848 : : if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
849 : : hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
850 : : switch (hfnum.b.frnum & 0x7) { \
851 : : case 7: \
852 : : _hcd->hfnum_7_samples_##_letter++; \
853 : : _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
854 : : break; \
855 : : case 0: \
856 : : _hcd->hfnum_0_samples_##_letter++; \
857 : : _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
858 : : break; \
859 : : default: \
860 : : _hcd->hfnum_other_samples_##_letter++; \
861 : : _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
862 : : break; \
863 : : } \
864 : : } \
865 : : }
866 : : #else
867 : : #define dwc_sample_frrem(_hcd, _qh, _letter)
868 : : #endif
869 : : #endif
870 : : #endif /* DWC_DEVICE_ONLY */
|