| // Copyright lowRISC contributors. | |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | |
| // SPDX-License-Identifier: Apache-2.0 | |
| { name: "SPI_DEVICE", | |
| clocking: [ | |
| {clock: "clk_i", reset: "rst_ni", primary: true}, | |
| // The scan_rst_ni port isn't listed here because it's generated by the | |
| // "scan_reset: true" below. | |
| {clock: "scan_clk_i"} | |
| ] | |
| bus_interfaces: [ | |
| { protocol: "tlul", direction: "device" } | |
| ], | |
| available_input_list: [ | |
| { name: "sck", desc: "SPI Clock" }, | |
| { name: "csb", desc: "Chip Select#" }, | |
| { name: "tpm_csb", desc: "TPM Chip Select#"} | |
| ], | |
| available_output_list: [ | |
| ], | |
| available_inout_list: [ | |
| { name: "sd", | |
| width: "4", | |
| desc: "SPI IO, IO2/IO3 has multi-purpose (/WP, /HOLD)" | |
| } | |
| ] | |
| interrupt_list: [ | |
| { name: "generic_rx_full" | |
| desc: "RX SRAM FIFO Full" | |
| } | |
| { name: "generic_rx_watermark" | |
| desc: "RX SRAM FIFO is above the level" | |
| } | |
| { name: "generic_tx_watermark" | |
| desc: "TX SRAM FIFO is under the level" | |
| } | |
| { name: "generic_rx_error" | |
| desc: "SDI in FwMode has error" | |
| } | |
| { name: "generic_rx_overflow" | |
| desc: "RX Async FIFO overflow" | |
| } | |
| { name: "generic_tx_underflow" | |
| desc: "TX Async FIFO underflow" | |
| } | |
| { name: "upload_cmdfifo_not_empty" | |
| desc: "Upload Command FIFO is not empty" | |
| } | |
| { name: "upload_payload_not_empty" | |
| desc: '''Upload paylod is not empty. | |
| The event occurs after SPI transaction completed | |
| ''' | |
| } | |
| { name: "readbuf_watermark" | |
| desc: '''Read Buffer Threshold event. | |
| The host system accesses greater than or equal to the threshold of a | |
| buffer. | |
| ''' | |
| } | |
| { name: "readbuf_flip" | |
| desc: '''Read buffer flipped event. | |
| The host system accesses other side of buffer. | |
| ''' | |
| } | |
| { name: "tpm_header_not_empty" | |
| desc: "TPM Header(Command/Address) buffer available" | |
| } | |
| ], | |
| alert_list: [ | |
| { name: "fatal_fault", | |
| desc: ''' | |
| This fatal alert is triggered when a fatal TL-UL bus integrity fault is detected. | |
| ''' | |
| } | |
| ], | |
| scan: "true", // Enable `scanmode_i` port | |
| scan_reset: "true", // Enable `scan_rst_ni` port | |
| param_list: [ | |
| { name: "SramDepth" | |
| desc: "Sram Entries. Word size is 32bit width." | |
| type: "int unsigned" | |
| default: "1024" | |
| local: "true" | |
| } | |
| { name: "NumCmdInfo" | |
| desc: "Define the number of Command Info slots." | |
| type: "int unsigned" | |
| default: "24" | |
| local: "true" | |
| } | |
| { name: "NumLocality" | |
| desc: "The number of locality TPM module supports." | |
| type: "int unsigned" | |
| default: "5" | |
| local: "true" | |
| } // p: NumLocality | |
| ], | |
| inter_signal_list: [ | |
| { struct: "ram_2p_cfg", | |
| package: "prim_ram_2p_pkg", | |
| type: "uni", | |
| name: "ram_cfg", | |
| act: "rcv" | |
| } | |
| { struct: "passthrough", | |
| package: "spi_device_pkg" | |
| type: "req_rsp" | |
| name: "passthrough", | |
| act: "req" | |
| } | |
| { struct: "logic" | |
| package: "" | |
| type: "uni" | |
| name: "mbist_en" | |
| act: "rcv" | |
| } | |
| { struct: "logic" | |
| package: "" | |
| type: "uni" | |
| name: "sck_monitor" | |
| act: "req" | |
| } | |
| ], | |
| countermeasures: [ | |
| { name: "BUS.INTEGRITY", | |
| desc: "End-to-end bus integrity scheme." | |
| } | |
| ] | |
| regwidth: "32", | |
| registers: [ | |
| { name: "CONTROL", | |
| desc: "Control register", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { bits: "0", | |
| name: "ABORT", | |
| desc: ''' | |
| Abort pending jobs. If TX_FIFO (async) is full, | |
| this command can let TXF Control logic back to Idle state | |
| ''' | |
| resval: "0" | |
| }, | |
| { bits: "5:4", | |
| name: "MODE", | |
| desc: "SPI Device operation mode. Currently only FwMode is supported.", | |
| enum: [ | |
| { value: "0", | |
| name: "fwmode", | |
| desc: ''' | |
| FW operation mode. | |
| HW just dumps incoming data to SRAM and reads from SRAM and | |
| sends to SDO. This mode doesn't support Dual or Quad mode | |
| ''' | |
| }, | |
| ] | |
| tags: [// Changing modes randomly can result in unknown values being | |
| // passed between spi_dev/host due to passthrough | |
| "excl:CsrNonInitTests:CsrExclWrite"] | |
| }, | |
| { bits: "16", | |
| name: "rst_txfifo", | |
| desc: ''' | |
| Reset Async TX_FIFO. | |
| This only resets asynchronous fifo. If firmware wants to reset SRAM | |
| FIFO, it should write 0 into read/write pointers. | |
| _Note_: This value should be controlled only when SPI interface is | |
| in Idle state as this reset signal doesn't have reset synchronizer. | |
| ''' | |
| resval: "0", | |
| }, | |
| { bits: "17", | |
| name: "rst_rxfifo", | |
| desc: ''' | |
| Reset Async RX_FIFO. | |
| This only resets asynchronous fifo. If firmware wants to reset SRAM | |
| FIFO, it should write 0 into read pointer and write pointer. | |
| _Note_: This value should be controlled only when SPI interface is | |
| in Idle state as this reset signal doesn't have reset synchronizer. | |
| ''' | |
| resval: "0", | |
| }, | |
| { bits: "31" | |
| name: "sram_clk_en", | |
| desc: '''SRAM Clock Enable. | |
| This controls the clock gating cell lying on DP SRAM clock. As the | |
| nature of absent of SPI_CLK in idle state, the clock mux for SRAM | |
| B port cannot be glitch-free MUX. So, it is up to SW to change the | |
| clock safely. | |
| Programming sequence: | |
| 1. Check if SPI line is idle | |
| 2. Clear sram_clk_en to 0. | |
| 3. Change mode to FwMode for peri clk, FlashMode or PassThrough | |
| for SPI_CLK. | |
| 4. Set sram_clk_en to 1. | |
| ''' | |
| resval: "1" | |
| } | |
| ] | |
| }, | |
| { name: "CFG", | |
| desc: "Configuration Register", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { bits: "0", | |
| name: "CPOL", | |
| desc: "Clock polarity. 0 for normal SPI, 1 for negative edge latch", | |
| resval: "0", | |
| }, | |
| { bits: "1", | |
| name: "CPHA", | |
| desc: "Data phase. 0 for negative edge change, 1 for positive edge change", | |
| resval: "0", | |
| }, | |
| { bits: "2", | |
| name: "tx_order", | |
| desc: "TX bit order on SDO. 0 for MSB to LSB, 1 for LSB to MSB", | |
| resval: "0", | |
| }, | |
| { bits: "3", | |
| name: "rx_order", | |
| desc: "RX bit order on SDI. Module stores bitstream from MSB to LSB if value is 0.", | |
| resval: "0", | |
| }, | |
| { bits: "15:8", | |
| name: "timer_v", | |
| desc: ''' | |
| number of clocks for RXF to wait. | |
| To reduce traffic to SRAM, RXF control module waits given clock cycle | |
| if it doesn't fill SRAM data width even if Async RX FIFO is empty. | |
| ''' | |
| resval: "0x7F", | |
| }, | |
| { bits: "16" | |
| name: "addr_4b_en" | |
| swaccess: "rw" | |
| hwaccess: "hrw" // Updated by EN4B/EX4B | |
| desc: '''4B Address Mode enable. | |
| This field configures the internal module to receive 32 bits of the SPI commands. The affected commands are the SPI read commands except QPI, and program commands. | |
| Even though Read SFDP command has address fields, the SFDP command | |
| is not affected by this field. The command always parse 24 bits on | |
| the SPI line 0 following the SPI command as the address field. | |
| ''' | |
| } | |
| { bits: "24" | |
| name: "mailbox_en" | |
| desc: '''Mailbox enable. | |
| If 1, in the flash and passthrough mode, the IP checks the incoming | |
| address and return from the internal Mailbox buffer if the address | |
| falls into the MAILBOX range | |
| (MAILBOX_ADDR:MAILBOX_ADDR+MAILBOX_SIZE)}. | |
| ''' | |
| } // f: mailbox_en | |
| ] | |
| }, | |
| { name: "FIFO_LEVEL", | |
| desc: "RX/ TX FIFO levels.", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { bits: "15:0", | |
| name: "rxlvl", | |
| resval: "0x80", | |
| desc: ''' | |
| RX FIFO level. | |
| If RX SRAM FIFO level exceeds this value, it triggers interrupt. | |
| ''' | |
| }, | |
| { bits: "31:16", | |
| name: "txlvl", | |
| resval: "0x0", | |
| desc: ''' | |
| TX FIFO level. | |
| If TX SRAM FIFO level drops below this value, it triggers interrupt. | |
| ''' | |
| }, | |
| ], | |
| }, | |
| { name: "ASYNC_FIFO_LEVEL", | |
| desc: "RX/ TX Async FIFO levels between main clk and spi clock", | |
| swaccess: "ro", | |
| hwaccess: "hwo", | |
| hwext: "true", | |
| fields: [ | |
| { bits: "23:16", | |
| name: "txlvl", | |
| desc: ''' | |
| TX Async FIFO level. | |
| This value shows the number of available entry in TX Async FIFO. | |
| If the software writes message into SRAM FIFO and update FIFO write pointer | |
| but no clock from the host is given, the data stuck at this async fifo waiting | |
| host toggles SCK. This value represents the number of bytes. | |
| ''' | |
| tags: [// HW modifies async_fifo_level.txlvl when txf_ptr.wptr is updated. | |
| "excl:CsrNonInitTests:CsrExclWriteCheck"] | |
| }, | |
| { bits: "7:0", | |
| name: "rxlvl", | |
| desc: ''' | |
| RX Async FIFO level. | |
| This value shows the number of available entry in RX Async FIFO. | |
| ''' | |
| } | |
| ] | |
| }, | |
| { name: "STATUS", | |
| desc: "SPI Device status register", | |
| swaccess: "ro", | |
| hwaccess: "hwo", | |
| hwext: "true", | |
| fields: [ | |
| { bits: "0", name: "rxf_full", desc: "RX FIFO full" }, | |
| { bits: "1", name: "rxf_empty", desc: "RX FIFO empty", resval: "1"}, | |
| { bits: "2", name: "txf_full", desc: "TX FIFO full"}, | |
| { bits: "3", name: "txf_empty", desc: "TX FIFO empty", resval: "1"}, | |
| { bits: "4", name: "abort_done", desc: "Abort process is completed", resval: "1" }, | |
| { bits: "5", name: "csb", desc: "Direct input of CSb signal", resval: "1" }, | |
| ] | |
| tags: [// Status reads back unexpected values due to writes to other CSRs. | |
| "excl:CsrNonInitTests:CsrExclWriteCheck"] | |
| }, | |
| { name: "RXF_PTR", | |
| desc: "Receiver FIFO (SRAM) pointers", | |
| swaccess: "rw", | |
| hwaccess: "hrw", | |
| fields: [ | |
| { bits: "15:0", | |
| name: "RPTR", | |
| desc: "Read pointer. bit x is for phase bit. check circular fifo description", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| resval: "0", | |
| tags: [// Updating rptr will cause unexpected interrupts. These interrupts may take a | |
| // while to generate and cip_base_vseq::clear_all_interrupts may not be able to | |
| // clear them in time. Leftover interrupts will cause sim error | |
| "excl:CsrNonInitTests:CsrExclWrite"] | |
| }, | |
| { bits: "31:16", | |
| name: "WPTR", | |
| desc: "Write pointer. Bit x is phase bit.", | |
| swaccess: "ro", | |
| hwaccess: "hwo", | |
| resval: "0", | |
| } | |
| ] | |
| }, | |
| { name: "TXF_PTR", | |
| desc: "Transmitter FIFO (SRAM) pointers", | |
| swaccess: "rw", | |
| hwaccess: "hrw", | |
| fields: [ | |
| { bits: "15:0", | |
| name: "RPTR", | |
| desc: "Read pointer. bit x is for phase bit. check circular fifo description", | |
| swaccess: "ro", | |
| hwaccess: "hwo", | |
| resval: "0", | |
| }, | |
| { bits: "31:16", | |
| name: "WPTR", | |
| desc: "Write pointer. Bit x is phase bit.", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| resval: "0", | |
| tags: [// Updating rptr will cause unexpected interrupts. These interrupts may take a | |
| // while to generate and cip_base_vseq::clear_all_interrupts may not be able to | |
| // clear them in time. Leftover interrupts will cause sim error | |
| "excl:CsrNonInitTests:CsrExclWrite"] | |
| } | |
| ] | |
| }, | |
| { name: "RXF_ADDR", | |
| desc: "Receiver FIFO (SRAM) Addresses", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { bits: "15:0", | |
| name: "base", | |
| desc: "Base offset in bytes in the SRAM. Lower 2 bits are ignored.", | |
| resval: "0", | |
| }, | |
| { bits: "31:16", | |
| name: "limit", | |
| desc: "Limit offset in bytes in the SRAM. Lower 2 bits are ignored.", | |
| resval: "0x1FC", | |
| } | |
| ], | |
| }, | |
| { name: "TXF_ADDR", | |
| desc: "Transmitter FIFO (SRAM) Addresses", | |
| swaccess: "rw", | |
| hwaccess: "hro", | |
| fields: [ | |
| { bits: "15:0", | |
| name: "base", | |
| desc: "Base offset in bytes in the SRAM. Lower 2 bits are ignored.", | |
| resval: "0x200", | |
| }, | |
| { bits: "31:16", | |
| name: "limit", | |
| desc: "Limit offset in bytes in the SRAM. Lower 2 bits are ignored.", | |
| resval: "0x3FC", | |
| } | |
| ], | |
| }, | |
| //========================================================================= | |
| // Flash & Passthrough CSRs | |
| { name: "INTERCEPT_EN" | |
| desc: '''Intercept Passthrough datapath. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "0" | |
| name: "status" | |
| desc: "If set, Read Status is processed internally." | |
| } // f: status | |
| { bits: "1" | |
| name: "jedec" | |
| desc: "If set, Read JEDEC ID is processed internally." | |
| } // f: jedec | |
| { bits: "2" | |
| name: "sfdp" | |
| desc: "If set, Read SFDP is processed internally." | |
| } // f: sfdp | |
| { bits: "3" | |
| name: "mbx" | |
| desc: "If set, Read Command to Mailbox region is processed internally." | |
| } // f: mailbox | |
| ] | |
| } // R: INTERCEPT_EN | |
| { name: "LAST_READ_ADDR" | |
| desc: '''Last Read Address | |
| This register shows the last address accessed by the host system. | |
| It is updated by the HW when CSb is de-asserted. | |
| ''' | |
| swaccess: "ro" | |
| hwaccess: "hwo" | |
| hwext: true | |
| fields: [ | |
| { bits: "31:0" | |
| name: "addr" | |
| desc: "Last address" | |
| } | |
| ] | |
| } // R: LAST_READ_ADDR | |
| { name: "FLASH_STATUS" | |
| desc: '''SPI Flash Status register. | |
| This register emulates the SPI Flash Status 3, 2, 1 registers. | |
| bit [7:0] is for Status register, bit [15:8] is for Status-2 register, | |
| and bit [23:16] is for Status-3 register. It is SW responsibility to | |
| maintain this register value up to date. | |
| The HW latches the value when SPI Flash transaction begins. Any updates | |
| during the transaction will be updated after the transaction is | |
| completed. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hrw" | |
| hwext: true | |
| hwqe: true | |
| fields: [ | |
| { bits: "0" | |
| name: "busy" | |
| desc: "BUSY" | |
| swaccess: "rw0c" | |
| hwaccess: "hrw" | |
| tags: [ | |
| // STATUS[0] is updated by HW when CSb is de-asserted. | |
| // So excluded from CSR automation test. | |
| "excl:CsrNonInitTests:CsrExclWrite" | |
| ] | |
| } // f: busy | |
| { bits: "23:1" | |
| name: "status" | |
| desc: '''Rest of the status register. | |
| Fields other than the bit 0 (BUSY) field are SW-maintained fields. | |
| HW just reads and returns to the host system. | |
| [ 1]: WEL | |
| [ 2]: BP0 | |
| [ 3]: BP1 | |
| [ 4]: BP2 | |
| [ 5]: TB | |
| [ 6]: SEC | |
| [ 7]: SRP0 | |
| [ 8]: SRP1 | |
| [ 9]: QE | |
| [11]: LB1 | |
| [12]: LB2 | |
| [13]: LB3 | |
| [14]: CMP | |
| [15]: SUS | |
| [18]: WPS | |
| [21]: DRV0 | |
| [22]: DRV1 | |
| [23]: HOLD /RST | |
| ''' | |
| } // f: status | |
| ] | |
| } // R: FLASH_STATUS | |
| { | |
| name: "JEDEC_CC" | |
| desc: '''JEDEC Continuation Code configuration register. | |
| Read JEDEC ID must return the continuation code if the manufacturer ID | |
| is not shown in the first page of JEDEC table. This register controls | |
| the Continuation Code. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "15:8" | |
| name: "num_cc" | |
| desc: "The number that Continuation Code repeats" | |
| } // f: num_cc | |
| { bits: "7:0" | |
| name: "cc" | |
| desc: "Continuation Code byte" | |
| resval: "0x7F" | |
| } // f: cc | |
| ] | |
| } // R: JEDEC_CC | |
| { | |
| name: "JEDEC_ID" | |
| desc: '''JEDEC ID register. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "23:16" | |
| name: "mf" | |
| desc: "Manufacturer ID" | |
| } // f: manufacturer id | |
| { bits: "15:0" | |
| name: "id" | |
| desc: "Device ID" | |
| } // f: device id | |
| ] | |
| } // R: JEDEC_ID | |
| { name: "READ_THRESHOLD" | |
| desc: '''Read Buffer threshold register. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "9:0" | |
| name: "threshold" | |
| desc: '''If 0, disable the watermark. If non-zero, when the host | |
| access above or equal to the threshold, it reports an interrupt. | |
| ''' | |
| } // f: threshold | |
| ] | |
| } // R: READ_THRESHOLD | |
| { name: "MAILBOX_ADDR" | |
| desc: '''Mailbox Base address register. | |
| The mailbox size is fixed. In this version of IP, the size is 1kB. | |
| Lower 10 bits of the Mailbox address is tied to 0. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| name: "addr" | |
| desc: "Mailbox Address. Lower 10 bits are ignored" | |
| } // f: addr | |
| ] | |
| } // R: MAILBOX_ADDR | |
| { name: "UPLOAD_STATUS" | |
| desc: '''Upload module status register. | |
| ''' | |
| swaccess: "ro" | |
| hwaccess: "hwo" | |
| fields: [ | |
| { bits: "4:0" | |
| name: "cmdfifo_depth" | |
| desc: "Command FIFO Entry" | |
| } // f: cmdfifo_depth | |
| { bits: "7" | |
| name: "cmdfifo_notempty" | |
| desc: "Upload Command FIFO Not Empty" | |
| } // f: cmdfifo_notempty | |
| { bits: "12:8" | |
| name: "addrfifo_depth" | |
| desc: "Address FIFO Entry" | |
| } // f: addrfifo_depth | |
| { bits: "15" | |
| name: "addrfifo_notempty" | |
| desc: "Upload Address FIFO Not Empty" | |
| } // f: addrfifo_notempty | |
| { bits: "24:16" | |
| name: "payload_depth" | |
| desc: '''Payload buffer depth | |
| ''' | |
| } // f: payload_depth | |
| ] | |
| } // R: UPLOAD_STATUS | |
| { name: "UPLOAD_CMDFIFO" | |
| desc: '''Command Fifo Read Port. | |
| ''' | |
| swaccess: "ro" | |
| hwaccess: "hrw" | |
| hwre: "true" | |
| hwext: "true" | |
| fields: [ | |
| { bits: "7:0" | |
| name: "data" | |
| desc: "read data" | |
| } | |
| ] | |
| } // R: UPLOAD_CMDFIFO | |
| { name: "UPLOAD_ADDRFIFO" | |
| desc: '''Address Fifo Read Port. | |
| ''' | |
| swaccess: "ro" | |
| hwaccess: "hrw" | |
| hwre: "true" | |
| hwext: "true" | |
| fields: [ | |
| { bits: "31:0" | |
| name: "data" | |
| desc: "read data" | |
| } | |
| ] | |
| } // R: UPLOAD_ADDRFIFO | |
| { multireg: { | |
| cname: "SPI_DEVICE" | |
| name: "CMD_FILTER" | |
| desc: '''Command Filter | |
| If a bit in this CSR is 1, then corresponding SPI command w.r.t the | |
| bit position among 256 bit is dropped in SPI Passthrough mode. | |
| ''' | |
| count: "256" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| compact: true | |
| fields: [ | |
| { bits: "0" | |
| name: "filter" | |
| resval: "0" | |
| desc: "If 1, command will be filtered" | |
| } | |
| ] | |
| } | |
| } | |
| { name: "ADDR_SWAP_MASK" | |
| desc: '''Address Swap Mask register. | |
| This register is used in the SPI passthrough mode. If any of bits in | |
| this register is set, the corresponding address bit in the SPI Read | |
| commands is replaced with the data from !!ADDR_SWAP_DATA. | |
| If 3B address mode is active, upper 8bit [31:24] is ignored. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| resval: "0", | |
| name: "mask" | |
| desc: '''When a bit is 1, the SPI read address to the downstream SPI | |
| Flash device is swapped to !!ADDR_SWAP_DATA. | |
| ''' | |
| } | |
| ] | |
| } | |
| { name: "ADDR_SWAP_DATA" | |
| desc: '''The address value for the address swap feature. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| resval: "0" | |
| name: "data" | |
| desc: "Desired value to be swapped for the SPI read commands." | |
| } | |
| ] | |
| } | |
| { name: "PAYLOAD_SWAP_MASK" | |
| desc: '''Write Data Swap in the passthrough mode. | |
| PAYLOAD_SWAP_MASK CSR provides the SW to change certain bits in the | |
| first 4 bytes of the write payload in the passthrough mode. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| resval: "0" | |
| name: "mask" | |
| desc: "byte mask" | |
| } // f: mask | |
| ] | |
| } // R: PAYLOAD_SWAP_MASK | |
| { name: "PAYLOAD_SWAP_DATA" | |
| desc: '''Write Data Swap in the passthrough mode. | |
| PAYLOAD_SWAP_DATA combined with PAYLOAD_SWAP_MASK provides the SW to | |
| change certain bits in the first 4 bytes of the write payload in the | |
| passthrough mode. | |
| The register should be written in Little-Endian order. [7:0] bits are | |
| processed in the first received payload byte. [31:24] bits for the 4th | |
| byte. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| resval: "0" | |
| name: "data" | |
| desc: "replaced data" | |
| } // f: data | |
| ] | |
| } // R: PAYLOAD_SWAP_DATA | |
| { multireg: { | |
| cname: "SPI_DEVICE" | |
| name: "CMD_INFO" | |
| desc: '''Command Info register. | |
| ''' | |
| count: "NumCmdInfo" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "7:0" | |
| resval: "0" | |
| name: "opcode" | |
| desc: '''Command Opcode | |
| ''' | |
| } | |
| { bits: "9:8" | |
| resval: "0" | |
| name: "addr_mode" | |
| desc: '''Command address mode | |
| A command can have four modes: | |
| - 0: Command does not have an address field | |
| - 1: CFG.addr_4b_en decides the address size (3B/4B) | |
| - 2: Address size is always 3B regardless of CFG.addr_4b_en | |
| - 3: Address size is always 4B regardless of CFG.addr_4b_en | |
| ''' | |
| enum: [ | |
| { value: "0" | |
| name: "AddrDisabled" | |
| desc: "Address field does not exist" | |
| } // e: AddrDisabled | |
| { value: "1" | |
| name: "AddrCfg" | |
| desc: "CFG.addr_4b_en determines the address size" | |
| } // e: AddrCfg | |
| { value: "2" | |
| name: "Addr3B" | |
| desc: "Address size in the command is always 3B." | |
| } // e: Addr3B | |
| { value: "3" | |
| name: "Addr4B" | |
| desc: "Address size in the command is always 4B." | |
| } // e: Addr4B | |
| ] | |
| } // f: addr_mode | |
| { bits: "10" | |
| resval: "0" | |
| name: "addr_swap_en" | |
| desc: '''This field is used in the passthrough logic. | |
| If this field is set to 1, the address in the passthrough command | |
| is replaced to the preconfigured value. | |
| ''' | |
| } | |
| { bits: "11" | |
| name: "mbyte_en" | |
| desc: '''If 1, the command has a MByte field following the | |
| address field. This is set to 1 for DualIO, QuadIO commands. | |
| ''' | |
| } | |
| { bits: "14:12" | |
| resval: "7" | |
| name: "dummy_size" | |
| desc: "The number of dummy cycles -1 for the command" | |
| } | |
| { bits: "15" | |
| name: "dummy_en" | |
| desc: "Set to 1 if the command has a dummy cycle following the address field." | |
| } | |
| { bits: "19:16" | |
| name: "payload_en" | |
| desc: '''Payload Enable per SPI lane. | |
| Set to non-zero if the command has payload at the end of the | |
| protocol. This field has four bits. Each bit represents the SPI | |
| line. If a command is a Single IO command and returns data to the | |
| host system, the data is returned on the MISO line (IO[1]). In | |
| this case, SW sets payload_en to 4'b 0010. | |
| ''' | |
| } | |
| { bits: "20" | |
| name: "payload_dir" | |
| desc: '''Set to 1 if the command returns data. If 0, the payload | |
| sends to the downstream Flash device. | |
| ''' | |
| enum: [ | |
| { value: "0" | |
| name: "PayloadIn" | |
| desc: "From host to the downstream flash device" | |
| } // e: PayloadIn | |
| { value: "1" | |
| name: "PayloadOut" | |
| desc: "From the downstream flash device to the host" | |
| } // e: PayloadOut | |
| ] | |
| } // f: payload_dir | |
| { bits: "21" | |
| name: "payload_swap_en" | |
| desc: '''Swap the first byte of the write payload. | |
| If `payload_swap_en` is set, the passthrough logic swaps the first byte of the write payload with DATA_SWAP CSR. | |
| `payload_swap_en` only works with write data and SingleIO mode. `payload_en` must be 4'b 0001 and `paylod_dir` to be PayloadIn. | |
| ''' | |
| } // f: payload_swap_en | |
| { bits: "24" | |
| name: "upload" | |
| desc: '''Set to 1 to upload the command. | |
| If upload field in the command info entry is set, the cmdparse | |
| activates the upload submodule when the opcode is received. | |
| `addr_en`, `addr_4B_affected`, and `addr_4b_forced` (TBD) affect | |
| the upload functionality. The three address related configs | |
| defines the command address field size. | |
| The logic assumes the following SPI input stream as payload, | |
| which max size is 256B. If the command exceeds the maximum | |
| payload size 256B, the logic wraps the payload and overwrites. | |
| ''' | |
| } // f: upload | |
| { bits: "25" | |
| name: "busy" | |
| desc: '''Set to 1 to set the BUSY bit in the FLASH_STATUS when the | |
| command is received. This bit is active only when `upload` bit is | |
| set. | |
| ''' | |
| } // f: busy | |
| { bits: "31" | |
| name: "valid" | |
| desc: '''Set to 1 if the config in the register is valid | |
| ''' | |
| } // f: valid | |
| ] | |
| } | |
| } | |
| { name: "CMD_INFO_EN4B" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| desc: '''Opcode for EN4B. | |
| If the register is active, it affects in flash / passthrough modes. | |
| ''' | |
| fields: [ | |
| { bits: "31" | |
| name: "valid" | |
| desc: "If 1, Opcode affects" | |
| } // f: valid | |
| { bits: "7:0" | |
| name: "opcode" | |
| desc: "EN4B opcode" | |
| } // f: opcode | |
| ] | |
| } // R: CMD_INFO_EN4B | |
| { name: "CMD_INFO_EX4B" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| desc: '''Opcode for EX4B | |
| ''' | |
| fields: [ | |
| { bits: "31" | |
| name: "valid" | |
| desc: "If 1, Opcode affects" | |
| } // f: valid | |
| { bits: "7:0" | |
| name: "opcode" | |
| desc: "EX4B opcode" | |
| } // f: opcode | |
| ] | |
| } // R: CMD_INFO_EX4B | |
| //=============================================================== | |
| // TPM registers | |
| { skipto: "0x800"} | |
| { name: "TPM_CAP" | |
| desc: '''TPM HWIP Capability register. | |
| This register shows the features the current TPM HWIP supports. | |
| ''' | |
| swaccess: "ro" | |
| hwaccess: "hwo" | |
| fields: [ | |
| { bits: "7:0" | |
| name: "rev" | |
| desc: "Revision of the TPM submodule" | |
| resval: "0" | |
| } // f: rev | |
| { bits: "8" | |
| name: "locality" | |
| desc: '''If 1, the TPM submodule supports 5 Locality. | |
| If 0, only one Locality is provided | |
| ''' | |
| resval: "1" | |
| } // f: locality | |
| { bits: "18:16" | |
| name: "max_xfer_size" | |
| desc: '''The maximum transfer size in bytes the TPM submodule supports. | |
| The value is the exponent of the 2. | |
| - 3'b 010: Support up to 4B | |
| - 3'b 011: Support up to 8B | |
| - 3'b 101: Support up to 32B | |
| - 3'b 110: Support up to 64B | |
| All other values are reserved. | |
| The SW may advertises as supporting more than `max_xfer_size` to the South Brige. | |
| If the SW reports the transfer size more than the value described in this field, | |
| the SW must read the data from the write FIFO before the FIFO becomes full in order not to make FIFO overflow. | |
| ''' | |
| resval: "2" | |
| } // f: max_xfer_size | |
| ] | |
| tags: [ | |
| // Remove Read check (reset value) | |
| "excl:CsrAllTests:CsrExclCheck"] | |
| } // R: TPM_CAP | |
| { name: "TPM_CFG" | |
| desc: '''TPM Configuration register. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "0" | |
| name: "en" | |
| desc: "If 1, TPM submodule accepts the transactions over SPI" | |
| } // f: en | |
| { bits: "1" | |
| name: "tpm_mode" | |
| desc: '''Configure the TPM mode. 1 for CRB, 0 for FIFO. | |
| If the SW set this field to 1, the HW logic always pushes the | |
| command/addr and write data to buffers. The logic does not compare | |
| the incoming address to the list of managed-by-HW register | |
| addresses. | |
| The invalid locality check still runs based on the invalid_locality | |
| configuration. | |
| ''' | |
| } // f: tpm_mode | |
| { bits: "2" | |
| name: "hw_reg_dis" | |
| desc: '''If 0, TPM submodule directly returns the return-by-HW registers for the read requests. | |
| If 1, TPM submodule uploads the TPM command regardless of the address, and the SW may return the value through the read FIFO. | |
| ''' | |
| } // f: hw_reg_dis | |
| { bits: "3" | |
| name: "tpm_reg_chk_dis" | |
| desc: '''If 1, the logic does not compare the upper 8 bit of the | |
| received address with the TpmAddr constant, D4h. | |
| If this field is 0, the HW uploads the command, address, and write | |
| payload to the buffers in case of address that is not 0xD4_XXXX. | |
| ''' | |
| } // f: tpm_reg_chk_dis | |
| { bits: "4" | |
| name: "invalid_locality" | |
| desc: '''If 1, TPM submodule returns the invalid data (0xFF) for the | |
| out of the max Locality request. | |
| If it is a write request, it discards the request. | |
| If 0, TPM submodule uploads the TPM command and address. The SW may | |
| write 0xFF to the read FIFO. | |
| Note: The TPM submodule uploads the TPM commands that do not fall | |
| into the FIFO registers (0xD4_XXXX) regardless of | |
| `invalid_locality` bit. | |
| ''' | |
| } // f: invalid_locality | |
| ] | |
| tags: [ | |
| // Remove Write check (reset value) | |
| "excl:CsrAllTests:CsrExclAll"] | |
| } // R: TPM_CFG | |
| { name: "TPM_STATUS" | |
| desc: '''TPM submodule state register. | |
| The TPM_STATUS CSR provides the current TPM status, mostly the buffer and FIFO status. | |
| ''' | |
| swaccess: "ro" | |
| hwaccess: "hwo" | |
| fields: [ | |
| { bits: "0" | |
| name: "cmdaddr_notempty" | |
| desc: "If 1, the TPM_CMD_ADDR has a valid data. This status is reported via the interrupt also." | |
| } // f: cmdaddr_notempty | |
| { bits: "1" | |
| name: "rdfifo_notempty" | |
| desc: "If 1, the TPM_READ_FIFO still has pending data." | |
| } // f: rdfifo_notempty | |
| { bits: "6:4" | |
| name: "rdfifo_depth" | |
| desc: "This field represents the current read FIFO depth" | |
| } // f: rdfifo_depth | |
| { bits: "10:8" | |
| name: "wrfifo_depth" | |
| desc: "This field represents the current write FIFO depth." | |
| } // f: wrfifo_depth | |
| ] | |
| } // R: TPM_STATUS | |
| { multireg: { | |
| cname: "TPM" | |
| name: "TPM_ACCESS" | |
| desc: '''TPM_ACCESS_x register. | |
| ''' | |
| count: "NumLocality" | |
| compact: true | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "7:0" | |
| name: "access" | |
| desc: "TPM_ACCESS" | |
| } | |
| ] | |
| }} // mr: TPM_ACCESS | |
| { name: "TPM_STS" | |
| desc: '''TPM_STS_x register. | |
| The register is mirrored to all Localities. | |
| The value is returned to the host system only when the activeLocality | |
| in the TPM_ACCESS_x is matched to the current received Locality. | |
| ''' | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| name: "sts" | |
| desc: "TPM_STS_x" | |
| } | |
| ] | |
| } // R: TPM_STS | |
| { name: "TPM_INTF_CAPABILITY" | |
| desc: "TPM_INTF_CAPABILITY" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| name: "intf_capability" | |
| desc: "TPM_INTF_CAPABILITY" | |
| } | |
| ] | |
| } // R: TPM_INTF_CAPABILITY | |
| { name: "TPM_INT_ENABLE" | |
| desc: "TPM_INT_ENABLE" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| name: "int_enable" | |
| desc: "TPM_INT_ENABLE" | |
| } | |
| ] | |
| } // R: TPM_INT_ENABLE | |
| { name: "TPM_INT_VECTOR" | |
| desc: "TPM_INT_VECTOR" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "7:0" | |
| name: "int_vector" | |
| desc: "TPM_INT_VECTOR" | |
| } | |
| ] | |
| } // R: TPM_INT_VECTOR | |
| { name: "TPM_INT_STATUS" | |
| desc: "TPM_INT_STATUS" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "31:0" | |
| name: "int_status" | |
| desc: "TPM_INT_STATUS" | |
| } | |
| ] | |
| } // R: TPM_INT_STATUS | |
| { name: "TPM_DID_VID" | |
| desc: "TPM_DID/ TPM_VID register" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "15:0" | |
| name: "vid" | |
| desc: "TPM_VID" | |
| } // f: vid | |
| { bits: "31:16" | |
| name: "did" | |
| desc: "TPM_DID" | |
| } // f: did | |
| ] | |
| } // R: TPM_DID_VID | |
| { name: "TPM_RID" | |
| desc: "TPM_RID" | |
| swaccess: "rw" | |
| hwaccess: "hro" | |
| fields: [ | |
| { bits: "7:0" | |
| name: "rid" | |
| desc: "TPM_RID" | |
| } | |
| ] | |
| } // R: TPM_RID | |
| { name: "TPM_CMD_ADDR" | |
| desc: '''TPM Command and Address buffer | |
| The SW may get the received TPM command and address by readin gthis CSR. | |
| ''' | |
| swaccess: "ro" | |
| hwaccess: "hrw" | |
| hwext: "true" | |
| hwre: "true" | |
| hwqe: "true" | |
| fields: [ | |
| { bits: "23:0" | |
| name: "addr" | |
| desc: "received address" | |
| } // f: addr | |
| { bits: "31:24" | |
| name: "cmd" | |
| desc: "received command" | |
| } // f: cmd | |
| ] | |
| } // R: TPM_CMD_ADDR | |
| { name: "TPM_READ_FIFO" | |
| desc: '''TPM Read command return data FIFO. | |
| The write port of the read command FIFO. | |
| ''' | |
| swaccess: "wo" | |
| hwaccess: "hro" | |
| hwqe: "true" | |
| hwext: "true" | |
| fields: [ | |
| { bits: "7:0" | |
| name: "value" | |
| desc: "write port of the read FIFO" | |
| } | |
| ] | |
| tags: [// Updating FIFO randomly can result in tpm_status value change | |
| "excl:CsrNonInitTests:CsrExclWrite"] | |
| } // R: TPM_READ_FIFO | |
| { name: "TPM_WRITE_FIFO" | |
| desc: '''TPM Write command received data FIFO. | |
| ''' | |
| swaccess: "ro" | |
| hwaccess: "hrw" | |
| hwext: "true" | |
| hwqe: "true" | |
| hwre: "true" | |
| fields: [ | |
| { bits: "7:0" | |
| name: "value" | |
| desc: "Read only port of the write FIFO" | |
| } | |
| ] | |
| tags: ["excl:CsrNonInitTests:CsrExclAll"] | |
| } // R: TPM_WRITE_FIFO | |
| //--------------------------------------------------------------- | |
| { skipto: "0x1000" } | |
| { window: { | |
| name: "buffer", | |
| items: "SramDepth", | |
| validbits: "32", | |
| byte-write: "false", | |
| unusual: "false" | |
| swaccess: "rw", | |
| desc: ''' | |
| SPI internal buffer. | |
| In Generic mode, this buffer is used for RX/TX buffer. In Flash & | |
| Passthrough mode, lower 2kB is for Read content emulating eFlash. | |
| next 1kB is for Mailbox read/write buffer. The rest is 64B of | |
| CmdFIFO, 64B of AddrFIFO, and 256B of payload FIFO. | |
| ''' | |
| }, | |
| }, | |
| ] | |
| } |