xref: /openbmc/linux/drivers/usb/dwc2/hcd.h (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1b0d84e45SNishad Kamdar /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
2197ba5f4SPaul Zimmerman /*
3197ba5f4SPaul Zimmerman  * hcd.h - DesignWare HS OTG Controller host-mode declarations
4197ba5f4SPaul Zimmerman  *
5197ba5f4SPaul Zimmerman  * Copyright (C) 2004-2013 Synopsys, Inc.
6197ba5f4SPaul Zimmerman  */
7*b4e05668SChristophe JAILLET 
8197ba5f4SPaul Zimmerman #ifndef __DWC2_HCD_H__
9197ba5f4SPaul Zimmerman #define __DWC2_HCD_H__
10197ba5f4SPaul Zimmerman 
11197ba5f4SPaul Zimmerman /*
12197ba5f4SPaul Zimmerman  * This file contains the structures, constants, and interfaces for the
13197ba5f4SPaul Zimmerman  * Host Contoller Driver (HCD)
14197ba5f4SPaul Zimmerman  *
15197ba5f4SPaul Zimmerman  * The Host Controller Driver (HCD) is responsible for translating requests
16197ba5f4SPaul Zimmerman  * from the USB Driver into the appropriate actions on the DWC_otg controller.
17197ba5f4SPaul Zimmerman  * It isolates the USBD from the specifics of the controller by providing an
18197ba5f4SPaul Zimmerman  * API to the USBD.
19197ba5f4SPaul Zimmerman  */
20197ba5f4SPaul Zimmerman 
21197ba5f4SPaul Zimmerman struct dwc2_qh;
22197ba5f4SPaul Zimmerman 
23197ba5f4SPaul Zimmerman /**
24197ba5f4SPaul Zimmerman  * struct dwc2_host_chan - Software host channel descriptor
25197ba5f4SPaul Zimmerman  *
26197ba5f4SPaul Zimmerman  * @hc_num:             Host channel number, used for register address lookup
27197ba5f4SPaul Zimmerman  * @dev_addr:           Address of the device
28197ba5f4SPaul Zimmerman  * @ep_num:             Endpoint of the device
29197ba5f4SPaul Zimmerman  * @ep_is_in:           Endpoint direction
30197ba5f4SPaul Zimmerman  * @speed:              Device speed. One of the following values:
31197ba5f4SPaul Zimmerman  *                       - USB_SPEED_LOW
32197ba5f4SPaul Zimmerman  *                       - USB_SPEED_FULL
33197ba5f4SPaul Zimmerman  *                       - USB_SPEED_HIGH
34197ba5f4SPaul Zimmerman  * @ep_type:            Endpoint type. One of the following values:
35197ba5f4SPaul Zimmerman  *                       - USB_ENDPOINT_XFER_CONTROL: 0
36197ba5f4SPaul Zimmerman  *                       - USB_ENDPOINT_XFER_ISOC:    1
37197ba5f4SPaul Zimmerman  *                       - USB_ENDPOINT_XFER_BULK:    2
38197ba5f4SPaul Zimmerman  *                       - USB_ENDPOINT_XFER_INTR:    3
39197ba5f4SPaul Zimmerman  * @max_packet:         Max packet size in bytes
40197ba5f4SPaul Zimmerman  * @data_pid_start:     PID for initial transaction.
41197ba5f4SPaul Zimmerman  *                       0: DATA0
42197ba5f4SPaul Zimmerman  *                       1: DATA2
43197ba5f4SPaul Zimmerman  *                       2: DATA1
44197ba5f4SPaul Zimmerman  *                       3: MDATA (non-Control EP),
45197ba5f4SPaul Zimmerman  *                          SETUP (Control EP)
46197ba5f4SPaul Zimmerman  * @multi_count:        Number of additional periodic transactions per
47197ba5f4SPaul Zimmerman  *                      (micro)frame
48197ba5f4SPaul Zimmerman  * @xfer_buf:           Pointer to current transfer buffer position
49197ba5f4SPaul Zimmerman  * @xfer_dma:           DMA address of xfer_buf
50af424a41SWilliam Wu  * @align_buf:          In Buffer DMA mode this will be used if xfer_buf is not
51af424a41SWilliam Wu  *                      DWORD aligned
52197ba5f4SPaul Zimmerman  * @xfer_len:           Total number of bytes to transfer
53197ba5f4SPaul Zimmerman  * @xfer_count:         Number of bytes transferred so far
54197ba5f4SPaul Zimmerman  * @start_pkt_count:    Packet count at start of transfer
55197ba5f4SPaul Zimmerman  * @xfer_started:       True if the transfer has been started
566fb914d7SGrigor Tovmasyan  * @do_ping:            True if a PING request should be issued on this channel
57197ba5f4SPaul Zimmerman  * @error_state:        True if the error count for this transaction is non-zero
58197ba5f4SPaul Zimmerman  * @halt_on_queue:      True if this channel should be halted the next time a
59197ba5f4SPaul Zimmerman  *                      request is queued for the channel. This is necessary in
60197ba5f4SPaul Zimmerman  *                      slave mode if no request queue space is available when
61197ba5f4SPaul Zimmerman  *                      an attempt is made to halt the channel.
62197ba5f4SPaul Zimmerman  * @halt_pending:       True if the host channel has been halted, but the core
63197ba5f4SPaul Zimmerman  *                      is not finished flushing queued requests
64197ba5f4SPaul Zimmerman  * @do_split:           Enable split for the channel
65197ba5f4SPaul Zimmerman  * @complete_split:     Enable complete split
66197ba5f4SPaul Zimmerman  * @hub_addr:           Address of high speed hub for the split
67197ba5f4SPaul Zimmerman  * @hub_port:           Port of the low/full speed device for the split
68197ba5f4SPaul Zimmerman  * @xact_pos:           Split transaction position. One of the following values:
69197ba5f4SPaul Zimmerman  *                       - DWC2_HCSPLT_XACTPOS_MID
70197ba5f4SPaul Zimmerman  *                       - DWC2_HCSPLT_XACTPOS_BEGIN
71197ba5f4SPaul Zimmerman  *                       - DWC2_HCSPLT_XACTPOS_END
72197ba5f4SPaul Zimmerman  *                       - DWC2_HCSPLT_XACTPOS_ALL
73197ba5f4SPaul Zimmerman  * @requests:           Number of requests issued for this channel since it was
74197ba5f4SPaul Zimmerman  *                      assigned to the current transfer (not counting PINGs)
75197ba5f4SPaul Zimmerman  * @schinfo:            Scheduling micro-frame bitmap
76197ba5f4SPaul Zimmerman  * @ntd:                Number of transfer descriptors for the transfer
77197ba5f4SPaul Zimmerman  * @halt_status:        Reason for halting the host channel
786fb914d7SGrigor Tovmasyan  * @hcint:               Contents of the HCINT register when the interrupt came
79197ba5f4SPaul Zimmerman  * @qh:                 QH for the transfer being processed by this channel
80197ba5f4SPaul Zimmerman  * @hc_list_entry:      For linking to list of host channels
81197ba5f4SPaul Zimmerman  * @desc_list_addr:     Current QH's descriptor list DMA address
8295105a99SGregory Herrero  * @desc_list_sz:       Current QH's descriptor list size
83c9c8ac01SDouglas Anderson  * @split_order_list_entry: List entry for keeping track of the order of splits
84197ba5f4SPaul Zimmerman  *
85197ba5f4SPaul Zimmerman  * This structure represents the state of a single host channel when acting in
86197ba5f4SPaul Zimmerman  * host mode. It contains the data items needed to transfer packets to an
87197ba5f4SPaul Zimmerman  * endpoint via a host channel.
88197ba5f4SPaul Zimmerman  */
89197ba5f4SPaul Zimmerman struct dwc2_host_chan {
90197ba5f4SPaul Zimmerman 	u8 hc_num;
91197ba5f4SPaul Zimmerman 
92197ba5f4SPaul Zimmerman 	unsigned dev_addr:7;
93197ba5f4SPaul Zimmerman 	unsigned ep_num:4;
94197ba5f4SPaul Zimmerman 	unsigned ep_is_in:1;
95197ba5f4SPaul Zimmerman 	unsigned speed:4;
96197ba5f4SPaul Zimmerman 	unsigned ep_type:2;
97197ba5f4SPaul Zimmerman 	unsigned max_packet:11;
98197ba5f4SPaul Zimmerman 	unsigned data_pid_start:2;
99197ba5f4SPaul Zimmerman #define DWC2_HC_PID_DATA0	TSIZ_SC_MC_PID_DATA0
100197ba5f4SPaul Zimmerman #define DWC2_HC_PID_DATA2	TSIZ_SC_MC_PID_DATA2
101197ba5f4SPaul Zimmerman #define DWC2_HC_PID_DATA1	TSIZ_SC_MC_PID_DATA1
102197ba5f4SPaul Zimmerman #define DWC2_HC_PID_MDATA	TSIZ_SC_MC_PID_MDATA
103197ba5f4SPaul Zimmerman #define DWC2_HC_PID_SETUP	TSIZ_SC_MC_PID_SETUP
104197ba5f4SPaul Zimmerman 
105197ba5f4SPaul Zimmerman 	unsigned multi_count:2;
106197ba5f4SPaul Zimmerman 
107197ba5f4SPaul Zimmerman 	u8 *xfer_buf;
108197ba5f4SPaul Zimmerman 	dma_addr_t xfer_dma;
109af424a41SWilliam Wu 	dma_addr_t align_buf;
110197ba5f4SPaul Zimmerman 	u32 xfer_len;
111197ba5f4SPaul Zimmerman 	u32 xfer_count;
112197ba5f4SPaul Zimmerman 	u16 start_pkt_count;
113197ba5f4SPaul Zimmerman 	u8 xfer_started;
114197ba5f4SPaul Zimmerman 	u8 do_ping;
115197ba5f4SPaul Zimmerman 	u8 error_state;
116197ba5f4SPaul Zimmerman 	u8 halt_on_queue;
117197ba5f4SPaul Zimmerman 	u8 halt_pending;
118197ba5f4SPaul Zimmerman 	u8 do_split;
119197ba5f4SPaul Zimmerman 	u8 complete_split;
120197ba5f4SPaul Zimmerman 	u8 hub_addr;
121197ba5f4SPaul Zimmerman 	u8 hub_port;
122197ba5f4SPaul Zimmerman 	u8 xact_pos;
123197ba5f4SPaul Zimmerman #define DWC2_HCSPLT_XACTPOS_MID	HCSPLT_XACTPOS_MID
124197ba5f4SPaul Zimmerman #define DWC2_HCSPLT_XACTPOS_END	HCSPLT_XACTPOS_END
125197ba5f4SPaul Zimmerman #define DWC2_HCSPLT_XACTPOS_BEGIN HCSPLT_XACTPOS_BEGIN
126197ba5f4SPaul Zimmerman #define DWC2_HCSPLT_XACTPOS_ALL	HCSPLT_XACTPOS_ALL
127197ba5f4SPaul Zimmerman 
128197ba5f4SPaul Zimmerman 	u8 requests;
129197ba5f4SPaul Zimmerman 	u8 schinfo;
130197ba5f4SPaul Zimmerman 	u16 ntd;
131197ba5f4SPaul Zimmerman 	enum dwc2_halt_status halt_status;
132197ba5f4SPaul Zimmerman 	u32 hcint;
133197ba5f4SPaul Zimmerman 	struct dwc2_qh *qh;
134197ba5f4SPaul Zimmerman 	struct list_head hc_list_entry;
135197ba5f4SPaul Zimmerman 	dma_addr_t desc_list_addr;
13695105a99SGregory Herrero 	u32 desc_list_sz;
137c9c8ac01SDouglas Anderson 	struct list_head split_order_list_entry;
138197ba5f4SPaul Zimmerman };
139197ba5f4SPaul Zimmerman 
140197ba5f4SPaul Zimmerman struct dwc2_hcd_pipe_info {
141197ba5f4SPaul Zimmerman 	u8 dev_addr;
142197ba5f4SPaul Zimmerman 	u8 ep_num;
143197ba5f4SPaul Zimmerman 	u8 pipe_type;
144197ba5f4SPaul Zimmerman 	u8 pipe_dir;
145babd1839SDouglas Anderson 	u16 maxp;
146babd1839SDouglas Anderson 	u16 maxp_mult;
147197ba5f4SPaul Zimmerman };
148197ba5f4SPaul Zimmerman 
149197ba5f4SPaul Zimmerman struct dwc2_hcd_iso_packet_desc {
150197ba5f4SPaul Zimmerman 	u32 offset;
151197ba5f4SPaul Zimmerman 	u32 length;
152197ba5f4SPaul Zimmerman 	u32 actual_length;
153197ba5f4SPaul Zimmerman 	u32 status;
154197ba5f4SPaul Zimmerman };
155197ba5f4SPaul Zimmerman 
156197ba5f4SPaul Zimmerman struct dwc2_qtd;
157197ba5f4SPaul Zimmerman 
158197ba5f4SPaul Zimmerman struct dwc2_hcd_urb {
159197ba5f4SPaul Zimmerman 	void *priv;
160197ba5f4SPaul Zimmerman 	struct dwc2_qtd *qtd;
161197ba5f4SPaul Zimmerman 	void *buf;
162197ba5f4SPaul Zimmerman 	dma_addr_t dma;
163197ba5f4SPaul Zimmerman 	void *setup_packet;
164197ba5f4SPaul Zimmerman 	dma_addr_t setup_dma;
165197ba5f4SPaul Zimmerman 	u32 length;
166197ba5f4SPaul Zimmerman 	u32 actual_length;
167197ba5f4SPaul Zimmerman 	u32 status;
168197ba5f4SPaul Zimmerman 	u32 error_count;
169197ba5f4SPaul Zimmerman 	u32 packet_count;
170197ba5f4SPaul Zimmerman 	u32 flags;
171197ba5f4SPaul Zimmerman 	u16 interval;
172197ba5f4SPaul Zimmerman 	struct dwc2_hcd_pipe_info pipe_info;
1736bc3f397SGustavo A. R. Silva 	struct dwc2_hcd_iso_packet_desc iso_descs[];
174197ba5f4SPaul Zimmerman };
175197ba5f4SPaul Zimmerman 
176197ba5f4SPaul Zimmerman /* Phases for control transfers */
177197ba5f4SPaul Zimmerman enum dwc2_control_phase {
178197ba5f4SPaul Zimmerman 	DWC2_CONTROL_SETUP,
179197ba5f4SPaul Zimmerman 	DWC2_CONTROL_DATA,
180197ba5f4SPaul Zimmerman 	DWC2_CONTROL_STATUS,
181197ba5f4SPaul Zimmerman };
182197ba5f4SPaul Zimmerman 
183197ba5f4SPaul Zimmerman /* Transaction types */
184197ba5f4SPaul Zimmerman enum dwc2_transaction_type {
185197ba5f4SPaul Zimmerman 	DWC2_TRANSACTION_NONE,
186197ba5f4SPaul Zimmerman 	DWC2_TRANSACTION_PERIODIC,
187197ba5f4SPaul Zimmerman 	DWC2_TRANSACTION_NON_PERIODIC,
188197ba5f4SPaul Zimmerman 	DWC2_TRANSACTION_ALL,
189197ba5f4SPaul Zimmerman };
190197ba5f4SPaul Zimmerman 
1919f9f09b0SDouglas Anderson /* The number of elements per LS bitmap (per port on multi_tt) */
1929f9f09b0SDouglas Anderson #define DWC2_ELEMENTS_PER_LS_BITMAP	DIV_ROUND_UP(DWC2_LS_SCHEDULE_SLICES, \
1939f9f09b0SDouglas Anderson 						     BITS_PER_LONG)
1949f9f09b0SDouglas Anderson 
1959f9f09b0SDouglas Anderson /**
1969f9f09b0SDouglas Anderson  * struct dwc2_tt - dwc2 data associated with a usb_tt
1979f9f09b0SDouglas Anderson  *
1989f9f09b0SDouglas Anderson  * @refcount:           Number of Queue Heads (QHs) holding a reference.
1999f9f09b0SDouglas Anderson  * @usb_tt:             Pointer back to the official usb_tt.
2009f9f09b0SDouglas Anderson  * @periodic_bitmaps:   Bitmap for which parts of the 1ms frame are accounted
2019f9f09b0SDouglas Anderson  *                      for already.  Each is DWC2_ELEMENTS_PER_LS_BITMAP
2029f9f09b0SDouglas Anderson  *			elements (so sizeof(long) times that in bytes).
2039f9f09b0SDouglas Anderson  *
2049f9f09b0SDouglas Anderson  * This structure is stored in the hcpriv of the official usb_tt.
2059f9f09b0SDouglas Anderson  */
2069f9f09b0SDouglas Anderson struct dwc2_tt {
2079f9f09b0SDouglas Anderson 	int refcount;
2089f9f09b0SDouglas Anderson 	struct usb_tt *usb_tt;
2099f9f09b0SDouglas Anderson 	unsigned long periodic_bitmaps[];
2109f9f09b0SDouglas Anderson };
2119f9f09b0SDouglas Anderson 
2129f9f09b0SDouglas Anderson /**
2139f9f09b0SDouglas Anderson  * struct dwc2_hs_transfer_time - Info about a transfer on the high speed bus.
2149f9f09b0SDouglas Anderson  *
2156fb914d7SGrigor Tovmasyan  * @start_schedule_us:  The start time on the main bus schedule.  Note that
2169f9f09b0SDouglas Anderson  *                         the main bus schedule is tightly packed and this
2179f9f09b0SDouglas Anderson  *			   time should be interpreted as tightly packed (so
2189f9f09b0SDouglas Anderson  *			   uFrame 0 starts at 0 us, uFrame 1 starts at 100 us
2199f9f09b0SDouglas Anderson  *			   instead of 125 us).
2209f9f09b0SDouglas Anderson  * @duration_us:           How long this transfer goes.
2219f9f09b0SDouglas Anderson  */
2229f9f09b0SDouglas Anderson 
2239f9f09b0SDouglas Anderson struct dwc2_hs_transfer_time {
2249f9f09b0SDouglas Anderson 	u32 start_schedule_us;
2259f9f09b0SDouglas Anderson 	u16 duration_us;
2269f9f09b0SDouglas Anderson };
2279f9f09b0SDouglas Anderson 
228197ba5f4SPaul Zimmerman /**
229197ba5f4SPaul Zimmerman  * struct dwc2_qh - Software queue head structure
230197ba5f4SPaul Zimmerman  *
23117dd5b64SDouglas Anderson  * @hsotg:              The HCD state structure for the DWC OTG controller
232197ba5f4SPaul Zimmerman  * @ep_type:            Endpoint type. One of the following values:
233197ba5f4SPaul Zimmerman  *                       - USB_ENDPOINT_XFER_CONTROL
234197ba5f4SPaul Zimmerman  *                       - USB_ENDPOINT_XFER_BULK
235197ba5f4SPaul Zimmerman  *                       - USB_ENDPOINT_XFER_INT
236197ba5f4SPaul Zimmerman  *                       - USB_ENDPOINT_XFER_ISOC
237197ba5f4SPaul Zimmerman  * @ep_is_in:           Endpoint direction
238197ba5f4SPaul Zimmerman  * @maxp:               Value from wMaxPacketSize field of Endpoint Descriptor
239babd1839SDouglas Anderson  * @maxp_mult:          Multiplier for maxp
240197ba5f4SPaul Zimmerman  * @dev_speed:          Device speed. One of the following values:
241197ba5f4SPaul Zimmerman  *                       - USB_SPEED_LOW
242197ba5f4SPaul Zimmerman  *                       - USB_SPEED_FULL
243197ba5f4SPaul Zimmerman  *                       - USB_SPEED_HIGH
244197ba5f4SPaul Zimmerman  * @data_toggle:        Determines the PID of the next data packet for
245197ba5f4SPaul Zimmerman  *                      non-controltransfers. Ignored for control transfers.
246197ba5f4SPaul Zimmerman  *                      One of the following values:
247197ba5f4SPaul Zimmerman  *                       - DWC2_HC_PID_DATA0
248197ba5f4SPaul Zimmerman  *                       - DWC2_HC_PID_DATA1
249197ba5f4SPaul Zimmerman  * @ping_state:         Ping state
250197ba5f4SPaul Zimmerman  * @do_split:           Full/low speed endpoint on high-speed hub requires split
251197ba5f4SPaul Zimmerman  * @td_first:           Index of first activated isochronous transfer descriptor
252197ba5f4SPaul Zimmerman  * @td_last:            Index of last activated isochronous transfer descriptor
253ced9eee1SDouglas Anderson  * @host_us:            Bandwidth in microseconds per transfer as seen by host
2549f9f09b0SDouglas Anderson  * @device_us:          Bandwidth in microseconds per transfer as seen by device
255ced9eee1SDouglas Anderson  * @host_interval:      Interval between transfers as seen by the host.  If
256ced9eee1SDouglas Anderson  *                      the host is high speed and the device is low speed this
257ced9eee1SDouglas Anderson  *                      will be 8 times device interval.
2589f9f09b0SDouglas Anderson  * @device_interval:    Interval between transfers as seen by the device.
2599f9f09b0SDouglas Anderson  *                      interval.
2609f9f09b0SDouglas Anderson  * @next_active_frame:  (Micro)frame _before_ we next need to put something on
261ced9eee1SDouglas Anderson  *                      the bus.  We'll move the qh to active here.  If the
262ced9eee1SDouglas Anderson  *                      host is in high speed mode this will be a uframe.  If
263ced9eee1SDouglas Anderson  *                      the host is in low speed mode this will be a full frame.
264fb616e3fSDouglas Anderson  * @start_active_frame: If we are partway through a split transfer, this will be
265fb616e3fSDouglas Anderson  *			what next_active_frame was when we started.  Otherwise
266fb616e3fSDouglas Anderson  *			it should always be the same as next_active_frame.
2679f9f09b0SDouglas Anderson  * @num_hs_transfers:   Number of transfers in hs_transfers.
2689f9f09b0SDouglas Anderson  *                      Normally this is 1 but can be more than one for splits.
2699f9f09b0SDouglas Anderson  *                      Always >= 1 unless the host is in low/full speed mode.
2709f9f09b0SDouglas Anderson  * @hs_transfers:       Transfers that are scheduled as seen by the high speed
2719f9f09b0SDouglas Anderson  *                      bus.  Not used if host is in low or full speed mode (but
2729f9f09b0SDouglas Anderson  *                      note that it IS USED if the device is low or full speed
2739f9f09b0SDouglas Anderson  *                      as long as the HOST is in high speed mode).
2749f9f09b0SDouglas Anderson  * @ls_start_schedule_slice: Start time (in slices) on the low speed bus
2759f9f09b0SDouglas Anderson  *                           schedule that's being used by this device.  This
2769f9f09b0SDouglas Anderson  *			     will be on the periodic_bitmap in a
2779f9f09b0SDouglas Anderson  *                           "struct dwc2_tt".  Not used if this device is high
2789f9f09b0SDouglas Anderson  *                           speed.  Note that this is in "schedule slice" which
2799f9f09b0SDouglas Anderson  *                           is tightly packed.
280197ba5f4SPaul Zimmerman  * @ntd:                Actual number of transfer descriptors in a list
281af424a41SWilliam Wu  * @dw_align_buf:       Used instead of original buffer if its physical address
282af424a41SWilliam Wu  *                      is not dword-aligned
283af424a41SWilliam Wu  * @dw_align_buf_dma:   DMA address for dw_align_buf
284197ba5f4SPaul Zimmerman  * @qtd_list:           List of QTDs for this QH
285197ba5f4SPaul Zimmerman  * @channel:            Host channel currently processing transfers for this QH
286197ba5f4SPaul Zimmerman  * @qh_list_entry:      Entry for QH in either the periodic or non-periodic
287197ba5f4SPaul Zimmerman  *                      schedule
288197ba5f4SPaul Zimmerman  * @desc_list:          List of transfer descriptors
289197ba5f4SPaul Zimmerman  * @desc_list_dma:      Physical address of desc_list
29095105a99SGregory Herrero  * @desc_list_sz:       Size of descriptors list
291197ba5f4SPaul Zimmerman  * @n_bytes:            Xfer Bytes array. Each element corresponds to a transfer
292197ba5f4SPaul Zimmerman  *                      descriptor and indicates original XferSize value for the
293197ba5f4SPaul Zimmerman  *                      descriptor
29417dd5b64SDouglas Anderson  * @unreserve_timer:    Timer for releasing periodic reservation.
29538d2b5fbSDouglas Anderson  * @wait_timer:         Timer used to wait before re-queuing.
2966fb914d7SGrigor Tovmasyan  * @dwc_tt:            Pointer to our tt info (or NULL if no tt).
2979f9f09b0SDouglas Anderson  * @ttport:             Port number within our tt.
298197ba5f4SPaul Zimmerman  * @tt_buffer_dirty     True if clear_tt_buffer_complete is pending
29917dd5b64SDouglas Anderson  * @unreserve_pending:  True if we planned to unreserve but haven't yet.
3009f9f09b0SDouglas Anderson  * @schedule_low_speed: True if we have a low/full speed component (either the
3019f9f09b0SDouglas Anderson  *			host is in low/full speed mode or do_split).
30238d2b5fbSDouglas Anderson  * @want_wait:          We should wait before re-queuing; only matters for non-
30338d2b5fbSDouglas Anderson  *                      periodic transfers and is ignored for periodic ones.
30438d2b5fbSDouglas Anderson  * @wait_timer_cancel:  Set to true to cancel the wait_timer.
305197ba5f4SPaul Zimmerman  *
3066fb914d7SGrigor Tovmasyan  * @tt_buffer_dirty:	True if EP's TT buffer is not clean.
307197ba5f4SPaul Zimmerman  * A Queue Head (QH) holds the static characteristics of an endpoint and
308197ba5f4SPaul Zimmerman  * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
309197ba5f4SPaul Zimmerman  * be entered in either the non-periodic or periodic schedule.
310197ba5f4SPaul Zimmerman  */
311197ba5f4SPaul Zimmerman struct dwc2_qh {
31217dd5b64SDouglas Anderson 	struct dwc2_hsotg *hsotg;
313197ba5f4SPaul Zimmerman 	u8 ep_type;
314197ba5f4SPaul Zimmerman 	u8 ep_is_in;
315197ba5f4SPaul Zimmerman 	u16 maxp;
316babd1839SDouglas Anderson 	u16 maxp_mult;
317197ba5f4SPaul Zimmerman 	u8 dev_speed;
318197ba5f4SPaul Zimmerman 	u8 data_toggle;
319197ba5f4SPaul Zimmerman 	u8 ping_state;
320197ba5f4SPaul Zimmerman 	u8 do_split;
321197ba5f4SPaul Zimmerman 	u8 td_first;
322197ba5f4SPaul Zimmerman 	u8 td_last;
323ced9eee1SDouglas Anderson 	u16 host_us;
3249f9f09b0SDouglas Anderson 	u16 device_us;
325ced9eee1SDouglas Anderson 	u16 host_interval;
3269f9f09b0SDouglas Anderson 	u16 device_interval;
327ced9eee1SDouglas Anderson 	u16 next_active_frame;
328fb616e3fSDouglas Anderson 	u16 start_active_frame;
3299f9f09b0SDouglas Anderson 	s16 num_hs_transfers;
3309f9f09b0SDouglas Anderson 	struct dwc2_hs_transfer_time hs_transfers[DWC2_HS_SCHEDULE_UFRAMES];
3319f9f09b0SDouglas Anderson 	u32 ls_start_schedule_slice;
332197ba5f4SPaul Zimmerman 	u16 ntd;
333af424a41SWilliam Wu 	u8 *dw_align_buf;
334af424a41SWilliam Wu 	dma_addr_t dw_align_buf_dma;
335197ba5f4SPaul Zimmerman 	struct list_head qtd_list;
336197ba5f4SPaul Zimmerman 	struct dwc2_host_chan *channel;
337197ba5f4SPaul Zimmerman 	struct list_head qh_list_entry;
338ec703251SVahram Aharonyan 	struct dwc2_dma_desc *desc_list;
339197ba5f4SPaul Zimmerman 	dma_addr_t desc_list_dma;
34095105a99SGregory Herrero 	u32 desc_list_sz;
341197ba5f4SPaul Zimmerman 	u32 *n_bytes;
34217dd5b64SDouglas Anderson 	struct timer_list unreserve_timer;
3436ed30a7dSTerin Stock 	struct hrtimer wait_timer;
3449f9f09b0SDouglas Anderson 	struct dwc2_tt *dwc_tt;
3459f9f09b0SDouglas Anderson 	int ttport;
346197ba5f4SPaul Zimmerman 	unsigned tt_buffer_dirty:1;
34717dd5b64SDouglas Anderson 	unsigned unreserve_pending:1;
3489f9f09b0SDouglas Anderson 	unsigned schedule_low_speed:1;
34938d2b5fbSDouglas Anderson 	unsigned want_wait:1;
35038d2b5fbSDouglas Anderson 	unsigned wait_timer_cancel:1;
351197ba5f4SPaul Zimmerman };
352197ba5f4SPaul Zimmerman 
353197ba5f4SPaul Zimmerman /**
354197ba5f4SPaul Zimmerman  * struct dwc2_qtd - Software queue transfer descriptor (QTD)
355197ba5f4SPaul Zimmerman  *
356197ba5f4SPaul Zimmerman  * @control_phase:      Current phase for control transfers (Setup, Data, or
357197ba5f4SPaul Zimmerman  *                      Status)
358197ba5f4SPaul Zimmerman  * @in_process:         Indicates if this QTD is currently processed by HW
359197ba5f4SPaul Zimmerman  * @data_toggle:        Determines the PID of the next data packet for the
360197ba5f4SPaul Zimmerman  *                      data phase of control transfers. Ignored for other
361197ba5f4SPaul Zimmerman  *                      transfer types. One of the following values:
362197ba5f4SPaul Zimmerman  *                       - DWC2_HC_PID_DATA0
363197ba5f4SPaul Zimmerman  *                       - DWC2_HC_PID_DATA1
364197ba5f4SPaul Zimmerman  * @complete_split:     Keeps track of the current split type for FS/LS
365197ba5f4SPaul Zimmerman  *                      endpoints on a HS Hub
366197ba5f4SPaul Zimmerman  * @isoc_split_pos:     Position of the ISOC split in full/low speed
367197ba5f4SPaul Zimmerman  * @isoc_frame_index:   Index of the next frame descriptor for an isochronous
368197ba5f4SPaul Zimmerman  *                      transfer. A frame descriptor describes the buffer
369197ba5f4SPaul Zimmerman  *                      position and length of the data to be transferred in the
370197ba5f4SPaul Zimmerman  *                      next scheduled (micro)frame of an isochronous transfer.
371197ba5f4SPaul Zimmerman  *                      It also holds status for that transaction. The frame
372197ba5f4SPaul Zimmerman  *                      index starts at 0.
373197ba5f4SPaul Zimmerman  * @isoc_split_offset:  Position of the ISOC split in the buffer for the
374197ba5f4SPaul Zimmerman  *                      current frame
375197ba5f4SPaul Zimmerman  * @ssplit_out_xfer_count: How many bytes transferred during SSPLIT OUT
376197ba5f4SPaul Zimmerman  * @error_count:        Holds the number of bus errors that have occurred for
377197ba5f4SPaul Zimmerman  *                      a transaction within this transfer
378197ba5f4SPaul Zimmerman  * @n_desc:             Number of DMA descriptors for this QTD
379197ba5f4SPaul Zimmerman  * @isoc_frame_index_last: Last activated frame (packet) index, used in
380197ba5f4SPaul Zimmerman  *                      descriptor DMA mode only
38138d2b5fbSDouglas Anderson  * @num_naks:           Number of NAKs received on this QTD.
382197ba5f4SPaul Zimmerman  * @urb:                URB for this transfer
383197ba5f4SPaul Zimmerman  * @qh:                 Queue head for this QTD
384197ba5f4SPaul Zimmerman  * @qtd_list_entry:     For linking to the QH's list of QTDs
3856fb914d7SGrigor Tovmasyan  * @isoc_td_first:	Index of first activated isochronous transfer
3866fb914d7SGrigor Tovmasyan  *			descriptor in Descriptor DMA mode
3876fb914d7SGrigor Tovmasyan  * @isoc_td_last:	Index of last activated isochronous transfer
3886fb914d7SGrigor Tovmasyan  *			descriptor in Descriptor DMA mode
389197ba5f4SPaul Zimmerman  *
390197ba5f4SPaul Zimmerman  * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
391197ba5f4SPaul Zimmerman  * interrupt, or isochronous transfer. A single QTD is created for each URB
392197ba5f4SPaul Zimmerman  * (of one of these types) submitted to the HCD. The transfer associated with
393197ba5f4SPaul Zimmerman  * a QTD may require one or multiple transactions.
394197ba5f4SPaul Zimmerman  *
395197ba5f4SPaul Zimmerman  * A QTD is linked to a Queue Head, which is entered in either the
396197ba5f4SPaul Zimmerman  * non-periodic or periodic schedule for execution. When a QTD is chosen for
397197ba5f4SPaul Zimmerman  * execution, some or all of its transactions may be executed. After
398197ba5f4SPaul Zimmerman  * execution, the state of the QTD is updated. The QTD may be retired if all
399197ba5f4SPaul Zimmerman  * its transactions are complete or if an error occurred. Otherwise, it
400197ba5f4SPaul Zimmerman  * remains in the schedule so more transactions can be executed later.
401197ba5f4SPaul Zimmerman  */
402197ba5f4SPaul Zimmerman struct dwc2_qtd {
403197ba5f4SPaul Zimmerman 	enum dwc2_control_phase control_phase;
404197ba5f4SPaul Zimmerman 	u8 in_process;
405197ba5f4SPaul Zimmerman 	u8 data_toggle;
406197ba5f4SPaul Zimmerman 	u8 complete_split;
407197ba5f4SPaul Zimmerman 	u8 isoc_split_pos;
408197ba5f4SPaul Zimmerman 	u16 isoc_frame_index;
409197ba5f4SPaul Zimmerman 	u16 isoc_split_offset;
410c17b337cSGregory Herrero 	u16 isoc_td_last;
411c17b337cSGregory Herrero 	u16 isoc_td_first;
412197ba5f4SPaul Zimmerman 	u32 ssplit_out_xfer_count;
413197ba5f4SPaul Zimmerman 	u8 error_count;
414197ba5f4SPaul Zimmerman 	u8 n_desc;
415197ba5f4SPaul Zimmerman 	u16 isoc_frame_index_last;
41638d2b5fbSDouglas Anderson 	u16 num_naks;
417197ba5f4SPaul Zimmerman 	struct dwc2_hcd_urb *urb;
418197ba5f4SPaul Zimmerman 	struct dwc2_qh *qh;
419197ba5f4SPaul Zimmerman 	struct list_head qtd_list_entry;
420197ba5f4SPaul Zimmerman };
421197ba5f4SPaul Zimmerman 
422197ba5f4SPaul Zimmerman #ifdef DEBUG
423197ba5f4SPaul Zimmerman struct hc_xfer_info {
424197ba5f4SPaul Zimmerman 	struct dwc2_hsotg *hsotg;
425197ba5f4SPaul Zimmerman 	struct dwc2_host_chan *chan;
426197ba5f4SPaul Zimmerman };
427197ba5f4SPaul Zimmerman #endif
428197ba5f4SPaul Zimmerman 
429b02038faSJohn Youn u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg);
430b02038faSJohn Youn 
431197ba5f4SPaul Zimmerman /* Gets the struct usb_hcd that contains a struct dwc2_hsotg */
dwc2_hsotg_to_hcd(struct dwc2_hsotg * hsotg)432197ba5f4SPaul Zimmerman static inline struct usb_hcd *dwc2_hsotg_to_hcd(struct dwc2_hsotg *hsotg)
433197ba5f4SPaul Zimmerman {
434197ba5f4SPaul Zimmerman 	return (struct usb_hcd *)hsotg->priv;
435197ba5f4SPaul Zimmerman }
436197ba5f4SPaul Zimmerman 
437197ba5f4SPaul Zimmerman /*
438197ba5f4SPaul Zimmerman  * Inline used to disable one channel interrupt. Channel interrupts are
439197ba5f4SPaul Zimmerman  * disabled when the channel is halted or released by the interrupt handler.
440197ba5f4SPaul Zimmerman  * There is no need to handle further interrupts of that type until the
441197ba5f4SPaul Zimmerman  * channel is re-assigned. In fact, subsequent handling may cause crashes
442197ba5f4SPaul Zimmerman  * because the channel structures are cleaned up when the channel is released.
443197ba5f4SPaul Zimmerman  */
disable_hc_int(struct dwc2_hsotg * hsotg,int chnum,u32 intr)444197ba5f4SPaul Zimmerman static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr)
445197ba5f4SPaul Zimmerman {
446f25c42b8SGevorg Sahakyan 	u32 mask = dwc2_readl(hsotg, HCINTMSK(chnum));
447197ba5f4SPaul Zimmerman 
448197ba5f4SPaul Zimmerman 	mask &= ~intr;
449f25c42b8SGevorg Sahakyan 	dwc2_writel(hsotg, mask, HCINTMSK(chnum));
450197ba5f4SPaul Zimmerman }
451197ba5f4SPaul Zimmerman 
452b02038faSJohn Youn void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan);
453b02038faSJohn Youn void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
454b02038faSJohn Youn 		  enum dwc2_halt_status halt_status);
455b02038faSJohn Youn void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg,
456b02038faSJohn Youn 				 struct dwc2_host_chan *chan);
457b02038faSJohn Youn 
458197ba5f4SPaul Zimmerman /*
459197ba5f4SPaul Zimmerman  * Reads HPRT0 in preparation to modify. It keeps the WC bits 0 so that if they
460197ba5f4SPaul Zimmerman  * are read as 1, they won't clear when written back.
461197ba5f4SPaul Zimmerman  */
dwc2_read_hprt0(struct dwc2_hsotg * hsotg)462197ba5f4SPaul Zimmerman static inline u32 dwc2_read_hprt0(struct dwc2_hsotg *hsotg)
463197ba5f4SPaul Zimmerman {
464f25c42b8SGevorg Sahakyan 	u32 hprt0 = dwc2_readl(hsotg, HPRT0);
465197ba5f4SPaul Zimmerman 
466197ba5f4SPaul Zimmerman 	hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
467197ba5f4SPaul Zimmerman 	return hprt0;
468197ba5f4SPaul Zimmerman }
469197ba5f4SPaul Zimmerman 
dwc2_hcd_get_ep_num(struct dwc2_hcd_pipe_info * pipe)470197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_get_ep_num(struct dwc2_hcd_pipe_info *pipe)
471197ba5f4SPaul Zimmerman {
472197ba5f4SPaul Zimmerman 	return pipe->ep_num;
473197ba5f4SPaul Zimmerman }
474197ba5f4SPaul Zimmerman 
dwc2_hcd_get_pipe_type(struct dwc2_hcd_pipe_info * pipe)475197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_get_pipe_type(struct dwc2_hcd_pipe_info *pipe)
476197ba5f4SPaul Zimmerman {
477197ba5f4SPaul Zimmerman 	return pipe->pipe_type;
478197ba5f4SPaul Zimmerman }
479197ba5f4SPaul Zimmerman 
dwc2_hcd_get_maxp(struct dwc2_hcd_pipe_info * pipe)480babd1839SDouglas Anderson static inline u16 dwc2_hcd_get_maxp(struct dwc2_hcd_pipe_info *pipe)
481197ba5f4SPaul Zimmerman {
482babd1839SDouglas Anderson 	return pipe->maxp;
483babd1839SDouglas Anderson }
484babd1839SDouglas Anderson 
dwc2_hcd_get_maxp_mult(struct dwc2_hcd_pipe_info * pipe)485babd1839SDouglas Anderson static inline u16 dwc2_hcd_get_maxp_mult(struct dwc2_hcd_pipe_info *pipe)
486babd1839SDouglas Anderson {
487babd1839SDouglas Anderson 	return pipe->maxp_mult;
488197ba5f4SPaul Zimmerman }
489197ba5f4SPaul Zimmerman 
dwc2_hcd_get_dev_addr(struct dwc2_hcd_pipe_info * pipe)490197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_get_dev_addr(struct dwc2_hcd_pipe_info *pipe)
491197ba5f4SPaul Zimmerman {
492197ba5f4SPaul Zimmerman 	return pipe->dev_addr;
493197ba5f4SPaul Zimmerman }
494197ba5f4SPaul Zimmerman 
dwc2_hcd_is_pipe_isoc(struct dwc2_hcd_pipe_info * pipe)495197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_is_pipe_isoc(struct dwc2_hcd_pipe_info *pipe)
496197ba5f4SPaul Zimmerman {
497197ba5f4SPaul Zimmerman 	return pipe->pipe_type == USB_ENDPOINT_XFER_ISOC;
498197ba5f4SPaul Zimmerman }
499197ba5f4SPaul Zimmerman 
dwc2_hcd_is_pipe_int(struct dwc2_hcd_pipe_info * pipe)500197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_is_pipe_int(struct dwc2_hcd_pipe_info *pipe)
501197ba5f4SPaul Zimmerman {
502197ba5f4SPaul Zimmerman 	return pipe->pipe_type == USB_ENDPOINT_XFER_INT;
503197ba5f4SPaul Zimmerman }
504197ba5f4SPaul Zimmerman 
dwc2_hcd_is_pipe_bulk(struct dwc2_hcd_pipe_info * pipe)505197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_is_pipe_bulk(struct dwc2_hcd_pipe_info *pipe)
506197ba5f4SPaul Zimmerman {
507197ba5f4SPaul Zimmerman 	return pipe->pipe_type == USB_ENDPOINT_XFER_BULK;
508197ba5f4SPaul Zimmerman }
509197ba5f4SPaul Zimmerman 
dwc2_hcd_is_pipe_control(struct dwc2_hcd_pipe_info * pipe)510197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_is_pipe_control(struct dwc2_hcd_pipe_info *pipe)
511197ba5f4SPaul Zimmerman {
512197ba5f4SPaul Zimmerman 	return pipe->pipe_type == USB_ENDPOINT_XFER_CONTROL;
513197ba5f4SPaul Zimmerman }
514197ba5f4SPaul Zimmerman 
dwc2_hcd_is_pipe_in(struct dwc2_hcd_pipe_info * pipe)515197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_is_pipe_in(struct dwc2_hcd_pipe_info *pipe)
516197ba5f4SPaul Zimmerman {
517197ba5f4SPaul Zimmerman 	return pipe->pipe_dir == USB_DIR_IN;
518197ba5f4SPaul Zimmerman }
519197ba5f4SPaul Zimmerman 
dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info * pipe)520197ba5f4SPaul Zimmerman static inline u8 dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info *pipe)
521197ba5f4SPaul Zimmerman {
522197ba5f4SPaul Zimmerman 	return !dwc2_hcd_is_pipe_in(pipe);
523197ba5f4SPaul Zimmerman }
524197ba5f4SPaul Zimmerman 
5254fe160d5SHeiner Kallweit int dwc2_hcd_init(struct dwc2_hsotg *hsotg);
5269da51974SJohn Youn void dwc2_hcd_remove(struct dwc2_hsotg *hsotg);
527197ba5f4SPaul Zimmerman 
528197ba5f4SPaul Zimmerman /* Transaction Execution Functions */
5299da51974SJohn Youn enum dwc2_transaction_type dwc2_hcd_select_transactions(
530197ba5f4SPaul Zimmerman 						struct dwc2_hsotg *hsotg);
5319da51974SJohn Youn void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
532197ba5f4SPaul Zimmerman 				 enum dwc2_transaction_type tr_type);
533197ba5f4SPaul Zimmerman 
534197ba5f4SPaul Zimmerman /* Schedule Queue Functions */
535197ba5f4SPaul Zimmerman /* Implemented in hcd_queue.c */
5369da51974SJohn Youn struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
537b58e6ceeSMian Yousaf Kaukab 				   struct dwc2_hcd_urb *urb,
538b58e6ceeSMian Yousaf Kaukab 					  gfp_t mem_flags);
5399da51974SJohn Youn void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
5409da51974SJohn Youn int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
5419da51974SJohn Youn void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
5429da51974SJohn Youn void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
543197ba5f4SPaul Zimmerman 			    int sched_csplit);
544197ba5f4SPaul Zimmerman 
5459da51974SJohn Youn void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb);
5469da51974SJohn Youn int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
547b58e6ceeSMian Yousaf Kaukab 		     struct dwc2_qh *qh);
548197ba5f4SPaul Zimmerman 
549197ba5f4SPaul Zimmerman /* Unlinks and frees a QTD */
dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg * hsotg,struct dwc2_qtd * qtd,struct dwc2_qh * qh)550197ba5f4SPaul Zimmerman static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
551197ba5f4SPaul Zimmerman 						struct dwc2_qtd *qtd,
552197ba5f4SPaul Zimmerman 						struct dwc2_qh *qh)
553197ba5f4SPaul Zimmerman {
554197ba5f4SPaul Zimmerman 	list_del(&qtd->qtd_list_entry);
555197ba5f4SPaul Zimmerman 	kfree(qtd);
556197ba5f4SPaul Zimmerman }
557197ba5f4SPaul Zimmerman 
558197ba5f4SPaul Zimmerman /* Descriptor DMA support functions */
5599da51974SJohn Youn void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg,
560197ba5f4SPaul Zimmerman 			      struct dwc2_qh *qh);
5619da51974SJohn Youn void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg,
562197ba5f4SPaul Zimmerman 				 struct dwc2_host_chan *chan, int chnum,
563197ba5f4SPaul Zimmerman 					enum dwc2_halt_status halt_status);
564197ba5f4SPaul Zimmerman 
5659da51974SJohn Youn int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
566197ba5f4SPaul Zimmerman 			  gfp_t mem_flags);
5679da51974SJohn Youn void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
568197ba5f4SPaul Zimmerman 
569197ba5f4SPaul Zimmerman /* Check if QH is non-periodic */
570197ba5f4SPaul Zimmerman #define dwc2_qh_is_non_per(_qh_ptr_) \
571197ba5f4SPaul Zimmerman 	((_qh_ptr_)->ep_type == USB_ENDPOINT_XFER_BULK || \
572197ba5f4SPaul Zimmerman 	 (_qh_ptr_)->ep_type == USB_ENDPOINT_XFER_CONTROL)
573197ba5f4SPaul Zimmerman 
574197ba5f4SPaul Zimmerman #ifdef CONFIG_USB_DWC2_DEBUG_PERIODIC
dbg_hc(struct dwc2_host_chan * hc)575197ba5f4SPaul Zimmerman static inline bool dbg_hc(struct dwc2_host_chan *hc) { return true; }
dbg_qh(struct dwc2_qh * qh)576197ba5f4SPaul Zimmerman static inline bool dbg_qh(struct dwc2_qh *qh) { return true; }
dbg_urb(struct urb * urb)577197ba5f4SPaul Zimmerman static inline bool dbg_urb(struct urb *urb) { return true; }
dbg_perio(void)578197ba5f4SPaul Zimmerman static inline bool dbg_perio(void) { return true; }
579197ba5f4SPaul Zimmerman #else /* !CONFIG_USB_DWC2_DEBUG_PERIODIC */
dbg_hc(struct dwc2_host_chan * hc)580197ba5f4SPaul Zimmerman static inline bool dbg_hc(struct dwc2_host_chan *hc)
581197ba5f4SPaul Zimmerman {
582197ba5f4SPaul Zimmerman 	return hc->ep_type == USB_ENDPOINT_XFER_BULK ||
583197ba5f4SPaul Zimmerman 	       hc->ep_type == USB_ENDPOINT_XFER_CONTROL;
584197ba5f4SPaul Zimmerman }
585197ba5f4SPaul Zimmerman 
dbg_qh(struct dwc2_qh * qh)586197ba5f4SPaul Zimmerman static inline bool dbg_qh(struct dwc2_qh *qh)
587197ba5f4SPaul Zimmerman {
588197ba5f4SPaul Zimmerman 	return qh->ep_type == USB_ENDPOINT_XFER_BULK ||
589197ba5f4SPaul Zimmerman 	       qh->ep_type == USB_ENDPOINT_XFER_CONTROL;
590197ba5f4SPaul Zimmerman }
591197ba5f4SPaul Zimmerman 
dbg_urb(struct urb * urb)592197ba5f4SPaul Zimmerman static inline bool dbg_urb(struct urb *urb)
593197ba5f4SPaul Zimmerman {
594197ba5f4SPaul Zimmerman 	return usb_pipetype(urb->pipe) == PIPE_BULK ||
595197ba5f4SPaul Zimmerman 	       usb_pipetype(urb->pipe) == PIPE_CONTROL;
596197ba5f4SPaul Zimmerman }
597197ba5f4SPaul Zimmerman 
dbg_perio(void)598197ba5f4SPaul Zimmerman static inline bool dbg_perio(void) { return false; }
599197ba5f4SPaul Zimmerman #endif
600197ba5f4SPaul Zimmerman 
601197ba5f4SPaul Zimmerman /*
602b9392d99SGregory Herrero  * Returns true if frame1 index is greater than frame2 index. The comparison
603b9392d99SGregory Herrero  * is done modulo FRLISTEN_64_SIZE. This accounts for the rollover of the
604b9392d99SGregory Herrero  * frame number when the max index frame number is reached.
605b9392d99SGregory Herrero  */
dwc2_frame_idx_num_gt(u16 fr_idx1,u16 fr_idx2)606b9392d99SGregory Herrero static inline bool dwc2_frame_idx_num_gt(u16 fr_idx1, u16 fr_idx2)
607b9392d99SGregory Herrero {
608b9392d99SGregory Herrero 	u16 diff = fr_idx1 - fr_idx2;
609b9392d99SGregory Herrero 	u16 sign = diff & (FRLISTEN_64_SIZE >> 1);
610b9392d99SGregory Herrero 
611b9392d99SGregory Herrero 	return diff && !sign;
612b9392d99SGregory Herrero }
613b9392d99SGregory Herrero 
614b9392d99SGregory Herrero /*
615197ba5f4SPaul Zimmerman  * Returns true if frame1 is less than or equal to frame2. The comparison is
616197ba5f4SPaul Zimmerman  * done modulo HFNUM_MAX_FRNUM. This accounts for the rollover of the
617197ba5f4SPaul Zimmerman  * frame number when the max frame number is reached.
618197ba5f4SPaul Zimmerman  */
dwc2_frame_num_le(u16 frame1,u16 frame2)619197ba5f4SPaul Zimmerman static inline int dwc2_frame_num_le(u16 frame1, u16 frame2)
620197ba5f4SPaul Zimmerman {
621197ba5f4SPaul Zimmerman 	return ((frame2 - frame1) & HFNUM_MAX_FRNUM) <= (HFNUM_MAX_FRNUM >> 1);
622197ba5f4SPaul Zimmerman }
623197ba5f4SPaul Zimmerman 
624197ba5f4SPaul Zimmerman /*
625197ba5f4SPaul Zimmerman  * Returns true if frame1 is greater than frame2. The comparison is done
626197ba5f4SPaul Zimmerman  * modulo HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
627197ba5f4SPaul Zimmerman  * number when the max frame number is reached.
628197ba5f4SPaul Zimmerman  */
dwc2_frame_num_gt(u16 frame1,u16 frame2)629197ba5f4SPaul Zimmerman static inline int dwc2_frame_num_gt(u16 frame1, u16 frame2)
630197ba5f4SPaul Zimmerman {
631197ba5f4SPaul Zimmerman 	return (frame1 != frame2) &&
632197ba5f4SPaul Zimmerman 	       ((frame1 - frame2) & HFNUM_MAX_FRNUM) < (HFNUM_MAX_FRNUM >> 1);
633197ba5f4SPaul Zimmerman }
634197ba5f4SPaul Zimmerman 
635197ba5f4SPaul Zimmerman /*
636197ba5f4SPaul Zimmerman  * Increments frame by the amount specified by inc. The addition is done
637197ba5f4SPaul Zimmerman  * modulo HFNUM_MAX_FRNUM. Returns the incremented value.
638197ba5f4SPaul Zimmerman  */
dwc2_frame_num_inc(u16 frame,u16 inc)639197ba5f4SPaul Zimmerman static inline u16 dwc2_frame_num_inc(u16 frame, u16 inc)
640197ba5f4SPaul Zimmerman {
641197ba5f4SPaul Zimmerman 	return (frame + inc) & HFNUM_MAX_FRNUM;
642197ba5f4SPaul Zimmerman }
643197ba5f4SPaul Zimmerman 
dwc2_frame_num_dec(u16 frame,u16 dec)64474fc4a75SDouglas Anderson static inline u16 dwc2_frame_num_dec(u16 frame, u16 dec)
64574fc4a75SDouglas Anderson {
64674fc4a75SDouglas Anderson 	return (frame + HFNUM_MAX_FRNUM + 1 - dec) & HFNUM_MAX_FRNUM;
64774fc4a75SDouglas Anderson }
64874fc4a75SDouglas Anderson 
dwc2_full_frame_num(u16 frame)649197ba5f4SPaul Zimmerman static inline u16 dwc2_full_frame_num(u16 frame)
650197ba5f4SPaul Zimmerman {
651197ba5f4SPaul Zimmerman 	return (frame & HFNUM_MAX_FRNUM) >> 3;
652197ba5f4SPaul Zimmerman }
653197ba5f4SPaul Zimmerman 
dwc2_micro_frame_num(u16 frame)654197ba5f4SPaul Zimmerman static inline u16 dwc2_micro_frame_num(u16 frame)
655197ba5f4SPaul Zimmerman {
656197ba5f4SPaul Zimmerman 	return frame & 0x7;
657197ba5f4SPaul Zimmerman }
658197ba5f4SPaul Zimmerman 
659197ba5f4SPaul Zimmerman /*
660197ba5f4SPaul Zimmerman  * Returns the Core Interrupt Status register contents, ANDed with the Core
661197ba5f4SPaul Zimmerman  * Interrupt Mask register contents
662197ba5f4SPaul Zimmerman  */
dwc2_read_core_intr(struct dwc2_hsotg * hsotg)663197ba5f4SPaul Zimmerman static inline u32 dwc2_read_core_intr(struct dwc2_hsotg *hsotg)
664197ba5f4SPaul Zimmerman {
665f25c42b8SGevorg Sahakyan 	return dwc2_readl(hsotg, GINTSTS) &
666f25c42b8SGevorg Sahakyan 	       dwc2_readl(hsotg, GINTMSK);
667197ba5f4SPaul Zimmerman }
668197ba5f4SPaul Zimmerman 
dwc2_hcd_urb_get_status(struct dwc2_hcd_urb * dwc2_urb)669197ba5f4SPaul Zimmerman static inline u32 dwc2_hcd_urb_get_status(struct dwc2_hcd_urb *dwc2_urb)
670197ba5f4SPaul Zimmerman {
671197ba5f4SPaul Zimmerman 	return dwc2_urb->status;
672197ba5f4SPaul Zimmerman }
673197ba5f4SPaul Zimmerman 
dwc2_hcd_urb_get_actual_length(struct dwc2_hcd_urb * dwc2_urb)674197ba5f4SPaul Zimmerman static inline u32 dwc2_hcd_urb_get_actual_length(
675197ba5f4SPaul Zimmerman 		struct dwc2_hcd_urb *dwc2_urb)
676197ba5f4SPaul Zimmerman {
677197ba5f4SPaul Zimmerman 	return dwc2_urb->actual_length;
678197ba5f4SPaul Zimmerman }
679197ba5f4SPaul Zimmerman 
dwc2_hcd_urb_get_error_count(struct dwc2_hcd_urb * dwc2_urb)680197ba5f4SPaul Zimmerman static inline u32 dwc2_hcd_urb_get_error_count(struct dwc2_hcd_urb *dwc2_urb)
681197ba5f4SPaul Zimmerman {
682197ba5f4SPaul Zimmerman 	return dwc2_urb->error_count;
683197ba5f4SPaul Zimmerman }
684197ba5f4SPaul Zimmerman 
dwc2_hcd_urb_set_iso_desc_params(struct dwc2_hcd_urb * dwc2_urb,int desc_num,u32 offset,u32 length)685197ba5f4SPaul Zimmerman static inline void dwc2_hcd_urb_set_iso_desc_params(
686197ba5f4SPaul Zimmerman 		struct dwc2_hcd_urb *dwc2_urb, int desc_num, u32 offset,
687197ba5f4SPaul Zimmerman 		u32 length)
688197ba5f4SPaul Zimmerman {
689197ba5f4SPaul Zimmerman 	dwc2_urb->iso_descs[desc_num].offset = offset;
690197ba5f4SPaul Zimmerman 	dwc2_urb->iso_descs[desc_num].length = length;
691197ba5f4SPaul Zimmerman }
692197ba5f4SPaul Zimmerman 
dwc2_hcd_urb_get_iso_desc_status(struct dwc2_hcd_urb * dwc2_urb,int desc_num)693197ba5f4SPaul Zimmerman static inline u32 dwc2_hcd_urb_get_iso_desc_status(
694197ba5f4SPaul Zimmerman 		struct dwc2_hcd_urb *dwc2_urb, int desc_num)
695197ba5f4SPaul Zimmerman {
696197ba5f4SPaul Zimmerman 	return dwc2_urb->iso_descs[desc_num].status;
697197ba5f4SPaul Zimmerman }
698197ba5f4SPaul Zimmerman 
dwc2_hcd_urb_get_iso_desc_actual_length(struct dwc2_hcd_urb * dwc2_urb,int desc_num)699197ba5f4SPaul Zimmerman static inline u32 dwc2_hcd_urb_get_iso_desc_actual_length(
700197ba5f4SPaul Zimmerman 		struct dwc2_hcd_urb *dwc2_urb, int desc_num)
701197ba5f4SPaul Zimmerman {
702197ba5f4SPaul Zimmerman 	return dwc2_urb->iso_descs[desc_num].actual_length;
703197ba5f4SPaul Zimmerman }
704197ba5f4SPaul Zimmerman 
dwc2_hcd_is_bandwidth_allocated(struct dwc2_hsotg * hsotg,struct usb_host_endpoint * ep)705197ba5f4SPaul Zimmerman static inline int dwc2_hcd_is_bandwidth_allocated(struct dwc2_hsotg *hsotg,
706197ba5f4SPaul Zimmerman 						  struct usb_host_endpoint *ep)
707197ba5f4SPaul Zimmerman {
708197ba5f4SPaul Zimmerman 	struct dwc2_qh *qh = ep->hcpriv;
709197ba5f4SPaul Zimmerman 
710197ba5f4SPaul Zimmerman 	if (qh && !list_empty(&qh->qh_list_entry))
711197ba5f4SPaul Zimmerman 		return 1;
712197ba5f4SPaul Zimmerman 
713197ba5f4SPaul Zimmerman 	return 0;
714197ba5f4SPaul Zimmerman }
715197ba5f4SPaul Zimmerman 
dwc2_hcd_get_ep_bandwidth(struct dwc2_hsotg * hsotg,struct usb_host_endpoint * ep)716197ba5f4SPaul Zimmerman static inline u16 dwc2_hcd_get_ep_bandwidth(struct dwc2_hsotg *hsotg,
717197ba5f4SPaul Zimmerman 					    struct usb_host_endpoint *ep)
718197ba5f4SPaul Zimmerman {
719197ba5f4SPaul Zimmerman 	struct dwc2_qh *qh = ep->hcpriv;
720197ba5f4SPaul Zimmerman 
721197ba5f4SPaul Zimmerman 	if (!qh) {
722197ba5f4SPaul Zimmerman 		WARN_ON(1);
723197ba5f4SPaul Zimmerman 		return 0;
724197ba5f4SPaul Zimmerman 	}
725197ba5f4SPaul Zimmerman 
726ced9eee1SDouglas Anderson 	return qh->host_us;
727197ba5f4SPaul Zimmerman }
728197ba5f4SPaul Zimmerman 
7299da51974SJohn Youn void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
730197ba5f4SPaul Zimmerman 			       struct dwc2_host_chan *chan, int chnum,
731197ba5f4SPaul Zimmerman 				      struct dwc2_qtd *qtd);
732197ba5f4SPaul Zimmerman 
733197ba5f4SPaul Zimmerman /* HCD Core API */
734197ba5f4SPaul Zimmerman 
735197ba5f4SPaul Zimmerman /**
736197ba5f4SPaul Zimmerman  * dwc2_handle_hcd_intr() - Called on every hardware interrupt
737197ba5f4SPaul Zimmerman  *
738197ba5f4SPaul Zimmerman  * @hsotg: The DWC2 HCD
739197ba5f4SPaul Zimmerman  *
740197ba5f4SPaul Zimmerman  * Returns IRQ_HANDLED if interrupt is handled
741197ba5f4SPaul Zimmerman  * Return IRQ_NONE if interrupt is not handled
742197ba5f4SPaul Zimmerman  */
7439da51974SJohn Youn irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg);
744197ba5f4SPaul Zimmerman 
745197ba5f4SPaul Zimmerman /**
746197ba5f4SPaul Zimmerman  * dwc2_hcd_stop() - Halts the DWC_otg host mode operation
747197ba5f4SPaul Zimmerman  *
748197ba5f4SPaul Zimmerman  * @hsotg: The DWC2 HCD
749197ba5f4SPaul Zimmerman  */
7509da51974SJohn Youn void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
751197ba5f4SPaul Zimmerman 
752197ba5f4SPaul Zimmerman /**
753197ba5f4SPaul Zimmerman  * dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host,
754197ba5f4SPaul Zimmerman  * and 0 otherwise
755197ba5f4SPaul Zimmerman  *
756197ba5f4SPaul Zimmerman  * @hsotg: The DWC2 HCD
757197ba5f4SPaul Zimmerman  */
7589da51974SJohn Youn int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
759197ba5f4SPaul Zimmerman 
760197ba5f4SPaul Zimmerman /**
761197ba5f4SPaul Zimmerman  * dwc2_hcd_dump_state() - Dumps hsotg state
762197ba5f4SPaul Zimmerman  *
763197ba5f4SPaul Zimmerman  * @hsotg: The DWC2 HCD
764197ba5f4SPaul Zimmerman  *
765197ba5f4SPaul Zimmerman  * NOTE: This function will be removed once the peripheral controller code
766197ba5f4SPaul Zimmerman  * is integrated and the driver is stable
767197ba5f4SPaul Zimmerman  */
7689da51974SJohn Youn void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg);
769197ba5f4SPaul Zimmerman 
770197ba5f4SPaul Zimmerman /* URB interface */
771197ba5f4SPaul Zimmerman 
772197ba5f4SPaul Zimmerman /* Transfer flags */
773197ba5f4SPaul Zimmerman #define URB_GIVEBACK_ASAP	0x1
774197ba5f4SPaul Zimmerman #define URB_SEND_ZERO_PACKET	0x2
775197ba5f4SPaul Zimmerman 
776197ba5f4SPaul Zimmerman /* Host driver callbacks */
7779da51974SJohn Youn struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg,
7789f9f09b0SDouglas Anderson 				      void *context, gfp_t mem_flags,
7799f9f09b0SDouglas Anderson 				      int *ttport);
7809f9f09b0SDouglas Anderson 
7819da51974SJohn Youn void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg,
7829f9f09b0SDouglas Anderson 			   struct dwc2_tt *dwc_tt);
7839da51974SJohn Youn int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context);
7849da51974SJohn Youn void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
785197ba5f4SPaul Zimmerman 			int status);
786197ba5f4SPaul Zimmerman 
787197ba5f4SPaul Zimmerman #endif /* __DWC2_HCD_H__ */
788