1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12/*
13 * These functions need to be implemented by platform
14 * specific code.
15 */
16
17#ifndef __USB_USB_HOST_H_
18#define __USB_USB_HOST_H_
19
20#include <platsupport/io.h>
21#include <platsupport/sync/sync.h>
22#include <usb/plat/usb.h>
23
24enum usb_speed {
25/// 1.5Mbps connection
26    USBSPEED_LOW  = 0,
27/// 12Mbps connection
28    USBSPEED_FULL = 1,
29/// 480Mbps connection
30    USBSPEED_HIGH = 2
31};
32
33/*
34 * Endpoint types
35 * NOTE: do not change the defined order, see USB 2.0 spec(9.6.6)
36 */
37enum usb_endpoint_type {
38    EP_CONTROL = 0,
39    EP_ISOCHRONOUS,
40    EP_BULK,
41    EP_INTERRUPT
42};
43
44/* NOTE: do not change the defined order, see USB 2.0 spec(9.6.6) */
45enum usb_endpoint_dir {
46    EP_DIR_OUT = 0,
47    EP_DIR_IN
48};
49
50struct endpoint {
51    enum usb_endpoint_type type;
52    uint8_t   num;               // Endpoint number
53    enum usb_endpoint_dir  dir;  // Endpoint direction
54    uint16_t  max_pkt;   // Maximum packet size
55    uint8_t   interval;  // Interval for polling or NAK rate for Bulk/Control
56
57    /* For host controller driver only, actually holds queue head. */
58    void      *hcpriv;
59};
60
61enum usb_xact_type {
62/// Input PID
63    PID_IN,
64/// Output PID
65    PID_OUT,
66/// Setup PID
67    PID_SETUP
68};
69
70enum usb_xact_status {
71/// The transaction completed successfully
72    XACTSTAT_SUCCESS,
73/// The transaction has not been processed
74    XACTSTAT_PENDING,
75/// The transaction was cancelled due to disconnect, etc
76    XACTSTAT_CANCELLED,
77/// There was an error in processing the transaction
78    XACTSTAT_ERROR,
79/// The host exhibited a failure during the transaction.
80    XACTSTAT_HOSTERROR
81};
82
83/*
84 * XXX: The xact size has to meet the QTD limitation. We only allocate one QTD
85 * for each xact.
86 */
87#define MAX_XACT_SIZE  (5 * PAGE_SIZE_4K)
88struct xact {
89/// Transfer type
90    enum usb_xact_type type;
91/// DMA buffer to exchange
92    void* vaddr;
93    uintptr_t paddr;
94/// The length of @ref{buf}
95    int len;
96};
97
98static inline void* xact_get_vaddr(struct xact* xact)
99{
100    return xact->vaddr;
101}
102
103static inline uintptr_t xact_get_paddr(struct xact* xact)
104{
105    return xact->paddr;
106}
107
108/** Callback type for asynchronous USB transactions
109 * @param[in] token  An unmodified opaque token as passed to
110 *                   the associated transaction request.
111 * @param[in] stat   The status of the transaction.
112 * @param[in] rbytes The number of bytes remaining in the transaction.
113 *                   This value is generally 0 on successful transmission
114 *                   unless a short read or write occurs.
115 * @return           1 if the transaction should be rescheduled,
116 *                   otherwise, 0.
117 */
118typedef int (*usb_cb_t)(void* token, enum usb_xact_status stat, int rbytes);
119
120struct usb_host;
121typedef struct usb_host usb_host_t;
122
123struct usb_host {
124    /// Device ID
125    enum usb_host_id id;
126    /// Number of ports provided by this host controller
127    int nports;
128
129    /// DMA allocator
130    ps_dma_man_t* dman;
131
132    /// Synchronization operations
133    ps_mutex_ops_t* sync;
134
135    /// Submit a transaction for transfer.
136    int (*schedule_xact)(usb_host_t* hdev, uint8_t addr, int8_t hub_addr, uint8_t hub_port,
137                         enum usb_speed speed, struct endpoint *ep,
138                         struct xact* xact, int nxact, usb_cb_t cb, void* t);
139    /// Cancel all transactions for a given device endpoint
140    int (*cancel_xact)(usb_host_t* hdev, struct endpoint *ep);
141    /// Handle an IRQ
142    void (*handle_irq)(usb_host_t* hdev);
143
144    /// IRQ numbers tied to this device
145    const int* irqs;
146    /// Host private data
147    struct usb_hc_data* pdata;
148};
149
150
151/**
152 * Schedules a USB transaction
153 * @param[in] hdev     The host controller that should be used for the transfer
154 * @param[in] addr     The destination USB device address
155 * @param[in] hub_addr The USB device address of the hub at which the destination
156 *                     device is connected. -1 must be used if the device is not
157 *                     connected to a hub (i.e. when it is the root hub).
158 *                     0 may be used if the device is a SPEED_FULL device.
159 * @param[in] hub_port The port at which the destination device is connected to
160 *                     its parent hub.
161 *                     0 may be used if the device is a SPEED_FULL device.
162 * @param[in] speed    The USB speed of the device.
163 * @param[in] ep       The destination endpoint of the destination device.
164 * @param[in] xact     An array of packet descriptors.
165 * @param[in] nxact    The number of packet descriptors in the array.
166 * @param[in] cb       A callback function to call on completion.
167 *                     NULL will result in blocking operation.
168 * @param[in] t        A token to pass, unmodified, to the provided callback
169 *                     function on completion.
170 * @return             Negative values represent failure, otherwise, the
171 *                     number of bytes remaining to be transferred is returned.
172 */
173static inline int
174usb_hcd_schedule(usb_host_t* hdev, uint8_t addr, uint8_t hub_addr, uint8_t hub_port,
175                 enum usb_speed speed, struct endpoint *ep,
176                 struct xact* xact, int nxact, usb_cb_t cb, void* t)
177{
178    return hdev->schedule_xact(hdev, addr, hub_addr, hub_port, speed, ep,
179                               xact, nxact, cb, t);
180}
181
182static inline void
183usb_hcd_handle_irq(usb_host_t* hdev)
184{
185    hdev->handle_irq(hdev);
186}
187
188static inline int
189usb_hcd_count_ports(usb_host_t* hdev)
190{
191    return hdev->nports;
192}
193
194/**
195 * Initialise USB host controller.
196 * This function should only be called if you wish to use a raw API for the usb host controller, otherwise,
197 * this function will be called by usb_init and the appropriate book keeping for device management
198 * will be created and maintained.
199 * @param[in]  id     The id of the host controller to initialise
200 * @param[in]  ioops  a list of io operation functions.
201 *                    of the initialised host controller
202 * @param[in]  sync   a list of mutex operation functions.
203 * @param[out] hdev   A host structure to populate. This must
204 *                    already be filled with a DMA allocator.
205 *                    and the device ID.
206 * @return            0 on success
207 */
208int usb_host_init(enum usb_host_id id, ps_io_ops_t* ioops, ps_mutex_ops_t *sync, usb_host_t* hdev);
209
210/** Return a list of IRQ numbers handled by the provided host
211 * @param[in]  host   A handle to the USB host device in question
212 * @param[out] nirqs  The number of IRQs handled by this host.
213 * @return            A NULL terminated list of IRQs
214 */
215const int* usb_host_irqs(usb_host_t* host, int* nirqs);
216
217
218#endif /* __USB_USB_HOST_H_ */
219
220