blob: ecb59b20cc881c0590844b37b76f6a35dc170f55 [file] [log] [blame]
// 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.
'''
},
},
]
}