blob: c01ce7521d65d18c8da8bed6008a0fbbb91b54b0 [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
Miguel Young de la Sota960fd8e2020-01-14 13:52:13 -05005#ifndef OPENTITAN_SW_DEVICE_LIB_USBDEV_H_
6#define OPENTITAN_SW_DEVICE_LIB_USBDEV_H_
lowRISC Contributors802543a2019-08-31 12:12:56 +01007
Pirmin Vogel098128c2020-10-05 16:15:11 +02008#include <stdbool.h>
lowRISC Contributors802543a2019-08-31 12:12:56 +01009#include <stddef.h>
10#include <stdint.h>
11
12// Hardware parameters
13#define NUM_BUFS 32
14#define BUF_LENGTH 64
15#define NUM_ENDPOINTS 12
16
17// USB buffers are held in the SRAM in the interface, referenced by ID
18// Buffer IDs are 0 to NUM_BUFS
19// Use negative buffer ID for error
20typedef int usbbufid_t;
21typedef struct usbdev_ctx usbdev_ctx_t;
22
23// Note: this is only needed here because the caller of init needs it
24struct usbdev_ctx {
25 // TODO: base_addr goes here once header files support using it
26 int can_wake;
27 uint8_t freebuf[NUM_BUFS];
28 uint32_t halted; // bit vector per endpoint
29 int nfree;
30 int flushed;
31 usbdev_ctx_t *ep_ctx[NUM_ENDPOINTS];
32 void (*tx_done_callback[NUM_ENDPOINTS])(void *);
33 void (*rx_callback[NUM_ENDPOINTS])(void *, usbbufid_t, int, int);
34 void (*flush[NUM_ENDPOINTS])(void *);
Stefan Lippuner3a10e762020-01-09 16:06:42 +010035 void (*reset[NUM_ENDPOINTS])(void *);
lowRISC Contributors802543a2019-08-31 12:12:56 +010036};
37
38/**
Alphan Ulusoya14b2ce2020-12-09 08:50:51 -050039 * Select USB lines P or N
40 */
41typedef enum line_sel { kDpSel = 0, kDnSel = 1 } line_sel_t;
42
43/**
lowRISC Contributors802543a2019-08-31 12:12:56 +010044 * Allocate a buffer for the caller to use
45 *
46 * @param ctx usbdev context pointer
47 * @return buffer ID or negative for out of buffer error
48 */
49usbbufid_t usbdev_buf_allocate_byid(usbdev_ctx_t *ctx);
50
51/**
52 * Free a buffer when caller no longer needs it
53 *
54 * @param ctx usbdev context pointer
55 * @param buf buffer ID being returned to free pool
56 * @return 0 or -1 if the free pool is full (shouldn't happen)
57 */
58int usbdev_buf_free_byid(usbdev_ctx_t *ctx, usbbufid_t buf);
59
60/**
61 * Get memory address for accessing data in a buffer
62 *
63 * Hardware restriction: buffer can only be written with 32-bit words
64 * Ok to cast the return value to int8_t * for reading
65 *
66 * @param ctx usbdev context pointer
67 * @param buf buffer ID to access
68 * @return pointer to access the data of @p buf
69 */
70uint32_t *usbdev_buf_idtoaddr(usbdev_ctx_t *ctx, usbbufid_t buf);
71
72/**
73 * Copy from memory into a buffer, referencing by buffer ID
74 *
75 * Implementation restriction: from must be 4-byte aligned
Tobias Wölfel7840d7b2019-10-07 12:29:33 +020076 * TODO remove restriction
lowRISC Contributors802543a2019-08-31 12:12:56 +010077 *
78 * @param ctx usbdev context pointer
79 * @param buf buffer ID to copy to
80 * @param from source address for data
81 * @param len_bytes length in bytes of data to copy
82 */
83void usbdev_buf_copyto_byid(usbdev_ctx_t *ctx, usbbufid_t buf, const void *from,
84 size_t len_bytes);
85
86/**
87 * Schedule a buffer for transmission on an endpoint
88 *
89 * Send happens on next IN request for that endpoint from the host.
90 * Once this call is made the buffer is owned by the hardware
91 *
92 * @param ctx usbdev context pointer
93 * @param buf buffer ID to send
94 * @param size length in bytes of data to send, zero is valid (used as ack)
95 * @param endpoint endpoint to send from
96 */
97void usbdev_sendbuf_byid(usbdev_ctx_t *ctx, usbbufid_t buf, size_t size,
98 int endpoint);
99
100/**
101 * Call regularly to poll the usbdev interface
102 *
103 * @param ctx usbdev context pointer
104 */
105void usbdev_poll(usbdev_ctx_t *ctx);
106
107/**
Stefan Lippuner3a10e762020-01-09 16:06:42 +0100108 * Get the content of the USB status register
109 * @param ctx usbdev context pointer
110 * @return USB status register
111 */
112unsigned int usbdev_get_status(usbdev_ctx_t *ctx);
113
114/**
115 * Get the current USB link state
116 * @param ctx usbdev context pointer
117 * @return USB link state
118 */
119unsigned int usbdev_get_link_state(usbdev_ctx_t *ctx);
120
121/**
122 * Get the current USB address
123 * @param ctx usbdev context pointer
124 * @return USB address
125 */
126unsigned int usbdev_get_address(usbdev_ctx_t *ctx);
127
128/**
lowRISC Contributors802543a2019-08-31 12:12:56 +0100129 * Set the USB device ID
130 *
131 * Device ID must be zero at init. When the host assigns an ID
132 * with a SET_ADDRESS packet and the complete SETUP transaction is
133 * complete, this function should be called to set the new ID. Note
134 * on a reset the hardware will clear the device ID back to 0.
135 *
Tobias Wölfel01ec7cf2021-02-12 11:57:12 +0100136 * @param ctx usbdev context pointer
137 * @param deviceid new deviceid
lowRISC Contributors802543a2019-08-31 12:12:56 +0100138 */
139void usbdev_set_deviceid(usbdev_ctx_t *ctx, int deviceid);
140
141/**
142 * Halt or release an endpoint
143 *
144 * By default endpoints are enabled, but they can be halted but the host
145 *
Tobias Wölfel01ec7cf2021-02-12 11:57:12 +0100146 * @param ctx usbdev context pointer
lowRISC Contributors802543a2019-08-31 12:12:56 +0100147 * @param endpoint number
148 * @param enable set/clear
149 */
150void usbdev_halt(usbdev_ctx_t *ctx, int endpoint, int enable);
151
152/**
153 * Get halted status for an endpoint
154 *
Tobias Wölfel01ec7cf2021-02-12 11:57:12 +0100155 * @param ctx usbdev context pointer
156 * @param endpoint number
lowRISC Contributors802543a2019-08-31 12:12:56 +0100157 * @return 1 if endpoint is halted else 0
158 */
159inline int usbdev_halted(usbdev_ctx_t *ctx, int endpoint) {
160 return (ctx->halted >> endpoint) & 0x1;
161}
162
163/**
Stefan Lippuner3a10e762020-01-09 16:06:42 +0100164 * Configure an endpoint as ISO / non-ISO
165 *
166 * By default endpoints are non-ISO, but they can be set to ISO
167 *
Tobias Wölfel01ec7cf2021-02-12 11:57:12 +0100168 * @param ctx usbdev context pointer
Stefan Lippuner3a10e762020-01-09 16:06:42 +0100169 * @param endpoint number
170 * @param enable 0: non-ISO, 1: ISO
171 */
172void usbdev_set_iso(usbdev_ctx_t *ctx, int endpoint, int enable);
173
174/**
175 * Clear the data toggle bit for an endpoint
Tobias Wölfel01ec7cf2021-02-12 11:57:12 +0100176 * @param ctx usbdev context pointer
Stefan Lippuner3a10e762020-01-09 16:06:42 +0100177 * @param endpoint Endpoint number
178 */
179void usbdev_clear_data_toggle(usbdev_ctx_t *ctx, int endpoint);
180
181/**
182 * Updates the stall setting for EP0. If stall is set then an IN, or
183 * OUT transaction to EP0 will be responded to with a STALL return. This
184 * flag is cleared on a a SETUP transaction
185 * @param ctx usbdev context pointer
186 * @param stall
187 */
188void usbdev_set_ep0_stall(usbdev_ctx_t *ctx, int stall);
189
190/**
lowRISC Contributors802543a2019-08-31 12:12:56 +0100191 * Enable or disable remote wake
192 *
Tobias Wölfel01ec7cf2021-02-12 11:57:12 +0100193 * @param ctx usbdev context pointer
lowRISC Contributors802543a2019-08-31 12:12:56 +0100194 * @param enable set/clear
195 */
196inline void usbdev_rem_wake_en(usbdev_ctx_t *ctx, int enable) {
197 ctx->can_wake = (enable) ? 1 : 0;
198}
199
200/**
201 * Get ability to wake the host
202 *
Tobias Wölfel01ec7cf2021-02-12 11:57:12 +0100203 * @param ctx usbdev context pointer
lowRISC Contributors802543a2019-08-31 12:12:56 +0100204 * @return 1 if remote wake is permitted else 0
205 */
206int usbdev_can_rem_wake(usbdev_ctx_t *ctx);
207
208/**
209 * Call to setup an endpoint
210 *
211 * @param ctx usbdev context pointer
212 * @param ep endpoint number
213 * @param enableout boolean, true to enable OUT transactions on the endpoint
214 * (OUT means host->device, ie receive by us)
215 * @param ep_ctx context pointer for callee
216 * @param tx_done(void *ep_ctx) callback once send has been Acked
217 * @param rx(void *ep_ctx, usbbufid_t buf, int size, int setup)
218 called when a packet is received
219 * @param flush(void *ep_ctx) called every 16ms based USB host timebase
Stefan Lippuner3a10e762020-01-09 16:06:42 +0100220 * @param reset(void *ep_ctx) called when an USB link reset is detected
lowRISC Contributors802543a2019-08-31 12:12:56 +0100221 */
222void usbdev_endpoint_setup(usbdev_ctx_t *ctx, int ep, int enableout,
223 void *ep_ctx, void (*tx_done)(void *),
224 void (*rx)(void *, usbbufid_t, int, int),
Stefan Lippuner3a10e762020-01-09 16:06:42 +0100225 void (*flush)(void *), void (*reset)(void *));
lowRISC Contributors802543a2019-08-31 12:12:56 +0100226
227/**
Alexander Williamse18d88b2022-01-21 16:30:39 -0800228 * Connect the device to the bus.
229 *
230 * @param ctx the usbdev context.
231 */
232void usbdev_connect(usbdev_ctx_t *ctx);
233
234/**
lowRISC Contributors802543a2019-08-31 12:12:56 +0100235 * Initialize the usbdev interface
236 *
Alexander Williamse18d88b2022-01-21 16:30:39 -0800237 * Does not connect the device, since the default endpoint is not yet enabled.
238 * See usbdev_connect().
239 *
lowRISC Contributors802543a2019-08-31 12:12:56 +0100240 * @param ctx uninitialized usbdev context pointer
Pirmin Vogel098128c2020-10-05 16:15:11 +0200241 * @param pinflip boolean to indicate if PHY should be configured for D+/D- flip
242 * @param diff_rx boolean to indicate if PHY uses differential RX
243 * @param diff_tx boolean to indicate if PHY uses differential TX
lowRISC Contributors802543a2019-08-31 12:12:56 +0100244 */
Pirmin Vogel098128c2020-10-05 16:15:11 +0200245void usbdev_init(usbdev_ctx_t *ctx, bool pinflip, bool diff_rx, bool diff_tx);
lowRISC Contributors802543a2019-08-31 12:12:56 +0100246
Alphan Ulusoya14b2ce2020-12-09 08:50:51 -0500247/**
248 * Force usbdev to output suspend state for testing purposes
249 */
250void usbdev_force_suspend(void);
251
252/**
253 * Force usbdev pull-up to specific value
254 */
255void usbdev_force_dx_pullup(line_sel_t line, bool set);
256
257/**
258 * Enable usb wake
259 */
260void usbdev_wake(bool set);
261
Pirmin Vogelea91b302020-01-14 18:53:01 +0000262// Used for tracing what is going on. This may impact timing which is critical
263// when simulating with the USB DPI module.
264//#define ENABLE_TRC
265#ifdef ENABLE_TRC
Alexander Williamse18d88b2022-01-21 16:30:39 -0800266#include "sw/device/lib/runtime/log.h"
267#define TRC_S(s) LOG_INFO("%s", s)
268#define TRC_I(i, b) LOG_INFO("0x%x", i)
269#define TRC_C(c) LOG_INFO("%c", c)
Pirmin Vogelea91b302020-01-14 18:53:01 +0000270#else
271#define TRC_S(s)
272#define TRC_I(i, b)
273#define TRC_C(c)
274#endif
lowRISC Contributors802543a2019-08-31 12:12:56 +0100275
Miguel Young de la Sota960fd8e2020-01-14 13:52:13 -0500276#endif // OPENTITAN_SW_DEVICE_LIB_USBDEV_H_