blob: 06e4d0be867fa03e2da8af493ba8a3b6c6fce89f [file] [log] [blame]
// 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_DIF_DIF_USBDEV_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_USBDEV_H_
/**
* @file
* @brief <a href="/hw/ip/usbdev/doc/">USB Device</a> Device Interface Functions
*/
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_warn_unused_result.h"
#include <stddef.h>
#include <stdint.h>
/**
* Hardware constants.
*/
#define USBDEV_NUM_ENDPOINTS 12
#define USBDEV_MAX_PACKET_SIZE 64
// Internal constant that should not be used by clients. Defined here because
// it is used in the definition of `dif_usbdev_buffer_pool` below.
#define USBDEV_NUM_BUFFERS 32
/**
* Free buffer pool.
*
* A USB device has a fixed number of buffers that are used for storing incoming
* and outgoing packets and the software is responsible for keeping track of
* free buffers. The pool is implemented as a stack for constant-time add and
* remove. `top` points to the last free buffer added to the pool. The pool is
* full when `top == USBDEV_NUM_BUFFERS - 1` and empty when `top == -1`.
*/
typedef struct dif_usbdev_buffer_pool {
uint8_t entries[USBDEV_NUM_BUFFERS];
int8_t top;
} dif_usbdev_buffer_pool_t;
/**
* State of a read buffer operation.
*
* This struct is used to track the state of a read buffer operation internally.
* Thus, clients can freely choose their buffer sizes and easily process
* packets that are larger than their buffers by simply calling
* `dif_usbdev_rx_packet_read_bytes` repeatedly until they read the entire
* payload of each packet.
*
* See also: `dif_usbdev_rx_packet_get_info`, `dif_usbdev_rx_packet_read_bytes`.
*/
typedef struct dif_usbdev_read_buffer_op_state {
/**
* Buffer to read from.
*/
uint8_t buffer_entry;
/**
* Number of remaining bytes.
*/
size_t remaining_bytes;
/**
* Offset to start reading from.
*/
size_t offset;
} dif_usbdev_read_buffer_op_state_t;
/**
* Internal state of a USB device.
*
* Instances of this struct must be initialized by `dif_usbdev_init()` before
* being passed to other functions in this library. Its fields should be
* considered private and are only provided here so that callers can allocate
* it.
*/
typedef struct dif_usbdev {
mmio_region_t base_addr;
dif_usbdev_buffer_pool_t buffer_pool;
dif_usbdev_read_buffer_op_state_t read_buffer_op_state;
uint16_t active_buffer_ops;
} dif_usbdev_t;
/**
* Enumeration for enabling/disabling various functionality.
*/
typedef enum dif_usbdev_toggle {
kDifUsbdevToggleDisable,
kDifUsbdevToggleEnable,
} dif_usbdev_toggle_t;
/**
* Set of allowed configurations for USB power sense override.
*/
typedef enum dif_usbdev_power_sense_override {
kDifUsbdevPowerSenseOverrideDisabled,
kDifUsbdevPowerSenseOverridePresent,
kDifUsbdevPowerSenseOverrideNotPresent
} dif_usbdev_power_sense_override_t;
/**
* Configuration for initializing a USB device.
*/
typedef struct dif_usbdev_config {
/**
* Base address of the USB device.
*/
mmio_region_t base_addr;
/**
* Use the differential rx signal instead of the single-ended signals.
*/
dif_usbdev_toggle_t differential_rx;
/**
* Use the differential tx signal instead of the single-ended signals.
*/
dif_usbdev_toggle_t differential_tx;
/*
* Recognize a single SE0 bit as end of packet instead of requiring
* two bits.
*/
dif_usbdev_toggle_t single_bit_eop;
/**
* Override USB power sense.
*/
dif_usbdev_power_sense_override_t power_sense_override;
} dif_usbdev_config_t;
/**
* Common return codes for the functions in this library.
*/
typedef enum dif_usbdev_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevOK = 0,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevError = 1,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevBadArg = 2,
} dif_usbdev_result_t;
/**
* Initialize a USB device.
*
* A USB device must first be initialized by this function before calling other
* functions in this library.
*
* @param config Configuration for initializing a USB device.
* @param usbdev Internal state of the initialized USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_init(dif_usbdev_config_t *config,
dif_usbdev_t *usbdev);
/**
* Fill the available buffer FIFO of a USB device.
*
* The USB device has a small FIFO (AV FIFO) that stores free buffers for
* incoming packets. It is the responsibility of the software to ensure that the
* AV FIFO is never empty. If the host tries to send a packet when the AV FIFO
* is empty, the USB device will respond with a NAK. While this will typically
* cause the host to retry transmission for regular data packets, there are
* transactions in the USB protocol during which the USB device is not allowed
* to send a NAK. Thus, the software must make sure that the AV FIFO is never
* empty by calling this function periodically.
*
* @param usbdev A USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_fill_available_fifo(dif_usbdev_t *usbdev);
/**
* Enable or disable reception of SETUP packets for an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New SETUP packet reception state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_setup_enable(
dif_usbdev_t *usbdev, uint8_t endpoint, dif_usbdev_toggle_t new_state);
/**
* Enable or disable reception of OUT packets for an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New OUT packet reception state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_out_enable(
dif_usbdev_t *usbdev, uint8_t endpoint, dif_usbdev_toggle_t new_state);
/**
* Enable or disable STALL for an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New STALL state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_stall_enable(
dif_usbdev_t *usbdev, uint8_t endpoint, dif_usbdev_toggle_t new_state);
/**
* Get STALL state of an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param state Current STALL state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_stall_get(dif_usbdev_t *usbdev,
uint8_t endpoint,
bool *state);
/**
* Enable or disable isochronous mode for an endpoint.
*
* Isochronous endpoints transfer data periodically. Since isochronous transfers
* do not have a handshaking stage, isochronous endpoints cannot report errors
* or STALL conditions.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New isochronous state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_iso_enable(
dif_usbdev_t *usbdev, uint8_t endpoint, dif_usbdev_toggle_t new_state);
/**
* Enable the USB interface of a USB device.
*
* Calling this function causes the USB device to assert the full-speed pull-up
* signal to indicate its presence to the host.
*
* @param usbdev A USB device.
* @param new_state New interface state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_interface_enable(dif_usbdev_t *usbdev,
dif_usbdev_toggle_t new_state);
/**
* Information about a received packet.
*/
typedef struct dif_usbdev_rx_packet_info {
/**
* Endpoint of the packet.
*/
uint8_t endpoint;
/**
* Length of the packet in bytes.
*/
uint8_t len;
/**
* Indicates if the packet is a SETUP packet.
*/
bool is_setup;
} dif_usbdev_rx_packet_info_t;
/**
* Return codes for `dif_usbdev_rx_packet_get_info`.
*/
typedef enum dif_usbdev_rx_packet_get_info_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevRxPacketGetInfoResultOK = kDifUsbdevOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevRxPacketGetInfoResultError = kDifUsbdevError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevRxPacketGetInfoResultBadArg = kDifUsbdevBadArg,
/**
* Indicates that there is already a read buffer operation in progress.
*/
kDifUsbdevRxPacketGetInfoResultBusy,
/**
* Indicates that RX FIFO is empty.
*/
kDifUsbdevRxPacketGetInfoResultNoPackets,
} dif_usbdev_rx_packet_get_info_result_t;
/**
* Get information about the packet at the front of RX FIFO.
*
* The USB device has a small FIFO (RX FIFO) that stores received packets until
* the software has a chance to process them. It is the responsibility of the
* software to ensure that the RX FIFO is never full. If the host tries to send
* a packet when the RX FIFO is full, the USB device will respond with a NAK.
* While this will typically cause the host to retry transmission for regular
* data packets, there are transactions in the USB protocol during which the USB
* device is not allowed to send a NAK. Thus, the software must read received
* packets as soon as possible.
*
* Reading received packets involves two main steps:
* - Calling this function, i.e. `dif_usbdev_rx_packet_get_info`, and
* - Calling `dif_usbdev_rx_packet_read_bytes` until the entire packet payload
* is read or calling `dif_usbdev_rx_packet_discard_bytes`.
*
* In order to read an incoming packet, clients should first call this function
* to get information about the packet. In addition to populating a
* `dif_usbdev_rx_packet_info_t` struct, this also starts an internal read
* buffer operation. The state of this operation, i.e. the buffer to read from,
* number of bytes remaining and the offset to start reading from, is tracked by
* this library, therefore clients do not need to perform any additional state
* tracking. Then, clients should call `dif_usbdev_rx_packet_read_bytes` one or
* more times (depending on the sizes of their internal buffers) until the
* entire packet payload is read. Once the entire packet is read, the read
* buffer operation ends and the buffer that holds the packet payload is
* returned to the free buffer pool. If the clients want to ignore the payload
* of a packet, e.g. for an unsupported or a zero-length packet, they can call
* `dif_usbdev_rx_packet_discard_bytes` to immediately return the buffer that
* holds the packet payload to the free buffer pool and end the read buffer
* operation.
*
* @param usbdev A USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_rx_packet_get_info_result_t dif_usbdev_rx_packet_get_info(
dif_usbdev_t *usbdev, dif_usbdev_rx_packet_info_t *packet);
/**
* Return codes for `dif_usbdev_rx_packet_read_bytes`.
*/
typedef enum dif_usbdev_rx_packet_read_bytes_result {
/**
* Indicates that the call succeeded and the entire packet payload is read.
*/
kDifUsbdevRxPacketReadBytesResultOK = kDifUsbdevOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevRxPacketReadBytesResultError = kDifUsbdevError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevRxPacketReadBytesResultBadArg = kDifUsbdevBadArg,
/**
* Indicates that the call was successful but there are remaining bytes to be
* read.
*/
kDifUsbdevRxPacketReadBytesResultContinue,
/**
* Indicates that there is no active read buffer operation.
*/
kDifUsbdevRxPacketReadBytesResultNotReading,
} dif_usbdev_rx_packet_read_bytes_result_t;
/**
* Read the payload of the last received packet.
*
* The clients should call this function to read the payload of the last
* received packet after calling `dif_usbdev_rx_packet_get_info`. This function
* copies the smaller of `dst_len` and remaining number of bytes to `dst`. The
* active read buffer operation ends and the buffer that holds the packet
* payload is returned to the free buffer pool when the entire packet payload is
* read.
*
* See also: `dif_usbdev_rx_packet_get_info`.
*
* @param usbdev A USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_rx_packet_read_bytes_result_t dif_usbdev_rx_packet_read_bytes(
dif_usbdev_t *usbdev, uint8_t *dst, size_t dst_len, size_t *bytes_written);
/**
* Return codes for `dif_usbdev_rx_packet_discard_bytes`.
*/
typedef enum dif_usbdev_rx_packet_discard_bytes_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevRxPacketDiscardBytesResultOK = kDifUsbdevOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevRxPacketDiscardBytesResultError = kDifUsbdevError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevRxPacketDiscardBytesResultBadArg = kDifUsbdevBadArg,
/**
* Indicates that there is no active read buffer operation.
*/
kDifUsbdevRxPacketDiscardBytesResultNotReading,
} dif_usbdev_rx_packet_discard_bytes_result_t;
/**
* Discard the payload of the last received packet.
*
* The clients should call this function to discard the payload of the last
* received packet after calling `dif_usbdev_rx_packet_get_info`. This function
* immediately ends the active read buffer operation and returns the buffer
* that holds the packet payload to the free buffer pool.
*
* See also: `dif_usbdev_rx_packet_get_info`.
*
* @param usbdev A USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_rx_packet_discard_bytes_result_t dif_usbdev_rx_packet_discard_bytes(
dif_usbdev_t *usbdev);
/**
* Return codes for `dif_usbdev_tx_packet_write_bytes`.
*/
typedef enum dif_usbdev_tx_packet_write_bytes_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevTxPacketWriteBytesResultOK = kDifUsbdevOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevTxPacketWriteBytesResultError = kDifUsbdevError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevTxPacketWriteBytesResultBadArg = kDifUsbdevBadArg,
/**
* Indicates that there are no free buffers.
*/
kDifUsbdevTxPacketWriteBytesResultNoBuffers,
/**
* Indicates that the requested write exceeds the device buffer size.
*/
kDifUsbdevTxPacketWriteBytesResultBufferFull,
/**
* Indicates that the endpoint already has a packet pending transmission.
*/
kDifUsbdevTxPacketWriteBytesResultBusy,
} dif_usbdev_tx_packet_write_bytes_result_t;
/**
* Write outgoing packet payload for an endpoint.
*
* The USB device has 12 endpoints, each of which can be used to send packets to
* the host. Since a packet is not actually transmitted to the host until the
* host sends an IN token, clients must write the packet payload to a device
* buffer and mark it as ready for transmission from a particular endpoint. Note
* that this can be done in parallel for multiple endpoints. A packet queued for
* transmission from a particular endpoint is transmitted once the host sends an
* IN token for that endpoint.
*
* After a packet is queued for transmission, clients should periodically check
* its status. While the USB device handles transmission errors automatically by
* retrying transmission, transmission of a packet may be canceled if the
* endpoint receives a SETUP packet or the link is reset before the queued
* packet is transmitted. In these cases, clients should handle the SETUP packet
* or the link reset first and then optionally send the same packet again.
*
* Sending a packet from a particular endpoint to the host involves three main
* steps:
* - Calling this function, i.e. `dif_usbdev_tx_packet_write_bytes`,
* - Calling `dif_usbdev_tx_packet_send`, and
* - Calling `dif_usbdev_tx_packet_get_status`.
*
* In order to send a packet, clients should first call this function (one or
* more times depending on the sizes of their internal buffers) to write the
* packet payload to a device buffer. Calling this function also starts an
* internal write buffer operation similar to `dif_usbdev_rx_packet_get_info`.
* After writing the packet payload, clients should call
* `dif_usbdev_tx_packet_send` to mark the packet as ready for transmission,
* which also ends the active write buffer operation. Then, clients should
* periodically call `dif_usbdev_tx_packet_get_status` to check the status of
* the packet. `dif_usbdev_tx_packet_get_status` returns the buffer that holds
* the packet payload to the free buffer pool once the packet is either
* successfully transmitted or canceled due to an incoming SETUP packet.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param src Source buffer.
* @param src_len Length of the source buffer.
* @bytes_written Number of bytes written to the USB device buffer.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_tx_packet_write_bytes_result_t dif_usbdev_tx_packet_write_bytes(
dif_usbdev_t *usbdev, uint8_t endpoint, uint8_t *src, size_t src_len,
size_t *bytes_written);
/**
* Return codes for `dif_usbdev_tx_packet_send`.
*/
typedef enum dif_usbdev_tx_packet_send_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevTxPacketSendResultOK = kDifUsbdevOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevTxPacketSendResultError = kDifUsbdevError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevTxPacketSendResultBadArg = kDifUsbdevBadArg,
/**
* Indicates that the endpoint does not have a packet to be sent.
*/
kDifUsbdevTxPacketSendResultNotWriting,
} dif_usbdev_tx_packet_send_result_t;
/**
* Mark the packet buffered for the given endpoint as ready for transmission.
*
* See also: `dif_usbdev_tx_packet_write_bytes`.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_tx_packet_send_result_t dif_usbdev_tx_packet_send(
dif_usbdev_t *usbdev, uint8_t endpoint);
/**
* Status of an outgoing packet.
*/
typedef enum dif_usbdev_tx_packet_status {
/**
* There is no packet for the given endpoint.
*/
kDifUsbdevTxPacketStatusNoPacket,
/**
* There is an active write buffer operation and the packet is not marked as
* ready for transmission yet.
*/
kDifUsbdevTxPacketStatusStillWriting,
/**
* Packet is pending transmission.
*/
kDifUsbdevTxPacketStatusPending,
/**
* Packet was sent successfully.
*/
kDifUsbdevTxPacketStatusSent,
/**
* Transmission was canceled due to an incoming SETUP packet.
*/
kDifUsbdevTxPacketStatusCancelled,
} dif_usbdev_tx_packet_status_t;
/**
* Get the status of a packet that has been queued to be sent from an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param status Status of the packet.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_tx_packet_get_status(
dif_usbdev_t *usbdev, uint8_t endpoint,
dif_usbdev_tx_packet_status_t *status);
/**
* Set the address of a USB device.
*
* @param usbdev A USB device.
* @param addr New address. Only the last 7 bits are significant.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_address_set(dif_usbdev_t *usbdev, uint8_t addr);
/**
* Get the address of a USB device.
*
* @param usbdev A USB device.
* @param addr Current address.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_address_get(dif_usbdev_t *usbdev, uint8_t *addr);
/**
* Get USB frame index.
*
* @param usbdev A USB device.
* @param frame_index USB frame index.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_frame(dif_usbdev_t *usbdev,
uint16_t *frame_index);
/**
* Check if the host is lost.
*
* The host is lost if the link is still active but a start of frame packet has
* not been received in the last 4.096ms.
*
* @param usbdev A USB device.
* @param host_lost Status of the host. `true` if the host is lost, `false`
* otherwise.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_host_lost(dif_usbdev_t *usbdev,
bool *host_lost);
/**
* USB link state.
*/
typedef enum dif_usbdev_link_state {
kDifUsbdevLinkStateDisconnected,
kDifUsbdevLinkStatePowered,
kDifUsbdevLinkStatePoweredSuspend,
kDifUsbdevLinkStateActive,
kDifUsbdevLinkStateSuspend,
} dif_usbdev_link_state_t;
/**
* Get USB link state.
*
* @param usbdev A USB device.
* @param link_state USB link state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_link_state(
dif_usbdev_t *usbdev, dif_usbdev_link_state_t *link_state);
/**
* Get the state of the sense pin.
*
* @param usbdev A USB device.
* @param sense State of the sense pin. `true` if the host is providing VBUS,
* `false` otherwise.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_sense(dif_usbdev_t *usbdev,
bool *sense);
/**
* Get the depth of the AV FIFO.
*
* See also: `dif_usbdev_fill_available_fifo`.
*
* @param usbdev A USB device.
* @param depth Depth of the AV FIFO.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_available_fifo_depth(
dif_usbdev_t *usbdev, uint8_t *depth);
/**
* Check if AV FIFO is full.
*
* See also: `dif_usbdev_fill_available_fifo`.
*
* @param usbdev A USB device.
* @param is_full State of the AV FIFO. `true` if full, false otherwise.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_available_fifo_full(
dif_usbdev_t *usbdev, bool *is_full);
/**
* Get the depth of the RX FIFO.
*
* See also: `dif_usbdev_rx_packet_get_info`.
*
* @param usbdev A USB device.
* @param depth Depth of the RX FIFO.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_rx_fifo_depth(dif_usbdev_t *usbdev,
uint8_t *depth);
/**
* Check if the RX FIFO is empty.
*
* See also: `dif_usbdev_rx_packet_get_info`.
*
* @param usbdev A USB device.
* @param is_empty State of the RX FIFO. `true` if empty, `false` otherwise.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_rx_fifo_empty(dif_usbdev_t *usbdev,
bool *is_empty);
/**
* USB device interrupts.
*/
typedef enum dif_usbdev_irq {
/**
* \internal First USB device interrupt.
*/
kDifUsbdevIrqFirst,
/**
* A packet was received as part of an OUT or SETUP transaction.
*/
kDifUsbdevIrqPktReceived = kDifUsbdevIrqFirst,
/**
* A packet was sent as part of an IN transaction.
*/
kDifUsbdevIrqPktSent,
/**
* VBUS was lost and the link was disconnected.
*/
kDifUsbdevIrqDisconnected,
/**
* A Start-of-Frame (SOF) packet was not received on an active link
* for 4.096 ms. The host must send a SOF packet every 1 ms.
*/
kDifUsbdevIrqHostLost,
/**
* Link was reset by the host.
*/
kDifUsbdevIrqLinkReset,
/**
* Link was suspended by the host.
*/
kDifUsbdevIrqLinkSuspend,
/**
* Link became active again after being suspended.
*/
kDifUsbdevIrqLinkResume,
/**
* Available buffer FIFO was empty.
*/
kDifUsbdevIrqAvEmpty,
/**
* Received buffer FIFO was full.
*/
kDifUsbdevIrqRxFull,
/**
* A write was done to available buffer FIFO when it was full.
*/
kDifUsbdevIrqAvOverflow,
/**
* The ACK packet expected in response to an IN transaction was
* not received.
*/
kDifUsbdevIrqLinkInError,
/**
* A CRC error occurred.
*/
kDifUsbdevIrqRxCrcError,
/**
* A packet with an invalid packet identifier (PID) was received.
*/
kDifUsbdevIrqRxPidError,
/**
* A packet with invalid bitstuffing was received.
*/
kDifUsbdevIrqRxBitstuffError,
/**
* USB frame number was updated with a valid SOF packet.
*/
kDifUsbdevIrqFrame,
/**
* VBUS was detected.
*/
kDifUsbdevIrqConnected,
/**
* \internal Last USB device interrupt.
*/
kDifUsbdevIrqLast = kDifUsbdevIrqConnected
} dif_usbdev_irq_t;
/**
* Enable or disable an interrupt.
*
* @param usbdev A USB device.
* @param irq An interrupt.
* @param state New state of the interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_enable(dif_usbdev_t *usbdev,
dif_usbdev_irq_t irq,
dif_usbdev_toggle_t state);
/**
* Check if there is a pending request for an interrupt.
*
* @param usbdev A USB device.
* @param irq An interrupt.
* @param state State of the interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_get(dif_usbdev_t *usbdev,
dif_usbdev_irq_t irq, bool *state);
/**
* Clear an interrupt.
*
* @param usbdev A USB device.
* @param irq An interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_clear(dif_usbdev_t *usbdev,
dif_usbdev_irq_t irq);
/**
* Clear all pending interrupts.
*
* @param usbdev A USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_clear_all(dif_usbdev_t *usbdev);
/**
* Disable all interrupts and optionally return the current interrupt
* configuration.
*
* @param usbdev A USB device.
* @param cur_config Current interrupt configuration.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_disable_all(dif_usbdev_t *usbdev,
uint32_t *cur_config);
/**
* Restore interrupt configuration.
*
* @param usbdev A USB device.
* @param new_config New interrupt configuration.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_restore(dif_usbdev_t *usbdev,
uint32_t new_config);
/**
* Test an interrupt.
*
* @param usbdev A USB device.
* @param irq An interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_test(dif_usbdev_t *usbdev,
dif_usbdev_irq_t irq);
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_USBDEV_H_