|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | { | 
|  | name:               "usbdev", | 
|  | human_name:         "USB Device", | 
|  | one_line_desc:      "USB 2.0 Full Speed device interface (12 Mbit/s)", | 
|  | one_paragraph_desc: ''' | 
|  | USB Device provides compatibility with the industry standard Universal Serial Bus by implementing a Full Speed device (12 Mbit/s) according to the USB 2.0 Specification. | 
|  | USB Device supports up to 12 bidirectional endpoints which may be used to support all of the USB 2.0 transfer types, including Isochronous transfers. | 
|  | Support for packet transmission and reception is provided in hardware, with the generation of interrupts for software to mediate the different stages of Control and Data Transfers. | 
|  | The maximum packet size for transfers is configurable up to the specification limit of 64 bytes per packet, reducing the protocol overhead for Bulk transfers, and the inbuilt 2 KiB memory can accommodate 32 packets. | 
|  | USB Device may be configured to use either a single-ended interface to an external differential transceiver or a differential input/output for more direct interfacing and reduced hardware complexity when prototyping. | 
|  | ''' | 
|  | design_spec:        "../doc", | 
|  | dv_doc:             "../doc/dv", | 
|  | hw_checklist:       "../doc/checklist", | 
|  | sw_checklist:       "/sw/device/lib/dif/dif_usbdev", | 
|  | version:            "1.0", | 
|  | life_stage:         "L1", | 
|  | design_stage:       "D2S", | 
|  | verification_stage: "V0", | 
|  | dif_stage:          "S2", | 
|  | clocking: [ | 
|  | // clk_i must be 48 MHz | 
|  | {clock: "clk_i", reset: "rst_ni", primary: true}, | 
|  | {clock: "clk_aon_i", reset: "rst_aon_ni"}, | 
|  | ] | 
|  | bus_interfaces: [ | 
|  | { protocol: "tlul", direction: "device" } | 
|  | ], | 
|  | available_inout_list: [ | 
|  | { name: "usb_dp", desc: "USB data D+" } | 
|  | { name: "usb_dn", desc: "USB data D-" } | 
|  | ], | 
|  | available_input_list: [ | 
|  | {  name: "sense", desc: "USB host VBUS sense" } | 
|  | ], | 
|  | available_output_list: [], | 
|  | inter_signal_list: [ | 
|  | { name:    "usb_rx_d", | 
|  | desc:    "USB RX data from an external differential receiver, if available" | 
|  | type:    "uni", | 
|  | act:     "rcv", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | } | 
|  | { name:    "usb_tx_d", | 
|  | desc:    "USB transmit data value (not used if usb_tx_se0 is set)" | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | } | 
|  | { name:    "usb_tx_se0", | 
|  | desc:    "Force transmission of a USB single-ended zero (i.e. both D+ and D- are low) regardless of usb_tx_d" | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | } | 
|  | { name:    "usb_tx_use_d_se0", | 
|  | desc:    "Use the usb_tx_d and usb_tx_se0 TX interface, instead of usb_dp_o and usb_dn_o" | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | } | 
|  | { name:    "usb_dp_pullup", | 
|  | desc:    "USB D+ pullup control" | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | } | 
|  | { name:    "usb_dn_pullup", | 
|  | desc:    "USB D- pullup control" | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | } | 
|  | { name:    "usb_rx_enable", | 
|  | desc:    "USB differential receiver enable" | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | } | 
|  | { name:    "usb_ref_val", | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | } | 
|  | { name:    "usb_ref_pulse", | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | }, | 
|  | { name:    "usb_aon_suspend_req", | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | }, | 
|  | { name:    "usb_aon_wake_ack", | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | }, | 
|  | { name:    "usb_aon_bus_reset", | 
|  | type:    "uni", | 
|  | act:     "rcv", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | }, | 
|  | { name:    "usb_aon_sense_lost", | 
|  | type:    "uni", | 
|  | act:     "rcv", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | }, | 
|  | { name:    "usb_aon_wake_detect_active", | 
|  | type:    "uni", | 
|  | act:     "rcv", | 
|  | package: "", | 
|  | struct:  "logic", | 
|  | width:   "1" | 
|  | }, | 
|  | { struct:  "ram_2p_cfg", | 
|  | package: "prim_ram_2p_pkg", | 
|  | type:    "uni", | 
|  | name:    "ram_cfg", | 
|  | act:     "rcv" | 
|  | } | 
|  | ] | 
|  | param_list: [ | 
|  | { name:    "Stub", | 
|  | type:    "bit", | 
|  | default: "0", | 
|  | desc:    "Stub out the core of entropy_src logic" | 
|  | local:   "false", | 
|  | expose:  "true" | 
|  | }, | 
|  | { name:    "NEndpoints", | 
|  | type:    "int", | 
|  | default: "12", | 
|  | desc:    "Number of endpoints", | 
|  | local:   "true" | 
|  | }, | 
|  | { name:    "RcvrWakeTimeUs", | 
|  | type:    "int", | 
|  | default: "1", | 
|  | desc:    "Maximum number of microseconds for the differential receiver to become operational", | 
|  | local:   "false", | 
|  | expose:  "true" | 
|  | } | 
|  | ], | 
|  | interrupt_list: [ | 
|  | { name: "pkt_received" | 
|  | desc: ''' | 
|  | Raised if a packet was received using an OUT or SETUP transaction. | 
|  | This interrupt is directly tied to whether the RX FIFO is empty, so it should be cleared only after handling the FIFO entry. | 
|  | ''' | 
|  | } | 
|  | { name: "pkt_sent" | 
|  | desc: ''' | 
|  | Raised if a packet was sent as part of an IN transaction. | 
|  | This interrupt is directly tied to whether a sent packet has not been acknowledged in the !!in_sent register. | 
|  | It should be cleared only after clearing all bits in the !!in_sent register. | 
|  | ''' | 
|  | } | 
|  | { name: "disconnected", | 
|  | desc: ''' | 
|  | Raised if VBUS is lost thus the link is disconnected. | 
|  | ''' | 
|  | } | 
|  | { name: "host_lost", | 
|  | desc: ''' | 
|  | Raised if link is active but SOF was not received from host for 4.096 ms. The SOF should be every 1 ms. | 
|  | ''' | 
|  | } | 
|  | { name: "link_reset", | 
|  | desc: ''' | 
|  | Raised if the link is at SE0 longer than 3 us indicating a link reset (host asserts for min 10 ms, device can react after 2.5 us). | 
|  | ''' | 
|  | } | 
|  | { name: "link_suspend", | 
|  | desc: ''' | 
|  | Raised if the line has signaled J for longer than 3ms and is therefore in suspend state. | 
|  | ''' | 
|  | } | 
|  | { name: "link_resume", | 
|  | desc: ''' | 
|  | Raised when the link becomes active again after being suspended. | 
|  | ''' | 
|  | } | 
|  | { name: "av_empty", | 
|  | desc: ''' | 
|  | Raised when the AV FIFO is empty and the device interface is enabled. | 
|  | This interrupt is directly tied to the FIFO status, so the AV FIFO must be provided a free buffer before the interrupt is cleared. | 
|  | If the condition is not cleared, the interrupt can re-assert. | 
|  | ''' | 
|  | } | 
|  | { name: "rx_full", | 
|  | desc: ''' | 
|  | Raised when the RX FIFO is full and the device interface is enabled. | 
|  | This interrupt is directly tied to the FIFO status, so the RX FIFO must have an entry removed before the interrupt is cleared. | 
|  | If the condition is not cleared, the interrupt can re-assert. | 
|  | ''' | 
|  | } | 
|  | { name: "av_overflow", | 
|  | desc: ''' | 
|  | Raised if a write was done to the Available Buffer FIFO when the FIFO was full. | 
|  | ''' | 
|  | } | 
|  | { name: "link_in_err", | 
|  | desc: ''' | 
|  | Raised if a packet to an IN endpoint started to be received but was | 
|  | then dropped due to an error. After transmitting the IN payload, | 
|  | the USB device expects a valid ACK handshake packet. This error is | 
|  | raised if either the packet or CRC is invalid or a different token | 
|  | was received. | 
|  | ''' | 
|  | } | 
|  | { name: "rx_crc_err", | 
|  | desc: ''' | 
|  | Raised if a CRC error occured. | 
|  | ''' | 
|  | } | 
|  | { name: "rx_pid_err", | 
|  | desc: ''' | 
|  | Raised if an invalid packed identifier (PID) was received. | 
|  | ''' | 
|  | } | 
|  | { name: "rx_bitstuff_err", | 
|  | desc: ''' | 
|  | Raised if an invalid bitstuffing was received. | 
|  | ''' | 
|  | } | 
|  | { name: "frame", | 
|  | desc: ''' | 
|  | Raised when the USB frame number is updated with a valid SOF. | 
|  | ''' | 
|  | } | 
|  | { name: "powered", | 
|  | desc: "Raised if VBUS is applied." | 
|  | } | 
|  | { name: "link_out_err", | 
|  | desc: ''' | 
|  | Raised if a packet to an OUT endpoint started to be received but was then dropped due to an error. | 
|  | This error is raised if either the data toggle, token, packet or CRC is invalid or if there is no buffer available in the Received Buffer FIFO. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | alert_list: [ | 
|  | { name: "fatal_fault", | 
|  | desc: ''' | 
|  | This fatal alert is triggered when a fatal TL-UL bus integrity fault is detected. | 
|  | ''' | 
|  | } | 
|  | ], | 
|  | countermeasures: [ | 
|  | { name: "BUS.INTEGRITY", | 
|  | desc: "End-to-end bus integrity scheme." | 
|  | } | 
|  | ] | 
|  | regwidth: "32", | 
|  | registers: [ | 
|  | { name: "usbctrl", | 
|  | desc: "USB Control", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "enable", | 
|  | desc: ''' | 
|  | Set to connect the USB interface (i.e. assert the pullup). | 
|  | ''' | 
|  | tags: [// Prevent usb from being enabled to avoid other unforeseen side effects. | 
|  | "excl:CsrNonInitTests:CsrExclWrite"] | 
|  | } | 
|  | { | 
|  | bits: "1", | 
|  | name: "resume_link_active", | 
|  | swaccess: "wo" | 
|  | hwqe: "true", | 
|  | desc: ''' | 
|  | Write a 1 to this bit to instruct usbdev to jump to the LinkResuming state. | 
|  | The write will only have an effect when the device is in the LinkPowered state. | 
|  | Its intention is to handle a resume-from-suspend event after the IP has been powered down. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "22:16", | 
|  | name: "device_address", | 
|  | hwaccess: "hrw", | 
|  | desc: ''' | 
|  | Device address set by host (this should be copied from | 
|  | the Set Device ID SETUP packet). | 
|  |  | 
|  | This will be zeroed by the hardware when the link resets. | 
|  | ''' | 
|  | tags: [// This field is reset to 0 if usb is not enabled. | 
|  | "excl:CsrNonInitTests:CsrExclWriteCheck"] | 
|  | } | 
|  | ] | 
|  | } | 
|  | { multireg: { | 
|  | name: "ep_out_enable", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: ''' | 
|  | Enable an endpoint to respond to transactions in the downstream direction. | 
|  | Note that as the default endpoint, endpoint 0 must be enabled in both the IN and OUT directions before enabling the USB interface to connect. | 
|  | ''' | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "enable", | 
|  | desc: ''' | 
|  | This bit must be set to enable downstream transactions to be received on the endpoint and elicit responses. | 
|  | If the bit is clear, any SETUP or OUT packets sent to the endpoint will be ignored. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "ep_in_enable", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: ''' | 
|  | Enable an endpoint to respond to transactions in the upstream direction. | 
|  | Note that as the default endpoint, endpoint 0 must be enabled in both the IN and OUT directions before enabling the USB interface to connect. | 
|  | ''' | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "enable", | 
|  | desc: ''' | 
|  | This bit must be set to enable upstream transactions to be received on the endpoint and elicit responses. | 
|  | If the bit is clear then any IN packets sent to the endpoint will be ignored. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { name: "usbstat", | 
|  | desc: "USB Status", | 
|  | swaccess: "ro", | 
|  | hwaccess: "hwo", | 
|  | hwext: "true", | 
|  | fields: [ | 
|  | { | 
|  | bits: "10:0", | 
|  | name: "frame", | 
|  | desc: ''' | 
|  | Frame index received from host. On an active link, this will increment every milisecond. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "11", | 
|  | name: "host_lost", | 
|  | desc: ''' | 
|  | Start of frame not received from host for 4.096 ms and the line is active. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "14:12", | 
|  | name: "link_state", | 
|  | desc: ''' | 
|  | State of USB link, decoded from line. | 
|  | ''' | 
|  | enum: [ | 
|  | { value: "0", | 
|  | name: "disconnected", | 
|  | desc: "Link disconnected (no VBUS or no pull-up connected)" | 
|  | }, | 
|  | { value: "1", | 
|  | name: "powered", | 
|  | desc: "Link powered and connected, but not reset yet" | 
|  | }, | 
|  | { value: "2", | 
|  | name: "powered_suspended", | 
|  | desc: "Link suspended (constant idle/J for > 3 ms), but not reset yet" | 
|  | }, | 
|  | { value: "3", | 
|  | name: "active", | 
|  | desc: "Link active" | 
|  | }, | 
|  | { value: "4", | 
|  | name: "suspended", | 
|  | desc: "Link suspended (constant idle for > 3 ms), was active before becoming suspended" | 
|  | }, | 
|  | { value: "5", | 
|  | name: "active_nosof", | 
|  | desc: "Link active but no SOF has been received since the last reset." | 
|  | }, | 
|  | { value: "6", | 
|  | name: "resuming", | 
|  | desc: "Link resuming to an active state, pending the end of resume signaling" | 
|  | }, | 
|  | ] | 
|  | } | 
|  | { | 
|  | bits: "15", | 
|  | name: "sense", | 
|  | desc: ''' | 
|  | Reflects the state of the sense pin. | 
|  | 1 indicates that the host is providing VBUS. | 
|  | Note that this bit always shows the state of the actual pin and does not take account of the override control. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "18:16", | 
|  | name: "av_depth", | 
|  | desc: ''' | 
|  | Number of buffers in the Available Buffer FIFO. | 
|  |  | 
|  | These buffers are available for receiving packets. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "23", | 
|  | name: "av_full", | 
|  | desc: ''' | 
|  | Available Buffer FIFO is full. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "26:24", | 
|  | name: "rx_depth", | 
|  | desc: ''' | 
|  | Number of buffers in the Received Buffer FIFO. | 
|  |  | 
|  | These buffers have packets that have been received and | 
|  | should be popped from the FIFO and processed. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "31", | 
|  | name: "rx_empty", | 
|  | resval: "1", | 
|  | desc: ''' | 
|  | Received Buffer FIFO is empty. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | tags: [// Updated by HW based on observed USB signals, comprises also readbacks. | 
|  | // Pinmux configuration can affect at least the sense and link_state bits. | 
|  | // Exclude all read checks in all tests including reset tests. | 
|  | "excl:CsrAllTests:CsrExclCheck"] | 
|  | } | 
|  | { name: "avbuffer", | 
|  | desc: "Available Buffer FIFO", | 
|  | swaccess: "wo", | 
|  | hwaccess: "hro", | 
|  | hwqe: "true", | 
|  | fields: [ | 
|  | { | 
|  | bits: "4:0", | 
|  | name: "buffer", | 
|  | desc: ''' | 
|  | This field contains the buffer ID being passed to the USB receive engine. | 
|  |  | 
|  | If the Available Buffer FIFO is full, any write operations are discarded. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | tags: [// Writing this CSR affects the ral.usbstat.av_depth field. | 
|  | "excl:CsrNonInitTests:CsrExclWrite"] | 
|  | } | 
|  | { name: "rxfifo", | 
|  | desc: "Received Buffer FIFO", | 
|  | swaccess: "ro", | 
|  | hwaccess: "hrw", | 
|  | hwext: "true", | 
|  | hwre: "true", | 
|  | fields: [ | 
|  | { | 
|  | bits: "4:0", | 
|  | name: "buffer", | 
|  | desc: ''' | 
|  | This field contains the buffer ID that data was received into. | 
|  | On read the buffer ID is popped from the Received Buffer FIFO and returned to software. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "14:8", | 
|  | name: "size", | 
|  | desc: ''' | 
|  | This field contains the data length in bytes of the packet written to the buffer. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "19", | 
|  | name: "setup", | 
|  | desc: ''' | 
|  | This bit indicates if the received transaction is of type SETUP (1) or OUT (0). | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "23:20", | 
|  | name: "ep", | 
|  | desc: ''' | 
|  | This field contains the endpoint ID to which the packet was directed. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | { multireg: { | 
|  | name: "rxenable_setup", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "Receive SETUP transaction enable", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "setup", | 
|  | desc: ''' | 
|  | This bit must be set to enable SETUP transactions to be | 
|  | received on the endpoint. If the bit is clear then a | 
|  | SETUP packet will be ignored. The bit should be set for | 
|  | control endpoints (and only control endpoints). | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "rxenable_out", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "Receive OUT transaction enable", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hrw", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "out", | 
|  | desc: ''' | 
|  | This bit must be set to enable OUT transactions to be received on the endpoint. | 
|  | If the bit is clear then an OUT request will be responded to with a NAK, if the endpoint is enabled. | 
|  | If set_nak_out for this endpoint is set, hardware will clear this bit whenever an OUT transaction is received on this endpoint. | 
|  | Software must set this bit again to receive the next OUT transaction. | 
|  | Until that happens, hardware will continue to NAK any OUT transaction to this endpoint. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "set_nak_out", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "Set NAK after OUT transactions", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "enable", | 
|  | desc: ''' | 
|  | When this bit is set, hardware will clear this endpoint's rxenable_out bit whenever an OUT transaction is received on this endpoint. | 
|  | This bit should not be changed while the endpoint is active. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "in_sent", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "IN Transaction Sent", | 
|  | swaccess: "rw1c", | 
|  | hwaccess: "hrw", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "sent", | 
|  | desc: ''' | 
|  | This bit will be set when the ACK is received from | 
|  | the host to indicate successful packet delivery | 
|  | as part of an IN transaction. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "out_stall", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "OUT Endpoint STALL control", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hrw", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "endpoint", | 
|  | desc: ''' | 
|  | If this bit is set then an OUT transaction to this endpoint will elicit a STALL handshake, when a non-isochronous endpoint is enabled. | 
|  | If the configuration has both STALL and NAK enabled, the STALL handshake will take priority. | 
|  |  | 
|  | Note that SETUP transactions are always either accepted or ignored. | 
|  | For endpoints that accept SETUP transactions, a SETUP packet will clear the STALL flag on endpoints for both the IN and OUT directions. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "in_stall", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "IN Endpoint STALL control", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hrw", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "endpoint", | 
|  | desc: ''' | 
|  | If this bit is set then an IN transaction to this endpoint will elicit a STALL handshake, when a non-isochronous endpoint is enabled. | 
|  | If the configuration has both STALL and NAK enabled, the STALL handshake will take priority. | 
|  |  | 
|  | Note that SETUP transactions are always either accepted or ignored. | 
|  | For endpoints that accept SETUP transactions, a SETUP packet will clear the STALL flag on endpoints for both the IN and OUT directions. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "configin", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "Configure IN Transaction", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "4:0", | 
|  | name: "buffer", | 
|  | desc: ''' | 
|  | The buffer ID containing the data to send when an IN transaction is received on the endpoint. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "14:8", | 
|  | name: "size", | 
|  | desc: ''' | 
|  | The number of bytes to send from the buffer. | 
|  |  | 
|  | If this is 0 then a CRC only packet is sent. | 
|  |  | 
|  | If this is greater than 64 then 64 bytes are sent. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "30", | 
|  | name: "pend", | 
|  | swaccess: "rw1c" | 
|  | hwaccess: "hrw" | 
|  | desc: ''' | 
|  | This bit indicates a pending transaction was canceled by the hardware. | 
|  |  | 
|  | The bit is set when the rdy bit is cleared by hardware because of a | 
|  | SETUP packet being received or a link reset being detected. | 
|  |  | 
|  | The bit remains set until cleared by being written with a 1. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "31", | 
|  | name: "rdy", | 
|  | hwaccess: "hrw" | 
|  | desc: ''' | 
|  | This bit should be set to indicate the buffer is ready for sending. | 
|  | It will be cleared when the ACK is received indicating the host has accepted the data. | 
|  |  | 
|  | This bit will also be cleared if an enabled SETUP transaction is received on the endpoint. | 
|  | This allows use of the IN channel for transfer of SETUP information. | 
|  | The original buffer must be resubmitted after the SETUP sequence is complete. | 
|  | A link reset also clears the bit. | 
|  | In either of the cases where the hardware cancels the transaction it will also set the pend bit. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "out_iso", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "OUT Endpoint isochronous setting", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "iso", | 
|  | desc: ''' | 
|  | If this bit is set then the endpoint will be treated as an isochronous endpoint. | 
|  | No handshake packet will be sent for an OUT transaction. | 
|  | Note that if a rxenable_setup is set for this endpoint's number, this bit will not take effect. | 
|  | Control endpoint configuration trumps isochronous endpoint configuration. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "in_iso", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "IN Endpoint isochronous setting", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "iso", | 
|  | desc: ''' | 
|  | If this bit is set then the endpoint will be treated as an isochronous endpoint. | 
|  | No handshake packet will be expected for an IN transaction. | 
|  | Note that if a rxenable_setup is set for this endpoint's number, this bit will not take effect. | 
|  | Control endpoint configuration trumps isochronous endpoint configuration. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "data_toggle_clear", | 
|  | count: "NEndpoints" | 
|  | cname: "Endpoint" | 
|  | desc: "Clear the data toggle flag", | 
|  | swaccess: "wo", | 
|  | hwaccess: "hro", | 
|  | hwqe: "true", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "clear", | 
|  | desc: ''' | 
|  | Writing 1 to this bit will clear the data toggle bit for this endpoint to Data0 in both IN and OUT directions. | 
|  | The register must no be written again within 200 ns. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { name: "phy_pins_sense", | 
|  | desc: ''' | 
|  | USB PHY pins sense. | 
|  | This register can be used to read out the state of the USB device inputs and outputs from software. | 
|  | This is designed to be used for debugging purposes or during chip testing. | 
|  | ''' | 
|  | swaccess: "ro", | 
|  | hwaccess: "hwo", | 
|  | hwext: "true", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "rx_dp_i", | 
|  | desc: "USB D+ input." | 
|  | } | 
|  | { | 
|  | bits: "1", | 
|  | name: "rx_dn_i", | 
|  | desc: "USB D- input." | 
|  | } | 
|  | { | 
|  | bits: "2", | 
|  | name: "rx_d_i", | 
|  | desc: "USB data input from an external differential receiver, if available." | 
|  | } | 
|  | { | 
|  | bits: "8", | 
|  | name: "tx_dp_o", | 
|  | desc: "USB transmit D+ output (readback)." | 
|  | } | 
|  | { | 
|  | bits: "9", | 
|  | name: "tx_dn_o", | 
|  | desc: "USB transmit D- output (readback)." | 
|  | } | 
|  | { | 
|  | bits: "10", | 
|  | name: "tx_d_o", | 
|  | desc: "USB transmit data value (readback)." | 
|  | } | 
|  | { | 
|  | bits: "11", | 
|  | name: "tx_se0_o", | 
|  | desc: "USB single-ended zero output (readback)." | 
|  | } | 
|  | { | 
|  | bits: "12", | 
|  | name: "tx_oe_o", | 
|  | desc: "USB OE output (readback)." | 
|  | } | 
|  | { | 
|  | bits: "16", | 
|  | name: "pwr_sense", | 
|  | desc: "USB power sense signal." | 
|  | } | 
|  | ] | 
|  | tags: [// Updated by HW based on observed USB PHY signals, comprises also readbacks. | 
|  | // Exclude all read checks in all tests including reset tests. | 
|  | "excl:CsrAllTests:CsrExclCheck"] | 
|  | } | 
|  | { name: "phy_pins_drive", | 
|  | desc: ''' | 
|  | USB PHY pins drive. | 
|  | This register can be used to control the USB device inputs and outputs from software. | 
|  | This is designed to be used for debugging purposes or during chip testing. | 
|  | ''' | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | name: "dp_o", | 
|  | desc: "USB transmit D+ output, used with dn_o." | 
|  | } | 
|  | { | 
|  | bits: "1", | 
|  | name: "dn_o", | 
|  | desc: "USB transmit D- output, used with dp_o." | 
|  | } | 
|  | { | 
|  | bits: "2", | 
|  | name: "d_o", | 
|  | desc: "USB transmit data output, encoding K and J when se0_o is 0." | 
|  | } | 
|  | { | 
|  | bits: "3", | 
|  | name: "se0_o", | 
|  | desc: "USB single-ended zero output." | 
|  | } | 
|  | { | 
|  | bits: "4", | 
|  | name: "oe_o", | 
|  | desc: "USB OE output." | 
|  | } | 
|  | { | 
|  | bits: "5", | 
|  | name: "rx_enable_o", | 
|  | desc: "Enable differential receiver." | 
|  | } | 
|  | { | 
|  | bits: "6", | 
|  | name: "dp_pullup_en_o", | 
|  | desc: "USB D+ pullup enable output." | 
|  | } | 
|  | { | 
|  | bits: "7", | 
|  | name: "dn_pullup_en_o", | 
|  | desc: "USB D- pullup enable output." | 
|  | } | 
|  | { | 
|  | bits: "16", | 
|  | name: "en", | 
|  | desc: ''' | 
|  | 0: Outputs are controlled by the hardware block. | 
|  | 1: Outputs are controlled with this register. | 
|  | ''' | 
|  | tags: [// Prevent random csr tests from driving conflicting values into the chip | 
|  | "excl:CsrNonInitTests:CsrExclWrite"] | 
|  | } | 
|  | ] | 
|  | } | 
|  | { name: "phy_config", | 
|  | desc: "USB PHY Configuration", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hro", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | resval: "0", | 
|  | name: "use_diff_rcvr", | 
|  | desc: ''' | 
|  | Detect received K and J symbols from the usb_rx_d signal, which must be driven from an external differential receiver. | 
|  | If 1, make use of the usb_rx_d input. | 
|  | If 0, the usb_rx_d input is ignored and the usb_rx_dp and usb_rx_dn pair are used to detect K and J (useful for some environments, but will be unlikely to pass full USB compliance). | 
|  | Regardless of the state of this field usb_rx_dp and usb_rx_dn are always used to detect SE0. | 
|  | This bit also feeds the rx_enable pin, activating the receiver when the device is not suspended. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "1", | 
|  | resval: "0", | 
|  | name: "tx_use_d_se0", | 
|  | desc: ''' | 
|  | If 1, select the d and se0 TX interface. | 
|  | If 0, select the dp and dn TX interface. | 
|  | This directly controls the output pin of the same name. | 
|  | It is intended to be used to enable the use of a variety of external transceivers, to select an encoding that matches the transceiver. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "2", | 
|  | name: "eop_single_bit", | 
|  | resval: "1", | 
|  | desc: ''' | 
|  | Recognize a single SE0 bit as an end of packet, otherwise two successive bits are required. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "5", | 
|  | resval: "0", | 
|  | name: "pinflip", | 
|  | desc: ''' | 
|  | Flip the D+/D- pins. | 
|  | Particularly useful if D+/D- are mapped to SBU1/SBU2 pins of USB-C. | 
|  |  | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "6", | 
|  | resval: "0", | 
|  | name: "usb_ref_disable", | 
|  | desc: ''' | 
|  | 0: Enable reference signal generation for clock synchronization, 1: disable it by forcing the associated signals to zero. | 
|  |  | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "7", | 
|  | resval: "0", | 
|  | name: "tx_osc_test_mode", | 
|  | desc: ''' | 
|  | Disable (0) or enable (1) oscillator test mode. | 
|  | If enabled, the device constantly transmits a J/K pattern, which is useful for testing the USB clock. | 
|  | Note that while in oscillator test mode, the device no longer receives SOFs and consequently does not generate the reference signal for clock synchronization. | 
|  | The clock might drift off. | 
|  |  | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  |  | 
|  | { name: "wake_control", | 
|  | desc: "USB wake module control for suspend / resume", | 
|  | swaccess: "wo", | 
|  | hwaccess: "hro", | 
|  | hwext: "true", | 
|  | hwqe: "true", | 
|  | async: "clk_aon_i", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | resval: "0", | 
|  | name: "suspend_req", | 
|  | desc: ''' | 
|  | Suspend request to the wake detection module. | 
|  |  | 
|  | Trigger the wake detection module to begin monitoring for wake-from-suspend events. | 
|  | When written with a 1, the wake detection module will activate. | 
|  | Activation may not happen immediately, and its status can be verified by checking wake_events.module_active. | 
|  | ''' | 
|  | tags: [// Prevent usb wake functions from being turned on outside of directed tests | 
|  | "excl:CsrNonInitTests:CsrExclWrite"] | 
|  | } | 
|  | { | 
|  | bits: "1", | 
|  | resval: "0", | 
|  | name: "wake_ack", | 
|  | desc: ''' | 
|  | Wake acknowledgement. | 
|  |  | 
|  | Signal to the wake detection module that it may release control of the pull-ups back to the main block and return to an inactive state. | 
|  | The release back to normal state may not happen immediately. | 
|  | The status can be confirmed via wake_events.module_active. | 
|  |  | 
|  | Note that this bit can also be used without powering down, such as when usbdev detects resume signaling before transitions to low power states have begun. | 
|  | ''' | 
|  | }, | 
|  | ] | 
|  | } | 
|  |  | 
|  | { name: "wake_events", | 
|  | desc: "USB wake module events and debug", | 
|  | swaccess: "ro", | 
|  | hwaccess: "hwo", | 
|  | async: "clk_aon_i", | 
|  | fields: [ | 
|  | { | 
|  | bits: "0", | 
|  | resval: "0", | 
|  | name: "module_active", | 
|  | desc: ''' | 
|  | USB aon wake module is active, monitoring events and controlling the pull-ups. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "8", | 
|  | resval: "0", | 
|  | name: "disconnected", | 
|  | desc: ''' | 
|  | USB aon wake module detected VBUS was interrupted while monitoring events. | 
|  | ''' | 
|  | } | 
|  | { | 
|  | bits: "9", | 
|  | resval: "0", | 
|  | name: "bus_reset", | 
|  | desc: ''' | 
|  | USB aon wake module detected a bus reset while monitoring events. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | } | 
|  |  | 
|  | { window: { | 
|  | name: "buffer", | 
|  | items: "512", | 
|  | validbits: "32", | 
|  | byte-write: "false", | 
|  | unusual: "false" | 
|  | swaccess: "rw", | 
|  | desc: ''' | 
|  | 2 kB packet buffer. Divided into 32 64-byte buffers. | 
|  |  | 
|  | The packet buffer is used for sending and receiveing packets. | 
|  | ''' | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | } |