|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | { | 
|  | name:               "spi_device", | 
|  | human_name:         "SPI Device", | 
|  | one_line_desc:      "Serial peripheral interface supporting different device modes, suitable for bulk-load of data into and out of the chip", | 
|  | one_paragraph_desc: ''' | 
|  | SPI Device is a configurable, versatile hardware block that implements a generic SPI device mode, plus three additional modes (SPI Flash emulation mode, SPI passthrough mode, and TPM over SPI mode) to support a variety of different applications. | 
|  | For example, generic mode can be used in a raw data transfer protocol termed "Firmware Operation Mode", which is intended to be used to bulk-load data into and out of the chip. | 
|  | TPM over SPI operates in compliance with TPM PC Client Platform, unloading this protocol from a software solution. | 
|  | SPI Flash emulation mode supports many JEDEC standard commands such as Read Status, Read JEDEC ID, Read SFDP, EN4B/EX4B, and multiple other read commands, allowing OpenTitan to provide, for example, verified boot firmware to other external devices. | 
|  | ''' | 
|  | design_spec:        "../doc", | 
|  | dv_doc:             "../doc/dv", | 
|  | hw_checklist:       "../doc/checklist", | 
|  | sw_checklist:       "/sw/device/lib/dif/dif_spi_device", | 
|  | revisions: [ | 
|  | { | 
|  | version:            "0.5", | 
|  | life_stage:         "L1", | 
|  | design_stage:       "D1", | 
|  | verification_stage: "V1", | 
|  | dif_stage:          "S0", | 
|  | commit_id:          "553ca956e0204e5b67b3bbea47f2e067f60b5510", | 
|  | notes:              "" | 
|  | } | 
|  | { version:            "1.0", | 
|  | life_stage:         "L1", | 
|  | design_stage:       "D2S", | 
|  | verification_stage: "V2S", | 
|  | dif_stage:          "S2", | 
|  | commit_id:          "", | 
|  | notes:              "" | 
|  | } | 
|  | ] | 
|  | 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" | 
|  | type: "event" | 
|  | } | 
|  | { name: "generic_rx_overflow" | 
|  | desc: "RX Async FIFO overflow" | 
|  | type: "event" | 
|  | } | 
|  | { name: "generic_tx_underflow" | 
|  | desc: "TX Async FIFO underflow" | 
|  | type: "event" | 
|  | } | 
|  | { name: "upload_cmdfifo_not_empty" | 
|  | desc: "Upload Command FIFO is not empty" | 
|  | } | 
|  | { name: "upload_payload_not_empty" | 
|  | desc: '''Upload payload is not empty. | 
|  |  | 
|  | The event occurs after SPI transaction completed | 
|  | ''' | 
|  | } | 
|  | { name: "upload_payload_overflow" | 
|  | desc: '''Upload payload overflow event. | 
|  |  | 
|  | When a SPI Host system issues a command with payload more than 256B, | 
|  | this event is reported. When it happens, SW should read the last | 
|  | written payload index CSR to figure out the starting address of the | 
|  | last 256B. | 
|  | ''' | 
|  | type: "event" | 
|  | } | 
|  | { 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. | 
|  | ''' | 
|  | type: "event" | 
|  | } | 
|  | { name: "tpm_header_not_empty" | 
|  | desc: "TPM Header(Command/Address) buffer available" | 
|  | type: "status" | 
|  | } | 
|  | ], | 
|  | 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 | 
|  | { name:    "TpmWrFifoPtrW" | 
|  | desc:    "TPM WrFIFO Pointer Bit Width. clog2(Depth(64+1))" | 
|  | type:    "int unsigned" | 
|  | default: "7" | 
|  | local:   "true" | 
|  | } // p: TpmWrFifoPtrW | 
|  | { name:    "TpmRdFifoPtrW" | 
|  | desc:    "TPM RdFIFO Pointer Bit Width. clog2(Depth(16+1))" | 
|  | type:    "int unsigned" | 
|  | default: "5" | 
|  | local:   "true" | 
|  | } // p: TpmRdFifoPtrW | 
|  | { name:    "TpmRdFifoWidth" | 
|  | desc:    "TPM Read FIFO Data Width. (TpmRdFifoWidth/8) shall be power of two" | 
|  | type:    "int unsigned" | 
|  | default: "32" | 
|  | } // p: TpmRdFifoWidth | 
|  | ], | 
|  | 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 TX data in Generic mode. | 
|  |  | 
|  | If TX_FIFO (Asynchronous) is full, the TXF waits indefinitely to | 
|  | push the next byte into the asynchronous FIFO. SW may reset the | 
|  | Async FIFO along with aborting the current task. SW should update | 
|  | the write pointer of the TXF in order not to push the byte to | 
|  | Asynchronous FIFO again by TXF logic. | 
|  | ''' | 
|  | resval: "0" | 
|  | }, | 
|  | { bits: "5:4", | 
|  | name: "MODE", | 
|  | desc: "SPI Device operation mode. Currently only FwMode is supported.", | 
|  | resval: "1" | 
|  | 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 | 
|  | ''' | 
|  | }, | 
|  | { value: "1" | 
|  | name: "flashmode" | 
|  | desc: '''SPI Flash Emulation mode. | 
|  |  | 
|  | In flash mode, SPI Device IP accepts SPI Flash commands and | 
|  | processes internally, then returns data for the read commands. | 
|  | HW processes the Status, JEDEC ID, SFDP commands. | 
|  |  | 
|  | The current version does not support Dual/Quad IO and QPI | 
|  | commands. | 
|  | ''' | 
|  | } | 
|  | { value: "2" | 
|  | name: "passthrough" | 
|  | desc: ''' | 
|  | In passthrough mode, SPI Device IP forwards the incoming SPI | 
|  | flash traffics to the attached downstream flash device. HW may | 
|  | processes commands internally and returns data. | 
|  |  | 
|  | SW may configure the device to drop inadmissable commands. | 
|  | ''' | 
|  | } | 
|  | ] | 
|  | 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. It is expected for SW to | 
|  | configure this field at the configuration stage and leave the | 
|  | updation to HW until next reset. | 
|  |  | 
|  | 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. | 
|  | ''' | 
|  | }, | 
|  | { 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. | 
|  |  | 
|  | Current version does not implement abort_done logic. It is tied to | 
|  | 1 always. | 
|  | ''' | 
|  | resval: "1" }, | 
|  | { bits: "5", name: "csb",        desc: "Direct input of CSb signal", resval: "1" }, | 
|  | { bits: "6" | 
|  | name: "tpm_csb" | 
|  | desc: "Direct input of TPM CSb" | 
|  | resval: "1" | 
|  | tags: [ | 
|  | // the value of tpm_csb is determined by the | 
|  | // value on the pins, hence it cannot be predicted. | 
|  | "excl:CsrAllTests:CsrExclCheck" | 
|  | ] | 
|  | } | 
|  | ] | 
|  | }, | 
|  | { 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 | 
|  | tags: [ | 
|  | // SW is not able to read back the STATUS register right after write. | 
|  | // The read back value is committed value, which needs at least a SPI | 
|  | // transaction. | 
|  | // So excluded from CSR automation test. | 
|  | "excl:CsrNonInitTests:CsrExclWrite" | 
|  | ] | 
|  | fields: [ | 
|  | { bits: "0" | 
|  | name: "busy" | 
|  | desc: '''BUSY signal is cleared when CSb is high. SW should read | 
|  | back the register to confirm the value is cleared.''' | 
|  | swaccess: "rw0c" | 
|  | hwaccess: "hrw" | 
|  | } // f: busy | 
|  | { bits: "23:1" | 
|  | name: "status" | 
|  | desc: '''Rest of the status register. | 
|  |  | 
|  | Fields other than the bit 0 (BUSY) and bit 1 (WEL) fields are | 
|  | SW-maintained fields. HW just reads and returns to the host system. | 
|  |  | 
|  | Bit 1 (WEL) is a SW modifiable and HW modifiable field. HW updates | 
|  | the WEL field when `WRDI` or `WREN` command is received. | 
|  |  | 
|  | - [ 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. | 
|  | The value is byte-granularity not SRAM index. | 
|  | ''' | 
|  | } // 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 | 
|  | ] | 
|  | } // R: UPLOAD_STATUS | 
|  | { name: "UPLOAD_STATUS2" | 
|  | desc: '''Upload module status 2 register. | 
|  |  | 
|  | This register contains payload related status. payload_depth indicates | 
|  | the payload size (from 0 to 256 bytes). | 
|  |  | 
|  | payload_start_idx indicates the start of the 256B. This stays 0 | 
|  | usually. However, when the SPI host system issues more than 256B of | 
|  | payload in a command, this field may not be 0. For example, if the | 
|  | system issues 258B payload, the payload_depth is 256 (as the IP only | 
|  | holds 256B of payload), the payload_start_idx is 2. SW should read from | 
|  | 2 to 255 then 0 and 1. | 
|  | ''' | 
|  | swaccess: "ro" | 
|  | hwaccess: "hwo" | 
|  | fields: [ | 
|  | { bits: "8:0" | 
|  | name: "payload_depth" | 
|  | desc: '''Payload buffer depth | 
|  | ''' | 
|  | } // f: payload_depth | 
|  | { bits: "23:16" | 
|  | name: "payload_start_idx" | 
|  | desc: '''Payload Start Index''' | 
|  | } // f: payload_start_idx | 
|  | ] | 
|  | } // R: UPLOAD_STATUS2 | 
|  | { 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 | 
|  | { name: "CMD_INFO_WREN" | 
|  | swaccess: "rw" | 
|  | hwaccess: "hro" | 
|  | desc: '''Opcode for Write Enable (WREN) | 
|  | ''' | 
|  | fields: [ | 
|  | { bits: "31" | 
|  | name: "valid" | 
|  | desc: "If 1, opcode affects" | 
|  | } // f: valid | 
|  | { bits: "7:0" | 
|  | name: "opcode" | 
|  | desc: "WREN opcode" | 
|  | // Leave default value 0 to be consistent | 
|  | } // f: opcode | 
|  | ] | 
|  | } // R: CMD_INFO_WREN | 
|  | { name: "CMD_INFO_WRDI" | 
|  | swaccess: "rw" | 
|  | hwaccess: "hro" | 
|  | desc: '''Opcode for Write Disable (WRDI) | 
|  | ''' | 
|  | fields: [ | 
|  | { bits: "31" | 
|  | name: "valid" | 
|  | desc: "If 1, opcode affects" | 
|  | } // f: valid | 
|  | { bits: "7:0" | 
|  | name: "opcode" | 
|  | desc: "WRDI opcode" | 
|  | // Leave default value 0 to be consistent | 
|  | } // f: opcode | 
|  | ] | 
|  | } // R: CMD_INFO_WRDI | 
|  |  | 
|  | //=============================================================== | 
|  | // 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_wr_size" | 
|  | desc: '''The maximum write 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 100: Support up to 16B | 
|  | - 3'b 101: Support up to 32B | 
|  | - 3'b 110: Support up to 64B | 
|  |  | 
|  | All other values are reserved. | 
|  |  | 
|  | It is not recommended for SW to advertise TPM supporting more than `max_wr_size` to the South Bridge. | 
|  | ''' | 
|  | resval: "6" | 
|  | } // f: max_wr_size | 
|  | { bits: "22:20" | 
|  | name: "max_rd_size" | 
|  | desc: '''The maximum read 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 100: Support up to 16B | 
|  | - 3'b 101: Support up to 32B | 
|  | - 3'b 110: Support up to 64B | 
|  |  | 
|  | All other values are reserved. | 
|  |  | 
|  | It is not recommended for SW to advertise TPM supporting more than `max_rd_size` to the South Bridge. | 
|  | ''' | 
|  | resval: "6" | 
|  | } // f: max_rd_size | 
|  | ] | 
|  | } // 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" | 
|  | tags: [ | 
|  | // Enabling TPM could cause an assertion error if CSB isn't disabled properly in chip-level | 
|  | "excl:CsrNonInitTests:CsrExclWrite"] | 
|  | } // 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, HW still uploads the command and address. | 
|  | SW needs to process the incoming invalid command. | 
|  |  | 
|  | 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 | 
|  | ] | 
|  | } // 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: "15+TpmWrFifoPtrW:16" | 
|  | 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: "TpmRdFifoWidth-1: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" | 
|  | } | 
|  | ] | 
|  | } // 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 256B SFDP | 
|  | buffer, 32B of CmdFIFO, 32B of AddrFIFO, and 256B of payload FIFO. | 
|  | ''' | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | } |