dif_usbdev.h
To use this DIF, include the following C header:
#include "/workspace/sw/device/lib/dif/dif_usbdev.h"
This header provides the following device interface functions:
dif_usbdev_address_get
Get the address of a USB device.dif_usbdev_address_set
Set the address of a USB device.dif_usbdev_buffer_raw_read
Raw data transfer directly from the packet buffer memory.dif_usbdev_buffer_raw_write
Raw data transfer directly to the packet buffer memory.dif_usbdev_buffer_read
Read incoming packet payload.dif_usbdev_buffer_request
Request a buffer for outgoing packet payload.dif_usbdev_buffer_return
Return a buffer to the free buffer pool.dif_usbdev_buffer_write
Write outgoing packet payload.dif_usbdev_clear_data_toggle
Clear the data toggle bits for the selected endpoint.dif_usbdev_clear_tx_status
Clear the TX state of the provided endpoint and restore its associated buffer to the pool.dif_usbdev_configure
Configures a USB device with runtime information.dif_usbdev_data_toggle_in_read
Read the data toggle bits of the IN endpoints.dif_usbdev_data_toggle_in_write
Write to the data toggle bits of a subset of the IN endpoints.dif_usbdev_data_toggle_out_read
Read the data toggle bits of the OUT endpoints.dif_usbdev_data_toggle_out_write
Write to the data toggle bits of a subset of the OUT endpoints.dif_usbdev_endpoint_enable
Enable or disable an endpoint.dif_usbdev_endpoint_iso_enable
Enable or disable isochronous mode for an endpoint.dif_usbdev_endpoint_out_enable
Enable or disable reception of OUT packets for an active endpoint.dif_usbdev_endpoint_set_nak_out_enable
Enable or disable clearing the out_enable bit after completion of an OUT transaction to an endpoint.dif_usbdev_endpoint_setup_enable
Enable or disable reception of SETUP packets for an endpoint.dif_usbdev_endpoint_stall_enable
Enable or disable STALL for an endpoint.dif_usbdev_endpoint_stall_get
Get STALL state of an endpoint.dif_usbdev_fill_available_fifos
Fill the available buffer FIFO of a USB device.dif_usbdev_get_phy_pins_status
Get the current state of the USB PHY pins.dif_usbdev_get_tx_sent
Get which IN endpoints have sent packets.dif_usbdev_get_tx_status
Get the status of a packet that has been queued to be sent from an endpoint.dif_usbdev_get_wake_status
Get the status of the AON wake module.dif_usbdev_interface_enable
Enable the USB interface of a USB device.dif_usbdev_recv
Get the packet at the front of RX FIFO.dif_usbdev_resume_link_to_active
Force the link state machine to resume to an active state.dif_usbdev_send
Mark a packet ready for transmission from an endpoint.dif_usbdev_set_osc_test_mode
Control whether oscillator test mode is enabled.dif_usbdev_set_phy_pins_state
Control whether to override the USB PHY and drive pins as GPIOs.dif_usbdev_set_wake_enable
Control whether the AON wake module is active.dif_usbdev_status_get_available_fifo_depths
Get the depths of the AV OUT and AV SETUP FIFOs.dif_usbdev_status_get_available_fifo_full
Check if AV OUT and AV SETUP FIFOs are full.dif_usbdev_status_get_frame
Get USB frame index.dif_usbdev_status_get_host_lost
Check if the host is lost.dif_usbdev_status_get_link_state
Get USB link state.dif_usbdev_status_get_rx_fifo_depth
Get the depth of the RX FIFO.dif_usbdev_status_get_rx_fifo_empty
Check if the RX FIFO is empty.dif_usbdev_status_get_sense
Get the state of the sense pin.
Generated from dif_usbdev.h
// Copyright lowRISC contributors (OpenTitan project).
// 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 <stddef.h>
#include <stdint.h>
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/autogen/dif_usbdev_autogen.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* 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
// Constants used for the `dif_usbdev_endpoint_id` direction field.
#define USBDEV_ENDPOINT_DIR_IN 1
#define USBDEV_ENDPOINT_DIR_OUT 0
typedef struct dif_usbdev_endpoint_id {
/**
* Endpoint number.
*/
unsigned int number : 4;
/**
* Reserved. Should be zero.
*/
unsigned int reserved : 3;
/**
* Endpoint direction. 1 = IN endpoint, 0 = OUT endpoint
*/
unsigned int direction : 1;
} dif_usbdev_endpoint_id_t;
/**
* 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 buffers[USBDEV_NUM_BUFFERS];
int8_t top;
} dif_usbdev_buffer_pool_t;
/**
* Buffer types.
*/
typedef enum dif_usbdev_buffer_type {
/**
* For reading payloads of incoming packets.
*/
kDifUsbdevBufferTypeRead,
/**
* For writing payloads of outgoing packets.
*/
kDifUsbdevBufferTypeWrite,
/**
* Clients must not use a buffer after it is handed over to hardware or
* returned to the free buffer pool. This type exists to protect against such
* cases.
*/
kDifUsbdevBufferTypeStale,
} dif_usbdev_buffer_type_t;
/**
* A USB device buffer.
*
* This struct represents a USB device buffer that has been provided to a client
* in response to a buffer request. Clients should treat instances of this
* struct as opaque objects and should pass them to the appropriate functions of
* this library to read and write payloads of incoming and outgoing packets,
* respectively.
*
* See also: `dif_usbdev_recv`, `dif_usbdev_buffer_read`,
* `dif_usbdev_buffer_request`, `dif_usbdev_buffer_write`,
* `dif_usbdev_send`, `dif_usbdev_buffer_return`.
*/
typedef struct dif_usbdev_buffer {
/**
* Hardware buffer id.
*/
uint8_t id;
/**
* Byte offset for the next read or write operation.
*/
uint8_t offset;
/**
* For read buffers: remaining number of bytes to read.
* For write buffers: remaining number of bytes that can be written.
*/
uint8_t remaining_bytes;
/**
* Type of this buffer.
*/
dif_usbdev_buffer_type_t type;
} dif_usbdev_buffer_t;
/**
* Configuration for initializing a USB device.
*/
typedef struct dif_usbdev_config {
/**
* Activate the single-ended D signal for detecting K and J symbols, for use
* with a differential receiver.
*/
dif_toggle_t have_differential_receiver;
/**
* Use the TX interface with D and SE0 signals instead of Dp/Dn, for use with
* certain transceivers.
*/
dif_toggle_t use_tx_d_se0;
/*
* Recognize a single SE0 bit as end of packet instead of requiring
* two bits.
*/
dif_toggle_t single_bit_eop;
/**
* Flip the D+/D- pins.
*/
dif_toggle_t pin_flip;
/**
* Reference signal generation for clock synchronization.
*/
dif_toggle_t clock_sync_signals;
} dif_usbdev_config_t;
/**
* Configures a USB device with runtime information.
*
* This function should need to be called once for the lifetime of `handle`.
*
* @param usbdev A USB device.
* @param buffer_pool A USB device buffer pool.
* @param config Runtime configuration parameters for a USB device.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_configure(const dif_usbdev_t *usbdev,
dif_usbdev_buffer_pool_t *buffer_pool,
dif_usbdev_config_t config);
/**
* 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.
* @param buffer_pool A USB device buffer pool.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_fill_available_fifos(
const dif_usbdev_t *usbdev, dif_usbdev_buffer_pool_t *buffer_pool);
/**
* Enable or disable reception of SETUP packets for an endpoint.
*
* This controls whether the pair of IN and OUT endpoints with the specified
* endpoint number are control endpoints.
*
* @param usbdev A USB device.
* @param endpoint An endpoint number.
* @param new_state New SETUP packet reception state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_endpoint_setup_enable(const dif_usbdev_t *usbdev,
uint8_t endpoint,
dif_toggle_t new_state);
/**
* Enable or disable reception of OUT packets for an active endpoint.
*
* When disabling reception of OUT packets, what the endpoint will do depends
* on other factors. If the endpoint is currently configured as a control
* endpoint (receives SETUP packets) or it is configured as an isochronous
* endpoint, disabling reception of OUT packets will cause them to be ignored.
*
* If the endpoint is neither a control nor isochronous endpoint, then its
* behavior depends on whether it is configured to respond with STALL. If the
* STALL response is not active, then disabling reception will cause usbdev to
* NAK the packet. Otherwise, the STALL response takes priority, regardless of
* the setting here.
*
* @param usbdev A USB device.
* @param endpoint An OUT endpoint number.
* @param new_state New OUT packet reception state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_endpoint_out_enable(const dif_usbdev_t *usbdev,
uint8_t endpoint,
dif_toggle_t new_state);
/**
* Enable or disable clearing the out_enable bit after completion of an OUT
* transaction to an endpoint.
*
* If set_nak_out is enabled, an OUT endpoint will disable reception of OUT
* packets after each successful OUT transaction to that endpoint, requiring a
* call to `dif_usbdev_endpoint_out_enable()` to enable reception again.
*
* @param usbdev A USB device.
* @param endpoint An OUT endpoint number.
* @param new_state New set_nak_on_out state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_endpoint_set_nak_out_enable(const dif_usbdev_t *usbdev,
uint8_t endpoint,
dif_toggle_t new_state);
/**
* Enable or disable STALL for an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint ID.
* @param new_state New STALL state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_endpoint_stall_enable(const dif_usbdev_t *usbdev,
dif_usbdev_endpoint_id_t endpoint,
dif_toggle_t new_state);
/**
* Get STALL state of an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint ID.
* @param[out] state Current STALL state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_endpoint_stall_get(const dif_usbdev_t *usbdev,
dif_usbdev_endpoint_id_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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_endpoint_iso_enable(const dif_usbdev_t *usbdev,
dif_usbdev_endpoint_id_t endpoint,
dif_toggle_t new_state);
/**
* Enable or disable an endpoint.
*
* An enabled endpoint responds to packets from the host. A disabled endpoint
* ignores them.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New endpoint state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_endpoint_enable(const dif_usbdev_t *usbdev,
dif_usbdev_endpoint_id_t endpoint,
dif_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. Ensure the default endpoint is
* set up before enabling the interface.
*
* @param usbdev A USB device.
* @param new_state New interface state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_interface_enable(const dif_usbdev_t *usbdev,
dif_toggle_t new_state);
/**
* Information about a received packet.
*/
typedef struct dif_usbdev_rx_packet_info {
/**
* Endpoint of the packet.
*/
uint8_t endpoint;
/**
* Payload length in bytes.
*/
uint8_t length;
/**
* Indicates if the packet is a SETUP packet.
*/
bool is_setup;
} dif_usbdev_rx_packet_info_t;
/**
* Get 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_recv`, and
* - Calling `dif_usbdev_buffer_read` until the entire packet payload
* is read.
*
* In order to read an incoming packet, clients should first call this function
* to get information about the packet and the buffer that holds the packet
* payload. Then, clients should call `dif_usbdev_buffer_read` with this buffer
* one or more times (depending on the sizes of their internal buffers) until
* the entire packet payload is read. Once the entire payload is read, the
* buffer 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_buffer_return` to immediately return the buffer to the
* free buffer pool.
*
* @param usbdev A USB device.
* @param[out] packet_info Packet information.
* @param[out] buffer Buffer that holds the packet payload.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_recv(const dif_usbdev_t *usbdev,
dif_usbdev_rx_packet_info_t *packet_info,
dif_usbdev_buffer_t *buffer);
/**
* Read incoming packet payload.
*
* Clients should call this function with a buffer provided by `dif_usbdev_recv`
* to read the payload of an incoming packet. This function copies the smaller
* of `dst_len` and remaining number of bytes in the buffer to `dst`. 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_recv`.
*
* @param usbdev A USB device.
* @param buffer_pool A USB device buffer pool.
* @param buffer A buffer provided by `dif_usbdev_recv`.
* @param[out] dst Destination buffer.
* @param dst_len Length of the destination buffer.
* @param[out] bytes_written Number of bytes written to destination buffer.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_buffer_read(const dif_usbdev_t *usbdev,
dif_usbdev_buffer_pool_t *buffer_pool,
dif_usbdev_buffer_t *buffer, uint8_t *dst,
size_t dst_len, size_t *bytes_written);
/**
* Return a buffer to the free buffer pool.
*
* This function immediately returns the given buffer to the free buffer pool.
* Since `dif_usbdev_buffer_read` and `dif_usbdev_get_tx_status` return the
* buffers that they work on to the free buffer pool automatically, this
* function should only be called to discard the payload of a received
* packet or a packet that was being prepared for transmission before it is
* queued for transmission from an endpoint.
*
* See also: `dif_usbdev_recv`, `dif_usbdev_buffer_request`.
*
* @param usbdev A USB device.
* @param buffer_pool A USB device buffer pool.
* @param buffer A buffer provided by `dif_usbdev_recv` or
* `dif_usbdev_buffer_request`.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_buffer_return(const dif_usbdev_t *usbdev,
dif_usbdev_buffer_pool_t *buffer_pool,
dif_usbdev_buffer_t *buffer);
/**
* Request a buffer for outgoing packet payload.
*
* Clients should call this function to request a buffer to write the payload of
* an outgoing packet. Sending a packet from a particular endpoint to the host
* involves four main steps:
* - Calling this function, i.e. `dif_usbdev_buffer_request`,
* - Calling `dif_usbdev_buffer_write`,
* - Calling `dif_usbdev_send`, and
* - Calling `dif_usbdev_get_tx_status`.
*
* In order to send a packet, clients should first call this function to obtain
* a buffer for the packet payload. Clients should then call
* `dif_usbdev_buffer_write` (one or more times depending on the sizes of their
* internal buffers) to write the packet payload to this buffer. After writing
* the packet payload, clients should call `dif_usbdev_send` to mark the packet
* as ready for transmission from a particular endpoint. Then, clients should
* call `dif_usbdev_get_tx_status` to check the status of the transmission.
* `dif_usbdev_get_tx_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 or a link reset. If the packet
* should no longer be sent, clients can call `dif_usbdev_buffer_return` to
* return the buffer to the free buffer pool as long as `dif_usbdev_send` is not
* called yet.
*
* See also: `dif_usbdev_buffer_write`, `dif_usbdev_send`,
* `dif_usbdev_get_tx_status`, `dif_usbdev_buffer_return`.
*
* @param usbdev A USB device.
* @param buffer_pool A USB device buffer pool.
* @param[out] buffer A buffer for writing outgoing packet payload.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_buffer_request(const dif_usbdev_t *usbdev,
dif_usbdev_buffer_pool_t *buffer_pool,
dif_usbdev_buffer_t *buffer);
/**
* Write outgoing packet payload.
*
* Clients should call this function with a buffer provided by
* `dif_usbdev_buffer_request` to write the payload of an outgoing packet. This
* function copies the smaller of `src_len` and remaining number of bytes in the
* buffer to the buffer. Clients should then call `dif_usbdev_send` to queue the
* packet for transmission from a particular endpoint.
*
* See also: `dif_usbdev_buffer_request`, `dif_usbdev_send`,
* `dif_usbdev_get_tx_status`, `dif_usbdev_buffer_return`.
*
* @param usbdev A USB device.
* @param buffer A buffer provided by `dif_usbdev_buffer_request`.
* @param src Source buffer.
* @param src_len Length of the source buffer.
* @param[out] bytes_written Number of bytes written to the USB device buffer.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_buffer_write(const dif_usbdev_t *usbdev,
dif_usbdev_buffer_t *buffer,
const uint8_t *src, size_t src_len,
size_t *bytes_written);
/**
* Mark a packet ready for transmission from 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. 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 check its status by
* calling `dif_usbdev_get_tx_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. Clients must also make sure that the given endpoint does
* not already have a packet pending for transmission before calling this
* function.
*
* See also: `dif_usbdev_buffer_request`, `dif_usbdev_buffer_write`,
* `dif_usbdev_get_tx_status`, `dif_usbdev_buffer_return`.
*
* @param usbdev A USB device.
* @param endpoint An OUT endpoint number.
* @param buffer A buffer provided by `dif_usbdev_buffer_request`.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_send(const dif_usbdev_t *usbdev, uint8_t endpoint,
dif_usbdev_buffer_t *buffer);
/**
* Get which IN endpoints have sent packets.
*
* This function provides which endpoints have buffers that have successfully
* completed transmission to the host. It may be used to guide calls to
* `dif_usbdev_clear_tx_status` to return the used buffer to the pool and clear
* the state for the next transaction.
*
* @param usbdev A USB device.
* @param[out] sent A bitmap of which endpoints have sent packets.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_get_tx_sent(const dif_usbdev_t *usbdev, uint16_t *sent);
/**
* Clear the TX state of the provided endpoint and restore its associated buffer
* to the pool.
*
* Note that this function should only be called when an endpoint has been
* provided a buffer. Without it, the buffer pool will become corrupted, as this
* function does not check the status.
*
* In addition, if the endpoint has not yet completed or canceled the
* transaction, the user must not call this function while the device is in an
* active state. Otherwise, the user risks corrupting an ongoing transaction.
*
* @param usbdev A USB device.
* @param buffer_pool A USB device buffer pool.
* @param endpoint An IN endpoint number.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_clear_tx_status(const dif_usbdev_t *usbdev,
dif_usbdev_buffer_pool_t *buffer_pool,
uint8_t endpoint);
/**
* Status of an outgoing packet.
*/
typedef enum dif_usbdev_tx_status {
/**
* There is no packet for the given OUT endpoint.
*/
kDifUsbdevTxStatusNoPacket,
/**
* Packet is pending transmission.
*/
kDifUsbdevTxStatusPending,
/**
* Packet was sent successfully.
*/
kDifUsbdevTxStatusSent,
/**
* Transmission was canceled due to an incoming SETUP packet.
*/
kDifUsbdevTxStatusCancelled,
} dif_usbdev_tx_status_t;
/**
* Get the status of a packet that has been queued to be sent from an endpoint.
*
* 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.
*
* This function does not modify any device state. `dif_usbdev_clear_tx_status`
* can be used to clear the status and return the buffer to the pool.
*
* @param usbdev A USB device.
* @param endpoint An IN endpoint number.
* @param[out] status Status of the packet.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_get_tx_status(const dif_usbdev_t *usbdev,
uint8_t endpoint,
dif_usbdev_tx_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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_address_set(const dif_usbdev_t *usbdev, uint8_t addr);
/**
* Get the address of a USB device.
*
* @param usbdev A USB device.
* @param[out] addr Current address.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_address_get(const dif_usbdev_t *usbdev, uint8_t *addr);
/**
* Read the data toggle bits of the OUT endpoints.
*
* @param usbdev A USB device.
* @param[out]toggles Current state of OUT data toggle bits.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_data_toggle_out_read(const dif_usbdev_t *usbdev,
uint16_t *toggles);
/**
* Read the data toggle bits of the IN endpoints.
*
* @param usbdev A USB device.
* @param[out]toggles Current state of IN data toggle bits.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_data_toggle_in_read(const dif_usbdev_t *usbdev,
uint16_t *toggles);
/**
* Write to the data toggle bits of a subset of the OUT endpoints.
* Set 1 in `mask` to change the data toggle bit of an OUT endpoint to the value
* of the corresponding bit in `state`.
*
* @param usbdev A USB device.
* @param mask Mask of OUT endpoint data toggles to be changed.
* @param state New states of that OUT endpoint data toggles being changed.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_data_toggle_out_write(const dif_usbdev_t *usbdev,
uint16_t mask, uint16_t state);
/**
* Write to the data toggle bits of a subset of the IN endpoints.
* Set 1 in `mask` to change the data toggle bit of an IN endpoint to the value
* of the corresponding bit in `state`.
*
* @param usbdev A USB device.
* @param mask Mask of IN endpoint data toggles to be changed.
* @param state New states of that IN endpoint data toggles being changed.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_data_toggle_in_write(const dif_usbdev_t *usbdev,
uint16_t mask, uint16_t state);
/**
* Clear the data toggle bits for the selected endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint number.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_clear_data_toggle(const dif_usbdev_t *usbdev,
uint8_t endpoint);
/**
* Get USB frame index.
*
* @param usbdev A USB device.
* @param[out] frame_index USB frame index.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_status_get_frame(const 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[out] host_lost Status of the host. `true` if the host is lost, `false`
* otherwise.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_status_get_host_lost(const dif_usbdev_t *usbdev,
bool *host_lost);
/**
* USB link state.
*/
typedef enum dif_usbdev_link_state {
kDifUsbdevLinkStateDisconnected,
kDifUsbdevLinkStatePowered,
kDifUsbdevLinkStatePoweredSuspended,
kDifUsbdevLinkStateActive,
kDifUsbdevLinkStateSuspended,
kDifUsbdevLinkStateActiveNoSof,
kDifUsbdevLinkStateResuming,
} dif_usbdev_link_state_t;
/**
* Get USB link state.
*
* @param usbdev A USB device.
* @param[out] link_state USB link state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_status_get_link_state(
const dif_usbdev_t *usbdev, dif_usbdev_link_state_t *link_state);
/**
* Get the state of the sense pin.
*
* @param usbdev A USB device.
* @param[out] sense State of the sense pin. `true` if the host is providing
* VBUS, `false` otherwise.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_status_get_sense(const dif_usbdev_t *usbdev,
bool *sense);
/**
* Get the depths of the AV OUT and AV SETUP FIFOs.
*
* See also: `dif_usbdev_fill_available_fifos`.
*
* @param usbdev A USB device.
* @param[out] setup_depth Depth of the AV SETUP FIFO.
* @param[out] out_depth Depth of the AV OUT FIFO.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_status_get_available_fifo_depths(
const dif_usbdev_t *usbdev, uint8_t *setup_depth, uint8_t *out_depth);
/**
* Check if AV OUT and AV SETUP FIFOs are full.
*
* See also: `dif_usbdev_fill_available_fifos`.
*
* @param usbdev A USB device.
* @param[out] setup_is_full State of the AV SETUP FIFO. `true` if full, false
* otherwise.
* @param[out] out_is_full State of the AV OUT FIFO. `true` if full, false
* otherwise.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_status_get_available_fifo_full(
const dif_usbdev_t *usbdev, bool *setup_is_full, bool *out_is_full);
/**
* Get the depth of the RX FIFO.
*
* See also: `dif_usbdev_recv`.
*
* @param usbdev A USB device.
* @param[out] depth Depth of the RX FIFO.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_status_get_rx_fifo_depth(const dif_usbdev_t *usbdev,
uint8_t *depth);
/**
* Check if the RX FIFO is empty.
*
* See also: `dif_usbdev_recv`.
*
* @param usbdev A USB device.
* @param[out] is_empty State of the RX FIFO. `true` if empty, `false`
* otherwise.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_status_get_rx_fifo_empty(const dif_usbdev_t *usbdev,
bool *is_empty);
/**
* Control whether oscillator test mode is enabled.
*
* In oscillator test mode, usbdev transmits a continuous 0101 pattern for
* evaluating the reference clock's quality.
*
* @param usbdev A USB device.
* @param enable Whether the test mode should be enabled.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_set_osc_test_mode(const dif_usbdev_t *usbdev,
dif_toggle_t enable);
/**
* Control whether the AON wake module is active.
*
* @param usbdev A USB device.
* @param enable Whether the AON wake module is enabled.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_set_wake_enable(const dif_usbdev_t *usbdev,
dif_toggle_t enable);
typedef struct dif_usbdev_wake_status {
/** Whether the AON wake module is active. */
bool active;
/** Whether the USB disconnected while the AON wake module was active. */
bool disconnected;
/** Whether the USB was reset while the AON wake module was active. */
bool bus_reset;
} dif_usbdev_wake_status_t;
/**
* Get the status of the AON wake module.
*
* Note that the conditions triggering exit from suspended state must be read
* before disabling the AON wake module. Once the AON wake module is
* deactivated, that status information is lost.
*
* Also note that the ordinary resume condition does not report to the usbdev
* module. Instead, it should be obtained from the module monitoring wakeup
* sources.
*
* @param usbdev A USB device.
* @param[out] status The status of the module.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_get_wake_status(const dif_usbdev_t *usbdev,
dif_usbdev_wake_status_t *status);
/**
* Force the link state machine to resume to an active state.
*
* This is used when waking from a low-power suspended state to resume to an
* active state. It moves the usbdev out of the Powered state (from the USB
* device state machine in the spec) without receiving a bus reset. Without help
* from software, the usbdev module cannot determine on its own when a bus reset
* is required.
*
* @param usbdev A USB device.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_resume_link_to_active(const dif_usbdev_t *usbdev);
typedef struct dif_usbdev_phy_pins_sense {
/** USB D+ input. */
bool rx_dp : 1;
/** USB D- input. */
bool rx_dn : 1;
/** USB data input from an external differential receiver, if available. */
bool rx_d : 1;
/** USB transmit D+ output. */
bool tx_dp : 1;
/** USB transmit D- output. */
bool tx_dn : 1;
/** USB transmit data value output. */
bool tx_d : 1;
/** USB single-ended zero output. */
bool tx_se0 : 1;
/** USB output enable for D+ / D-. */
bool output_enable : 1;
/** USB VBUS sense pin. */
bool vbus_sense : 1;
} dif_usbdev_phy_pins_sense_t;
/**
* Get the current state of the USB PHY pins.
*
* @param usbdev A USB device.
* @param[out] status The current state of the pins.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_get_phy_pins_status(
const dif_usbdev_t *usbdev, dif_usbdev_phy_pins_sense_t *status);
typedef struct dif_usbdev_phy_pins_drive {
/** USB D+ output, for use with dn. */
bool dp : 1;
/** USB D- output. for use with dp. */
bool dn : 1;
/** USB data output, encoding K and J when se0 is 0. */
bool data : 1;
/** USB single-ended zero output. */
bool se0 : 1;
/** USB output enable for D+ / D-. */
bool output_enable : 1;
/** Enable control pin for the differential receiver. */
bool diff_receiver_enable : 1;
/** Controls whether to pull up the D+ pin. */
bool dp_pullup_en : 1;
/** Controls whether to pull up the D- pin. */
bool dn_pullup_en : 1;
} dif_usbdev_phy_pins_drive_t;
/**
* Control whether to override the USB PHY and drive pins as GPIOs.
*
* @param usbdev A USB device.
* @param override_enable Enable / disable the GPIO-like overrides.
* @param overrides The values to set the pins to.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_set_phy_pins_state(
const dif_usbdev_t *usbdev, dif_toggle_t override_enable,
dif_usbdev_phy_pins_drive_t overrides);
/**
* Raw data transfer directly to the packet buffer memory. This is a faster
* implementation of the generic `mmio_memcpy_to_mmio32` that is specialized for
* the USB device and gives a significant performance improvement.
*
* @param usbdev A USB device.
* @param id Buffer number.
* @param src Source data.
* @param src_len Number of bytes to transfer.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_buffer_raw_write(const dif_usbdev_t *usbdev, uint8_t id,
const uint8_t *src, size_t src_len);
/**
* Raw data transfer directly from the packet buffer memory. This is a faster
* implementation of the generic `mmio_memcpy_from_mmio32` that is specialized
* for the USB device and gives a significant performance improvemenet.
*
* @param usbdev A USB device.
* @param id Buffer number.
* @param dst Destination buffer.
* @param dst_len Number of bytes to transfer.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_usbdev_buffer_raw_read(const dif_usbdev_t *usbdev, uint8_t id,
uint8_t *dst, size_t dst_len);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_USBDEV_H_