[sw/usb] Rebase USB software stack atop DIFs
Also fix up tests to use the DIFs.
Signed-off-by: Alexander Williams <awill@google.com>
diff --git a/sw/device/examples/hello_usbdev/BUILD b/sw/device/examples/hello_usbdev/BUILD
index 1f51e33..fe00326 100644
--- a/sw/device/examples/hello_usbdev/BUILD
+++ b/sw/device/examples/hello_usbdev/BUILD
@@ -27,8 +27,6 @@
deps = [
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/examples:demos",
- "//sw/device/lib:usb",
- "//sw/device/lib:usb_simpleserial",
"//sw/device/lib/arch:device",
"//sw/device/lib/crt",
"//sw/device/lib/dif:gpio",
@@ -39,6 +37,8 @@
"//sw/device/lib/runtime:log",
"//sw/device/lib/runtime:print",
"//sw/device/lib/testing:pinmux_testutils",
+ "//sw/device/lib/testing:usb_testutils",
+ "//sw/device/lib/testing:usb_testutils_simpleserial",
"//sw/device/lib/testing/test_framework:check",
"//sw/device/lib/testing/test_framework:ottf_start",
"//sw/device/lib/testing/test_framework:ottf_test_config",
diff --git a/sw/device/examples/hello_usbdev/hello_usbdev.c b/sw/device/examples/hello_usbdev/hello_usbdev.c
index c6351a6..9c29c8a 100644
--- a/sw/device/examples/hello_usbdev/hello_usbdev.c
+++ b/sw/device/examples/hello_usbdev/hello_usbdev.c
@@ -17,9 +17,9 @@
#include "sw/device/lib/testing/pinmux_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_test_config.h"
-#include "sw/device/lib/usb_controlep.h"
-#include "sw/device/lib/usb_simpleserial.h"
-#include "sw/device/lib/usbdev.h"
+#include "sw/device/lib/testing/usb_testutils.h"
+#include "sw/device/lib/testing/usb_testutils_controlep.h"
+#include "sw/device/lib/testing/usb_testutils_simpleserial.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
@@ -49,10 +49,10 @@
/**
* USB device context types.
*/
-static usbdev_ctx_t usbdev;
-static usb_controlep_ctx_t usbdev_control;
-static usb_ss_ctx_t simple_serial0;
-static usb_ss_ctx_t simple_serial1;
+static usb_testutils_ctx_t usbdev;
+static usb_testutils_controlep_ctx_t usbdev_control;
+static usb_testutils_ss_ctx_t simple_serial0;
+static usb_testutils_ss_ctx_t simple_serial1;
/**
* Makes `c` into a printable character, replacing it with `replacement`
@@ -101,9 +101,9 @@
* @param string Zero terminated string to send.
* @param ss_ctx Pointer to simple string endpoint context to send through.
*/
-static void usb_send_str(const char *string, usb_ss_ctx_t *ss_ctx) {
+static void usb_send_str(const char *string, usb_testutils_ss_ctx_t *ss_ctx) {
for (int i = 0; string[i] != 0; ++i) {
- usb_simpleserial_send_byte(ss_ctx, string[i]);
+ usb_testutils_simpleserial_send_byte(ss_ctx, string[i]);
}
}
@@ -181,20 +181,23 @@
CHECK_DIF_OK(dif_spi_device_send(&spi, "SPI!", 4, /*bytes_sent=*/NULL));
// The TI phy always uses a differential TX interface
- usbdev_init(&usbdev, pinflip, differential_xcvr, differential_xcvr && !uphy);
+ usb_testutils_init(&usbdev, pinflip, differential_xcvr,
+ differential_xcvr && !uphy);
- usb_controlep_init(&usbdev_control, &usbdev, 0, config_descriptors,
- sizeof(config_descriptors));
- while (usbdev_control.device_state != kUsbDeviceConfigured) {
- usbdev_poll(&usbdev);
+ usb_testutils_controlep_init(&usbdev_control, &usbdev, 0, config_descriptors,
+ sizeof(config_descriptors));
+ while (usbdev_control.device_state != kUsbTestutilsDeviceConfigured) {
+ usb_testutils_poll(&usbdev);
}
- usb_simpleserial_init(&simple_serial0, &usbdev, 1, usb_receipt_callback_0);
- usb_simpleserial_init(&simple_serial1, &usbdev, 2, usb_receipt_callback_1);
+ usb_testutils_simpleserial_init(&simple_serial0, &usbdev, 1,
+ usb_receipt_callback_0);
+ usb_testutils_simpleserial_init(&simple_serial1, &usbdev, 2,
+ usb_receipt_callback_1);
bool say_hello = true;
bool pass_signaled = false;
while (true) {
- usbdev_poll(&usbdev);
+ usb_testutils_poll(&usbdev);
gpio_state = demo_gpio_to_log_echo(&gpio, gpio_state);
demo_spi_to_log_echo(&spi);
@@ -218,8 +221,8 @@
uint32_t usb_stat = REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET);
LOG_INFO("I%04x-%08x", usb_irq_state, usb_stat);
} else {
- usb_simpleserial_send_byte(&simple_serial0, rcv_char);
- usb_simpleserial_send_byte(&simple_serial1, rcv_char + 1);
+ usb_testutils_simpleserial_send_byte(&simple_serial0, rcv_char);
+ usb_testutils_simpleserial_send_byte(&simple_serial1, rcv_char + 1);
}
}
if (say_hello && usb_chars_recved_total > 2) {
diff --git a/sw/device/lib/BUILD b/sw/device/lib/BUILD
index 8e69231..6646e50 100644
--- a/sw/device/lib/BUILD
+++ b/sw/device/lib/BUILD
@@ -41,29 +41,3 @@
"//sw/device/lib/base:csr",
],
)
-
-cc_library(
- name = "usb",
- srcs = [
- "usb_controlep.c",
- "usbdev.c",
- ],
- hdrs = [
- "usb_consts.h",
- "usb_controlep.h",
- "usbdev.h",
- ],
- target_compatible_with = [OPENTITAN_CPU],
- deps = [
- "//hw/ip/usbdev/data:usbdev_regs",
- "//hw/top_earlgrey/sw/autogen:top_earlgrey",
- ],
-)
-
-cc_library(
- name = "usb_simpleserial",
- srcs = ["usb_simpleserial.c"],
- hdrs = ["usb_simpleserial.h"],
- target_compatible_with = [OPENTITAN_CPU],
- deps = [":usb"],
-)
diff --git a/sw/device/lib/dif/dif_usbdev.c b/sw/device/lib/dif/dif_usbdev.c
index 625f0c7..3e5105f 100644
--- a/sw/device/lib/dif/dif_usbdev.c
+++ b/sw/device/lib/dif/dif_usbdev.c
@@ -576,7 +576,7 @@
if (usbdev == NULL || buffer_pool == NULL || !is_valid_endpoint(endpoint)) {
return kDifBadArg;
}
- // Get the configin register offset and bit index of the endpoint
+ // Get the configin register offset and bit index of the endpoint.
uint32_t config_in_reg_offset =
kEndpointHwInfos[endpoint].config_in_reg_offset;
uint32_t config_in_reg_val =
@@ -586,10 +586,10 @@
mmio_region_write32(usbdev->base_addr, config_in_reg_offset,
1u << USBDEV_CONFIGIN_0_PEND_0_BIT);
- // Clear IN_SENT bit (rw1c)
+ // Clear IN_SENT bit (rw1c).
mmio_region_write32(usbdev->base_addr, USBDEV_IN_SENT_REG_OFFSET,
1u << endpoint);
- // Return the buffer back to the free buffer pool
+ // Return the buffer back to the free buffer pool.
if (!buffer_pool_add(buffer_pool, buffer)) {
return kDifError;
}
@@ -603,29 +603,29 @@
return kDifBadArg;
}
- // Get the configin register offset and bit index of the endpoint
+ // Get the configin register offset and bit index of the endpoint.
uint32_t config_in_reg_offset =
kEndpointHwInfos[endpoint].config_in_reg_offset;
uint8_t endpoint_bit_index = kEndpointHwInfos[endpoint].bit_index;
- // Read the configin register
+ // Read the configin register.
uint32_t config_in_val =
mmio_region_read32(usbdev->base_addr, config_in_reg_offset);
- // Check the status of the packet
+ // Check the status of the packet.
if (bitfield_bit32_read(config_in_val, USBDEV_CONFIGIN_0_RDY_0_BIT)) {
- // Packet is marked as ready to be sent and pending transmission
+ // Packet is marked as ready to be sent and pending transmission.
*status = kDifUsbdevTxStatusPending;
} else if (bitfield_bit32_read(mmio_region_read32(usbdev->base_addr,
USBDEV_IN_SENT_REG_OFFSET),
endpoint_bit_index)) {
- // Packet was sent successfully
+ // Packet was sent successfully.
*status = kDifUsbdevTxStatusSent;
} else if (bitfield_bit32_read(config_in_val, USBDEV_CONFIGIN_0_PEND_0_BIT)) {
- // Canceled due to an IN SETUP packet or link reset
+ // Canceled due to an IN SETUP packet or link reset.
*status = kDifUsbdevTxStatusCancelled;
} else {
- // No packet has been queued for this endpoint
+ // No packet has been queued for this endpoint.
*status = kDifUsbdevTxStatusNoPacket;
}
diff --git a/sw/device/lib/testing/BUILD b/sw/device/lib/testing/BUILD
index 1bd2774..acb05ec 100644
--- a/sw/device/lib/testing/BUILD
+++ b/sw/device/lib/testing/BUILD
@@ -256,3 +256,32 @@
"//sw/device/lib/testing/test_framework:check",
],
)
+
+cc_library(
+ name = "usb_testutils",
+ srcs = [
+ "usb_testutils.c",
+ "usb_testutils_controlep.c",
+ ],
+ hdrs = [
+ "usb_testutils.h",
+ "usb_testutils_controlep.h",
+ ],
+ target_compatible_with = [OPENTITAN_CPU],
+ deps = [
+ "//hw/top_earlgrey/sw/autogen:top_earlgrey",
+ "//sw/device/lib/dif:usbdev",
+ "//sw/device/lib/testing/test_framework:check",
+ ],
+)
+
+cc_library(
+ name = "usb_testutils_simpleserial",
+ srcs = ["usb_testutils_simpleserial.c"],
+ hdrs = ["usb_testutils_simpleserial.h"],
+ target_compatible_with = [OPENTITAN_CPU],
+ deps = [
+ ":usb_testutils",
+ "//sw/device/lib/testing/test_framework:check",
+ ],
+)
diff --git a/sw/device/lib/testing/usb_testutils.c b/sw/device/lib/testing/usb_testutils.c
new file mode 100644
index 0000000..343a588
--- /dev/null
+++ b/sw/device/lib/testing/usb_testutils.c
@@ -0,0 +1,191 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/lib/testing/usb_testutils.h"
+
+#include "sw/device/lib/dif/dif_usbdev.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+
+#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
+
+#define USBDEV_BASE_ADDR TOP_EARLGREY_USBDEV_BASE_ADDR
+
+static dif_usbdev_t usbdev;
+static dif_usbdev_buffer_pool_t buffer_pool;
+
+void usb_testutils_poll(usb_testutils_ctx_t *ctx) {
+ uint32_t istate;
+ CHECK_DIF_OK(dif_usbdev_irq_get_state(ctx->dev, &istate));
+
+ // Do this first to keep things going
+ CHECK_DIF_OK(dif_usbdev_fill_available_fifo(ctx->dev, ctx->buffer_pool));
+
+ // Process IN completions first so we get the fact that send completed
+ // before processing a response
+ if (istate & (1u << kDifUsbdevIrqPktSent)) {
+ uint16_t sentep;
+ CHECK_DIF_OK(dif_usbdev_get_tx_sent(ctx->dev, &sentep));
+ TRC_C('a' + sentep);
+ for (int ep = 0; ep < USBDEV_NUM_ENDPOINTS; ep++) {
+ if (sentep & (1 << ep)) {
+ // Free up the buffer and optionally callback
+ CHECK_DIF_OK(
+ dif_usbdev_clear_tx_status(ctx->dev, ctx->buffer_pool, ep));
+ if (ctx->tx_done_callback[ep]) {
+ ctx->tx_done_callback[ep](ctx->ep_ctx[ep]);
+ }
+ }
+ }
+ }
+
+ if (istate & (1u << kDifUsbdevIrqPktReceived)) {
+ while (true) {
+ bool is_empty;
+ CHECK_DIF_OK(dif_usbdev_status_get_rx_fifo_empty(ctx->dev, &is_empty));
+ if (is_empty) {
+ break;
+ }
+
+ dif_usbdev_rx_packet_info_t packet_info;
+ dif_usbdev_buffer_t buffer;
+ CHECK_DIF_OK(dif_usbdev_recv(ctx->dev, &packet_info, &buffer));
+
+ uint8_t endpoint = packet_info.endpoint;
+ if (ctx->rx_callback[endpoint]) {
+ ctx->rx_callback[endpoint](ctx->ep_ctx[endpoint], packet_info, buffer);
+ } else {
+ TRC_S("USB: unexpected RX ");
+ TRC_I(rxinfo, 24);
+ CHECK_DIF_OK(
+ dif_usbdev_buffer_return(ctx->dev, ctx->buffer_pool, &buffer));
+ }
+ }
+ }
+ if (istate & (1u << kDifUsbdevIrqLinkReset)) {
+ TRC_S("USB: Bus reset");
+ // Link reset
+ for (int ep = 0; ep < USBDEV_NUM_ENDPOINTS; ep++) {
+ if (ctx->reset[ep]) {
+ ctx->reset[ep](ctx->ep_ctx[ep]);
+ }
+ }
+ }
+ if (istate &
+ ~((1u << kDifUsbdevIrqLinkReset) | (1u << kDifUsbdevIrqPktReceived) |
+ (1u << kDifUsbdevIrqPktSent))) {
+ TRC_C('I');
+ TRC_I(istate, 12);
+ TRC_C(' ');
+ }
+ // Clear the interupts
+ CHECK_DIF_OK(dif_usbdev_irq_acknowledge_all(ctx->dev));
+
+ // TODO - clean this up
+ // Frame ticks every 1ms, use to flush data every 16ms
+ // (faster in DPI but this seems to work ok)
+ // At reset frame count is 0, compare to 1 so no calls before SOF received
+ uint16_t usbframe;
+ CHECK_DIF_OK(dif_usbdev_status_get_frame(ctx->dev, &usbframe));
+ if ((usbframe & 0xf) == 1) {
+ if (ctx->flushed == 0) {
+ for (int i = 0; i < USBDEV_NUM_ENDPOINTS; i++) {
+ if (ctx->flush[i]) {
+ ctx->flush[i](ctx->ep_ctx[i]);
+ }
+ }
+ ctx->flushed = 1;
+ }
+ } else {
+ ctx->flushed = 0;
+ }
+ // TODO Errors? What Errors?
+}
+
+void usb_testutils_endpoint_setup(
+ usb_testutils_ctx_t *ctx, int ep,
+ usb_testutils_out_transfer_mode_t out_mode, void *ep_ctx,
+ void (*tx_done)(void *),
+ void (*rx)(void *, dif_usbdev_rx_packet_info_t, dif_usbdev_buffer_t),
+ void (*flush)(void *), void (*reset)(void *)) {
+ ctx->ep_ctx[ep] = ep_ctx;
+ ctx->tx_done_callback[ep] = tx_done;
+ ctx->rx_callback[ep] = rx;
+ ctx->flush[ep] = flush;
+ ctx->reset[ep] = reset;
+
+ dif_usbdev_endpoint_id_t endpoint = {
+ .number = ep,
+ .direction = USBDEV_ENDPOINT_DIR_IN,
+ };
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_enable(ctx->dev, endpoint, kDifToggleEnabled));
+
+ endpoint.direction = USBDEV_ENDPOINT_DIR_OUT;
+ if (out_mode != kUsbdevOutDisabled) {
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_enable(ctx->dev, endpoint, kDifToggleEnabled));
+ CHECK_DIF_OK(dif_usbdev_endpoint_out_enable(ctx->dev, endpoint.number,
+ kDifToggleEnabled));
+ }
+ if (out_mode == kUsbdevOutMessage) {
+ CHECK_DIF_OK(dif_usbdev_endpoint_set_nak_out_enable(
+ ctx->dev, endpoint.number, kDifToggleEnabled));
+ }
+}
+
+void usb_testutils_init(usb_testutils_ctx_t *ctx, bool pinflip,
+ bool en_diff_rcvr, bool tx_use_d_se0) {
+ CHECK(ctx != NULL);
+ ctx->dev = &usbdev;
+ ctx->buffer_pool = &buffer_pool;
+
+ CHECK_DIF_OK(
+ dif_usbdev_init(mmio_region_from_addr(USBDEV_BASE_ADDR), ctx->dev));
+
+ dif_usbdev_config_t config = {
+ .have_differential_receiver = dif_bool_to_toggle(en_diff_rcvr),
+ .use_tx_d_se0 = dif_bool_to_toggle(tx_use_d_se0),
+ .single_bit_eop = kDifToggleDisabled,
+ .pin_flip = dif_bool_to_toggle(pinflip),
+ .clock_sync_signals = kDifToggleEnabled,
+ };
+ CHECK_DIF_OK(dif_usbdev_configure(ctx->dev, ctx->buffer_pool, config));
+
+ // setup context
+ for (int i = 0; i < USBDEV_NUM_ENDPOINTS; i++) {
+ usb_testutils_endpoint_setup(ctx, i, kUsbdevOutDisabled, NULL, NULL, NULL,
+ NULL, NULL);
+ }
+
+ // All about polling...
+ CHECK_DIF_OK(dif_usbdev_irq_disable_all(ctx->dev, NULL));
+
+ // Provide buffers for any reception
+ CHECK_DIF_OK(dif_usbdev_fill_available_fifo(ctx->dev, ctx->buffer_pool));
+
+ dif_usbdev_endpoint_id_t endpoint = {
+ .number = 0,
+ .direction = 1,
+ };
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_enable(ctx->dev, endpoint, kDifToggleEnabled));
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_stall_enable(ctx->dev, endpoint, kDifToggleDisabled));
+
+ endpoint.direction = 0;
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_enable(ctx->dev, endpoint, kDifToggleEnabled));
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_stall_enable(ctx->dev, endpoint, kDifToggleDisabled));
+ CHECK_DIF_OK(dif_usbdev_endpoint_setup_enable(ctx->dev, endpoint.number,
+ kDifToggleEnabled));
+ CHECK_DIF_OK(dif_usbdev_endpoint_out_enable(ctx->dev, endpoint.number,
+ kDifToggleEnabled));
+}
+
+// `extern` declarations to give the inline functions in the
+// corresponding header a link location.
+
+extern int usb_testutils_halted(usb_testutils_ctx_t *ctx,
+ dif_usbdev_endpoint_id_t endpoint);
diff --git a/sw/device/lib/testing/usb_testutils.h b/sw/device/lib/testing/usb_testutils.h
new file mode 100644
index 0000000..1f57059
--- /dev/null
+++ b/sw/device/lib/testing/usb_testutils.h
@@ -0,0 +1,109 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_H_
+#define OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "sw/device/lib/dif/dif_usbdev.h"
+
+typedef struct usb_testutils_ctx usb_testutils_ctx_t;
+
+struct usb_testutils_ctx {
+ dif_usbdev_t *dev;
+ dif_usbdev_buffer_pool_t *buffer_pool;
+ int flushed;
+ void *ep_ctx[USBDEV_NUM_ENDPOINTS];
+ void (*tx_done_callback[USBDEV_NUM_ENDPOINTS])(void *);
+ void (*rx_callback[USBDEV_NUM_ENDPOINTS])(void *, dif_usbdev_rx_packet_info_t,
+ dif_usbdev_buffer_t);
+ void (*flush[USBDEV_NUM_ENDPOINTS])(void *);
+ void (*reset[USBDEV_NUM_ENDPOINTS])(void *);
+};
+
+/**
+ * Call regularly to poll the usbdev interface
+ *
+ * @param ctx usbdev context pointer
+ */
+void usb_testutils_poll(usb_testutils_ctx_t *ctx);
+
+typedef enum usb_testutils_out_transfer_mode {
+ /**
+ * The endpoint does not support OUT transactions.
+ */
+ kUsbdevOutDisabled = 0,
+ /**
+ * Software does NOT need to call usb_testutils_clear_out_nak() after every
+ * received transaction. If software takes no action, usbdev will allow an
+ * endpoint's transactions to proceed as long as a buffer is available.
+ */
+ kUsbdevOutStream = 1,
+ /**
+ * Software must call usb_testutils_clear_out_nak() after every received
+ * transaction to re-enable packet reception. This gives software time to
+ * respond with the appropriate handshake when it's ready.
+ */
+ kUsbdevOutMessage = 2,
+} usb_testutils_out_transfer_mode_t;
+
+/**
+ * Call to set up endpoints.
+ *
+ * Note that this library currently only supports setting up both the IN and OUT
+ * endpoints in the same call, using the same `ep_ctx` for their callbacks.
+ *
+ * @param ctx usbdev context pointer
+ * @param ep endpoint number
+ * @param out_mode the transfer mode for OUT transactions
+ * @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
+ * @param reset(void *ep_ctx) called when an USB link reset is detected
+ */
+void usb_testutils_endpoint_setup(usb_testutils_ctx_t *ctx, int ep,
+ usb_testutils_out_transfer_mode_t out_mode,
+ void *ep_ctx, void (*tx_done)(void *),
+ void (*rx)(void *,
+ dif_usbdev_rx_packet_info_t,
+ dif_usbdev_buffer_t),
+ void (*flush)(void *), void (*reset)(void *));
+
+/**
+ * Initialize the usbdev interface
+ *
+ * Does not connect the device, since the default endpoint is not yet enabled.
+ * See usb_testutils_connect().
+ *
+ * @param ctx uninitialized usbdev context pointer
+ * @param pinflip boolean to indicate if PHY should be configured for D+/D- flip
+ * @param en_diff_rcvr boolean to indicate if PHY should enable an external
+ * differential receiver, activating the single-ended D
+ * input
+ * @param tx_use_d_se0 boolean to indicate if PHY uses D/SE0 for TX instead of
+ * Dp/Dn
+ */
+void usb_testutils_init(usb_testutils_ctx_t *ctx, bool pinflip,
+ bool en_diff_rcvr, bool tx_use_d_se0);
+
+// Used for tracing what is going on. This may impact timing which is critical
+// when simulating with the USB DPI module.
+// #define ENABLE_TRC
+#ifdef ENABLE_TRC
+#include "sw/device/lib/runtime/log.h"
+#define TRC_S(s) LOG_INFO("%s", s)
+#define TRC_I(i, b) LOG_INFO("0x%x", i)
+#define TRC_C(c) LOG_INFO("%c", c)
+#else
+#define TRC_S(s)
+#define TRC_I(i, b)
+#define TRC_C(c)
+#endif
+
+#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_H_
diff --git a/sw/device/lib/testing/usb_testutils_controlep.c b/sw/device/lib/testing/usb_testutils_controlep.c
new file mode 100644
index 0000000..698f6d5
--- /dev/null
+++ b/sw/device/lib/testing/usb_testutils_controlep.c
@@ -0,0 +1,340 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/lib/testing/usb_testutils_controlep.h"
+
+#include "sw/device/lib/dif/dif_usbdev.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/usb_testutils.h"
+
+// Device descriptor
+static uint8_t dev_dscr[] = {
+ 18, // bLength
+ 1, // bDescriptorType
+ 0x00, // bcdUSB[0]
+ 0x02, // bcdUSB[1]
+ 0x00, // bDeviceClass (defined at interface level)
+ 0x00, // bDeviceSubClass
+ 0x00, // bDeviceProtocol
+ 64, // bMaxPacketSize0
+
+ 0xd1, // idVendor[0] 0x18d1 Google Inc.
+ 0x18, // idVendor[1]
+ 0x3a, // idProduct[0] lowRISC generic FS USB
+ 0x50, // idProduct[1] (allocated by Google)
+
+ 0, // bcdDevice[0]
+ 0x1, // bcdDevice[1]
+ 0, // iManufacturer
+ 0, // iProduct
+ 0, // iSerialNumber
+ 1 // bNumConfigurations
+};
+
+// SETUP requests
+typedef enum usb_setup_req {
+ kUsbSetupReqGetStatus = 0,
+ kUsbSetupReqClearFeature = 1,
+ kUsbSetupReqSetFeature = 3,
+ kUsbSetupReqSetAddress = 5,
+ kUsbSetupReqGetDescriptor = 6,
+ kUsbSetupReqSetDescriptor = 7,
+ kUsbSetupReqGetConfiguration = 8,
+ kUsbSetupReqSetConfiguration = 9,
+ kUsbSetupReqGetInterface = 10,
+ kUsbSetupReqSetInterface = 11,
+ kUsbSetupReqSynchFrame = 12
+} usb_setup_req_t;
+
+typedef enum usb_req_type { // bmRequestType
+ kUsbReqTypeRecipientMask = 0x1f,
+ kUsbReqTypeDevice = 0,
+ kUsbReqTypeInterface = 1,
+ kUsbReqTypeEndpoint = 2,
+ kUsbReqTypeOther = 3,
+ kUsbReqTypeTypeMask = 0x60,
+ KUsbReqTypeStandard = 0,
+ KUsbReqTypeClass = 0x20,
+ KUsbReqTypeVendor = 0x40,
+ KUsbReqTypeReserved = 0x60,
+ kUsbReqTypeDirMask = 0x80,
+ kUsbReqTypeDirH2D = 0x00,
+ kUsbReqTypeDirD2H = 0x80,
+} usb_req_type_t;
+
+typedef enum usb_feature_req {
+ kUsbFeatureEndpointHalt = 0, // recipient is endpoint
+ kUsbFeatureDeviceRemoteWakeup = 1, // recipient is device
+ kUsbFeatureTestMode = 2, // recipient is device
+ kUsbFeatureBHnpEnable = 3, // recipient is device only if OTG
+ kUsbFeatureAHnpSupport = 4, // recipient is device only if OTG
+ kUsbFeatureAAltHnpSupport = 5 // recipient is device only if OTG
+} usb_feature_req_t;
+
+typedef enum usb_status {
+ kUsbStatusSelfPowered = 1, // Device status request
+ kUsbStatusRemWake = 2, // Device status request
+ kUsbStatusHalted = 1 // Endpoint status request
+} usb_status_t;
+
+static usb_testutils_ctstate_t setup_req(usb_testutils_controlep_ctx_t *ctctx,
+ usb_testutils_ctx_t *ctx,
+ int bmRequestType, int bRequest,
+ int wValue, int wIndex, int wLength) {
+ size_t len;
+ uint32_t stat;
+ int zero, type;
+ size_t bytes_written;
+ dif_usbdev_endpoint_id_t endpoint = {
+ .number = bmRequestType & 0x0f,
+ .direction = bmRequestType & 0x80,
+ };
+ dif_usbdev_buffer_t buffer;
+ CHECK_DIF_OK(dif_usbdev_buffer_request(ctx->dev, ctx->buffer_pool, &buffer));
+ switch (bRequest) {
+ case kUsbSetupReqGetDescriptor:
+ if ((wValue & 0xff00) == 0x100) {
+ // Device descriptor
+ len = sizeof(dev_dscr);
+ if (wLength < len) {
+ len = wLength;
+ }
+ CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &buffer, dev_dscr, len,
+ &bytes_written));
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtWaitIn;
+ } else if ((wValue & 0xff00) == 0x200) {
+ // Configuration descriptor
+ len = ctctx->cfg_dscr_len;
+ if (wLength < len) {
+ len = wLength;
+ }
+ CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &buffer, ctctx->cfg_dscr,
+ len, &bytes_written));
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtWaitIn;
+ }
+ return kUsbTestutilsCtError; // unknown
+
+ case kUsbSetupReqSetAddress:
+ ctctx->new_dev = wValue & 0x7f;
+ // send zero length packet for status phase
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtAddrStatIn;
+
+ case kUsbSetupReqSetConfiguration:
+ // only ever expect this to be 1 since there is one config descriptor
+ ctctx->usb_config = wValue;
+ // send zero length packet for status phase
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ ctctx->device_state = kUsbTestutilsDeviceConfigured;
+ return kUsbTestutilsCtStatIn;
+
+ case kUsbSetupReqGetConfiguration:
+ len = sizeof(ctctx->usb_config);
+ if (wLength < len) {
+ len = wLength;
+ }
+ // return the value that was set
+ CHECK_DIF_OK(dif_usbdev_buffer_write(
+ ctx->dev, &buffer, &ctctx->usb_config, len, &bytes_written));
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtWaitIn;
+
+ case kUsbSetupReqSetFeature:
+ if (wValue == kUsbFeatureEndpointHalt) {
+ CHECK_DIF_OK(dif_usbdev_endpoint_stall_enable(ctx->dev, endpoint,
+ kDifToggleEnabled));
+ // send zero length packet for status phase
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtStatIn;
+ }
+ return kUsbTestutilsCtError; // unknown
+
+ case kUsbSetupReqClearFeature:
+ if (wValue == kUsbFeatureEndpointHalt) {
+ CHECK_DIF_OK(dif_usbdev_endpoint_stall_enable(ctx->dev, endpoint,
+ kDifToggleDisabled));
+ // send zero length packet for status phase
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ }
+ return kUsbTestutilsCtStatIn;
+
+ case kUsbSetupReqGetStatus:
+ len = 2;
+ type = bmRequestType & kUsbReqTypeRecipientMask;
+ if (type == kUsbReqTypeDevice) {
+ stat = kUsbStatusSelfPowered;
+ } else if (type == kUsbReqTypeEndpoint) {
+ bool halted;
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_stall_get(ctx->dev, endpoint, &halted));
+ stat = halted ? kUsbStatusHalted : 0;
+ } else {
+ stat = 0;
+ }
+ if (wLength < len) {
+ len = wLength;
+ }
+ // return the value that was set
+ CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &buffer, (uint8_t *)&stat,
+ len, &bytes_written));
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtWaitIn;
+
+ case kUsbSetupReqSetInterface:
+ // Don't support alternate interfaces, so just ignore
+ // send zero length packet for status phase
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtStatIn;
+
+ case kUsbSetupReqGetInterface:
+ zero = 0;
+ len = 1;
+ if (wLength < len) {
+ len = wLength;
+ }
+ // Don't support interface, so return zero
+ CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &buffer, (uint8_t *)&zero,
+ len, &bytes_written));
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtWaitIn;
+
+ case kUsbSetupReqSynchFrame:
+ zero = 0;
+ len = 2;
+ if (wLength < len) {
+ len = wLength;
+ }
+ // Don't support synch_frame so return zero
+ CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &buffer, (uint8_t *)&zero,
+ len, &bytes_written));
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ctctx->ep, &buffer));
+ return kUsbTestutilsCtWaitIn;
+
+ default:
+ return kUsbTestutilsCtError;
+ }
+ return kUsbTestutilsCtError;
+}
+
+static void ctrl_tx_done(void *ctctx_v) {
+ usb_testutils_controlep_ctx_t *ctctx =
+ (usb_testutils_controlep_ctx_t *)ctctx_v;
+ usb_testutils_ctx_t *ctx = ctctx->ctx;
+ TRC_C('A' + ctctx->ctrlstate);
+ switch (ctctx->ctrlstate) {
+ case kUsbTestutilsCtAddrStatIn:
+ // Now the status was sent on device 0 can switch to new device ID
+ CHECK_DIF_OK(dif_usbdev_address_set(ctx->dev, ctctx->new_dev));
+ TRC_I(ctctx->new_dev, 8);
+ ctctx->ctrlstate = kUsbTestutilsCtIdle;
+ // Should be kUsbTestutilsDeviceAddressed only, but test controller is
+ // borked ctctx->device_state = kUsbTestutilsDeviceAddressed;
+ ctctx->device_state = kUsbTestutilsDeviceConfigured;
+ return;
+ case kUsbTestutilsCtStatIn:
+ ctctx->ctrlstate = kUsbTestutilsCtIdle;
+ return;
+ case kUsbTestutilsCtWaitIn:
+ ctctx->ctrlstate = kUsbTestutilsCtStatOut;
+ return;
+ default:
+ break;
+ }
+ TRC_S("USB: unexpected IN ");
+ TRC_I((ctctx->ctrlstate << 24), 32);
+}
+
+static void ctrl_rx(void *ctctx_v, dif_usbdev_rx_packet_info_t packet_info,
+ dif_usbdev_buffer_t buffer) {
+ usb_testutils_controlep_ctx_t *ctctx =
+ (usb_testutils_controlep_ctx_t *)ctctx_v;
+ usb_testutils_ctx_t *ctx = ctctx->ctx;
+ CHECK_DIF_OK(dif_usbdev_endpoint_out_enable(ctx->dev, /*endpoint=*/0,
+ kDifToggleEnabled));
+
+ TRC_C('0' + ctctx->ctrlstate);
+ uint32_t bytes_written;
+ // TODO: Should check for canceled IN transactions due to receiving a SETUP
+ // packet.
+ switch (ctctx->ctrlstate) {
+ case kUsbTestutilsCtIdle:
+ // Waiting to be set up
+ if (packet_info.is_setup && (packet_info.length == 8)) {
+ alignas(uint32_t) uint8_t bp[8];
+ CHECK_DIF_OK(dif_usbdev_buffer_read(ctx->dev, ctx->buffer_pool, &buffer,
+ bp, sizeof(bp), &bytes_written));
+ int bmRequestType = bp[0];
+ int bRequest = bp[1];
+ int wValue = (bp[3] << 8) | bp[2];
+ int wIndex = (bp[5] << 8) | bp[4];
+ int wLength = (bp[7] << 8) | bp[6];
+ TRC_C('0' + bRequest);
+
+ ctctx->ctrlstate = setup_req(ctctx, ctx, bmRequestType, bRequest,
+ wValue, wIndex, wLength);
+ if (ctctx->ctrlstate != kUsbTestutilsCtError) {
+ return;
+ }
+ }
+ break;
+
+ case kUsbTestutilsCtStatOut:
+ // Have sent some data, waiting STATUS stage
+ if (!packet_info.is_setup && (packet_info.length == 0)) {
+ CHECK_DIF_OK(
+ dif_usbdev_buffer_return(ctx->dev, ctx->buffer_pool, &buffer));
+ ctctx->ctrlstate = kUsbTestutilsCtIdle;
+ return;
+ }
+ // anything else is unexpected
+ break;
+
+ default:
+ // Error
+ break;
+ }
+ dif_usbdev_endpoint_id_t endpoint = {
+ .number = 0,
+ .direction = USBDEV_ENDPOINT_DIR_IN,
+ };
+ // Enable responding with STALL. Will be cleared by the HW.
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_stall_enable(ctx->dev, endpoint, kDifToggleEnabled));
+ endpoint.direction = USBDEV_ENDPOINT_DIR_OUT;
+ CHECK_DIF_OK(
+ dif_usbdev_endpoint_stall_enable(ctx->dev, endpoint, kDifToggleEnabled));
+ TRC_S("USB: unCT ");
+ TRC_I((ctctx->ctrlstate << 24) | setup << 16 | size, 32);
+ TRC_C(':');
+ for (int i = 0; i < packet_info.length; i++) {
+ TRC_I(bp[i], 8);
+ TRC_C(' ');
+ }
+ CHECK_DIF_OK(dif_usbdev_buffer_return(ctx->dev, ctx->buffer_pool, &buffer));
+ ctctx->ctrlstate = kUsbTestutilsCtIdle;
+}
+
+// Callback for the USB link reset
+static void ctrl_reset(void *ctctx_v) {
+ usb_testutils_controlep_ctx_t *ctctx =
+ (usb_testutils_controlep_ctx_t *)ctctx_v;
+ ctctx->ctrlstate = kUsbTestutilsCtIdle;
+}
+
+void usb_testutils_controlep_init(usb_testutils_controlep_ctx_t *ctctx,
+ usb_testutils_ctx_t *ctx, int ep,
+ const uint8_t *cfg_dscr,
+ size_t cfg_dscr_len) {
+ ctctx->ctx = ctx;
+ usb_testutils_endpoint_setup(ctx, ep, kUsbdevOutMessage, ctctx, ctrl_tx_done,
+ ctrl_rx, NULL, ctrl_reset);
+ ctctx->ep = ep;
+ ctctx->ctrlstate = kUsbTestutilsCtIdle;
+ ctctx->cfg_dscr = cfg_dscr;
+ ctctx->cfg_dscr_len = cfg_dscr_len;
+ CHECK_DIF_OK(dif_usbdev_interface_enable(ctx->dev, kDifToggleEnabled));
+ ctctx->device_state = kUsbTestutilsDeviceDefault;
+}
diff --git a/sw/device/lib/usb_controlep.h b/sw/device/lib/testing/usb_testutils_controlep.h
similarity index 73%
rename from sw/device/lib/usb_controlep.h
rename to sw/device/lib/testing/usb_testutils_controlep.h
index 9333af1..eeacbd4 100644
--- a/sw/device/lib/usb_controlep.h
+++ b/sw/device/lib/testing/usb_testutils_controlep.h
@@ -2,42 +2,43 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-#ifndef OPENTITAN_SW_DEVICE_LIB_USB_CONTROLEP_H_
-#define OPENTITAN_SW_DEVICE_LIB_USB_CONTROLEP_H_
+#ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_CONTROLEP_H_
+#define OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_CONTROLEP_H_
#include <stddef.h>
#include <stdint.h>
-#include "sw/device/lib/usbdev.h"
+#include "sw/device/lib/testing/usb_testutils.h"
-typedef enum ctstate {
- kCtIdle,
- kCtWaitIn, // Queued IN data stage, waiting ack
- kCtStatOut, // Waiting for OUT status stage
- kCtAddrStatIn, // Queued status stage, waiting ack afterwhich set dev_addr
- kCtStatIn, // Queued status stage, waiting ack
- kCtError // Something bad
-} ctstate_t;
+typedef enum usb_testutils_ctstate {
+ kUsbTestutilsCtIdle,
+ kUsbTestutilsCtWaitIn, // Queued IN data stage, waiting ack
+ kUsbTestutilsCtStatOut, // Waiting for OUT status stage
+ kUsbTestutilsCtAddrStatIn, // Queued status stage, waiting ack afterwhich set
+ // dev_addr
+ kUsbTestutilsCtStatIn, // Queued status stage, waiting ack
+ kUsbTestutilsCtError // Something bad
+} usb_testutils_ctstate_t;
-typedef enum usbdevice_state {
- kUsbDeviceAttached,
- kUsbDevicePowered,
- kUsbDeviceDefault,
- kUsbDeviceAddressed,
- kUsbDeviceConfigured,
- kUsbDeviceSuspended,
-} usb_device_state_t;
+typedef enum usb_testutils_device_state {
+ kUsbTestutilsDeviceAttached,
+ kUsbTestutilsDevicePowered,
+ kUsbTestutilsDeviceDefault,
+ kUsbTestutilsDeviceAddressed,
+ kUsbTestutilsDeviceConfigured,
+ kUsbTestutilsDeviceSuspended,
+} usb_testutils_device_state_t;
-typedef struct usb_controlep_ctx {
- usbdev_ctx_t *ctx;
+typedef struct usb_testutils_controlep_ctx {
+ usb_testutils_ctx_t *ctx;
int ep;
- ctstate_t ctrlstate;
- usb_device_state_t device_state;
+ usb_testutils_ctstate_t ctrlstate;
+ usb_testutils_device_state_t device_state;
uint32_t new_dev;
uint8_t usb_config;
const uint8_t *cfg_dscr;
size_t cfg_dscr_len;
-} usb_controlep_ctx_t;
+} usb_testutils_controlep_ctx_t;
/**
* Initialize control endpoint
@@ -48,8 +49,9 @@
* @param cfg_dscr configuration descriptor for the device
* @param cfg_dscr_len length of cfg_dscr
*/
-void usb_controlep_init(usb_controlep_ctx_t *ctctx, usbdev_ctx_t *ctx, int ep,
- const uint8_t *cfg_dscr, size_t cfg_dscr_len);
+void usb_testutils_controlep_init(usb_testutils_controlep_ctx_t *ctctx,
+ usb_testutils_ctx_t *ctx, int ep,
+ const uint8_t *cfg_dscr, size_t cfg_dscr_len);
/********************************************************************/
/* Below this point are macros used to construct the USB descriptor */
@@ -104,4 +106,4 @@
// KEEP BLANK LINE ABOVE, it is in the macro!
-#endif // OPENTITAN_SW_DEVICE_LIB_USB_CONTROLEP_H_
+#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_CONTROLEP_H_
diff --git a/sw/device/lib/testing/usb_testutils_simpleserial.c b/sw/device/lib/testing/usb_testutils_simpleserial.c
new file mode 100644
index 0000000..05a799d
--- /dev/null
+++ b/sw/device/lib/testing/usb_testutils_simpleserial.c
@@ -0,0 +1,76 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/lib/testing/usb_testutils_simpleserial.h"
+
+#include "sw/device/lib/dif/dif_usbdev.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/usb_testutils.h"
+
+#define MAX_GATHER 16
+
+static void ss_rx(void *ssctx_v, dif_usbdev_rx_packet_info_t packet_info,
+ dif_usbdev_buffer_t buffer) {
+ usb_testutils_ss_ctx_t *ssctx = (usb_testutils_ss_ctx_t *)ssctx_v;
+ usb_testutils_ctx_t *ctx = ssctx->ctx;
+
+ while (packet_info.length--) {
+ uint8_t data;
+ size_t bytes_written;
+ CHECK_DIF_OK(dif_usbdev_buffer_read(ctx->dev, ctx->buffer_pool, &buffer,
+ &data, sizeof(data), &bytes_written));
+ ssctx->got_byte(data);
+ }
+}
+
+// Called periodically by the main loop to ensure characters don't
+// stick around too long
+static void ss_flush(void *ssctx_v) {
+ usb_testutils_ss_ctx_t *ssctx = (usb_testutils_ss_ctx_t *)ssctx_v;
+ usb_testutils_ctx_t *ctx = ssctx->ctx;
+ if (ssctx->cur_cpos <= 0) {
+ return;
+ }
+ if ((ssctx->cur_cpos & 0x3) != 0) {
+ size_t bytes_written;
+ CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &ssctx->cur_buf,
+ ssctx->chold.data_b, /*src_len=*/4,
+ &bytes_written));
+ }
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ssctx->ep, &ssctx->cur_buf));
+ ssctx->cur_cpos = -1; // given it to the hardware
+}
+
+// Simple send byte will gather data for a while and send
+void usb_testutils_simpleserial_send_byte(usb_testutils_ss_ctx_t *ssctx,
+ uint8_t c) {
+ usb_testutils_ctx_t *ctx = ssctx->ctx;
+ if (ssctx->cur_cpos == -1) {
+ CHECK_DIF_OK(
+ dif_usbdev_buffer_request(ctx->dev, ctx->buffer_pool, &ssctx->cur_buf));
+ ssctx->cur_cpos = 0;
+ }
+ ssctx->chold.data_b[ssctx->cur_cpos++ & 0x3] = c;
+ if ((ssctx->cur_cpos & 0x3) == 0) {
+ size_t bytes_written;
+ CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &ssctx->cur_buf,
+ ssctx->chold.data_b, /*src_len=*/4,
+ &bytes_written));
+ if (ssctx->cur_cpos >= MAX_GATHER) {
+ CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ssctx->ep, &ssctx->cur_buf));
+ ssctx->cur_cpos = -1; // given it to the hardware
+ }
+ }
+}
+
+void usb_testutils_simpleserial_init(usb_testutils_ss_ctx_t *ssctx,
+ usb_testutils_ctx_t *ctx, int ep,
+ void (*got_byte)(uint8_t)) {
+ usb_testutils_endpoint_setup(ctx, ep, kUsbdevOutStream, ssctx, NULL, ss_rx,
+ ss_flush, NULL);
+ ssctx->ctx = ctx;
+ ssctx->ep = ep;
+ ssctx->got_byte = got_byte;
+ ssctx->cur_cpos = -1;
+}
diff --git a/sw/device/lib/testing/usb_testutils_simpleserial.h b/sw/device/lib/testing/usb_testutils_simpleserial.h
new file mode 100644
index 0000000..3172f87
--- /dev/null
+++ b/sw/device/lib/testing/usb_testutils_simpleserial.h
@@ -0,0 +1,48 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_SIMPLESERIAL_H_
+#define OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_SIMPLESERIAL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "sw/device/lib/dif/dif_usbdev.h"
+#include "sw/device/lib/testing/usb_testutils.h"
+
+// This is only here because caller of _init needs it
+typedef struct usb_testutils_ss_ctx {
+ usb_testutils_ctx_t *ctx;
+ int ep;
+ dif_usbdev_buffer_t cur_buf;
+ int cur_cpos;
+ union usb_ss_b2w {
+ uint32_t data_w;
+ uint8_t data_b[4];
+ } chold;
+ void (*got_byte)(uint8_t);
+} usb_testutils_ss_ctx_t;
+
+/**
+ * Send a byte on a simpleserial endpoint
+ *
+ * @param ssctx instance context
+ * @param c byte to send
+ */
+void usb_testutils_simpleserial_send_byte(usb_testutils_ss_ctx_t *ssctx,
+ uint8_t c);
+
+/**
+ * Initialize a simpleserial endpoint
+ *
+ * @param ssctx unintialized simpleserial instance context
+ * @param ctx initialized usbdev context
+ * @param ep endpoint number for this instance
+ * @param got_byte callback function for when a byte is received
+ */
+void usb_testutils_simpleserial_init(usb_testutils_ss_ctx_t *ssctx,
+ usb_testutils_ctx_t *ctx, int ep,
+ void (*got_byte)(uint8_t));
+
+#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_USB_TESTUTILS_SIMPLESERIAL_H_
diff --git a/sw/device/lib/usb_consts.h b/sw/device/lib/usb_consts.h
deleted file mode 100644
index 460393f..0000000
--- a/sw/device/lib/usb_consts.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-#ifndef OPENTITAN_SW_DEVICE_LIB_USB_CONSTS_H_
-#define OPENTITAN_SW_DEVICE_LIB_USB_CONSTS_H_
-
-// SETUP requests
-typedef enum usb_setup_req {
- kUsbSetupReqGetStatus = 0,
- kUsbSetupReqClearFeature = 1,
- kUsbSetupReqSetFeature = 3,
- kUsbSetupReqSetAddress = 5,
- kUsbSetupReqGetDescriptor = 6,
- kUsbSetupReqSetDescriptor = 7,
- kUsbSetupReqGetConfiguration = 8,
- kUsbSetupReqSetConfiguration = 9,
- kUsbSetupReqGetInterface = 10,
- kUsbSetupReqSetInterface = 11,
- kUsbSetupReqSynchFrame = 12
-} usb_setup_req_t;
-
-typedef enum usb_req_type { // bmRequestType
- kUsbReqTypeRecipientMask = 0x1f,
- kUsbReqTypeDevice = 0,
- kUsbReqTypeInterface = 1,
- kUsbReqTypeEndpoint = 2,
- kUsbReqTypeOther = 3,
- kUsbReqTypeTypeMask = 0x60,
- KUsbReqTypeStandard = 0,
- KUsbReqTypeClass = 0x20,
- KUsbReqTypeVendor = 0x40,
- KUsbReqTypeReserved = 0x60,
- kUsbReqTypeDirMask = 0x80,
- kUsbReqTypeDirH2D = 0x00,
- kUsbReqTypeDirD2H = 0x80,
-} usb_req_type_t;
-
-typedef enum usb_feature_req {
- kUsbFeatureEndpointHalt = 0, // recipient is endpoint
- kUsbFeatureDeviceRemoteWakeup = 1, // recipient is device
- kUsbFeatureTestMode = 2, // recipient is device
- kUsbFeatureBHnpEnable = 3, // recipient is device only if OTG
- kUsbFeatureAHnpSupport = 4, // recipient is device only if OTG
- kUsbFeatureAAltHnpSupport = 5 // recipient is device only if OTG
-} usb_feature_req_t;
-
-typedef enum usb_status {
- kUsbStatusSelfPowered = 1, // Device status request
- kUsbStatusRemWake = 2, // Device status request
- kUsbStatusHalted = 1 // Endpoint status request
-} usb_status_t;
-
-#endif // OPENTITAN_SW_DEVICE_LIB_USB_CONSTS_H_
diff --git a/sw/device/lib/usb_controlep.c b/sw/device/lib/usb_controlep.c
deleted file mode 100644
index 466a6bd..0000000
--- a/sw/device/lib/usb_controlep.c
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-#include "sw/device/lib/usb_controlep.h"
-
-#include "sw/device/lib/usb_consts.h"
-#include "sw/device/lib/usbdev.h"
-
-// Device descriptor
-static uint8_t dev_dscr[] = {
- 18, // bLength
- 1, // bDescriptorType
- 0x00, // bcdUSB[0]
- 0x02, // bcdUSB[1]
- 0x00, // bDeviceClass (defined at interface level)
- 0x00, // bDeviceSubClass
- 0x00, // bDeviceProtocol
- 64, // bMaxPacketSize0
-
- 0xd1, // idVendor[0] 0x18d1 Google Inc.
- 0x18, // idVendor[1]
- 0x3a, // idProduct[0] lowRISC generic FS USB
- 0x50, // idProduct[1] (allocated by Google)
-
- 0, // bcdDevice[0]
- 0x1, // bcdDevice[1]
- 0, // iManufacturer
- 0, // iProduct
- 0, // iSerialNumber
- 1 // bNumConfigurations
-};
-
-static ctstate_t setup_req(usb_controlep_ctx_t *ctctx, void *ctx,
- usbbufid_t buf, int bmRequestType, int bRequest,
- int wValue, int wIndex, int wLength) {
- size_t len;
- uint32_t stat;
- int zero, type;
- switch (bRequest) {
- case kUsbSetupReqGetDescriptor:
- if ((wValue & 0xff00) == 0x100) {
- // Device descriptor
- len = sizeof(dev_dscr);
- if (wLength < len) {
- len = wLength;
- }
- usbdev_buf_copyto_byid(ctx, buf, dev_dscr, len);
- usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
- return kCtWaitIn;
- } else if ((wValue & 0xff00) == 0x200) {
- // Configuration descriptor
- len = ctctx->cfg_dscr_len;
- if (wLength < len) {
- len = wLength;
- }
- usbdev_buf_copyto_byid(ctx, buf, ctctx->cfg_dscr, len);
- usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
- return kCtWaitIn;
- }
- return kCtError; // unknown
-
- case kUsbSetupReqSetAddress:
- ctctx->new_dev = wValue & 0x7f;
- // send zero length packet for status phase
- usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
- return kCtAddrStatIn;
-
- case kUsbSetupReqSetConfiguration:
- // only ever expect this to be 1 since there is one config descriptor
- ctctx->usb_config = wValue;
- // send zero length packet for status phase
- usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
- ctctx->device_state = kUsbDeviceConfigured;
- return kCtStatIn;
-
- case kUsbSetupReqGetConfiguration:
- len = sizeof(ctctx->usb_config);
- if (wLength < len) {
- len = wLength;
- }
- // return the value that was set
- usbdev_buf_copyto_byid(ctx, buf, &ctctx->usb_config, len);
- usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
- return kCtWaitIn;
-
- case kUsbSetupReqSetFeature:
- if (wValue == kUsbFeatureEndpointHalt) {
- usbdev_halt(ctx, wIndex, 1);
- } else if (wValue == kUsbFeatureDeviceRemoteWakeup) {
- usbdev_rem_wake_en(ctx, 1);
- }
- // send zero length packet for status phase
- usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
- return kCtStatIn;
-
- case kUsbSetupReqClearFeature:
- if (wValue == kUsbFeatureEndpointHalt) {
- usbdev_halt(ctx, wIndex, 0);
- } else if (wValue == kUsbFeatureDeviceRemoteWakeup) {
- usbdev_rem_wake_en(ctx, 0);
- }
- // send zero length packet for status phase
- usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
- return kCtStatIn;
-
- case kUsbSetupReqGetStatus:
- len = 2;
- type = bmRequestType & kUsbReqTypeRecipientMask;
- if (type == kUsbReqTypeDevice) {
- stat = (usbdev_can_rem_wake(ctx) ? kUsbStatusRemWake : 0) |
- kUsbStatusSelfPowered;
- } else if (type == kUsbReqTypeEndpoint) {
- stat = usbdev_halted(ctx, wIndex) ? kUsbStatusHalted : 0;
- } else {
- stat = 0;
- }
- if (wLength < len) {
- len = wLength;
- }
- // return the value that was set
- usbdev_buf_copyto_byid(ctx, buf, &stat, len);
- usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
- return kCtWaitIn;
-
- case kUsbSetupReqSetInterface:
- // Don't support alternate interfaces, so just ignore
- // send zero length packet for status phase
- usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
- return kCtStatIn;
-
- case kUsbSetupReqGetInterface:
- zero = 0;
- len = 1;
- if (wLength < len) {
- len = wLength;
- }
- // Don't support interface, so return zero
- usbdev_buf_copyto_byid(ctx, buf, &zero, len);
- usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
- return kCtWaitIn;
-
- case kUsbSetupReqSynchFrame:
- zero = 0;
- len = 2;
- if (wLength < len) {
- len = wLength;
- }
- // Don't support synch_frame so return zero
- usbdev_buf_copyto_byid(ctx, buf, &zero, len);
- usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
- return kCtWaitIn;
-
- default:
- return kCtError;
- }
- return kCtError;
-}
-
-static void ctrl_tx_done(void *ctctx_v) {
- usb_controlep_ctx_t *ctctx = (usb_controlep_ctx_t *)ctctx_v;
- void *ctx = ctctx->ctx;
- TRC_C('A' + ctctx->ctrlstate);
- switch (ctctx->ctrlstate) {
- case kCtAddrStatIn:
- // Now the status was sent on device 0 can switch to new device ID
- usbdev_set_deviceid(ctx, ctctx->new_dev);
- TRC_I(ctctx->new_dev, 8);
- ctctx->ctrlstate = kCtIdle;
- // Should be kUsbDeviceAddressed only, but test controller is borked
- // ctctx->device_state = kUsbDeviceAddressed;
- ctctx->device_state = kUsbDeviceConfigured;
- return;
- case kCtStatIn:
- ctctx->ctrlstate = kCtIdle;
- return;
- case kCtWaitIn:
- ctctx->ctrlstate = kCtStatOut;
- return;
- default:
- break;
- }
- TRC_S("USB: unexpected IN ");
- TRC_I((ctctx->ctrlstate << 24), 32);
-}
-
-static void ctrl_rx(void *ctctx_v, usbbufid_t buf, int size, int setup) {
- usb_controlep_ctx_t *ctctx = (usb_controlep_ctx_t *)ctctx_v;
- void *ctx = ctctx->ctx;
- usbdev_clear_out_nak(ctx, 0);
- volatile uint8_t *bp = (volatile uint8_t *)usbdev_buf_idtoaddr(ctx, buf);
- if (size > BUF_LENGTH) {
- size = BUF_LENGTH;
- }
-
- TRC_C('0' + ctctx->ctrlstate);
- switch (ctctx->ctrlstate) {
- case kCtIdle:
- // Waiting to be set up
- if (setup && (size == 8)) {
- int bmRequestType = bp[0];
- int bRequest = bp[1];
- int wValue = (bp[3] << 8) | bp[2];
- int wIndex = (bp[5] << 8) | bp[4];
- int wLength = (bp[7] << 8) | bp[6];
- TRC_C('0' + bRequest);
-
- ctctx->ctrlstate = setup_req(ctctx, ctx, buf, bmRequestType, bRequest,
- wValue, wIndex, wLength);
- if (ctctx->ctrlstate != kCtError) {
- return;
- }
- }
- break;
-
- case kCtStatOut:
- // Have sent some data, waiting STATUS stage
- if (!setup && (size == 0)) {
- ctctx->ctrlstate = kCtIdle;
- return;
- }
- // anything else is unexpected
- break;
-
- default:
- // Error
- break;
- }
- usbdev_set_ep0_stall(ctx, 1); // send a STALL, will be cleared by the HW
- TRC_S("USB: unCT ");
- TRC_I((ctctx->ctrlstate << 24) | setup << 16 | size, 32);
- TRC_C(':');
- for (int i = 0; i < size; i++) {
- TRC_I(bp[i], 8);
- TRC_C(' ');
- }
- usbdev_buf_free_byid(ctx, buf);
- ctctx->ctrlstate = kCtIdle;
-}
-
-// Callback for the USB link reset
-void ctrl_reset(void *ctctx_v) {
- usb_controlep_ctx_t *ctctx = (usb_controlep_ctx_t *)ctctx_v;
- ctctx->ctrlstate = kCtIdle;
-}
-
-void usb_controlep_init(usb_controlep_ctx_t *ctctx, usbdev_ctx_t *ctx, int ep,
- const uint8_t *cfg_dscr, size_t cfg_dscr_len) {
- ctctx->ctx = ctx;
- usbdev_endpoint_setup(ctx, ep, kUsbdevOutMessage, ctctx, ctrl_tx_done,
- ctrl_rx, NULL, ctrl_reset);
- ctctx->ctrlstate = kCtIdle;
- ctctx->cfg_dscr = cfg_dscr;
- ctctx->cfg_dscr_len = cfg_dscr_len;
- usbdev_connect(ctx);
- ctctx->device_state = kUsbDeviceDefault;
-}
diff --git a/sw/device/lib/usb_simpleserial.c b/sw/device/lib/usb_simpleserial.c
deleted file mode 100644
index 03ae9a2..0000000
--- a/sw/device/lib/usb_simpleserial.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-#include "sw/device/lib/usb_simpleserial.h"
-
-#include "sw/device/lib/usbdev.h"
-
-#define MAX_GATHER 16
-
-static void ss_rx(void *ssctx_v, usbbufid_t buf, int size, int setup) {
- usb_ss_ctx_t *ssctx = (usb_ss_ctx_t *)ssctx_v;
- void *ctx = ssctx->ctx;
- volatile uint8_t *bp = (volatile uint8_t *)usbdev_buf_idtoaddr(ctx, buf);
-
- if (size > BUF_LENGTH) {
- size = BUF_LENGTH;
- }
-
- while (size--) {
- ssctx->got_byte(*bp++);
- }
-}
-
-// Called periodically by the main loop to ensure characters don't
-// stick around too long
-static void ss_flush(void *ssctx_v) {
- usb_ss_ctx_t *ssctx = (usb_ss_ctx_t *)ssctx_v;
- void *ctx = ssctx->ctx;
- volatile uint32_t *bp_w;
- if ((ssctx->cur_buf == -1) || (ssctx->cur_cpos <= 0)) {
- return;
- }
- if ((ssctx->cur_cpos & 0x3) != 0) {
- // unwritten data to copy over
- bp_w = usbdev_buf_idtoaddr(ctx, ssctx->cur_buf);
- // no -1 here because cpos is in the word we are writing
- bp_w[(ssctx->cur_cpos / 4)] = ssctx->chold.data_w;
- }
- usbdev_sendbuf_byid(ctx, ssctx->cur_buf, ssctx->cur_cpos, ssctx->ep);
- ssctx->cur_buf = -1; // given it to the hardware
-}
-
-// Simple send byte will gather data for a while and send
-void usb_simpleserial_send_byte(usb_ss_ctx_t *ssctx, uint8_t c) {
- volatile uint32_t *bp_w;
- if (ssctx->cur_buf == -1) {
- ssctx->cur_buf = usbdev_buf_allocate_byid(ssctx->ctx);
- ssctx->cur_cpos = 0;
- }
- // Abort if completely out of buffers and allocation returned -1
- if (ssctx->cur_buf < 0) {
- return;
- }
- ssctx->chold.data_b[ssctx->cur_cpos++ & 0x3] = c;
- if ((ssctx->cur_cpos & 0x3) == 0) {
- // just wrote last byte in word
- bp_w = usbdev_buf_idtoaddr(ssctx->ctx, ssctx->cur_buf);
- // -1 here because cpos already incremented to next word
- bp_w[(ssctx->cur_cpos / 4) - 1] = ssctx->chold.data_w;
- if (ssctx->cur_cpos >= MAX_GATHER) {
- usbdev_sendbuf_byid(ssctx->ctx, ssctx->cur_buf, ssctx->cur_cpos,
- ssctx->ep);
- ssctx->cur_buf = -1; // given it to the hardware
- }
- }
-}
-
-void usb_simpleserial_init(usb_ss_ctx_t *ssctx, usbdev_ctx_t *ctx, int ep,
- void (*got_byte)(uint8_t)) {
- usbdev_endpoint_setup(ctx, ep, kUsbdevOutStream, ssctx, NULL, ss_rx, ss_flush,
- NULL);
- ssctx->ctx = ctx;
- ssctx->ep = ep;
- ssctx->got_byte = got_byte;
- ssctx->cur_buf = -1;
-}
diff --git a/sw/device/lib/usb_simpleserial.h b/sw/device/lib/usb_simpleserial.h
deleted file mode 100644
index 8a81875..0000000
--- a/sw/device/lib/usb_simpleserial.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-#ifndef OPENTITAN_SW_DEVICE_LIB_USB_SIMPLESERIAL_H_
-#define OPENTITAN_SW_DEVICE_LIB_USB_SIMPLESERIAL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "sw/device/lib/usbdev.h"
-
-// This is only here because caller of _init needs it
-typedef struct usb_ss_ctx {
- void *ctx;
- int ep;
- int cur_buf;
- int cur_cpos;
- union usb_ss_b2w {
- uint32_t data_w;
- uint8_t data_b[4];
- } chold;
- void (*got_byte)(uint8_t);
-} usb_ss_ctx_t;
-
-/**
- * Send a byte on a simpleserial endpoint
- *
- * @param ssctx instance context
- * @param c byte to send
- */
-void usb_simpleserial_send_byte(usb_ss_ctx_t *ssctx, uint8_t c);
-
-/**
- * Initialize a simpleserial endpoint
- *
- * @param ssctx unintialized simpleserial instance context
- * @param ctx initialized usbdev context
- * @param ep endpoint number for this instance
- * @param got_byte callback function for when a byte is received
- */
-void usb_simpleserial_init(usb_ss_ctx_t *ssctx, usbdev_ctx_t *ctx, int ep,
- void (*got_byte)(uint8_t));
-
-#endif // OPENTITAN_SW_DEVICE_LIB_USB_SIMPLESERIAL_H_
diff --git a/sw/device/lib/usbdev.c b/sw/device/lib/usbdev.c
deleted file mode 100644
index f948458..0000000
--- a/sw/device/lib/usbdev.c
+++ /dev/null
@@ -1,382 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-#include "sw/device/lib/usbdev.h"
-
-#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
-#include "usbdev_regs.h" // Generated.
-
-#define USBDEV_BASE_ADDR TOP_EARLGREY_USBDEV_BASE_ADDR
-
-#define EXTRACT(n, f) ((n >> USBDEV_##f##_OFFSET) & USBDEV_##f##_MASK)
-
-#define SETBIT(val, bit) (val | 1 << bit)
-#define CLRBIT(val, bit) (val & ~(1 << bit))
-
-#define REG32(add) *((volatile uint32_t *)(add))
-
-static bool endpoint_is_in(uint8_t endpoint) { return endpoint & 0x80; }
-
-static uint8_t endpoint_number(uint8_t endpoint) { return endpoint & 0x7F; }
-
-// Free buffer pool is held on a simple stack
-// Initalize to all buffer IDs are free
-static void buf_init(usbdev_ctx_t *ctx) {
- for (int i = 0; i < NUM_BUFS; i++) {
- ctx->freebuf[i] = i;
- }
- ctx->nfree = NUM_BUFS;
-}
-
-// Allocating a buffer just pops next ID from the stack
-usbbufid_t usbdev_buf_allocate_byid(usbdev_ctx_t *ctx) {
- if (ctx->nfree <= 0) {
- return -1;
- }
- return ctx->freebuf[--ctx->nfree];
-}
-
-// Freeing a buffer just pushes the ID back on the stack
-int usbdev_buf_free_byid(usbdev_ctx_t *ctx, usbbufid_t buf) {
- if ((ctx->nfree >= NUM_BUFS) || (buf >= NUM_BUFS)) {
- return -1;
- }
- ctx->freebuf[ctx->nfree++] = buf;
- return 0;
-}
-
-uint32_t *usbdev_buf_idtoaddr(usbdev_ctx_t *ctx, usbbufid_t buf) {
- return (uint32_t *)(USBDEV_BASE_ADDR + USBDEV_BUFFER_REG_OFFSET +
- (buf * BUF_LENGTH));
-}
-
-void usbdev_buf_copyto_byid(usbdev_ctx_t *ctx, usbbufid_t buf, const void *from,
- size_t len_bytes) {
- int32_t *from_word = (int32_t *)from;
- int len_words;
- volatile uint32_t *bp = usbdev_buf_idtoaddr(ctx, buf);
-
- if (len_bytes > BUF_LENGTH) {
- len_bytes = BUF_LENGTH;
- }
- // This will round up if len_bytes is not on a multiple of int32_t
- // Always ok to fill the extra bytes since the buffers are aligned
- len_words = (len_bytes + sizeof(int32_t) - 1) / sizeof(int32_t);
- for (int i = 0; i < len_words; i++) {
- bp[i] = from_word[i];
- }
-}
-
-// Supply as many buffers to the receive available fifo as possible
-inline static void fill_av_fifo(usbdev_ctx_t *ctx) {
- while (!(REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET) &
- (1 << USBDEV_USBSTAT_AV_FULL_BIT))) {
- usbbufid_t buf = usbdev_buf_allocate_byid(ctx);
- if (buf < 0) {
- // no more free buffers, can't fill AV FIFO
- break;
- }
- REG32(USBDEV_BASE_ADDR + USBDEV_AVBUFFER_REG_OFFSET) = buf;
- }
-}
-
-void usbdev_sendbuf_byid(usbdev_ctx_t *ctx, usbbufid_t buf, size_t size,
- int endpoint) {
- uint32_t configin =
- USBDEV_BASE_ADDR + USBDEV_CONFIGIN_0_REG_OFFSET + (4 * endpoint);
-
- if ((endpoint >= NUM_ENDPOINTS) || (buf >= NUM_BUFS)) {
- return;
- }
-
- if (size > BUF_LENGTH) {
- size = BUF_LENGTH;
- }
-
- REG32(configin) = ((buf << USBDEV_CONFIGIN_0_BUFFER_0_OFFSET) |
- (size << USBDEV_CONFIGIN_0_SIZE_0_OFFSET) |
- (1 << USBDEV_CONFIGIN_0_RDY_0_BIT));
-}
-
-void usbdev_poll(usbdev_ctx_t *ctx) {
- uint32_t istate = REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET);
-
- // Do this first to keep things going
- fill_av_fifo(ctx);
-
- // Process IN completions first so we get the fact that send completed
- // before processing a response
- if (istate & (1 << USBDEV_INTR_STATE_PKT_SENT_BIT)) {
- uint32_t sentep = REG32(USBDEV_BASE_ADDR + USBDEV_IN_SENT_REG_OFFSET);
- uint32_t configin = USBDEV_BASE_ADDR + USBDEV_CONFIGIN_0_REG_OFFSET;
- TRC_C('a' + sentep);
- for (int ep = 0; ep < NUM_ENDPOINTS; ep++) {
- if (sentep & (1 << ep)) {
- // Free up the buffer and optionally callback
- int32_t cfgin = REG32(configin + (4 * ep));
- usbdev_buf_free_byid(ctx, EXTRACT(cfgin, CONFIGIN_0_BUFFER_0));
- if (ctx->tx_done_callback[ep]) {
- ctx->tx_done_callback[ep](ctx->ep_ctx[ep]);
- }
- }
- }
- // Write one to clear all the ones we handled
- REG32(USBDEV_BASE_ADDR + USBDEV_IN_SENT_REG_OFFSET) = sentep;
- // Clear the interupt
- REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET) =
- (1 << USBDEV_INTR_STATE_PKT_SENT_BIT);
- }
-
- if (istate & (1 << USBDEV_INTR_STATE_PKT_RECEIVED_BIT)) {
- while (!(REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET) &
- (1 << USBDEV_USBSTAT_RX_EMPTY_BIT))) {
- uint32_t rxinfo = REG32(USBDEV_BASE_ADDR + USBDEV_RXFIFO_REG_OFFSET);
- usbbufid_t buf = EXTRACT(rxinfo, RXFIFO_BUFFER);
- int size = EXTRACT(rxinfo, RXFIFO_SIZE);
- int endpoint = EXTRACT(rxinfo, RXFIFO_EP);
- int setup = (rxinfo >> USBDEV_RXFIFO_SETUP_BIT) & 1;
-
- if (ctx->rx_callback[endpoint]) {
- ctx->rx_callback[endpoint](ctx->ep_ctx[endpoint], buf, size, setup);
- } else {
- TRC_S("USB: unexpected RX ");
- TRC_I(rxinfo, 24);
- }
- usbdev_buf_free_byid(ctx, buf);
- }
- // Clear the interupt
- REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET) =
- (1 << USBDEV_INTR_STATE_PKT_RECEIVED_BIT);
- }
- if (istate & ~((1 << USBDEV_INTR_STATE_PKT_RECEIVED_BIT) |
- (1 << USBDEV_INTR_STATE_PKT_SENT_BIT))) {
- TRC_C('I');
- TRC_I(istate, 12);
- TRC_C(' ');
- REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET) =
- istate & ~((1 << USBDEV_INTR_STATE_PKT_RECEIVED_BIT) |
- (1 << USBDEV_INTR_STATE_PKT_SENT_BIT));
- if (istate & (1 << USBDEV_INTR_ENABLE_LINK_RESET_BIT)) {
- // Link reset
- for (int ep = 0; ep < NUM_ENDPOINTS; ep++) {
- if (ctx->reset[ep]) {
- ctx->reset[ep](ctx->ep_ctx[ep]);
- }
- }
-
- // Clear the interupt
- REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET) =
- (1 << USBDEV_INTR_ENABLE_LINK_RESET_BIT);
- }
- }
- // TODO - clean this up
- // Frame ticks every 1ms, use to flush data every 16ms
- // (faster in DPI but this seems to work ok)
- // At reset frame count is 0, compare to 1 so no calls before SOF received
- uint32_t usbframe = EXTRACT(
- REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET), USBSTAT_FRAME);
- if ((usbframe & 0xf) == 1) {
- if (ctx->flushed == 0) {
- for (int i = 0; i < NUM_ENDPOINTS; i++) {
- if (ctx->flush[i]) {
- ctx->flush[i](ctx->ep_ctx[i]);
- }
- }
- ctx->flushed = 1;
- }
- } else {
- ctx->flushed = 0;
- }
- // TODO Errors? What Errors?
-}
-
-unsigned int usbdev_get_status(usbdev_ctx_t *ctx) {
- unsigned int status = REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET);
- return status;
-}
-
-unsigned int usbdev_get_link_state(usbdev_ctx_t *ctx) {
- unsigned int link_state = EXTRACT(
- REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET), USBSTAT_LINK_STATE);
- return link_state;
-}
-
-unsigned int usbdev_get_address(usbdev_ctx_t *ctx) {
- unsigned int addr =
- EXTRACT(REG32(USBDEV_BASE_ADDR + USBDEV_USBCTRL_REG_OFFSET),
- USBCTRL_DEVICE_ADDRESS);
- return addr;
-}
-
-void usbdev_set_deviceid(usbdev_ctx_t *ctx, int deviceid) {
- REG32(USBDEV_BASE_ADDR + USBDEV_USBCTRL_REG_OFFSET) =
- (1 << USBDEV_USBCTRL_ENABLE_BIT) |
- (deviceid << USBDEV_USBCTRL_DEVICE_ADDRESS_OFFSET);
-}
-
-void usbdev_halt(usbdev_ctx_t *ctx, int endpoint, int enable) {
- uint32_t reg_offset = endpoint_is_in(endpoint) ? USBDEV_IN_STALL_REG_OFFSET
- : USBDEV_OUT_STALL_REG_OFFSET;
- uint32_t epbit = 1 << endpoint_number(endpoint);
- uint32_t stall = REG32(USBDEV_BASE_ADDR + reg_offset);
- if (enable) {
- stall |= epbit;
- } else {
- stall &= ~epbit;
- }
- REG32(USBDEV_BASE_ADDR + reg_offset) = stall;
- ctx->halted = stall;
- // TODO future addition would be to callback the endpoint driver
- // for now it just sees its traffic has stopped
-}
-
-void usbdev_set_iso(usbdev_ctx_t *ctx, int endpoint, int enable) {
- uint32_t reg_offset;
- uint32_t ep_number = endpoint_number(endpoint);
- if (endpoint_is_in(endpoint)) {
- reg_offset = USBDEV_IN_ISO_REG_OFFSET;
- } else {
- reg_offset = USBDEV_OUT_ISO_REG_OFFSET;
- }
- if (enable) {
- REG32(USBDEV_BASE_ADDR + reg_offset) =
- SETBIT(REG32(USBDEV_BASE_ADDR + reg_offset), ep_number);
- } else {
- REG32(USBDEV_BASE_ADDR + reg_offset) =
- CLRBIT(REG32(USBDEV_BASE_ADDR + reg_offset), ep_number);
- }
-}
-
-void usbdev_clear_data_toggle(usbdev_ctx_t *ctx, int endpoint) {
- REG32(USBDEV_BASE_ADDR + USBDEV_DATA_TOGGLE_CLEAR_REG_OFFSET) =
- (1 << endpoint);
-}
-
-void usbdev_set_ep0_stall(usbdev_ctx_t *ctx, int stall) {
- if (stall) {
- REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) =
- REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) | 1;
- REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) =
- REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) | 1;
- } else {
- REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) =
- REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) & ~(1);
- REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) =
- REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) & ~(1);
- }
-}
-
-void usbdev_clear_out_nak(usbdev_ctx_t *ctx, int ep) {
- uint32_t rxen = REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_OUT_REG_OFFSET);
- rxen |= (1 << (ep + USBDEV_RXENABLE_OUT_OUT_0_BIT));
- REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_OUT_REG_OFFSET) = rxen;
-}
-
-// TODO got hang with this inline
-int usbdev_can_rem_wake(usbdev_ctx_t *ctx) { return ctx->can_wake; }
-
-void usbdev_endpoint_setup(usbdev_ctx_t *ctx, int ep,
- usbdev_out_transfer_mode_t out_mode, void *ep_ctx,
- void (*tx_done)(void *),
- void (*rx)(void *, usbbufid_t, int, int),
- void (*flush)(void *), void (*reset)(void *)) {
- ctx->ep_ctx[ep] = ep_ctx;
- ctx->tx_done_callback[ep] = tx_done;
- ctx->rx_callback[ep] = rx;
- ctx->flush[ep] = flush;
- ctx->reset[ep] = reset;
-
- uint32_t tx_ep_en = REG32(USBDEV_BASE_ADDR + USBDEV_EP_IN_ENABLE_REG_OFFSET);
- tx_ep_en |= (1 << (ep + USBDEV_EP_IN_ENABLE_ENABLE_0_BIT));
- REG32(USBDEV_BASE_ADDR + USBDEV_EP_IN_ENABLE_REG_OFFSET) = tx_ep_en;
-
- if (out_mode != kUsbdevOutDisabled) {
- uint32_t rxen = REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_OUT_REG_OFFSET);
- rxen |= (1 << (ep + USBDEV_RXENABLE_OUT_OUT_0_BIT));
- REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_OUT_REG_OFFSET) = rxen;
- uint32_t ep_en = REG32(USBDEV_BASE_ADDR + USBDEV_EP_OUT_ENABLE_REG_OFFSET);
- ep_en |= (1 << (ep + USBDEV_EP_OUT_ENABLE_ENABLE_0_BIT));
- REG32(USBDEV_BASE_ADDR + USBDEV_EP_OUT_ENABLE_REG_OFFSET) = ep_en;
- }
- if (out_mode == kUsbdevOutMessage) {
- uint32_t set_nak_out =
- REG32(USBDEV_BASE_ADDR + USBDEV_SET_NAK_OUT_REG_OFFSET);
- set_nak_out |= (1 << (ep + USBDEV_SET_NAK_OUT_ENABLE_0_BIT));
- REG32(USBDEV_BASE_ADDR + USBDEV_SET_NAK_OUT_REG_OFFSET) = set_nak_out;
- }
-}
-
-void usbdev_connect(usbdev_ctx_t *ctx) {
- REG32(USBDEV_BASE_ADDR + USBDEV_USBCTRL_REG_OFFSET) =
- (1 << USBDEV_USBCTRL_ENABLE_BIT);
-}
-
-void usbdev_init(usbdev_ctx_t *ctx, bool pinflip, bool en_diff_rcvr,
- bool tx_use_d_se0) {
- // setup context
- for (int i = 0; i < NUM_ENDPOINTS; i++) {
- usbdev_endpoint_setup(ctx, i, kUsbdevOutDisabled, NULL, NULL, NULL, NULL,
- NULL);
- }
- ctx->halted = 0;
- ctx->can_wake = 0;
- buf_init(ctx);
-
- // All about polling...
- REG32(USBDEV_BASE_ADDR + USBDEV_INTR_ENABLE_REG_OFFSET) = 0;
-
- // Provide buffers for any reception
- fill_av_fifo(ctx);
-
- REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_SETUP_REG_OFFSET) =
- (1 << USBDEV_RXENABLE_SETUP_SETUP_0_BIT);
- REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_OUT_REG_OFFSET) =
- (1 << USBDEV_RXENABLE_OUT_OUT_0_BIT);
- REG32(USBDEV_BASE_ADDR + USBDEV_EP_IN_ENABLE_REG_OFFSET) =
- (1 << USBDEV_EP_IN_ENABLE_ENABLE_0_BIT);
- REG32(USBDEV_BASE_ADDR + USBDEV_EP_OUT_ENABLE_REG_OFFSET) =
- (1 << USBDEV_EP_OUT_ENABLE_ENABLE_0_BIT);
- REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) = 0;
- REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) = 0;
-
- uint32_t phy_config = (pinflip << USBDEV_PHY_CONFIG_PINFLIP_BIT) |
- (en_diff_rcvr << USBDEV_PHY_CONFIG_USE_DIFF_RCVR_BIT) |
- (tx_use_d_se0 << USBDEV_PHY_CONFIG_TX_USE_D_SE0_BIT) |
- (1 << USBDEV_PHY_CONFIG_EOP_SINGLE_BIT_BIT);
- REG32(USBDEV_BASE_ADDR + USBDEV_PHY_CONFIG_REG_OFFSET) = phy_config;
-}
-
-void usbdev_force_dx_pullup(line_sel_t line, bool set) {
- // Force usb to pretend it is in suspend
- uint32_t reg_val = REG32(USBDEV_BASE_ADDR + USBDEV_PHY_PINS_DRIVE_REG_OFFSET);
- uint32_t mask;
-
- mask = line == kDpSel ? USBDEV_PHY_PINS_DRIVE_DP_PULLUP_EN_O_BIT
- : USBDEV_PHY_PINS_DRIVE_DN_PULLUP_EN_O_BIT;
-
- if (set) {
- reg_val = SETBIT(reg_val, mask);
- } else {
- reg_val = CLRBIT(reg_val, mask);
- }
-
- reg_val = SETBIT(reg_val, USBDEV_PHY_PINS_DRIVE_EN_BIT);
- REG32(USBDEV_BASE_ADDR + USBDEV_PHY_PINS_DRIVE_REG_OFFSET) = reg_val;
-}
-
-void usbdev_set_wake_module_active(bool set) {
- uint32_t reg_val = REG32(USBDEV_BASE_ADDR + USBDEV_WAKE_CONTROL_REG_OFFSET);
- if (set) {
- reg_val = SETBIT(reg_val, USBDEV_WAKE_CONTROL_SUSPEND_REQ_BIT);
- } else {
- reg_val = SETBIT(reg_val, USBDEV_WAKE_CONTROL_WAKE_ACK_BIT);
- }
- REG32(USBDEV_BASE_ADDR + USBDEV_WAKE_CONTROL_REG_OFFSET) = reg_val;
-}
-
-// `extern` declarations to give the inline functions in the
-// corresponding header a link location.
-
-extern int usbdev_halted(usbdev_ctx_t *ctx, int endpoint);
-extern void usbdev_rem_wake_en(usbdev_ctx_t *ctx, int enable);
diff --git a/sw/device/lib/usbdev.h b/sw/device/lib/usbdev.h
deleted file mode 100644
index 28edf82..0000000
--- a/sw/device/lib/usbdev.h
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-#ifndef OPENTITAN_SW_DEVICE_LIB_USBDEV_H_
-#define OPENTITAN_SW_DEVICE_LIB_USBDEV_H_
-
-#include <stdbool.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 *);
- void (*reset[NUM_ENDPOINTS])(void *);
-};
-
-/**
- * Select USB lines P or N
- */
-typedef enum line_sel { kDpSel = 0, kDnSel = 1 } line_sel_t;
-
-/**
- * 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 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);
-
-/**
- * Get the content of the USB status register
- * @param ctx usbdev context pointer
- * @return USB status register
- */
-unsigned int usbdev_get_status(usbdev_ctx_t *ctx);
-
-/**
- * Get the current USB link state
- * @param ctx usbdev context pointer
- * @return USB link state
- */
-unsigned int usbdev_get_link_state(usbdev_ctx_t *ctx);
-
-/**
- * Get the current USB address
- * @param ctx usbdev context pointer
- * @return USB address
- */
-unsigned int usbdev_get_address(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 ctx usbdev context pointer
- * @param deviceid 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 ctx 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 ctx usbdev context pointer
- * @param endpoint number
- * @return 1 if endpoint is halted else 0
- */
-inline int usbdev_halted(usbdev_ctx_t *ctx, int endpoint) {
- return (ctx->halted >> endpoint) & 0x1;
-}
-
-/**
- * Configure an endpoint as ISO / non-ISO
- *
- * By default endpoints are non-ISO, but they can be set to ISO
- *
- * @param ctx usbdev context pointer
- * @param endpoint number
- * @param enable 0: non-ISO, 1: ISO
- */
-void usbdev_set_iso(usbdev_ctx_t *ctx, int endpoint, int enable);
-
-/**
- * Clear the data toggle bit for an endpoint
- * @param ctx usbdev context pointer
- * @param endpoint Endpoint number
- */
-void usbdev_clear_data_toggle(usbdev_ctx_t *ctx, int endpoint);
-
-/**
- * Updates the stall setting for EP0. If stall is set then an IN, or
- * OUT transaction to EP0 will be responded to with a STALL return. This
- * flag is cleared on a a SETUP transaction
- * @param ctx usbdev context pointer
- * @param stall
- */
-void usbdev_set_ep0_stall(usbdev_ctx_t *ctx, int stall);
-
-/**
- * Enable or disable remote wake
- *
- * @param ctx 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 ctx usbdev context pointer
- * @return 1 if remote wake is permitted else 0
- */
-int usbdev_can_rem_wake(usbdev_ctx_t *ctx);
-
-/**
- * Re-enable OUT transactions for a given endpoint.
- *
- * This function must be called after reception of a packet for a given
- * endpoint, else the endpoint will NAK the next packet.
- *
- * @param ctx usbdev context pointer
- * @param endpoint endpoint number
- */
-void usbdev_clear_out_nak(usbdev_ctx_t *ctx, int ep);
-
-typedef enum usbdev_out_transfer_mode {
- /**
- * The endpoint does not support OUT transactions.
- */
- kUsbdevOutDisabled = 0,
- /**
- * Software does NOT need to call usbdev_clear_out_nak() after every received
- * transaction. If software takes no action, usbdev will allow an endpoint's
- * transactions to proceed as long as a buffer is available.
- */
- kUsbdevOutStream = 1,
- /**
- * Software must call usbdev_clear_out_nak() after every received transaction
- * to re-enable packet reception. This gives software time to respond with the
- * appropriate handshake when it's ready.
- */
- kUsbdevOutMessage = 2,
-} usbdev_out_transfer_mode_t;
-
-/**
- * Call to setup an endpoint
- *
- * @param ctx usbdev context pointer
- * @param ep endpoint number
- * @param out_mode the transfer mode for OUT transactions
- * @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
- * @param reset(void *ep_ctx) called when an USB link reset is detected
- */
-void usbdev_endpoint_setup(usbdev_ctx_t *ctx, int ep,
- usbdev_out_transfer_mode_t out_mode, void *ep_ctx,
- void (*tx_done)(void *),
- void (*rx)(void *, usbbufid_t, int, int),
- void (*flush)(void *), void (*reset)(void *));
-
-/**
- * Connect the device to the bus.
- *
- * @param ctx the usbdev context.
- */
-void usbdev_connect(usbdev_ctx_t *ctx);
-
-/**
- * Initialize the usbdev interface
- *
- * Does not connect the device, since the default endpoint is not yet enabled.
- * See usbdev_connect().
- *
- * @param ctx uninitialized usbdev context pointer
- * @param pinflip boolean to indicate if PHY should be configured for D+/D- flip
- * @param en_diff_rcvr boolean to indicate if PHY should enable an external
- * differential receiver, activating the single-ended D
- * input
- * @param tx_use_d_se0 boolean to indicate if PHY uses D/SE0 for TX instead of
- * Dp/Dn
- */
-void usbdev_init(usbdev_ctx_t *ctx, bool pinflip, bool en_diff_rcvr,
- bool tx_use_d_se0);
-
-/**
- * Force usbdev to output suspend state for testing purposes
- */
-void usbdev_force_suspend(void);
-
-/**
- * Force usbdev pull-up to specific value
- */
-void usbdev_force_dx_pullup(line_sel_t line, bool set);
-
-/**
- * Enable usb wake module to go active / inactive.
- */
-void usbdev_set_wake_module_active(bool set);
-
-// Used for tracing what is going on. This may impact timing which is critical
-// when simulating with the USB DPI module.
-//#define ENABLE_TRC
-#ifdef ENABLE_TRC
-#include "sw/device/lib/runtime/log.h"
-#define TRC_S(s) LOG_INFO("%s", s)
-#define TRC_I(i, b) LOG_INFO("0x%x", i)
-#define TRC_C(c) LOG_INFO("%c", c)
-#else
-#define TRC_S(s)
-#define TRC_I(i, b)
-#define TRC_C(c)
-#endif
-
-#endif // OPENTITAN_SW_DEVICE_LIB_USBDEV_H_
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index 45e46ec..d00bc5a 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -1257,12 +1257,12 @@
targets = ["verilator"],
deps = [
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
- "//sw/device/lib:usb",
- "//sw/device/lib:usb_simpleserial",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/runtime:log",
"//sw/device/lib/runtime:print",
"//sw/device/lib/testing:pinmux_testutils",
+ "//sw/device/lib/testing:usb_testutils",
+ "//sw/device/lib/testing:usb_testutils_simpleserial",
"//sw/device/lib/testing/test_framework:ottf_main",
],
)
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD
index d52fa40..3a1f053 100644
--- a/sw/device/tests/sim_dv/BUILD
+++ b/sw/device/tests/sim_dv/BUILD
@@ -447,9 +447,9 @@
srcs = ["pwrmgr_usbdev_smoketest.c"],
targets = ["dv"],
deps = [
- "//sw/device/lib:usb",
"//sw/device/lib/base:mmio",
"//sw/device/lib/dif:pwrmgr",
+ "//sw/device/lib/dif:usbdev",
"//sw/device/lib/runtime:hart",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing:pwrmgr_testutils",
@@ -583,13 +583,13 @@
"//hw/top_earlgrey/ip/pwrmgr/data/autogen:pwrmgr_regs",
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib:irq",
- "//sw/device/lib:usb",
"//sw/device/lib/base:mmio",
"//sw/device/lib/dif:adc_ctrl",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:pwrmgr",
"//sw/device/lib/dif:rv_plic",
"//sw/device/lib/dif:sensor_ctrl",
+ "//sw/device/lib/dif:usbdev",
"//sw/device/lib/runtime:ibex",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing:aon_timer_testutils",
@@ -608,12 +608,12 @@
"//hw/top_earlgrey/ip/pwrmgr/data/autogen:pwrmgr_regs",
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib:irq",
- "//sw/device/lib:usb",
"//sw/device/lib/base:mmio",
"//sw/device/lib/dif:adc_ctrl",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:pwrmgr",
"//sw/device/lib/dif:rv_plic",
+ "//sw/device/lib/dif:usbdev",
"//sw/device/lib/runtime:ibex",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing:aon_timer_testutils",
diff --git a/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_wake_ups.c b/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_wake_ups.c
index b499c9a..223863d 100644
--- a/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_wake_ups.c
+++ b/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_wake_ups.c
@@ -8,6 +8,7 @@
#include "sw/device/lib/dif/dif_pwrmgr.h"
#include "sw/device/lib/dif/dif_rv_plic.h"
#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/dif/dif_usbdev.h"
#include "sw/device/lib/irq.h"
#include "sw/device/lib/runtime/ibex.h"
#include "sw/device/lib/runtime/log.h"
@@ -16,7 +17,6 @@
#include "sw/device/lib/testing/rv_plic_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
-#include "sw/device/lib/usbdev.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "pwrmgr_regs.h"
@@ -147,14 +147,15 @@
/**
* Program usb config for test #4.
* . Fake low power entry through usb.
- * . Force usb to output suspend indication.
- * (*dif) handle is not used but leave as is
- * to be called from execute_test.
+ * . Force wake detection module active.
*/
static void prgm_usb_wakeup(void *dif) {
- usbdev_set_wake_module_active(true);
- usbdev_force_dx_pullup(kDpSel, true);
- usbdev_force_dx_pullup(kDnSel, false);
+ dif_usbdev_phy_pins_drive_t pins = {
+ .dp_pullup_en = true,
+ .dn_pullup_en = false,
+ };
+ CHECK_DIF_OK(dif_usbdev_set_phy_pins_state(dif, kDifToggleEnabled, pins));
+ CHECK_DIF_OK(dif_usbdev_set_wake_enable(dif, kDifToggleEnabled));
// Give the hardware a chance to recognize the wakeup values are the same.
busy_spin_micros(20);
@@ -310,7 +311,7 @@
LOG_INFO("Woke up by source %d", PWRMGR_PARAM_PINMUX_AON_USB_WKUP_REQ_IDX);
// Turn off wake up.
- usbdev_set_wake_module_active(false);
+ CHECK_DIF_OK(dif_usbdev_set_wake_enable(&usbdev, kDifToggleDisabled));
CHECK_DIF_OK(dif_pinmux_wakeup_cause_clear(&pinmux));
delay_n_clear(30);
execute_test(PWRMGR_PARAM_AON_TIMER_AON_WKUP_REQ_IDX);
diff --git a/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_wake_ups.c b/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_wake_ups.c
index 96ceb6a..4a25baf 100644
--- a/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_wake_ups.c
+++ b/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_wake_ups.c
@@ -9,6 +9,7 @@
#include "sw/device/lib/dif/dif_rv_plic.h"
#include "sw/device/lib/dif/dif_sensor_ctrl.h"
#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/dif/dif_usbdev.h"
#include "sw/device/lib/irq.h"
#include "sw/device/lib/runtime/ibex.h"
#include "sw/device/lib/runtime/log.h"
@@ -17,7 +18,6 @@
#include "sw/device/lib/testing/rv_plic_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
-#include "sw/device/lib/usbdev.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "pwrmgr_regs.h"
@@ -154,9 +154,12 @@
* to be called from execute_test
*/
static void prgm_usb_wakeup(void *dif) {
- usbdev_set_wake_module_active(true);
- usbdev_force_dx_pullup(kDpSel, true);
- usbdev_force_dx_pullup(kDnSel, false);
+ dif_usbdev_phy_pins_drive_t pins = {
+ .dp_pullup_en = true,
+ .dn_pullup_en = false,
+ };
+ CHECK_DIF_OK(dif_usbdev_set_phy_pins_state(dif, kDifToggleEnabled, pins));
+ CHECK_DIF_OK(dif_usbdev_set_wake_enable(dif, kDifToggleEnabled));
LOG_INFO("prgm_usb_wakeup: wait 20us (usb)");
// Give the hardware a chance to recognize the wakeup values are the same.
@@ -277,7 +280,7 @@
CHECK_DIF_OK(dif_pinmux_wakeup_cause_clear(&pinmux));
break;
case PWRMGR_PARAM_PINMUX_AON_USB_WKUP_REQ_IDX:
- usbdev_set_wake_module_active(false);
+ CHECK_DIF_OK(dif_usbdev_set_wake_enable(&usbdev, kDifToggleDisabled));
CHECK_DIF_OK(dif_pinmux_wakeup_cause_clear(&pinmux));
break;
case PWRMGR_PARAM_AON_TIMER_AON_WKUP_REQ_IDX:
diff --git a/sw/device/tests/sim_dv/pwrmgr_usbdev_smoketest.c b/sw/device/tests/sim_dv/pwrmgr_usbdev_smoketest.c
index 4809787..c17e963 100644
--- a/sw/device/tests/sim_dv/pwrmgr_usbdev_smoketest.c
+++ b/sw/device/tests/sim_dv/pwrmgr_usbdev_smoketest.c
@@ -14,16 +14,17 @@
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_usbdev.h"
#include "sw/device/lib/runtime/hart.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/pwrmgr_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
-#include "sw/device/lib/usbdev.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
static dif_pwrmgr_t pwrmgr;
+static dif_usbdev_t usbdev;
OTTF_DEFINE_TEST_CONFIG();
@@ -35,6 +36,8 @@
bool test_main(void) {
CHECK_DIF_OK(dif_pwrmgr_init(
mmio_region_from_addr(TOP_EARLGREY_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+ CHECK_DIF_OK(dif_usbdev_init(
+ mmio_region_from_addr(TOP_EARLGREY_USBDEV_BASE_ADDR), &usbdev));
// Assuming the chip hasn't slept yet, wakeup reason should be empty.
dif_pwrmgr_wakeup_reason_t wakeup_reason;
@@ -63,11 +66,16 @@
}
// Fake low power entry through usb
- // Force usb to output suspend indication
+ // Force wake detection module active
if (!low_power_exit) {
- usbdev_set_wake_module_active(true);
- usbdev_force_dx_pullup(kDpSel, true);
- usbdev_force_dx_pullup(kDnSel, false);
+ CHECK_DIF_OK(dif_usbdev_set_wake_enable(&usbdev, kDifToggleDisabled));
+ dif_usbdev_phy_pins_drive_t pins = {
+ .dp_pullup_en = true,
+ .dn_pullup_en = false,
+ };
+ CHECK_DIF_OK(
+ dif_usbdev_set_phy_pins_state(&usbdev, kDifToggleEnabled, pins));
+ CHECK_DIF_OK(dif_usbdev_set_wake_enable(&usbdev, kDifToggleEnabled));
// give the hardware a chance to recognize the wakeup values are the same
busy_spin_micros(20); // 20us
diff --git a/sw/device/tests/usbdev_test.c b/sw/device/tests/usbdev_test.c
index b53da0b..346fe2b 100644
--- a/sw/device/tests/usbdev_test.c
+++ b/sw/device/tests/usbdev_test.c
@@ -17,16 +17,15 @@
// transactions with a data payload of "Hi!" to Endpoint 1. If these two OUT
// transactions are succesfully received by the device, the test passes.
-#include "sw/device/lib/usbdev.h"
-
#include "sw/device/lib/dif/dif_pinmux.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/runtime/print.h"
#include "sw/device/lib/testing/pinmux_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
-#include "sw/device/lib/usb_controlep.h"
-#include "sw/device/lib/usb_simpleserial.h"
+#include "sw/device/lib/testing/usb_testutils.h"
+#include "sw/device/lib/testing/usb_testutils_controlep.h"
+#include "sw/device/lib/testing/usb_testutils_simpleserial.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
@@ -48,9 +47,9 @@
/**
* USB device context types.
*/
-static usbdev_ctx_t usbdev;
-static usb_controlep_ctx_t usbdev_control;
-static usb_ss_ctx_t simple_serial;
+static usb_testutils_ctx_t usbdev;
+static usb_testutils_controlep_ctx_t usbdev_control;
+static usb_testutils_ss_ctx_t simple_serial;
/**
* Pinmux handle
@@ -108,17 +107,18 @@
// Call `usbdev_init` here so that DPI will not start until the
// simulation has finished all of the printing, which takes a while
// if `--trace` was passed in.
- usbdev_init(&usbdev, /* pinflip= */ false, /* en_diff_rcvr= */ false,
- /* tx_use_d_se0= */ false);
- usb_controlep_init(&usbdev_control, &usbdev, 0, config_descriptors,
- sizeof(config_descriptors));
- while (usbdev_control.device_state != kUsbDeviceConfigured) {
- usbdev_poll(&usbdev);
+ usb_testutils_init(&usbdev, /*pinflip=*/false, /*en_diff_rcvr=*/false,
+ /*tx_use_d_se0=*/false);
+ usb_testutils_controlep_init(&usbdev_control, &usbdev, 0, config_descriptors,
+ sizeof(config_descriptors));
+ while (usbdev_control.device_state != kUsbTestutilsDeviceConfigured) {
+ usb_testutils_poll(&usbdev);
}
- usb_simpleserial_init(&simple_serial, &usbdev, 1, usb_receipt_callback);
+ usb_testutils_simpleserial_init(&simple_serial, &usbdev, 1,
+ usb_receipt_callback);
while (usb_chars_recved_total < kExpectedUsbCharsRecved) {
- usbdev_poll(&usbdev);
+ usb_testutils_poll(&usbdev);
}
base_printf("\r\n");