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