Start of public OpenTitan development history
Code contributors:
Alex Bradbury <asb@lowrisc.org>
Cindy Chen <chencindy@google.com>
Eunchan Kim <eunchan@google.com>
Gaurang Chitroda <gaurangg@google.com>
Mark Hayter <mark.hayter@gmail.com>
Michael Schaffner <msf@google.com>
Miguel Osorio <miguelosorio@google.com>
Nils Graf <nilsg@google.com>
Philipp Wagner <phw@lowrisc.org>
Pirmin Vogel <vogelpi@lowrisc.org>
Ram Babu Penugonda <rampenugonda@google.com>
Scott Johnson <scottdj@google.com>
Shail Kushwah <kushwahs@google.com>
Srikrishna Iyer <sriyer@google.com>
Steve Nelson <Steve.Nelson@wdc.com>
Tao Liu <taliu@google.com>
Timothy Chen <timothytim@google.com>
Tobias Wölfel <tobias.woelfel@mailbox.org>
Weicai Yang <weicai@google.com>
diff --git a/sw/lib/usbdev.h b/sw/lib/usbdev.h
new file mode 100644
index 0000000..003a388
--- /dev/null
+++ b/sw/lib/usbdev.h
@@ -0,0 +1,183 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef _USBDEV_H_
+#define _USBDEV_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// Hardware parameters
+#define NUM_BUFS 32
+#define BUF_LENGTH 64
+#define NUM_ENDPOINTS 12
+
+// USB buffers are held in the SRAM in the interface, referenced by ID
+// Buffer IDs are 0 to NUM_BUFS
+// Use negative buffer ID for error
+typedef int usbbufid_t;
+typedef struct usbdev_ctx usbdev_ctx_t;
+
+// Note: this is only needed here because the caller of init needs it
+struct usbdev_ctx {
+ // TODO: base_addr goes here once header files support using it
+ int can_wake;
+ uint8_t freebuf[NUM_BUFS];
+ uint32_t halted; // bit vector per endpoint
+ int nfree;
+ int flushed;
+ usbdev_ctx_t *ep_ctx[NUM_ENDPOINTS];
+ void (*tx_done_callback[NUM_ENDPOINTS])(void *);
+ void (*rx_callback[NUM_ENDPOINTS])(void *, usbbufid_t, int, int);
+ void (*flush[NUM_ENDPOINTS])(void *);
+};
+
+/**
+ * Allocate a buffer for the caller to use
+ *
+ * @param ctx usbdev context pointer
+ * @return buffer ID or negative for out of buffer error
+ */
+usbbufid_t usbdev_buf_allocate_byid(usbdev_ctx_t *ctx);
+
+/**
+ * Free a buffer when caller no longer needs it
+ *
+ * @param ctx usbdev context pointer
+ * @param buf buffer ID being returned to free pool
+ * @return 0 or -1 if the free pool is full (shouldn't happen)
+ */
+int usbdev_buf_free_byid(usbdev_ctx_t *ctx, usbbufid_t buf);
+
+/**
+ * Get memory address for accessing data in a buffer
+ *
+ * Hardware restriction: buffer can only be written with 32-bit words
+ * Ok to cast the return value to int8_t * for reading
+ *
+ * @param ctx usbdev context pointer
+ * @param buf buffer ID to access
+ * @return pointer to access the data of @p buf
+ */
+uint32_t *usbdev_buf_idtoaddr(usbdev_ctx_t *ctx, usbbufid_t buf);
+
+/**
+ * Copy from memory into a buffer, referencing by buffer ID
+ *
+ * Implementation restriction: from must be 4-byte aligned
+ * TODO(mdhayer) remove restriction
+ *
+ * @param ctx usbdev context pointer
+ * @param buf buffer ID to copy to
+ * @param from source address for data
+ * @param len_bytes length in bytes of data to copy
+ */
+void usbdev_buf_copyto_byid(usbdev_ctx_t *ctx, usbbufid_t buf, const void *from,
+ size_t len_bytes);
+
+/**
+ * Schedule a buffer for transmission on an endpoint
+ *
+ * Send happens on next IN request for that endpoint from the host.
+ * Once this call is made the buffer is owned by the hardware
+ *
+ * @param ctx usbdev context pointer
+ * @param buf buffer ID to send
+ * @param size length in bytes of data to send, zero is valid (used as ack)
+ * @param endpoint endpoint to send from
+ */
+void usbdev_sendbuf_byid(usbdev_ctx_t *ctx, usbbufid_t buf, size_t size,
+ int endpoint);
+
+/**
+ * Call regularly to poll the usbdev interface
+ *
+ * @param ctx usbdev context pointer
+ */
+void usbdev_poll(usbdev_ctx_t *ctx);
+
+/**
+ * Set the USB device ID
+ *
+ * Device ID must be zero at init. When the host assigns an ID
+ * with a SET_ADDRESS packet and the complete SETUP transaction is
+ * complete, this function should be called to set the new ID. Note
+ * on a reset the hardware will clear the device ID back to 0.
+ *
+ * @param usbdev context pointer
+ * @param new deviceid
+ */
+void usbdev_set_deviceid(usbdev_ctx_t *ctx, int deviceid);
+
+/**
+ * Halt or release an endpoint
+ *
+ * By default endpoints are enabled, but they can be halted but the host
+ *
+ * @param usbdev context pointer
+ * @param endpoint number
+ * @param enable set/clear
+ */
+void usbdev_halt(usbdev_ctx_t *ctx, int endpoint, int enable);
+
+/**
+ * Get halted status for an endpoint
+ *
+ * @param usbdev context pointer
+ * @return 1 if endpoint is halted else 0
+ */
+inline int usbdev_halted(usbdev_ctx_t *ctx, int endpoint) {
+ return (ctx->halted >> endpoint) & 0x1;
+}
+
+/**
+ * Enable or disable remote wake
+ *
+ * @param usbdev context pointer
+ * @param enable set/clear
+ */
+inline void usbdev_rem_wake_en(usbdev_ctx_t *ctx, int enable) {
+ ctx->can_wake = (enable) ? 1 : 0;
+}
+
+/**
+ * Get ability to wake the host
+ *
+ * @param usbdev context pointer
+ * @return 1 if remote wake is permitted else 0
+ */
+int usbdev_can_rem_wake(usbdev_ctx_t *ctx);
+
+/**
+ * Call to setup an endpoint
+ *
+ * @param ctx usbdev context pointer
+ * @param ep endpoint number
+ * @param enableout boolean, true to enable OUT transactions on the endpoint
+ * (OUT means host->device, ie receive by us)
+ * @param ep_ctx context pointer for callee
+ * @param tx_done(void *ep_ctx) callback once send has been Acked
+ * @param rx(void *ep_ctx, usbbufid_t buf, int size, int setup)
+ called when a packet is received
+ * @param flush(void *ep_ctx) called every 16ms based USB host timebase
+ */
+void usbdev_endpoint_setup(usbdev_ctx_t *ctx, int ep, int enableout,
+ void *ep_ctx, void (*tx_done)(void *),
+ void (*rx)(void *, usbbufid_t, int, int),
+ void (*flush)(void *));
+
+/**
+ * Initialize the usbdev interface
+ *
+ * @param ctx uninitialized usbdev context pointer
+ */
+void usbdev_init(usbdev_ctx_t *ctx);
+
+// Used for tracing what is going on
+#include "uart.h"
+#define TRC_S(s) uart_send_str(s)
+#define TRC_I(i, b) uart_send_uint(i, b)
+#define TRC_C(c) uart_send_char(c)
+
+#endif