| // Copyright lowRISC contributors. | |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | |
| // SPDX-License-Identifier: Apache-2.0 | |
| { name: "usbdev", | |
| clock_primary: "clk_i", | |
| other_clock_list: [ "clk_aon_i", "clk_usb_48mhz_i" ] | |
| reset_primary: "rst_ni", | |
| other_reset_list: [ "rst_aon_ni", "rst_usb_48mhz_ni" ] | |
| bus_device: "tlul", | |
| bus_host: "none", | |
| available_inout_list: [ | |
| { name: "d", desc: "USB data differential" } | |
| { name: "dp", desc: "USB data D+" } | |
| { name: "dn", desc: "USB data D-" } | |
| ], | |
| available_input_list: [ | |
| { name: "sense", desc: "USB host VBUS sense" } | |
| ], | |
| available_output_list: [ | |
| { name: "se0", desc: "USB single-ended zero link state" } | |
| { name: "dp_pullup", desc: "USB D+ pullup control" } | |
| { name: "dn_pullup", desc: "USB D- pullup control" } | |
| { name: "tx_mode_se", desc: "USB single-ended transmit mode control" } | |
| { name: "suspend", desc: "USB link suspend state" } | |
| ], | |
| inter_signal_list: [ | |
| { 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_out_of_rst", | |
| type: "uni", | |
| act: "req", | |
| package: "", | |
| struct: "logic", | |
| width: "1" | |
| }, | |
| { name: "usb_aon_wake_en", | |
| 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_suspend", | |
| type: "uni", | |
| act: "req", | |
| package: "", | |
| struct: "logic", | |
| width: "1" | |
| }, | |
| { name: "usb_state_debug", | |
| type: "uni", | |
| act: "rcv", | |
| package: "usbdev_pkg", | |
| struct: "awk_state", | |
| }, | |
| ] | |
| param_list: [ | |
| { name: "NEndpoints", | |
| type: "int", | |
| default: "12", | |
| desc: "Number of endpoints", | |
| local: "true" | |
| } | |
| ], | |
| interrupt_list: [ | |
| { name: "pkt_received" | |
| desc: ''' | |
| Raised if a packet was received using an OUT or SETUP transaction. | |
| ''' | |
| } | |
| { name: "pkt_sent" | |
| desc: ''' | |
| Raised if a packet was sent as part of an IN transaction. | |
| ''' | |
| } | |
| { 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 a transaction is NACKed because the Available Buffer FIFO for OUT or SETUP transactions is empty. | |
| ''' | |
| } | |
| { name: "rx_full", | |
| desc: ''' | |
| Raised when a transaction is NACKed because the Received Buffer FIFO for OUT or SETUP transactions is full. | |
| ''' | |
| } | |
| { 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: "connected", | |
| 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. | |
| ''' | |
| } | |
| ] | |
| regwidth: "32", | |
| registers: [ | |
| { name: "usbctrl", | |
| desc: "USB Control", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { | |
| bits: "0", | |
| name: "enable", | |
| desc: ''' | |
| Set to enable the USB interface and assert the pullup. | |
| ''' | |
| tags: [// Prevent usb from being enabled to avoid other unforeseen side effects. | |
| "excl:CsrNonInitTests:CsrExclWrite"] | |
| } | |
| { | |
| 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"] | |
| } | |
| ] | |
| } | |
| { 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: "disconnect", | |
| desc: "Link disconnected (no VBUS)" | |
| }, | |
| { value: "1", | |
| name: "powered", | |
| desc: "Link powered, but not reset yet" | |
| }, | |
| { value: "2", | |
| name: "powered_suspend", | |
| desc: "Link suspended (constant idle/J for > 3 ms), but not reset yet" | |
| }, | |
| { value: "3", | |
| name: "active", | |
| desc: "Link active" | |
| }, | |
| { value: "4", | |
| name: "suspend", | |
| 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." | |
| }, | |
| ] | |
| } | |
| { | |
| 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. | |
| ''' | |
| } | |
| ] | |
| } | |
| { 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 request will be responded to with a NACK. | |
| ''' | |
| } | |
| ] | |
| } | |
| } | |
| { multireg: { | |
| name: "rxenable_out", | |
| count: "NEndpoints" | |
| cname: "Endpoint" | |
| desc: "Receive OUT transaction enable", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| 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 NACK. | |
| ''' | |
| } | |
| ] | |
| } | |
| } | |
| { multireg: { | |
| name: "in_sent", | |
| count: "NEndpoints" | |
| cname: "Endpoint" | |
| desc: "IN Transaction Sent", | |
| swaccess: "rw1c", | |
| hwaccess: "hwo", | |
| 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: "stall", | |
| count: "NEndpoints" | |
| cname: "Endpoint" | |
| desc: "Endpoint STALL control", | |
| swaccess: "rw", | |
| hwaccess: "hrw", | |
| fields: [ | |
| { | |
| bits: "0", | |
| name: "stall", | |
| desc: ''' | |
| If this bit is set then an IN or OUT transaction to this endpoint will be responded to with a STALL return. | |
| This is used when the endpoint is disabled (functional stall) or when a control transfer is not supported (protocol stall). | |
| SETUP transactions are always accepted and a SETUP will clear the stall flag (this is necessary for protocol stalls, to avoid sending stalls on subsequent IN/OUT transfers). | |
| ''' | |
| } | |
| ] | |
| } | |
| } | |
| { 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: "iso", | |
| count: "NEndpoints" | |
| cname: "Endpoint" | |
| desc: "Endpoint ISO setting", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { | |
| bits: "0", | |
| name: "iso", | |
| desc: ''' | |
| If this bit is set then the endpoint will be treated as an ISO endpoint. | |
| No handshake packet will be sent for an OUT transaction and no handshake packet will be expected for an IN transaction. | |
| ''' | |
| } | |
| ] | |
| } | |
| } | |
| { 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 differential input." | |
| } | |
| { | |
| bits: "8", | |
| name: "tx_dp_o", | |
| desc: "USB D+ output (readback)." | |
| } | |
| { | |
| bits: "9", | |
| name: "tx_dn_o", | |
| desc: "USB D- output (readback)." | |
| } | |
| { | |
| bits: "10", | |
| name: "tx_d_o", | |
| desc: "USB differential output (readback)." | |
| } | |
| { | |
| bits: "11", | |
| name: "tx_se0_o", | |
| desc: "USB SE0 output (readback)." | |
| } | |
| { | |
| bits: "12", | |
| name: "tx_oe_o", | |
| desc: "USB OE output (readback)." | |
| } | |
| { | |
| bits: "13", | |
| name: "suspend_o", | |
| desc: "USB suspend 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 D+ output." | |
| } | |
| { | |
| bits: "1", | |
| name: "dn_o", | |
| desc: "USB D- output." | |
| } | |
| { | |
| bits: "2", | |
| name: "d_o", | |
| desc: "USB differential output." | |
| } | |
| { | |
| bits: "3", | |
| name: "se0_o", | |
| desc: "USB SE0 output." | |
| } | |
| { | |
| bits: "4", | |
| name: "oe_o", | |
| desc: "USB OE output." | |
| } | |
| { | |
| bits: "5", | |
| name: "tx_mode_se_o", | |
| desc: "USB TX mode. 0: Differential, 1: Single-ended." | |
| } | |
| { | |
| 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: "8", | |
| name: "suspend_o", | |
| desc: "USB suspend output." | |
| } | |
| { | |
| bits: "16", | |
| name: "en", | |
| desc: ''' | |
| 0: Outputs are controlled by the hardware block. | |
| 1: Outputs are controlled with this register. | |
| ''' | |
| } | |
| ] | |
| } | |
| { name: "phy_config", | |
| desc: "USB PHY Configuration", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { | |
| bits: "0", | |
| resval: "0", | |
| name: "rx_differential_mode", | |
| desc: ''' | |
| Use the differential RX signal instead of the single-ended signals. | |
| Currently only 0 (single-ended operation) is supported. | |
| ''' | |
| } | |
| { | |
| bits: "1", | |
| resval: "0", | |
| name: "tx_differential_mode", | |
| desc: ''' | |
| Use the differential TX signal instead of the single-ended signals. | |
| Currently only 0 (single-ended operation) is supported. | |
| ''' | |
| } | |
| { | |
| 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: "3", | |
| name: "override_pwr_sense_en", | |
| desc: ''' | |
| Override the USB power sense value with override_pwr_sense_val. | |
| ''' | |
| tags: [// Overriding pwr sense will cause the usbdev to think the link is powered up. | |
| "excl:CsrNonInitTests:CsrExclWrite"] | |
| } | |
| { | |
| bits: "4", | |
| name: "override_pwr_sense_val", | |
| desc: ''' | |
| 0: USB power not present, 1: present. | |
| ''' | |
| } | |
| { | |
| 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_config", | |
| desc: "USB wake configuration for suspend / resume", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { | |
| bits: "0", | |
| resval: "0", | |
| name: "wake_en", | |
| desc: ''' | |
| Enable the usb resume wake function. When this is set, a resume indication from | |
| a usb host can be used to drive a wake from sleep event. | |
| ''' | |
| } | |
| { | |
| bits: "1", | |
| resval: "0", | |
| name: "wake_ack", | |
| desc: ''' | |
| Wake acknowledgement. Once the usb device resumes from suspend, this acknowledgement is used | |
| to transition the module back to normal operation. | |
| Note wake acknowledgement is only necessary if wake_en was '1' when the usb device was suspended. | |
| However, setting/clearing this bit during other conditions has no side effects. | |
| ''' | |
| }, | |
| ] | |
| } | |
| { name: "wake_debug", | |
| desc: "USB wake module debug", | |
| swaccess: "ro", | |
| hwaccess: "hwo", | |
| fields: [ | |
| { | |
| bits: "2:0", | |
| resval: "0", | |
| name: "state", | |
| desc: ''' | |
| USB aon wake module state read back | |
| ''' | |
| } | |
| ] | |
| } | |
| { 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. | |
| ''' | |
| }, | |
| }, | |
| ] | |
| } |