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
145 return (!dwc_otg_hcd_is_pipe_in(pipe));
148 static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
149 uint8_t devaddr, uint8_t ep_num,
150 uint8_t pipe_type, uint8_t pipe_dir,
153 pipe->dev_addr = devaddr;
154 pipe->ep_num = ep_num;
155 pipe->pipe_type = pipe_type;
156 pipe->pipe_dir = pipe_dir;
161 * Phases for control transfers.
163 typedef enum dwc_otg_control_phase {
164 DWC_OTG_CONTROL_SETUP,
165 DWC_OTG_CONTROL_DATA,
166 DWC_OTG_CONTROL_STATUS
167 } dwc_otg_control_phase_e;
169 /** Transaction types. */
170 typedef enum dwc_otg_transaction_type {
171 DWC_OTG_TRANSACTION_NONE,
172 DWC_OTG_TRANSACTION_PERIODIC,
173 DWC_OTG_TRANSACTION_NON_PERIODIC,
174 DWC_OTG_TRANSACTION_ALL
175 } dwc_otg_transaction_type_e;
180 * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
181 * interrupt, or isochronous transfer. A single QTD is created for each URB
182 * (of one of these types) submitted to the HCD. The transfer associated with
183 * a QTD may require one or multiple transactions.
185 * A QTD is linked to a Queue Head, which is entered in either the
186 * non-periodic or periodic schedule for execution. When a QTD is chosen for
187 * execution, some or all of its transactions may be executed. After
188 * execution, the state of the QTD is updated. The QTD may be retired if all
189 * its transactions are complete or if an error occurred. Otherwise, it
190 * remains in the schedule so more transactions can be executed later.
192 typedef struct dwc_otg_qtd {
194 * Determines the PID of the next data packet for the data phase of
195 * control transfers. Ignored for other transfer types.<br>
196 * One of the following values:
197 * - DWC_OTG_HC_PID_DATA0
198 * - DWC_OTG_HC_PID_DATA1
202 /** Current phase for control transfers (Setup, Data, or Status). */
203 dwc_otg_control_phase_e control_phase;
205 /** Keep track of the current split type
206 * for FS/LS endpoints on a HS Hub */
207 uint8_t complete_split;
209 /** How many bytes transferred during SSPLIT OUT */
210 uint32_t ssplit_out_xfer_count;
213 * Holds the number of bus errors that have occurred for a transaction
214 * within this transfer.
219 * Index of the next frame descriptor for an isochronous transfer. A
220 * frame descriptor describes the buffer position and length of the
221 * data to be transferred in the next scheduled (micro)frame of an
222 * isochronous transfer. It also holds status for that transaction.
223 * The frame index starts at 0.
225 uint16_t isoc_frame_index;
227 /** Position of the ISOC split on full/low speed */
228 uint8_t isoc_split_pos;
230 /** Position of the ISOC split in the buffer for the current frame */
231 uint16_t isoc_split_offset;
233 /** URB for this transfer */
234 struct dwc_otg_hcd_urb *urb;
236 struct dwc_otg_qh *qh;
238 /** This list of QTDs */
239 DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
241 /** Indicates if this QTD is currently processed by HW. */
244 /** Number of DMA descriptors for this QTD */
248 * Last activated frame(packet) index.
249 * Used in Descriptor DMA mode only.
251 uint16_t isoc_frame_index_last;
255 DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
258 * A Queue Head (QH) holds the static characteristics of an endpoint and
259 * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
260 * be entered in either the non-periodic or periodic schedule.
262 typedef struct dwc_otg_qh {
265 * One of the following values:
274 /** wMaxPacketSize Field of Endpoint Descriptor. */
279 * One of the following values:
280 * - DWC_OTG_EP_SPEED_LOW
281 * - DWC_OTG_EP_SPEED_FULL
282 * - DWC_OTG_EP_SPEED_HIGH
287 * Determines the PID of the next data packet for non-control
288 * transfers. Ignored for control transfers.<br>
289 * One of the following values:
290 * - DWC_OTG_HC_PID_DATA0
291 * - DWC_OTG_HC_PID_DATA1
295 /** Ping state if 1. */
299 * List of QTDs for this QH.
301 struct dwc_otg_qtd_list qtd_list;
303 /** Host channel currently processing transfers for this QH. */
304 struct dwc_hc *channel;
306 /** Full/low speed endpoint on high-speed hub requires split. */
309 /** @name Periodic schedule information */
312 /** Bandwidth in microseconds per (micro)frame. */
315 /** Interval between transfers in (micro)frames. */
319 * (micro)frame to initialize a periodic transfer. The transfer
320 * executes in the following (micro)frame.
322 uint16_t sched_frame;
324 /** (micro)frame at which last start split was initialized. */
325 uint16_t start_split_frame;
330 * Used instead of original buffer if
331 * it(physical address) is not dword-aligned.
333 uint8_t *dw_align_buf;
334 dwc_dma_t dw_align_buf_dma;
336 /** Entry for QH in either the periodic or non-periodic schedule. */
337 dwc_list_link_t qh_list_entry;
339 /** @name Descriptor DMA support */
342 /** Descriptor List. */
343 dwc_otg_host_dma_desc_t *desc_list;
345 /** Descriptor List physical address. */
346 dwc_dma_t desc_list_dma;
350 * Each element corresponds to a descriptor and indicates
351 * original XferSize size value for the descriptor.
355 /** Actual number of transfer descriptors in a list. */
358 /** First activated isochronous transfer descriptor index. */
360 /** Last activated isochronous transfer descriptor index. */
367 DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
370 * This structure holds the state of the HCD, including the non-periodic and
371 * periodic schedules.
374 /** The DWC otg device pointer */
375 struct dwc_otg_device *otg_dev;
376 /** DWC OTG Core Interface Layer */
377 dwc_otg_core_if_t *core_if;
379 /** Function HCD driver callbacks */
380 struct dwc_otg_hcd_function_ops *fops;
382 /** Internal DWC HCD Flags */
383 volatile union dwc_otg_hcd_internal_flags {
386 unsigned port_connect_status_change:1;
387 unsigned port_connect_status:1;
388 unsigned port_reset_change:1;
389 unsigned port_enable_change:1;
390 unsigned port_suspend_change:1;
391 unsigned port_over_current_change:1;
392 unsigned port_l1_change:1;
393 unsigned reserved:26;
398 * Inactive items in the non-periodic schedule. This is a list of
399 * Queue Heads. Transfers associated with these Queue Heads are not
400 * currently assigned to a host channel.
402 dwc_list_link_t non_periodic_sched_inactive;
405 * Active items in the non-periodic schedule. This is a list of
406 * Queue Heads. Transfers associated with these Queue Heads are
407 * currently assigned to a host channel.
409 dwc_list_link_t non_periodic_sched_active;
412 * Pointer to the next Queue Head to process in the active
413 * non-periodic schedule.
415 dwc_list_link_t *non_periodic_qh_ptr;
418 * Inactive items in the periodic schedule. This is a list of QHs for
419 * periodic transfers that are _not_ scheduled for the next frame.
420 * Each QH in the list has an interval counter that determines when it
421 * needs to be scheduled for execution. This scheduling mechanism
422 * allows only a simple calculation for periodic bandwidth used (i.e.
423 * must assume that all periodic transfers may need to execute in the
424 * same frame). However, it greatly simplifies scheduling and should
425 * be sufficient for the vast majority of OTG hosts, which need to
426 * connect to a small number of peripherals at one time.
428 * Items move from this list to periodic_sched_ready when the QH
429 * interval counter is 0 at SOF.
431 dwc_list_link_t periodic_sched_inactive;
434 * List of periodic QHs that are ready for execution in the next
435 * frame, but have not yet been assigned to host channels.
437 * Items move from this list to periodic_sched_assigned as host
438 * channels become available during the current frame.
440 dwc_list_link_t periodic_sched_ready;
443 * List of periodic QHs to be executed in the next frame that are
444 * assigned to host channels.
446 * Items move from this list to periodic_sched_queued as the
447 * transactions for the QH are queued to the DWC_otg controller.
449 dwc_list_link_t periodic_sched_assigned;
452 * List of periodic QHs that have been queued for execution.
454 * Items move from this list to either periodic_sched_inactive or
455 * periodic_sched_ready when the channel associated with the transfer
456 * is released. If the interval for the QH is 1, the item moves to
457 * periodic_sched_ready because it must be rescheduled for the next
458 * frame. Otherwise, the item moves to periodic_sched_inactive.
460 dwc_list_link_t periodic_sched_queued;
463 * Total bandwidth claimed so far for periodic transfers. This value
464 * is in microseconds per (micro)frame. The assumption is that all
465 * periodic transfers may occur in the same (micro)frame.
467 uint16_t periodic_usecs;
470 * Frame number read from the core at SOF. The value ranges from 0 to
471 * DWC_HFNUM_MAX_FRNUM.
473 uint16_t frame_number;
476 * Count of periodic QHs, if using several eps. For SOF enable/disable.
478 uint16_t periodic_qh_count;
481 * Free host channels in the controller. This is a list of
484 struct hc_list free_hc_list;
486 * Number of host channels assigned to periodic transfers. Currently
487 * assuming that there is a dedicated host channel for each periodic
488 * transaction and at least one host channel available for
489 * non-periodic transactions.
491 int periodic_channels;
494 * Number of host channels assigned to non-periodic transfers.
496 int non_periodic_channels;
499 * Array of pointers to the host channel descriptors. Allows accessing
500 * a host channel descriptor given the host channel number. This is
501 * useful in interrupt handlers.
503 struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
506 * Buffer to use for any data received during the status phase of a
507 * control transfer. Normally no data is transferred during the status
508 * phase. This buffer is used as a bit bucket.
513 * DMA address for status_buf.
515 dma_addr_t status_buf_dma;
516 #define DWC_OTG_HCD_STATUS_BUF_SIZE 64
519 * Connection timer. An OTG host must display a message if the device
520 * does not connect. Started when the VBus power is turned on via
521 * sysfs attribute "buspower".
523 dwc_timer_t *conn_timer;
525 /* Tasket to do a reset */
526 dwc_tasklet_t *reset_tasklet;
529 dwc_spinlock_t *lock;
532 * Private data that could be used by OS wrapper.
539 uint32_t *frame_list;
541 /** Frame List DMA address */
542 dma_addr_t frame_list_dma;
545 uint32_t frrem_samples;
546 uint64_t frrem_accum;
548 uint32_t hfnum_7_samples_a;
549 uint64_t hfnum_7_frrem_accum_a;
550 uint32_t hfnum_0_samples_a;
551 uint64_t hfnum_0_frrem_accum_a;
552 uint32_t hfnum_other_samples_a;
553 uint64_t hfnum_other_frrem_accum_a;
555 uint32_t hfnum_7_samples_b;
556 uint64_t hfnum_7_frrem_accum_b;
557 uint32_t hfnum_0_samples_b;
558 uint64_t hfnum_0_frrem_accum_b;
559 uint32_t hfnum_other_samples_b;
560 uint64_t hfnum_other_frrem_accum_b;
562 /** Flag to indicate whether host controller is enabled.
563 * 0: force disable by sysfs
567 uint8_t host_enabled;
568 uint8_t host_setenable;
569 struct timer_list connect_detect_timer;
570 struct delayed_work host_enable_work;
573 /** @name Transaction Execution Functions */
575 extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
577 extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
578 dwc_otg_transaction_type_e tr_type);
582 /** @name Interrupt Handler Functions */
584 extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
585 extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
586 extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
588 extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
590 extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
592 extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
594 extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
595 extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
597 extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
598 extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
599 extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
601 extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
602 extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
606 /** @name Schedule Queue Functions */
609 /* Implemented in dwc_otg_hcd_queue.c */
610 extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
611 dwc_otg_hcd_urb_t * urb, int atomic_alloc);
612 extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
613 extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
614 extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
615 extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
618 /** Remove and free a QH */
619 static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
622 dwc_irqflags_t flags;
623 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
624 dwc_otg_hcd_qh_remove(hcd, qh);
625 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
626 dwc_otg_hcd_qh_free(hcd, qh);
629 /** Allocates memory for a QH structure.
630 * @return Returns the memory allocate or NULL on error. */
631 static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
634 return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
636 return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
639 extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
641 extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
642 extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
643 dwc_otg_qh_t ** qh, int atomic_alloc);
645 /** Allocates memory for a QTD structure.
646 * @return Returns the memory allocate or NULL on error. */
647 static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
650 return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
652 return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
655 /** Frees the memory for a QTD structure. QTD should already be removed from
657 * @param qtd QTD to free.*/
658 static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
663 /** Removes a QTD from list.
664 * @param hcd HCD instance.
665 * @param qtd QTD to remove from list.
666 * @param qh QTD belongs to.
668 static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
672 DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
675 /** Remove and free a QTD
676 * Need to disable IRQ and hold hcd lock while calling this function out of
677 * interrupt servicing chain */
678 static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
682 dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
683 dwc_otg_hcd_qtd_free(qtd);
688 /** @name Descriptor DMA Supporting Functions */
691 extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
692 extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
694 dwc_otg_hc_regs_t * hc_regs,
695 dwc_otg_halt_status_e halt_status);
697 extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
698 extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
702 /** @name Internal Functions */
704 dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
707 #ifdef CONFIG_USB_DWC_OTG_LPM
708 extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
710 extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
713 /** Gets the QH that contains the list_head */
714 #define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
716 /** Gets the QTD that contains the list_head */
717 #define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
719 /** Check if QH is non-periodic */
720 #define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
721 (_qh_ptr_->ep_type == UE_CONTROL))
723 /** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
724 #define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
726 /** Packet size for any kind of endpoint descriptor */
727 #define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
730 * Returns true if _frame1 is less than or equal to _frame2. The comparison is
731 * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
732 * frame number when the max frame number is reached.
734 static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
736 return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
737 (DWC_HFNUM_MAX_FRNUM >> 1);
741 * Returns true if _frame1 is greater than _frame2. The comparison is done
742 * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
743 * number when the max frame number is reached.
745 static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
747 return (frame1 != frame2) &&
748 (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
749 (DWC_HFNUM_MAX_FRNUM >> 1));
753 * Increments _frame by the amount specified by _inc. The addition is done
754 * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
756 static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
758 return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
761 static inline uint16_t dwc_full_frame_num(uint16_t frame)
763 return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
766 static inline uint16_t dwc_micro_frame_num(uint16_t frame)
771 void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
772 dwc_otg_hc_regs_t * hc_regs,
773 dwc_otg_qtd_t * qtd);
777 * Macro to sample the remaining PHY clocks left in the current frame. This
778 * may be used during debugging to determine the average time it takes to
779 * execute sections of code. There are two possible sample points, "a" and
780 * "b", so the _letter argument must be one of these values.
782 * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
783 * example, "cat /sys/devices/lm0/hcd_frrem".
785 #define dwc_sample_frrem(_hcd, _qh, _letter) \
787 hfnum_data_t hfnum; \
788 dwc_otg_qtd_t *qtd; \
789 qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
790 if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
791 hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
792 switch (hfnum.b.frnum & 0x7) { \
794 _hcd->hfnum_7_samples_##_letter++; \
795 _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
798 _hcd->hfnum_0_samples_##_letter++; \
799 _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
802 _hcd->hfnum_other_samples_##_letter++; \
803 _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
809 #define dwc_sample_frrem(_hcd, _qh, _letter)
812 #endif /* DWC_DEVICE_ONLY */