1 /* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_hcd.h $
4 * $Date: 2009-04-17 06:15:34 $
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.
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.
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
32 * ========================================================================== */
33 #ifndef DWC_DEVICE_ONLY
34 #if !defined(__DWC_HCD_H__)
37 #include <linux/list.h>
38 #include <linux/usb.h>
39 #include <linux/usb/hcd.h>
42 struct dwc_otg_device
;
44 #include "dwc_otg_cil.h"
45 //#include "dwc_otg_ifx.h" // winder
51 * This file contains the structures, constants, and interfaces for
52 * the Host Contoller Driver (HCD).
54 * The Host Controller Driver (HCD) is responsible for translating requests
55 * from the USB Driver into the appropriate actions on the DWC_otg controller.
56 * It isolates the USBD from the specifics of the controller by providing an
61 * Phases for control transfers.
63 typedef enum dwc_otg_control_phase
{
64 DWC_OTG_CONTROL_SETUP
,
66 DWC_OTG_CONTROL_STATUS
67 } dwc_otg_control_phase_e
;
69 /** Transaction types. */
70 typedef enum dwc_otg_transaction_type
{
71 DWC_OTG_TRANSACTION_NONE
,
72 DWC_OTG_TRANSACTION_PERIODIC
,
73 DWC_OTG_TRANSACTION_NON_PERIODIC
,
74 DWC_OTG_TRANSACTION_ALL
75 } dwc_otg_transaction_type_e
;
78 * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
79 * interrupt, or isochronous transfer. A single QTD is created for each URB
80 * (of one of these types) submitted to the HCD. The transfer associated with
81 * a QTD may require one or multiple transactions.
83 * A QTD is linked to a Queue Head, which is entered in either the
84 * non-periodic or periodic schedule for execution. When a QTD is chosen for
85 * execution, some or all of its transactions may be executed. After
86 * execution, the state of the QTD is updated. The QTD may be retired if all
87 * its transactions are complete or if an error occurred. Otherwise, it
88 * remains in the schedule so more transactions can be executed later.
91 typedef struct dwc_otg_qtd
{
93 * Determines the PID of the next data packet for the data phase of
94 * control transfers. Ignored for other transfer types.<br>
95 * One of the following values:
96 * - DWC_OTG_HC_PID_DATA0
97 * - DWC_OTG_HC_PID_DATA1
101 /** Current phase for control transfers (Setup, Data, or Status). */
102 dwc_otg_control_phase_e control_phase
;
104 /** Keep track of the current split type
105 * for FS/LS endpoints on a HS Hub */
106 uint8_t complete_split
;
108 /** How many bytes transferred during SSPLIT OUT */
109 uint32_t ssplit_out_xfer_count
;
112 * Holds the number of bus errors that have occurred for a transaction
113 * within this transfer.
118 * Index of the next frame descriptor for an isochronous transfer. A
119 * frame descriptor describes the buffer position and length of the
120 * data to be transferred in the next scheduled (micro)frame of an
121 * isochronous transfer. It also holds status for that transaction.
122 * The frame index starts at 0.
124 int isoc_frame_index
;
126 /** Position of the ISOC split on full/low speed */
127 uint8_t isoc_split_pos
;
129 /** Position of the ISOC split in the buffer for the current frame */
130 uint16_t isoc_split_offset
;
132 /** URB for this transfer */
135 /** This list of QTDs */
136 struct list_head qtd_list_entry
;
138 /* Field to track the qh pointer */
139 struct dwc_otg_qh
*qtd_qh_ptr
;
143 * A Queue Head (QH) holds the static characteristics of an endpoint and
144 * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
145 * be entered in either the non-periodic or periodic schedule.
147 typedef struct dwc_otg_qh
{
150 * One of the following values:
151 * - USB_ENDPOINT_XFER_CONTROL
152 * - USB_ENDPOINT_XFER_ISOC
153 * - USB_ENDPOINT_XFER_BULK
154 * - USB_ENDPOINT_XFER_INT
159 /** wMaxPacketSize Field of Endpoint Descriptor. */
163 * Determines the PID of the next data packet for non-control
164 * transfers. Ignored for control transfers.<br>
165 * One of the following values:
166 * - DWC_OTG_HC_PID_DATA0
167 * - DWC_OTG_HC_PID_DATA1
171 /** Ping state if 1. */
175 * List of QTDs for this QH.
177 struct list_head qtd_list
;
179 /** Host channel currently processing transfers for this QH. */
182 /** QTD currently assigned to a host channel for this QH. */
183 dwc_otg_qtd_t
*qtd_in_process
;
185 /** Full/low speed endpoint on high-speed hub requires split. */
188 /** @name Periodic schedule information */
191 /** Bandwidth in microseconds per (micro)frame. */
194 /** Interval between transfers in (micro)frames. */
198 * (micro)frame to initialize a periodic transfer. The transfer
199 * executes in the following (micro)frame.
201 uint16_t sched_frame
;
203 /** (micro)frame at which last start split was initialized. */
204 uint16_t start_split_frame
;
209 uint16_t frame_usecs
[8];
210 /** Entry for QH in either the periodic or non-periodic schedule. */
211 struct list_head qh_list_entry
;
215 * This structure holds the state of the HCD, including the non-periodic and
216 * periodic schedules.
218 typedef struct dwc_otg_hcd
{
221 /** DWC OTG Core Interface Layer */
222 dwc_otg_core_if_t
*core_if
;
224 /** Internal DWC HCD Flags */
225 volatile union dwc_otg_hcd_internal_flags
{
228 unsigned port_connect_status_change
: 1;
229 unsigned port_connect_status
: 1;
230 unsigned port_reset_change
: 1;
231 unsigned port_enable_change
: 1;
232 unsigned port_suspend_change
: 1;
233 unsigned port_over_current_change
: 1;
234 unsigned reserved
: 27;
239 * Inactive items in the non-periodic schedule. This is a list of
240 * Queue Heads. Transfers associated with these Queue Heads are not
241 * currently assigned to a host channel.
243 struct list_head non_periodic_sched_inactive
;
246 * Deferred items in the non-periodic schedule. This is a list of
247 * Queue Heads. Transfers associated with these Queue Heads are not
248 * currently assigned to a host channel.
249 * When we get an NAK, the QH goes here.
251 struct list_head non_periodic_sched_deferred
;
254 * Active items in the non-periodic schedule. This is a list of
255 * Queue Heads. Transfers associated with these Queue Heads are
256 * currently assigned to a host channel.
258 struct list_head non_periodic_sched_active
;
261 * Pointer to the next Queue Head to process in the active
262 * non-periodic schedule.
264 struct list_head
*non_periodic_qh_ptr
;
267 * Inactive items in the periodic schedule. This is a list of QHs for
268 * periodic transfers that are _not_ scheduled for the next frame.
269 * Each QH in the list has an interval counter that determines when it
270 * needs to be scheduled for execution. This scheduling mechanism
271 * allows only a simple calculation for periodic bandwidth used (i.e.
272 * must assume that all periodic transfers may need to execute in the
273 * same frame). However, it greatly simplifies scheduling and should
274 * be sufficient for the vast majority of OTG hosts, which need to
275 * connect to a small number of peripherals at one time.
277 * Items move from this list to periodic_sched_ready when the QH
278 * interval counter is 0 at SOF.
280 struct list_head periodic_sched_inactive
;
283 * List of periodic QHs that are ready for execution in the next
284 * frame, but have not yet been assigned to host channels.
286 * Items move from this list to periodic_sched_assigned as host
287 * channels become available during the current frame.
289 struct list_head periodic_sched_ready
;
292 * List of periodic QHs to be executed in the next frame that are
293 * assigned to host channels.
295 * Items move from this list to periodic_sched_queued as the
296 * transactions for the QH are queued to the DWC_otg controller.
298 struct list_head periodic_sched_assigned
;
301 * List of periodic QHs that have been queued for execution.
303 * Items move from this list to either periodic_sched_inactive or
304 * periodic_sched_ready when the channel associated with the transfer
305 * is released. If the interval for the QH is 1, the item moves to
306 * periodic_sched_ready because it must be rescheduled for the next
307 * frame. Otherwise, the item moves to periodic_sched_inactive.
309 struct list_head periodic_sched_queued
;
312 * Total bandwidth claimed so far for periodic transfers. This value
313 * is in microseconds per (micro)frame. The assumption is that all
314 * periodic transfers may occur in the same (micro)frame.
316 uint16_t periodic_usecs
;
319 * Total bandwidth claimed so far for all periodic transfers
321 * This will include a mixture of HS and FS transfers.
322 * Units are microseconds per (micro)frame.
323 * We have a budget per frame and have to schedule
324 * transactions accordingly.
325 * Watch out for the fact that things are actually scheduled for the
328 uint16_t frame_usecs
[8];
331 * Frame number read from the core at SOF. The value ranges from 0 to
332 * DWC_HFNUM_MAX_FRNUM.
334 uint16_t frame_number
;
337 * Free host channels in the controller. This is a list of
340 struct list_head free_hc_list
;
343 * Number of available host channels.
345 int available_host_channels
;
348 * Array of pointers to the host channel descriptors. Allows accessing
349 * a host channel descriptor given the host channel number. This is
350 * useful in interrupt handlers.
352 dwc_hc_t
*hc_ptr_array
[MAX_EPS_CHANNELS
];
355 * Buffer to use for any data received during the status phase of a
356 * control transfer. Normally no data is transferred during the status
357 * phase. This buffer is used as a bit bucket.
362 * DMA address for status_buf.
364 dma_addr_t status_buf_dma
;
365 #define DWC_OTG_HCD_STATUS_BUF_SIZE 64
368 * Structure to allow starting the HCD in a non-interrupt context
369 * during an OTG role change.
371 struct work_struct start_work
;
375 * Connection timer. An OTG host must display a message if the device
376 * does not connect. Started when the VBus power is turned on via
377 * sysfs attribute "buspower".
379 struct timer_list conn_timer
;
381 /* Tasket to do a reset */
382 struct tasklet_struct
*reset_tasklet
;
385 uint32_t frrem_samples
;
386 uint64_t frrem_accum
;
388 uint32_t hfnum_7_samples_a
;
389 uint64_t hfnum_7_frrem_accum_a
;
390 uint32_t hfnum_0_samples_a
;
391 uint64_t hfnum_0_frrem_accum_a
;
392 uint32_t hfnum_other_samples_a
;
393 uint64_t hfnum_other_frrem_accum_a
;
395 uint32_t hfnum_7_samples_b
;
396 uint64_t hfnum_7_frrem_accum_b
;
397 uint32_t hfnum_0_samples_b
;
398 uint64_t hfnum_0_frrem_accum_b
;
399 uint32_t hfnum_other_samples_b
;
400 uint64_t hfnum_other_frrem_accum_b
;
405 /** Gets the dwc_otg_hcd from a struct usb_hcd */
406 static inline dwc_otg_hcd_t
*hcd_to_dwc_otg_hcd(struct usb_hcd
*hcd
)
408 return (dwc_otg_hcd_t
*)(hcd
->hcd_priv
);
411 /** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
412 static inline struct usb_hcd
*dwc_otg_hcd_to_hcd(dwc_otg_hcd_t
*dwc_otg_hcd
)
414 return container_of((void *)dwc_otg_hcd
, struct usb_hcd
, hcd_priv
);
417 /** @name HCD Create/Destroy Functions */
419 extern int __devinit
dwc_otg_hcd_init(struct device
*_dev
, dwc_otg_device_t
* dwc_otg_device
);
420 extern void dwc_otg_hcd_remove(struct device
*_dev
);
423 /** @name Linux HC Driver API Functions */
426 extern int dwc_otg_hcd_start(struct usb_hcd
*hcd
);
427 extern void dwc_otg_hcd_stop(struct usb_hcd
*hcd
);
428 extern int dwc_otg_hcd_get_frame_number(struct usb_hcd
*hcd
);
429 extern void dwc_otg_hcd_free(struct usb_hcd
*hcd
);
431 extern int dwc_otg_hcd_urb_enqueue(struct usb_hcd
*hcd
,
434 extern int dwc_otg_hcd_urb_dequeue(struct usb_hcd
*hcd
,
437 extern irqreturn_t
dwc_otg_hcd_irq(struct usb_hcd
*hcd
);
439 extern void dwc_otg_hcd_endpoint_disable(struct usb_hcd
*hcd
,
440 struct usb_host_endpoint
*ep
);
442 extern int dwc_otg_hcd_hub_status_data(struct usb_hcd
*hcd
,
444 extern int dwc_otg_hcd_hub_control(struct usb_hcd
*hcd
,
453 /** @name Transaction Execution Functions */
455 extern dwc_otg_transaction_type_e
dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
*_hcd
);
456 extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t
*_hcd
,
457 dwc_otg_transaction_type_e _tr_type
);
458 extern void dwc_otg_hcd_complete_urb(dwc_otg_hcd_t
*_hcd
, struct urb
*_urb
,
462 /** @name Interrupt Handler Functions */
464 extern int32_t dwc_otg_hcd_handle_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
465 extern int32_t dwc_otg_hcd_handle_sof_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
466 extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
467 extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
468 extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
469 extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t
*_dwc_otg_hcd
);
470 extern int32_t dwc_otg_hcd_handle_port_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
471 extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
472 extern int32_t dwc_otg_hcd_handle_disconnect_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
473 extern int32_t dwc_otg_hcd_handle_hc_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
474 extern int32_t dwc_otg_hcd_handle_hc_n_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
, uint32_t _num
);
475 extern int32_t dwc_otg_hcd_handle_session_req_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
476 extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr (dwc_otg_hcd_t
*_dwc_otg_hcd
);
480 /** @name Schedule Queue Functions */
483 /* Implemented in dwc_otg_hcd_queue.c */
484 extern dwc_otg_qh_t
*dwc_otg_hcd_qh_create (dwc_otg_hcd_t
*_hcd
, struct urb
*_urb
);
485 extern void dwc_otg_hcd_qh_init (dwc_otg_hcd_t
*_hcd
, dwc_otg_qh_t
*_qh
, struct urb
*_urb
);
486 extern void dwc_otg_hcd_qh_free (dwc_otg_qh_t
*_qh
);
487 extern int dwc_otg_hcd_qh_add (dwc_otg_hcd_t
*_hcd
, dwc_otg_qh_t
*_qh
);
488 extern void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t
*_hcd
, dwc_otg_qh_t
*_qh
);
489 extern void dwc_otg_hcd_qh_deactivate (dwc_otg_hcd_t
*_hcd
, dwc_otg_qh_t
*_qh
, int sched_csplit
);
490 extern int dwc_otg_hcd_qh_deferr (dwc_otg_hcd_t
*_hcd
, dwc_otg_qh_t
*_qh
, int delay
);
492 /** Remove and free a QH */
493 static inline void dwc_otg_hcd_qh_remove_and_free (dwc_otg_hcd_t
*_hcd
,
496 dwc_otg_hcd_qh_remove (_hcd
, _qh
);
497 dwc_otg_hcd_qh_free (_qh
);
500 /** Allocates memory for a QH structure.
501 * @return Returns the memory allocate or NULL on error. */
502 static inline dwc_otg_qh_t
*dwc_otg_hcd_qh_alloc (void)
505 return (dwc_otg_qh_t
*) kmalloc (sizeof(dwc_otg_qh_t
), GFP_ATOMIC
);
507 return (dwc_otg_qh_t
*) kmalloc (sizeof(dwc_otg_qh_t
), GFP_KERNEL
);
511 extern dwc_otg_qtd_t
*dwc_otg_hcd_qtd_create (struct urb
*urb
);
512 extern void dwc_otg_hcd_qtd_init (dwc_otg_qtd_t
*qtd
, struct urb
*urb
);
513 extern int dwc_otg_hcd_qtd_add (dwc_otg_qtd_t
*qtd
, dwc_otg_hcd_t
*dwc_otg_hcd
);
515 /** Allocates memory for a QTD structure.
516 * @return Returns the memory allocate or NULL on error. */
517 static inline dwc_otg_qtd_t
*dwc_otg_hcd_qtd_alloc (void)
520 return (dwc_otg_qtd_t
*) kmalloc (sizeof(dwc_otg_qtd_t
), GFP_ATOMIC
);
522 return (dwc_otg_qtd_t
*) kmalloc (sizeof(dwc_otg_qtd_t
), GFP_KERNEL
);
526 /** Frees the memory for a QTD structure. QTD should already be removed from
528 * @param[in] _qtd QTD to free.*/
529 static inline void dwc_otg_hcd_qtd_free (dwc_otg_qtd_t
*_qtd
)
534 /** Removes a QTD from list.
535 * @param[in] _qtd QTD to remove from list. */
536 static inline void dwc_otg_hcd_qtd_remove (dwc_otg_qtd_t
*_qtd
)
539 local_irq_save (flags
);
540 list_del (&_qtd
->qtd_list_entry
);
541 local_irq_restore (flags
);
544 /** Remove and free a QTD */
545 static inline void dwc_otg_hcd_qtd_remove_and_free (dwc_otg_qtd_t
*_qtd
)
547 dwc_otg_hcd_qtd_remove (_qtd
);
548 dwc_otg_hcd_qtd_free (_qtd
);
554 /** @name Internal Functions */
556 dwc_otg_qh_t
*dwc_urb_to_qh(struct urb
*_urb
);
557 void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t
*_hcd
);
558 void dwc_otg_hcd_dump_state(dwc_otg_hcd_t
*_hcd
);
562 /** Gets the usb_host_endpoint associated with an URB. */
563 static inline struct usb_host_endpoint
*dwc_urb_to_endpoint(struct urb
*_urb
)
565 struct usb_device
*dev
= _urb
->dev
;
566 int ep_num
= usb_pipeendpoint(_urb
->pipe
);
567 if (usb_pipein(_urb
->pipe
))
568 return dev
->ep_in
[ep_num
];
570 return dev
->ep_out
[ep_num
];
574 * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
575 * qualified with its direction (possible 32 endpoints per device).
577 #define dwc_ep_addr_to_endpoint(_bEndpointAddress_) \
578 ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
579 ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
581 /** Gets the QH that contains the list_head */
582 #define dwc_list_to_qh(_list_head_ptr_) (container_of(_list_head_ptr_,dwc_otg_qh_t,qh_list_entry))
584 /** Gets the QTD that contains the list_head */
585 #define dwc_list_to_qtd(_list_head_ptr_) (container_of(_list_head_ptr_,dwc_otg_qtd_t,qtd_list_entry))
587 /** Check if QH is non-periodic */
588 #define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == USB_ENDPOINT_XFER_BULK) || \
589 (_qh_ptr_->ep_type == USB_ENDPOINT_XFER_CONTROL))
591 /** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
592 #define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
594 /** Packet size for any kind of endpoint descriptor */
595 #define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
598 * Returns true if _frame1 is less than or equal to _frame2. The comparison is
599 * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
600 * frame number when the max frame number is reached.
602 static inline int dwc_frame_num_le(uint16_t _frame1
, uint16_t _frame2
)
604 return ((_frame2
- _frame1
) & DWC_HFNUM_MAX_FRNUM
) <=
605 (DWC_HFNUM_MAX_FRNUM
>> 1);
609 * Returns true if _frame1 is greater than _frame2. The comparison is done
610 * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
611 * number when the max frame number is reached.
613 static inline int dwc_frame_num_gt(uint16_t _frame1
, uint16_t _frame2
)
615 return (_frame1
!= _frame2
) &&
616 (((_frame1
- _frame2
) & DWC_HFNUM_MAX_FRNUM
) <
617 (DWC_HFNUM_MAX_FRNUM
>> 1));
621 * Increments _frame by the amount specified by _inc. The addition is done
622 * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
624 static inline uint16_t dwc_frame_num_inc(uint16_t _frame
, uint16_t _inc
)
626 return (_frame
+ _inc
) & DWC_HFNUM_MAX_FRNUM
;
629 static inline uint16_t dwc_full_frame_num (uint16_t _frame
)
631 return ((_frame
) & DWC_HFNUM_MAX_FRNUM
) >> 3;
634 static inline uint16_t dwc_micro_frame_num (uint16_t _frame
)
636 return (_frame
) & 0x7;
641 * Macro to sample the remaining PHY clocks left in the current frame. This
642 * may be used during debugging to determine the average time it takes to
643 * execute sections of code. There are two possible sample points, "a" and
644 * "b", so the _letter argument must be one of these values.
646 * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
647 * example, "cat /sys/devices/lm0/hcd_frrem".
649 #define dwc_sample_frrem(_hcd, _qh, _letter) \
651 hfnum_data_t hfnum; \
652 dwc_otg_qtd_t *qtd; \
653 qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
654 if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
655 hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
656 switch (hfnum.b.frnum & 0x7) { \
658 _hcd->hfnum_7_samples_##_letter++; \
659 _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
662 _hcd->hfnum_0_samples_##_letter++; \
663 _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
666 _hcd->hfnum_other_samples_##_letter++; \
667 _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
673 #define dwc_sample_frrem(_hcd, _qh, _letter)
675 #endif // __DWC_HCD_H__
676 #endif /* DWC_DEVICE_ONLY */