Root/target/linux/cns3xxx/files/drivers/usb/dwc/otg_hcd.h

1/* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
3 * $Revision: #45 $
4 * $Date: 2008/07/15 $
5 * $Change: 1064918 $
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 <linux/list.h>
38#include <linux/usb.h>
39#include <linux/usb/hcd.h>
40
41struct dwc_otg_device;
42
43#include "otg_cil.h"
44
45/**
46 * @file
47 *
48 * This file contains the structures, constants, and interfaces for
49 * the Host Contoller Driver (HCD).
50 *
51 * The Host Controller Driver (HCD) is responsible for translating requests
52 * from the USB Driver into the appropriate actions on the DWC_otg controller.
53 * It isolates the USBD from the specifics of the controller by providing an
54 * API to the USBD.
55 */
56
57/**
58 * Phases for control transfers.
59 */
60typedef enum dwc_otg_control_phase {
61    DWC_OTG_CONTROL_SETUP,
62    DWC_OTG_CONTROL_DATA,
63    DWC_OTG_CONTROL_STATUS
64} dwc_otg_control_phase_e;
65
66/** Transaction types. */
67typedef enum dwc_otg_transaction_type {
68    DWC_OTG_TRANSACTION_NONE,
69    DWC_OTG_TRANSACTION_PERIODIC,
70    DWC_OTG_TRANSACTION_NON_PERIODIC,
71    DWC_OTG_TRANSACTION_ALL
72} dwc_otg_transaction_type_e;
73
74/**
75 * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
76 * interrupt, or isochronous transfer. A single QTD is created for each URB
77 * (of one of these types) submitted to the HCD. The transfer associated with
78 * a QTD may require one or multiple transactions.
79 *
80 * A QTD is linked to a Queue Head, which is entered in either the
81 * non-periodic or periodic schedule for execution. When a QTD is chosen for
82 * execution, some or all of its transactions may be executed. After
83 * execution, the state of the QTD is updated. The QTD may be retired if all
84 * its transactions are complete or if an error occurred. Otherwise, it
85 * remains in the schedule so more transactions can be executed later.
86 */
87typedef struct dwc_otg_qtd {
88    /**
89     * Determines the PID of the next data packet for the data phase of
90     * control transfers. Ignored for other transfer types.<br>
91     * One of the following values:
92     * - DWC_OTG_HC_PID_DATA0
93     * - DWC_OTG_HC_PID_DATA1
94     */
95    uint8_t data_toggle;
96
97    /** Current phase for control transfers (Setup, Data, or Status). */
98    dwc_otg_control_phase_e control_phase;
99
100    /** Keep track of the current split type
101     * for FS/LS endpoints on a HS Hub */
102    uint8_t complete_split;
103
104    /** How many bytes transferred during SSPLIT OUT */
105    uint32_t ssplit_out_xfer_count;
106
107    /**
108     * Holds the number of bus errors that have occurred for a transaction
109     * within this transfer.
110     */
111    uint8_t error_count;
112
113    /**
114     * Index of the next frame descriptor for an isochronous transfer. A
115     * frame descriptor describes the buffer position and length of the
116     * data to be transferred in the next scheduled (micro)frame of an
117     * isochronous transfer. It also holds status for that transaction.
118     * The frame index starts at 0.
119     */
120    int isoc_frame_index;
121
122    /** Position of the ISOC split on full/low speed */
123    uint8_t isoc_split_pos;
124
125    /** Position of the ISOC split in the buffer for the current frame */
126    uint16_t isoc_split_offset;
127
128    /** URB for this transfer */
129    struct urb *urb;
130
131    /** This list of QTDs */
132    struct list_head qtd_list_entry;
133
134} dwc_otg_qtd_t;
135
136/**
137 * A Queue Head (QH) holds the static characteristics of an endpoint and
138 * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
139 * be entered in either the non-periodic or periodic schedule.
140 */
141typedef struct dwc_otg_qh {
142    /**
143     * Endpoint type.
144     * One of the following values:
145     * - USB_ENDPOINT_XFER_CONTROL
146     * - USB_ENDPOINT_XFER_ISOC
147     * - USB_ENDPOINT_XFER_BULK
148     * - USB_ENDPOINT_XFER_INT
149     */
150    uint8_t ep_type;
151    uint8_t ep_is_in;
152
153    /** wMaxPacketSize Field of Endpoint Descriptor. */
154    uint16_t maxp;
155
156    /**
157     * Determines the PID of the next data packet for non-control
158     * transfers. Ignored for control transfers.<br>
159     * One of the following values:
160     * - DWC_OTG_HC_PID_DATA0
161     * - DWC_OTG_HC_PID_DATA1
162     */
163    uint8_t data_toggle;
164
165    /** Ping state if 1. */
166    uint8_t ping_state;
167
168    /**
169     * List of QTDs for this QH.
170     */
171    struct list_head qtd_list;
172
173    /** Host channel currently processing transfers for this QH. */
174    dwc_hc_t *channel;
175
176    /** QTD currently assigned to a host channel for this QH. */
177    dwc_otg_qtd_t *qtd_in_process;
178
179    /** Full/low speed endpoint on high-speed hub requires split. */
180    uint8_t do_split;
181
182    /** @name Periodic schedule information */
183    /** @{ */
184
185    /** Bandwidth in microseconds per (micro)frame. */
186    uint8_t usecs;
187
188    /** Interval between transfers in (micro)frames. */
189    uint16_t interval;
190
191    /**
192     * (micro)frame to initialize a periodic transfer. The transfer
193     * executes in the following (micro)frame.
194     */
195    uint16_t sched_frame;
196
197    /** (micro)frame at which last start split was initialized. */
198    uint16_t start_split_frame;
199
200    u16 speed;
201    u16 frame_usecs[8];
202
203    /** @} */
204
205    /** Entry for QH in either the periodic or non-periodic schedule. */
206    struct list_head qh_list_entry;
207} dwc_otg_qh_t;
208
209/**
210 * This structure holds the state of the HCD, including the non-periodic and
211 * periodic schedules.
212 */
213typedef struct dwc_otg_hcd {
214    /** The DWC otg device pointer */
215    struct dwc_otg_device *otg_dev;
216
217    /** DWC OTG Core Interface Layer */
218    dwc_otg_core_if_t *core_if;
219
220    /** Internal DWC HCD Flags */
221    volatile union dwc_otg_hcd_internal_flags {
222        uint32_t d32;
223        struct {
224            unsigned port_connect_status_change : 1;
225            unsigned port_connect_status : 1;
226            unsigned port_reset_change : 1;
227            unsigned port_enable_change : 1;
228            unsigned port_suspend_change : 1;
229            unsigned port_over_current_change : 1;
230            unsigned reserved : 27;
231        } b;
232    } flags;
233
234    /**
235     * Inactive items in the non-periodic schedule. This is a list of
236     * Queue Heads. Transfers associated with these Queue Heads are not
237     * currently assigned to a host channel.
238     */
239    struct list_head non_periodic_sched_inactive;
240
241    /**
242     * Active items in the non-periodic schedule. This is a list of
243     * Queue Heads. Transfers associated with these Queue Heads are
244     * currently assigned to a host channel.
245     */
246    struct list_head non_periodic_sched_active;
247
248    /**
249     * Pointer to the next Queue Head to process in the active
250     * non-periodic schedule.
251     */
252    struct list_head *non_periodic_qh_ptr;
253
254    /**
255     * Inactive items in the periodic schedule. This is a list of QHs for
256     * periodic transfers that are _not_ scheduled for the next frame.
257     * Each QH in the list has an interval counter that determines when it
258     * needs to be scheduled for execution. This scheduling mechanism
259     * allows only a simple calculation for periodic bandwidth used (i.e.
260     * must assume that all periodic transfers may need to execute in the
261     * same frame). However, it greatly simplifies scheduling and should
262     * be sufficient for the vast majority of OTG hosts, which need to
263     * connect to a small number of peripherals at one time.
264     *
265     * Items move from this list to periodic_sched_ready when the QH
266     * interval counter is 0 at SOF.
267     */
268    struct list_head periodic_sched_inactive;
269
270    /**
271     * List of periodic QHs that are ready for execution in the next
272     * frame, but have not yet been assigned to host channels.
273     *
274     * Items move from this list to periodic_sched_assigned as host
275     * channels become available during the current frame.
276     */
277    struct list_head periodic_sched_ready;
278
279    /**
280     * List of periodic QHs to be executed in the next frame that are
281     * assigned to host channels.
282     *
283     * Items move from this list to periodic_sched_queued as the
284     * transactions for the QH are queued to the DWC_otg controller.
285     */
286    struct list_head periodic_sched_assigned;
287
288    /**
289     * List of periodic QHs that have been queued for execution.
290     *
291     * Items move from this list to either periodic_sched_inactive or
292     * periodic_sched_ready when the channel associated with the transfer
293     * is released. If the interval for the QH is 1, the item moves to
294     * periodic_sched_ready because it must be rescheduled for the next
295     * frame. Otherwise, the item moves to periodic_sched_inactive.
296     */
297    struct list_head periodic_sched_queued;
298
299    /**
300     * Total bandwidth claimed so far for periodic transfers. This value
301     * is in microseconds per (micro)frame. The assumption is that all
302     * periodic transfers may occur in the same (micro)frame.
303     */
304    uint16_t periodic_usecs;
305
306    /*
307     * Total bandwidth claimed so far for all periodic transfers
308     * in a frame.
309     * This will include a mixture of HS and FS transfers.
310     * Units are microseconds per (micro)frame.
311     * We have a budget per frame and have to schedule
312     * transactions accordingly.
313     * Watch out for the fact that things are actually scheduled for the
314     * "next frame".
315     */
316    u16 frame_usecs[8];
317
318    /**
319     * Frame number read from the core at SOF. The value ranges from 0 to
320     * DWC_HFNUM_MAX_FRNUM.
321     */
322    uint16_t frame_number;
323
324    /**
325     * Free host channels in the controller. This is a list of
326     * dwc_hc_t items.
327     */
328    struct list_head free_hc_list;
329
330    /**
331     * Number of host channels assigned to periodic transfers. Currently
332     * assuming that there is a dedicated host channel for each periodic
333     * transaction and at least one host channel available for
334     * non-periodic transactions.
335     */
336    int periodic_channels;
337
338    /**
339     * Number of host channels assigned to non-periodic transfers.
340     */
341    int non_periodic_channels;
342
343    /**
344     * Array of pointers to the host channel descriptors. Allows accessing
345     * a host channel descriptor given the host channel number. This is
346     * useful in interrupt handlers.
347     */
348    dwc_hc_t *hc_ptr_array[MAX_EPS_CHANNELS];
349
350    /**
351     * Buffer to use for any data received during the status phase of a
352     * control transfer. Normally no data is transferred during the status
353     * phase. This buffer is used as a bit bucket.
354     */
355    uint8_t *status_buf;
356
357    /**
358     * DMA address for status_buf.
359     */
360    dma_addr_t status_buf_dma;
361#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
362
363    /**
364     * Structure to allow starting the HCD in a non-interrupt context
365     * during an OTG role change.
366     */
367    struct delayed_work start_work;
368
369    /**
370     * Connection timer. An OTG host must display a message if the device
371     * does not connect. Started when the VBus power is turned on via
372     * sysfs attribute "buspower".
373     */
374    struct timer_list conn_timer;
375
376    /* Tasket to do a reset */
377    struct tasklet_struct *reset_tasklet;
378
379    /* */
380    spinlock_t lock;
381
382#ifdef DEBUG
383    uint32_t frrem_samples;
384    uint64_t frrem_accum;
385
386    uint32_t hfnum_7_samples_a;
387    uint64_t hfnum_7_frrem_accum_a;
388    uint32_t hfnum_0_samples_a;
389    uint64_t hfnum_0_frrem_accum_a;
390    uint32_t hfnum_other_samples_a;
391    uint64_t hfnum_other_frrem_accum_a;
392
393    uint32_t hfnum_7_samples_b;
394    uint64_t hfnum_7_frrem_accum_b;
395    uint32_t hfnum_0_samples_b;
396    uint64_t hfnum_0_frrem_accum_b;
397    uint32_t hfnum_other_samples_b;
398    uint64_t hfnum_other_frrem_accum_b;
399#endif
400} dwc_otg_hcd_t;
401
402/** Gets the dwc_otg_hcd from a struct usb_hcd */
403static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
404{
405    return (dwc_otg_hcd_t *)(hcd->hcd_priv);
406}
407
408/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
409static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t *dwc_otg_hcd)
410{
411    return container_of((void *)dwc_otg_hcd, struct usb_hcd, hcd_priv);
412}
413
414/** @name HCD Create/Destroy Functions */
415/** @{ */
416extern int dwc_otg_hcd_init(struct platform_device *pdev);
417extern void dwc_otg_hcd_remove(struct platform_device *pdev);
418/** @} */
419
420/** @name Linux HC Driver API Functions */
421/** @{ */
422
423extern int dwc_otg_hcd_start(struct usb_hcd *hcd);
424extern void dwc_otg_hcd_stop(struct usb_hcd *hcd);
425extern int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd);
426extern void dwc_otg_hcd_free(struct usb_hcd *hcd);
427extern int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd,
428                // struct usb_host_endpoint *ep,
429                   struct urb *urb,
430                   gfp_t mem_flags
431                  );
432extern int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd,
433                   struct urb *urb, int status);
434extern void dwc_otg_hcd_endpoint_disable(struct usb_hcd *hcd,
435                     struct usb_host_endpoint *ep);
436extern irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
437extern int dwc_otg_hcd_hub_status_data(struct usb_hcd *hcd,
438                       char *buf);
439extern int dwc_otg_hcd_hub_control(struct usb_hcd *hcd,
440                   u16 typeReq,
441                   u16 wValue,
442                   u16 wIndex,
443                   char *buf,
444                   u16 wLength);
445
446/** @} */
447
448/** @name Transaction Execution Functions */
449/** @{ */
450extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t *hcd);
451extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *hcd,
452                       dwc_otg_transaction_type_e tr_type);
453extern void dwc_otg_hcd_complete_urb(dwc_otg_hcd_t *_hcd, struct urb *urb,
454                     int status);
455/** @} */
456
457/** @name Interrupt Handler Functions */
458/** @{ */
459extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t *dwc_otg_hcd);
460extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t *dwc_otg_hcd);
461extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *dwc_otg_hcd);
462extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *dwc_otg_hcd);
463extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *dwc_otg_hcd);
464extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *dwc_otg_hcd);
465extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t *dwc_otg_hcd);
466extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *dwc_otg_hcd);
467extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t *dwc_otg_hcd);
468extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t *dwc_otg_hcd);
469extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t *dwc_otg_hcd, uint32_t num);
470extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t *dwc_otg_hcd);
471extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *dwc_otg_hcd);
472/** @} */
473
474
475/** @name Schedule Queue Functions */
476/** @{ */
477
478/* Implemented in dwc_otg_hcd_queue.c */
479extern int init_hcd_usecs(dwc_otg_hcd_t *hcd);
480extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t *hcd, struct urb *urb);
481extern void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, struct urb *urb);
482extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
483extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
484extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
485extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, int sched_csplit);
486
487/** Remove and free a QH */
488static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t *hcd,
489                          dwc_otg_qh_t *qh)
490{
491    dwc_otg_hcd_qh_remove(hcd, qh);
492    dwc_otg_hcd_qh_free(hcd, qh);
493}
494
495/** Allocates memory for a QH structure.
496 * @return Returns the memory allocate or NULL on error. */
497static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(void)
498{
499    return (dwc_otg_qh_t *) kmalloc(sizeof(dwc_otg_qh_t), GFP_KERNEL);
500}
501
502extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(struct urb *urb);
503extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t *qtd, struct urb *urb);
504extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *qtd, dwc_otg_hcd_t *dwc_otg_hcd);
505
506/** Allocates memory for a QTD structure.
507 * @return Returns the memory allocate or NULL on error. */
508static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void)
509{
510    return (dwc_otg_qtd_t *) kmalloc(sizeof(dwc_otg_qtd_t), GFP_KERNEL);
511}
512
513/** Frees the memory for a QTD structure. QTD should already be removed from
514 * list.
515 * @param[in] qtd QTD to free.*/
516static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t *qtd)
517{
518    kfree(qtd);
519}
520
521/** Remove and free a QTD */
522static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t *hcd, dwc_otg_qtd_t *qtd)
523{
524    list_del(&qtd->qtd_list_entry);
525    dwc_otg_hcd_qtd_free(qtd);
526}
527
528/** @} */
529
530
531/** @name Internal Functions */
532/** @{ */
533dwc_otg_qh_t *dwc_urb_to_qh(struct urb *urb);
534void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t *hcd);
535void dwc_otg_hcd_dump_state(dwc_otg_hcd_t *hcd);
536/** @} */
537
538/** Gets the usb_host_endpoint associated with an URB. */
539static inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
540{
541    struct usb_device *dev = urb->dev;
542    int ep_num = usb_pipeendpoint(urb->pipe);
543
544    if (usb_pipein(urb->pipe))
545        return dev->ep_in[ep_num];
546    else
547        return dev->ep_out[ep_num];
548}
549
550/**
551 * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
552 * qualified with its direction (possible 32 endpoints per device).
553 */
554#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
555                             ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
556
557/** Gets the QH that contains the list_head */
558#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
559
560/** Gets the QTD that contains the list_head */
561#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
562
563/** Check if QH is non-periodic */
564#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == USB_ENDPOINT_XFER_BULK) || \
565                     (_qh_ptr_->ep_type == USB_ENDPOINT_XFER_CONTROL))
566
567/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
568#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
569
570/** Packet size for any kind of endpoint descriptor */
571#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
572
573/**
574 * Returns true if _frame1 is less than or equal to _frame2. The comparison is
575 * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
576 * frame number when the max frame number is reached.
577 */
578static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
579{
580    return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
581        (DWC_HFNUM_MAX_FRNUM >> 1);
582}
583
584/**
585 * Returns true if _frame1 is greater than _frame2. The comparison is done
586 * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
587 * number when the max frame number is reached.
588 */
589static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
590{
591    return (frame1 != frame2) &&
592        (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
593         (DWC_HFNUM_MAX_FRNUM >> 1));
594}
595
596/**
597 * Increments _frame by the amount specified by _inc. The addition is done
598 * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
599 */
600static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
601{
602    return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
603}
604
605static inline uint16_t dwc_full_frame_num(uint16_t frame)
606{
607    return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
608}
609
610static inline uint16_t dwc_micro_frame_num(uint16_t frame)
611{
612    return frame & 0x7;
613}
614
615#ifdef DEBUG
616/**
617 * Macro to sample the remaining PHY clocks left in the current frame. This
618 * may be used during debugging to determine the average time it takes to
619 * execute sections of code. There are two possible sample points, "a" and
620 * "b", so the _letter argument must be one of these values.
621 *
622 * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
623 * example, "cat /sys/devices/lm0/hcd_frrem".
624 */
625#define dwc_sample_frrem(_hcd, _qh, _letter) \
626{ \
627    hfnum_data_t hfnum; \
628    dwc_otg_qtd_t *qtd; \
629    qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
630    if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
631        hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
632        switch (hfnum.b.frnum & 0x7) { \
633        case 7: \
634            _hcd->hfnum_7_samples_##_letter++; \
635            _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
636            break; \
637        case 0: \
638            _hcd->hfnum_0_samples_##_letter++; \
639            _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
640            break; \
641        default: \
642            _hcd->hfnum_other_samples_##_letter++; \
643            _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
644            break; \
645        } \
646    } \
647}
648#else
649#define dwc_sample_frrem(_hcd, _qh, _letter)
650#endif
651#endif
652#endif /* DWC_DEVICE_ONLY */
653

Archive Download this file



interactive