36 static constexpr uint8_t BufferCount = 32u;
37 static constexpr uint8_t MaxEndpoints = 12u;
47 uint32_t interruptEnable;
48 uint32_t interruptTest;
51 uint32_t endpointOutEnable;
52 uint32_t endpointInEnable;
54 uint32_t availableOutBuffer;
55 uint32_t availableSetupBuffer;
56 uint32_t receiveBuffer;
80 uint32_t inIsochronous;
83 uint32_t inDataToggle;
93 [[maybe_unused]] uint32_t phyPinsSense;
94 [[maybe_unused]] uint32_t phyPinsDrive;
176 ResumeLinkActive = 1u << 1,
177 DeviceAddress = 0x7Fu << 16,
190 LinkState = 0x7u << 12,
192 AvailableOutDepth = 0xFu << 16,
193 AvailableSetupDepth = 0x7u << 20,
194 AvailableOutFull = 1u << 23,
195 ReceiveDepth = 0xFu << 24,
196 AvailableSetupFull = 1u << 30,
197 ReceiveEmpty = 1u << 31,
208 BufferId = 0x1Fu << 0,
211 EndpointId = 0xFu << 20,
223 BufferId = 0x1Fu << 0,
238 UseDifferentialReceiver = 1u << 0,
252 constexpr uint32_t SetupFullBit =
253 static_cast<uint32_t
>(UsbStatusField::AvailableSetupFull);
254 constexpr uint32_t OutFullBit =
255 static_cast<uint32_t
>(UsbStatusField::AvailableOutFull);
257 for (uint8_t index = 0; index < BufferCount; index++)
259 const uint32_t Buffer = (1u << index);
260 if (!(bufferBitmap & Buffer))
267 if (usbStatus & SetupFullBit)
269 if (usbStatus & OutFullBit)
273 availableOutBuffer = index;
277 availableSetupBuffer = index;
279 bufferBitmap &= ~Buffer;
289 interruptEnable = interruptEnable |
static_cast<uint32_t
>(interrupt);
297 interruptEnable = interruptEnable & ~static_cast<uint32_t>(interrupt);
311 [[nodiscard]]
int init(uint64_t &bufferBitmap)
volatile
316 static_cast<uint32_t
>(PhyConfigField::UseDifferentialReceiver);
335 bool isochronous)
volatile
337 if (endpointId >= MaxEndpoints)
341 const uint32_t Mask = 1u << endpointId;
342 endpointOutEnable = (endpointOutEnable & ~Mask) | (enabled ? Mask : 0u);
361 bool isochronous)
volatile
363 if (endpointId >= MaxEndpoints)
367 const uint32_t Mask = 1u << endpointId;
368 endpointInEnable = (endpointInEnable & ~Mask) | (enabled ? Mask : 0u);
369 inIsochronous = (inIsochronous & ~Mask) | (isochronous ? Mask : 0u);
382 bool stalling)
volatile
384 if (endpointId >= MaxEndpoints)
388 const uint32_t Mask = 1u << endpointId;
390 inStall = (inStall & ~Mask) | (stalling ? Mask : 0u);
405 if (!(endpointInEnable & endpointOutEnable & 0b1))
410 usbControl |
static_cast<uint32_t
>(UsbControlField::Enable);
422 usbControl & ~static_cast<uint32_t>(UsbControlField::Enable);
432 return (usbControl &
static_cast<uint32_t
>(UsbControlField::Enable));
450 constexpr uint32_t Mask =
451 static_cast<uint32_t
>(UsbControlField::DeviceAddress);
452 usbControl = (usbControl & ~Mask) | (address << 16);
469 uint8_t &bufferId)
volatile
471 constexpr uint32_t BufferIdMask =
472 static_cast<uint32_t
>(ConfigInField::BufferId);
476 for (endpointId = 0; endpointId < MaxEndpoints; endpointId++)
478 const uint32_t EndpointBit = 1u << endpointId;
479 if (sent & EndpointBit)
484 bufferId = (
configIn[endpointId] & BufferIdMask);
504 const uint32_t *data,
505 uint8_t size)
volatile
510 usbdev_transfer(buffer(bufferId), data, size,
true);
513 constexpr uint32_t ReadyBit =
514 static_cast<uint32_t
>(ConfigInField::Ready);
515 configIn[endpointId] = bufferId | (size << 8);
527 static_cast<uint32_t
>(ReceiveBufferField::EndpointId)) >>
533 return (info &
static_cast<uint32_t
>(ReceiveBufferField::Size)) >>
539 return (info &
static_cast<uint32_t
>(ReceiveBufferField::Setup)) !=
546 static_cast<uint32_t
>(ReceiveBufferField::BufferId)) >>
560 [[nodiscard]] std::optional<ReceiveBufferInfo>
packet_take()
volatile
562 if (!(usbStatus &
static_cast<uint32_t
>(UsbStatusField::ReceiveDepth)))
575 uint32_t *destination)
volatile
577 const auto [id, size] =
583 usbdev_transfer(destination, buffer(
id), size,
false);
596 uint32_t *buffer(uint8_t bufferId)
volatile
599 const uintptr_t Address =
reinterpret_cast<uintptr_t
>(
this) + Offset;
600 return const_cast<uint32_t *
>(
reinterpret_cast<uint32_t *
>(Address));
614 static void usbdev_transfer(uint32_t *destination,
615 const uint32_t *source,
621 constexpr uint8_t UnrollFactor = 4u;
622 constexpr uint32_t UnrollMask = (UnrollFactor * 4u) - 1;
625 const uint32_t UnrollSize = (size & ~UnrollMask);
626 const uint32_t *sourceEnd =
reinterpret_cast<uint32_t *
>(
627 reinterpret_cast<uintptr_t
>(source) + UnrollSize);
638 while (source < sourceEnd)
640 destination[0] = source[0];
641 destination[1] = source[1];
642 destination[2] = source[2];
643 destination[3] = source[3];
644 destination += UnrollFactor;
645 source += UnrollFactor;
649 for (size &= UnrollMask; size >= UnrollFactor; size -= UnrollFactor)
651 *destination++ = *source++;
662 const volatile uint8_t *trailingBytes =
663 reinterpret_cast<const volatile uint8_t *
>(source);
664 uint32_t partialWord = trailingBytes[0];
667 partialWord |= trailingBytes[1] << 8;
671 partialWord |= trailingBytes[2] << 16;
674 *destination = partialWord;
678 volatile uint8_t *destinationBytes =
679 reinterpret_cast<volatile uint8_t *
>(destination);
681 const uint32_t TrailingBytes = *source;
683 destinationBytes[0] =
static_cast<uint8_t
>(TrailingBytes);
686 destinationBytes[1] =
static_cast<uint8_t
>(TrailingBytes >> 8);
690 destinationBytes[2] =
static_cast<uint8_t
>(TrailingBytes >> 16);
A driver for OpenTitan USB Device, which is used in the Sonata system.
uint32_t outDataToggle
Registers for configuring if endpoints data toggle on transactions.
uint32_t phyConfig
Config register for the USB PHY pins.
uint32_t receiveEnableOut
Register to enable receive OUT transactions.
std::optional< ReceiveBufferInfo > packet_take() volatile
If a packet has been received, removes the packet's buffer from the receive FIFO giving it's informat...
void packet_data_get(ReceiveBufferInfo bufferInfo, uint32_t *destination) volatile
Retrieves the data from a buffer containing a received packet.
uint32_t receiveEnableSetup
Register to enable receive SETUP transactions.
UsbdevInterrupt
Interrupt definitions for OpenTitan's USB Device.
@ AvailableOutEmpty
Interrupt asserted whilst the Available OUT buffer is empty.
@ PacketReceived
Interrupt asserted whilst the receive FIFO (buffer) is not empty.
@ PacketSent
Interrupt asserted when a packet was sent as part of an IN transaction, but not cleared from the inSe...
@ ReceiveFull
Interrupt asserted whilst the Receive buffer is full.
@ LinkResume
Interrupt raised on link transition from suspended to non-idle.
@ LinkInError
Interrupt raised when an error occurs during an IN transaction.
@ Powered
Interrupt raised when VBUS (power supply) is detected.
@ FrameUpdated
Interrupt raised when the USB frame number is updated with a valid SOF (Start of Frame) packet.
@ AvailableBufferOverflow
Interrupt raised when the Available OUT buffer or the Available SETUP buffer overflows.
@ HostLost
Interrupt raised when the link is active, but a Start of Frame (SOF) packet has not been received wit...
@ LinkSuspend
Interrupt raised when the link has entered the suspend state, due to being idle for more than 3 milli...
@ LinkReset
Interrupt raised when a Bus Reset condition is indicated on the link by the link being held in an SE0...
@ BitstuffingError
Interrupt raised when a bit stuffing violation is detected.
@ PacketIdentifierError
Interrupt raised when an invalid Packet Identifier is received.
@ Disconnected
Interrupt raised when VBUS (power supply) is lost, i.e.
@ RedundancyCheckError
Interrupt raised when a CRC (cyclic redundancy check) error occurs on a received packet; i....
@ AvailableSetupEmpty
Interrupt asserted whilst the Available SETUP buffer is empty.
@ LinkOutError
Interrupt raised when an error occurs during an OUT transaction.
int connect() volatile
Connect the device to the USB, indicating its presence to the USB host controller.
int init(uint64_t &bufferBitmap) volatile
Initialise the USB device, ensuring that packet buffers are available for reception and that the PHY ...
int in_endpoint_configure(uint8_t endpointId, bool enabled, bool isochronous) volatile
Set up the configuration of an IN endpoint for the USB device.
int device_address_set(uint8_t address) volatile
Set the device address on the USB; this address will have been supplied by the USB host controller in...
bool connected() volatile
Check whether the USB device is connected (i.e.
uint32_t inSent
Register showing ACK receival to indicate a successful IN send.
uint64_t supply_buffers(uint64_t bufferBitmap) volatile
Ensure that the Available OUT and Available SETUP buffers are kept supplied with buffers for packet r...
static constexpr uint8_t MaxPacketLength
Supported sizes for the USB Device.
uint32_t outIsochronous
Registers for configuring which endpoints should be treated as isochronous endpoints.
ConfigInField
Definitions of fields (and their locations) for a Config In register (where there is one such registe...
void interrupt_disable(UsbdevInterrupt interrupt) volatile
Disable a specified interrupt / interrupts.
void packet_send(uint8_t bufferId, uint8_t endpointId, const uint32_t *data, uint8_t size) volatile
Present a packet on the specified IN endpoint for collection by the USB host controller.
uint32_t interruptState
Device Registers.
uint32_t outStall
Registers for controlling the stalling of OUT and IN endpoints.
ReceiveBufferField
Definitions of fields (and their locations) for the Receive FIFO buffer register (offset 0x28).
void disconnect() volatile
Disconnect the device from the USB.
UsbControlField
Definitions of fields (and their locations) for the USB Control register (offset 0x10).
void interrupt_enable(UsbdevInterrupt interrupt) volatile
Enable a specified interrupt / interrupts.
int endpoint_stalling_set(uint8_t endpointId, bool stalling) volatile
Set the STALL state of a specified endpoint pair (both IN and OUT).
static constexpr uint32_t BufferStartAddress
The offset from the start of the USB Device MMIO region at which packet buffer memory begins.
UsbStatusField
Definitions of fields (and their locations) for the USB Status register (offset 0x1c).
int out_endpoint_configure(uint8_t endpointId, bool enabled, bool setup, bool isochronous) volatile
Set up the configuration of an OUT endpoint for the USB device.
PhyConfigField
Definitions of fields (and their locations) for the PHY Config Register (offset 0x8c).
int retrieve_collected_packet(uint8_t &endpointId, uint8_t &bufferId) volatile
Check and retrieve the endpoint and buffer numbers of a recently-collected IN data packet.
uint32_t setNotAcknowledgeOut
Register to set NAK (Not/Negated Acknowledge) after OUT transactions.
uint32_t configIn[MaxEndpoints]
IN transaction configuration registers.
Utility class to delete copy and move contructors.
The information associated with a received packet.
constexpr uint16_t size()
The size of the received packet.
constexpr uint8_t buffer_id()
The buffer ID used to store the received packet.
constexpr bool is_setup()
Whether the received packet was a setup packet.
constexpr uint8_t endpoint_id()
The endpoint ID the received packet was received on.
Miscellaneous utility functions and classes.