blob: 7df5baece08908320a43546eaafc960d221b8dad [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",
clock_primary: "clk_i",
other_clock_list: [
"scan_clk_i"
],
bus_interfaces: [
{ protocol: "tlul", direction: "device" }
],
available_input_list: [
{ name: "sck", desc: "SPI Clock" },
{ name: "csb", desc: "Chip Enable#" },
],
available_output_list: [
],
available_inout_list: [
{ name: "sd",
width: "4",
desc: "SPI IO, IO2/IO3 has multi-purpose (/WP, /HOLD)"
}
]
interrupt_list: [
{ name: "rxf", desc: "RX SRAM FIFO Full" },
{ name: "rxlvl", desc: "RX SRAM FIFO is above the level" },
{ name: "txlvl", desc: "TX SRAM FIFO is under the level" },
{ name: "rxerr", desc: "SDI in FwMode has error" },
{ name: "rxoverflow", desc: "RX Async FIFO overflow" },
{ name: "txunderflow", desc: "TX Async FIFO underflow" },
],
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: "16"
local: "true"
}
],
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"
}
],
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"
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.
'''
}
]
},
{ 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",
}
],
},
{ 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."
}
]
}
{ 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: "8"
resval: "0"
name: "addr_en"
desc: "If 1, the command has an address field following the opcode"
}
{ bits: "9"
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: "10"
name: "addr_4b_affected"
desc: '''If 1, the address size is affected by `cfg_addr_4b_en`.
If not, the address size of the command is always 3B.
'''
}
{ 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."
}
]
}
}
{ 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.
'''
},
},
]
}