1 /* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
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
37 #include "dwc_otg_os_dep.h"
38 #include "common_port/usb.h"
39 #include "dwc_otg_hcd_if.h"
40 #include "dwc_otg_core_if.h"
41 #include "common_port/dwc_list.h"
42 #include "dwc_otg_cil.h"
47 * This file contains the structures, constants, and interfaces for
48 * the Host Contoller Driver (HCD).
50 * The Host Controller Driver (HCD) is responsible for translating requests
51 * from the USB Driver into the appropriate actions on the DWC_otg controller.
52 * It isolates the USBD from the specifics of the controller by providing an
56 struct dwc_otg_hcd_pipe_info {
64 struct dwc_otg_hcd_iso_packet_desc {
67 uint32_t actual_length;
73 struct dwc_otg_hcd_urb {
75 struct dwc_otg_qtd *qtd;
81 uint32_t actual_length;
84 uint32_t packet_count;
87 struct dwc_otg_hcd_pipe_info pipe_info;
88 struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
91 static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
96 static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
99 return pipe->pipe_type;
102 static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
107 static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
110 return pipe->dev_addr;
113 static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
116 return (pipe->pipe_type == UE_ISOCHRONOUS);
119 static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
122 return (pipe->pipe_type == UE_INTERRUPT);
125 static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
128 return (pipe->pipe_type == UE_BULK);
131 static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
134 return (pipe->pipe_type == UE_CONTROL);
137 static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
139 return (pipe->pipe_dir == UE_DIR_IN);
142 static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
146 ret = !dwc_otg_hcd_is_pipe_in(pipe);
150 static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
151 uint8_t devaddr, uint8_t ep_num,
152 uint8_t pipe_type, uint8_t pipe_dir,
155 pipe->dev_addr = devaddr;
156 pipe->ep_num = ep_num;
157 pipe->pipe_type = pipe_type;
158 pipe->pipe_dir = pipe_dir;
163 * Phases for control transfers.
165 typedef enum dwc_otg_control_phase {
166 DWC_OTG_CONTROL_SETUP,
167 DWC_OTG_CONTROL_DATA,
168 DWC_OTG_CONTROL_STATUS
169 } dwc_otg_control_phase_e;
171 /** Transaction types. */
172 typedef enum dwc_otg_transaction_type {
173 DWC_OTG_TRANSACTION_NONE,
174 DWC_OTG_TRANSACTION_PERIODIC,
175 DWC_OTG_TRANSACTION_NON_PERIODIC,
176 DWC_OTG_TRANSACTION_ALL
177 } dwc_otg_transaction_type_e;
182 * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
183 * interrupt, or isochronous transfer. A single QTD is created for each URB
184 * (of one of these types) submitted to the HCD. The transfer associated with
185 * a QTD may require one or multiple transactions.
187 * A QTD is linked to a Queue Head, which is entered in either the
188 * non-periodic or periodic schedule for execution. When a QTD is chosen for
189 * execution, some or all of its transactions may be executed. After
190 * execution, the state of the QTD is updated. The QTD may be retired if all
191 * its transactions are complete or if an error occurred. Otherwise, it
192 * remains in the schedule so more transactions can be executed later.
194 typedef struct dwc_otg_qtd {
196 * Determines the PID of the next data packet for the data phase of
197 * control transfers. Ignored for other transfer types.<br>
198 * One of the following values:
199 * - DWC_OTG_HC_PID_DATA0
200 * - DWC_OTG_HC_PID_DATA1
204 /** Current phase for control transfers (Setup, Data, or Status). */
205 dwc_otg_control_phase_e control_phase;
207 /** Keep track of the current split type
208 * for FS/LS endpoints on a HS Hub */
209 uint8_t complete_split;
211 /** How many bytes transferred during SSPLIT OUT */
212 uint32_t ssplit_out_xfer_count;
215 * Holds the number of bus errors that have occurred for a transaction
216 * within this transfer.
221 * Index of the next frame descriptor for an isochronous transfer. A
222 * frame descriptor describes the buffer position and length of the
223 * data to be transferred in the next scheduled (micro)frame of an
224 * isochronous transfer. It also holds status for that transaction.
225 * The frame index starts at 0.
227 uint16_t isoc_frame_index;
229 /** Position of the ISOC split on full/low speed */
230 uint8_t isoc_split_pos;
232 /** Position of the ISOC split in the buffer for the current frame */
233 uint16_t isoc_split_offset;
235 /** URB for this transfer */
236 struct dwc_otg_hcd_urb *urb;
238 struct dwc_otg_qh *qh;
240 /** This list of QTDs */
241 DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
243 /** Indicates if this QTD is currently processed by HW. */
246 /** Number of DMA descriptors for this QTD */
250 * Last activated frame(packet) index.
251 * Used in Descriptor DMA mode only.
253 uint16_t isoc_frame_index_last;
257 DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
260 * A Queue Head (QH) holds the static characteristics of an endpoint and
261 * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
262 * be entered in either the non-periodic or periodic schedule.
264 typedef struct dwc_otg_qh {
267 * One of the following values:
276 /** wMaxPacketSize Field of Endpoint Descriptor. */
281 * One of the following values:
282 * - DWC_OTG_EP_SPEED_LOW
283 * - DWC_OTG_EP_SPEED_FULL
284 * - DWC_OTG_EP_SPEED_HIGH
289 * Determines the PID of the next data packet for non-control
290 * transfers. Ignored for control transfers.<br>
291 * One of the following values:
292 * - DWC_OTG_HC_PID_DATA0
293 * - DWC_OTG_HC_PID_DATA1
297 /** Ping state if 1. */
301 * List of QTDs for this QH.
303 struct dwc_otg_qtd_list qtd_list;
305 /** Host channel currently processing transfers for this QH. */
306 struct dwc_hc *channel;
308 /** Full/low speed endpoint on high-speed hub requires split. */
311 /** @name Periodic schedule information */
314 /** Bandwidth in microseconds per (micro)frame. */
317 /** Interval between transfers in (micro)frames. */
321 * (micro)frame to initialize a periodic transfer. The transfer
322 * executes in the following (micro)frame.
324 uint16_t sched_frame;
326 /** (micro)frame at which last start split was initialized. */
327 uint16_t start_split_frame;
332 * Used instead of original buffer if
333 * it(physical address) is not dword-aligned.
335 uint8_t *dw_align_buf;
336 dwc_dma_t dw_align_buf_dma;
338 /** Entry for QH in either the periodic or non-periodic schedule. */
339 dwc_list_link_t qh_list_entry;
341 /** @name Descriptor DMA support */
344 /** Descriptor List. */
345 dwc_otg_host_dma_desc_t *desc_list;
347 /** Descriptor List physical address. */
348 dwc_dma_t desc_list_dma;
352 * Each element corresponds to a descriptor and indicates
353 * original XferSize size value for the descriptor.
357 /** Actual number of transfer descriptors in a list. */
360 /** First activated isochronous transfer descriptor index. */
362 /** Last activated isochronous transfer descriptor index. */
369 DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
372 * This structure holds the state of the HCD, including the non-periodic and
373 * periodic schedules.
376 /** The DWC otg device pointer */
377 struct dwc_otg_device *otg_dev;
378 /** DWC OTG Core Interface Layer */
379 dwc_otg_core_if_t *core_if;
381 /** Function HCD driver callbacks */
382 struct dwc_otg_hcd_function_ops *fops;
384 /** Internal DWC HCD Flags */
385 volatile union dwc_otg_hcd_internal_flags {
388 unsigned port_connect_status_change:1;
389 unsigned port_connect_status:1;
390 unsigned port_reset_change:1;
391 unsigned port_enable_change:1;
392 unsigned port_suspend_change:1;
393 unsigned port_over_current_change:1;
394 unsigned port_l1_change:1;
395 unsigned reserved:26;
400 * Inactive items in the non-periodic schedule. This is a list of
401 * Queue Heads. Transfers associated with these Queue Heads are not
402 * currently assigned to a host channel.
404 dwc_list_link_t non_periodic_sched_inactive;
407 * Active items in the non-periodic schedule. This is a list of
408 * Queue Heads. Transfers associated with these Queue Heads are
409 * currently assigned to a host channel.
411 dwc_list_link_t non_periodic_sched_active;
414 * Pointer to the next Queue Head to process in the active
415 * non-periodic schedule.
417 dwc_list_link_t *non_periodic_qh_ptr;
420 * Inactive items in the periodic schedule. This is a list of QHs for
421 * periodic transfers that are _not_ scheduled for the next frame.
422 * Each QH in the list has an interval counter that determines when it
423 * needs to be scheduled for execution. This scheduling mechanism
424 * allows only a simple calculation for periodic bandwidth used (i.e.
425 * must assume that all periodic transfers may need to execute in the
426 * same frame). However, it greatly simplifies scheduling and should
427 * be sufficient for the vast majority of OTG hosts, which need to
428 * connect to a small number of peripherals at one time.
430 * Items move from this list to periodic_sched_ready when the QH
431 * interval counter is 0 at SOF.
433 dwc_list_link_t periodic_sched_inactive;
436 * List of periodic QHs that are ready for execution in the next
437 * frame, but have not yet been assigned to host channels.
439 * Items move from this list to periodic_sched_assigned as host
440 * channels become available during the current frame.
442 dwc_list_link_t periodic_sched_ready;
445 * List of periodic QHs to be executed in the next frame that are
446 * assigned to host channels.
448 * Items move from this list to periodic_sched_queued as the
449 * transactions for the QH are queued to the DWC_otg controller.
451 dwc_list_link_t periodic_sched_assigned;
454 * List of periodic QHs that have been queued for execution.
456 * Items move from this list to either periodic_sched_inactive or
457 * periodic_sched_ready when the channel associated with the transfer
458 * is released. If the interval for the QH is 1, the item moves to
459 * periodic_sched_ready because it must be rescheduled for the next
460 * frame. Otherwise, the item moves to periodic_sched_inactive.
462 dwc_list_link_t periodic_sched_queued;
465 * Total bandwidth claimed so far for periodic transfers. This value
466 * is in microseconds per (micro)frame. The assumption is that all
467 * periodic transfers may occur in the same (micro)frame.
469 uint16_t periodic_usecs;
472 * Frame number read from the core at SOF. The value ranges from 0 to
473 * DWC_HFNUM_MAX_FRNUM.
475 uint16_t frame_number;
478 * Count of periodic QHs, if using several eps. For SOF enable/disable.
480 uint16_t periodic_qh_count;
483 * Free host channels in the controller. This is a list of
486 struct hc_list free_hc_list;
488 * Number of host channels assigned to periodic transfers. Currently
489 * assuming that there is a dedicated host channel for each periodic
490 * transaction and at least one host channel available for
491 * non-periodic transactions.
493 int periodic_channels;
496 * Number of host channels assigned to non-periodic transfers.
498 int non_periodic_channels;
501 * Array of pointers to the host channel descriptors. Allows accessing
502 * a host channel descriptor given the host channel number. This is
503 * useful in interrupt handlers.
505 struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
508 * Buffer to use for any data received during the status phase of a
509 * control transfer. Normally no data is transferred during the status
510 * phase. This buffer is used as a bit bucket.
515 * DMA address for status_buf.
517 dma_addr_t status_buf_dma;
518 #define DWC_OTG_HCD_STATUS_BUF_SIZE 64
521 * Connection timer. An OTG host must display a message if the device
522 * does not connect. Started when the VBus power is turned on via
523 * sysfs attribute "buspower".
525 dwc_timer_t *conn_timer;
527 /* Tasket to do a reset */
528 dwc_tasklet_t *reset_tasklet;
531 dwc_spinlock_t *lock;
534 * Private data that could be used by OS wrapper.
541 uint32_t *frame_list;
543 /** Frame List DMA address */
544 dma_addr_t frame_list_dma;
547 uint32_t frrem_samples;
548 uint64_t frrem_accum;
550 uint32_t hfnum_7_samples_a;
551 uint64_t hfnum_7_frrem_accum_a;
552 uint32_t hfnum_0_samples_a;
553 uint64_t hfnum_0_frrem_accum_a;
554 uint32_t hfnum_other_samples_a;
555 uint64_t hfnum_other_frrem_accum_a;
557 uint32_t hfnum_7_samples_b;
558 uint64_t hfnum_7_frrem_accum_b;
559 uint32_t hfnum_0_samples_b;
560 uint64_t hfnum_0_frrem_accum_b;
561 uint32_t hfnum_other_samples_b;
562 uint64_t hfnum_other_frrem_accum_b;
564 /** Flag to indicate whether host controller is enabled.
565 * 0: force disable by sysfs
569 uint8_t host_enabled;
570 uint8_t host_setenable;
571 struct timer_list connect_detect_timer;
572 struct delayed_work host_enable_work;
575 /** @name Transaction Execution Functions */
577 extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
579 extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *hcd,
580 dwc_otg_transaction_type_e tr_type);
584 /** @name Interrupt Handler Functions */
586 extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t *dwc_otg_hcd);
587 extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t *dwc_otg_hcd);
588 extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
590 extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
592 extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
594 extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
596 extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t *dwc_otg_hcd);
597 extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
599 extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t *dwc_otg_hcd);
600 extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t *dwc_otg_hcd);
601 extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t *dwc_otg_hcd,
603 extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t *dwc_otg_hcd);
604 extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
608 /** @name Schedule Queue Functions */
611 /* Implemented in dwc_otg_hcd_queue.c */
612 extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t *hcd,
613 dwc_otg_hcd_urb_t *urb,
615 extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
616 extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
617 extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
618 extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh,
621 /** Remove and free a QH */
622 static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t *hcd,
625 dwc_irqflags_t flags;
626 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
627 dwc_otg_hcd_qh_remove(hcd, qh);
628 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
629 dwc_otg_hcd_qh_free(hcd, qh);
632 /** Allocates memory for a QH structure.
633 * @return Returns the memory allocate or NULL on error. */
634 static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
637 return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
639 return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
642 extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t *urb,
644 extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t *qtd, dwc_otg_hcd_urb_t *urb);
645 extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *qtd, dwc_otg_hcd_t *dwc_otg_hcd,
646 dwc_otg_qh_t **qh, int atomic_alloc);
648 /** Allocates memory for a QTD structure.
649 * @return Returns the memory allocate or NULL on error. */
650 static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
653 return (dwc_otg_qtd_t *)
654 DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
656 return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
659 /** Frees the memory for a QTD structure. QTD should already be removed from
661 * @param qtd QTD to free.*/
662 static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t *qtd)
667 /** Removes a QTD from list.
668 * @param hcd HCD instance.
669 * @param qtd QTD to remove from list.
670 * @param qh QTD belongs to.
672 static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t *hcd,
676 DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
679 /** Remove and free a QTD
680 * Need to disable IRQ and hold hcd lock while calling this function out of
681 * interrupt servicing chain */
682 static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t *hcd,
686 dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
687 dwc_otg_hcd_qtd_free(qtd);
692 /** @name Descriptor DMA Supporting Functions */
695 extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
696 extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t *hcd,
698 dwc_otg_hc_regs_t *hc_regs,
699 dwc_otg_halt_status_e halt_status);
701 extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
702 extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
706 /** @name Internal Functions */
708 dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t *urb);
711 #ifdef CONFIG_USB_DWC_OTG_LPM
712 extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t *hcd,
714 extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t *hcd);
717 /** Gets the QH that contains the list_head */
718 #define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
720 /** Gets the QTD that contains the list_head */
721 #define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
723 /** Check if QH is non-periodic */
724 #define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
725 (_qh_ptr_->ep_type == UE_CONTROL))
727 /** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
728 #define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
730 /** Packet size for any kind of endpoint descriptor */
731 #define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
734 * Returns true if _frame1 is less than or equal to _frame2. The comparison is
735 * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
736 * frame number when the max frame number is reached.
738 static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
740 return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
741 (DWC_HFNUM_MAX_FRNUM >> 1);
745 * Returns true if _frame1 is greater than _frame2. The comparison is done
746 * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
747 * number when the max frame number is reached.
749 static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
751 return (frame1 != frame2) &&
752 (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
753 (DWC_HFNUM_MAX_FRNUM >> 1));
757 * Increments _frame by the amount specified by _inc. The addition is done
758 * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
760 static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
762 return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
765 static inline uint16_t dwc_full_frame_num(uint16_t frame)
767 return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
770 static inline uint16_t dwc_micro_frame_num(uint16_t frame)
775 void dwc_otg_hcd_save_data_toggle(dwc_hc_t *hc,
776 dwc_otg_hc_regs_t *hc_regs,
781 * Macro to sample the remaining PHY clocks left in the current frame. This
782 * may be used during debugging to determine the average time it takes to
783 * execute sections of code. There are two possible sample points, "a" and
784 * "b", so the _letter argument must be one of these values.
786 * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
787 * example, "cat /sys/devices/lm0/hcd_frrem".
789 #define dwc_sample_frrem(_hcd, _qh, _letter) \
791 hfnum_data_t hfnum; \
792 dwc_otg_qtd_t *qtd; \
793 qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
794 if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
795 hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
796 switch (hfnum.b.frnum & 0x7) { \
798 _hcd->hfnum_7_samples_##_letter++; \
799 _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
802 _hcd->hfnum_0_samples_##_letter++; \
803 _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
806 _hcd->hfnum_other_samples_##_letter++; \
807 _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
813 #define dwc_sample_frrem(_hcd, _qh, _letter)
816 #endif /* DWC_DEVICE_ONLY */