Serial Peripheral Interface (SPI)
SEP instantiates one OpenTitan SPI Host for software-controlled access to external devices. NOR flash is the primary source of the BL1 boot image. The controller uses commands and transmit/receive FIFOs; it does not provide a memory-mapped flash window for execute-in-place (XIP) access.
1. Use Cases
-
Read the BL1 boot image from external NOR flash.
-
Connect to sensors, particularly in automotive applications.
The intended flash interface uses the x1 and x4 modes of MT25-class devices. The host cannot drive the octal x8 DDR interface of MT35-class devices. Select a flash device and command protocol compatible with the supported modes below.
2. Features
| Capability | SEP implementation |
|---|---|
Transfer width |
Standard (x1), dual (x2) and quad (x4), selected per command segment. |
Transfer rate |
Single transfer rate only. No octal (x8), DDR or DQS read-data strobe. |
Chip select |
One chip-select output. The wrapper parameter |
Data buffering |
Separate transmit and receive FIFOs, with independently defined depths in the core configuration. |
Register interface |
32-bit AXI4-Lite converted to the core’s native TL-UL interface. |
External signals |
SCK, active-low chip select and four bidirectional data lines, with output enables. |
The frequency targets are up to 80 MHz in x1 mode and 166 MHz in x4 mode.
These are design targets, not guaranteed operating limits for an integrated
platform. Software sets the serial clock through CONFIGOPTS.CLKDIV:
f_SCK = f_clk_i / (2 * (CLKDIV + 1)). Select the divider and sampling timing
for the attached device and the platform’s validated clock and I/O timing.
3. Integration and Register Access
sep_io narrows the 64-bit peripheral AXI bus to 32 bits. The
sep_ot_spi_wrap wrapper then converts AXI4-Lite accesses to TL-UL for the
vendored OpenTitan SPI Host. Software submits command segments and moves data
through the FIFOs; controller activity is available in STATUS.ACTIVE,
not on a separate busy output.
An 8-byte write is split into two 4-byte writes. If the byte strobes select
only one half, the other reaches the AXI4-Lite bridge with all strobes clear.
The bridge completes that no-op locally with OKAY and sends no TL-UL request.
Forwarding it to the core would set ERROR_STATUS.ACCESSINVAL and return
an error.
The core’s access-control (RACL) interface is disabled and its SPI pass-through
interface is tied inactive. SEP contains no SPI slave device and does not use
the pass-through arrangement that lets a discrete secure element interpose on
another SPI device’s traffic. An integration requiring XIP, octal or DDR
operation needs a different controller; sep_io_spi is the existing SPI
integration boundary.
4. Interrupts
The core’s error and SPI-event interrupt outputs are ORed onto one line.
The irq field of sep_io_spi_req_t carries that line to
sep_internal_interrupts and the SEP PIC. Software reads INTR_STATE to
identify the source.
INTR_STATE bit |
Behavior and clearing |
|---|---|
|
Latched event. An enabled error event or an |
|
Level-sensitive status of the conditions selected by |
INTR_ENABLE qualifies only the outgoing interrupt line. It does not gate
either state bit. ERROR_ENABLE selects the configurable error events;
invalid register accesses always generate an error event.
5. DMA Trigger
The host’s lsio_trigger_o connects to Secure DMA handshake input 0. It is
the registered OR of the transmit and receive watermark conditions:
TXQD < TX_WATERMARK or RXQD >= RX_WATERMARK. These thresholds are in
32-bit FIFO words. The trigger does not depend on EVENT_ENABLE or
INTR_ENABLE; interrupt selection and DMA pacing are separate controls.
Configure the FIFO watermarks for the intended transfer direction and use
the DMA chapter’s handshake setup.
6. Core Reference
The OpenTitan SPI Host documentation describes core operation and command sequencing. The register map below records the integrated core’s registers and fields. The Programmer’s Guide gives the programming guidance for this block.
7. Memory Map and Register Reference
7.1. Memory Map
Register offsets are relative to the block base in the subsystem memory map. The detailed map below defines each register and its fields.
7.2. Detailed Register Map
SPI Host
Serial peripheral interface for host mode, suitable for interfacing external serial NOR flash devices
Register List:
| Address | Name | Access | Description |
|---|---|---|---|
| 0x0 | INTR_STATE | RW | - |
| 0x4 | INTR_ENABLE | RW | - |
| 0x8 | INTR_TEST | W | - |
| 0xC | ALERT_TEST | W | - |
| 0x10 | CONTROL | RW | - |
| 0x14 | STATUS | R | - |
| 0x18 | CONFIGOPTS | RW | - |
| 0x1C | CSID | RW | - |
| 0x20 | COMMAND | W | - |
| 0x2C | ERROR_ENABLE | RW | - |
| 0x30 | ERROR_STATUS | RW | - |
| 0x34 | EVENT_ENABLE | RW | - |
Register Details:
INTR_STATE
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:2 | Reserved | - | - | Reserved |
| 1 | SPI_EVENT | R | 0x0 | Event-related interrupts, see !!EVENT_ENABLE register for more information. |
| 0 | ERROR | RW1C | 0x0 | Error-related interrupts, see !!ERROR_ENABLE register for more information. |
INTR_ENABLE
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:2 | Reserved | - | - | Reserved |
| 1 | SPI_EVENT | RW | 0x0 | Enable interrupt when !!INTR_STATE.spi_event is set. |
| 0 | ERROR | RW | 0x0 | Enable interrupt when !!INTR_STATE.error is set. |
INTR_TEST
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:2 | Reserved | - | - | Reserved |
| 1 | SPI_EVENT | W | 0x0 | Write 1 to force !!INTR_STATE.spi_event to 1. |
| 0 | ERROR | W | 0x0 | Write 1 to force !!INTR_STATE.error to 1. |
ALERT_TEST
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:1 | Reserved | - | - | Reserved |
| 0 | FATAL_FAULT | W | 0x0 | Write 1 to trigger one alert event of this kind. |
CONTROL
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31 | SPIEN | RW | 0x0 | Enables the SPI host. On reset, this field is 0, meaning that no transactions can proceed. |
| 30 | SW_RST | RW | 0x0 | Clears the internal state (not registers) to the reset state when set to 1, including the FIFOs, the CDC's, the core state machine and the shift register. In the current implementation, the CDC FIFOs are drained not reset. Therefore software must confirm that both FIFO's empty before releasing the IP from reset. |
| 29 | OUTPUT_EN | RW | 0x0 | Enable the SPI host output buffers for the sck, csb, and sd lines. This allows the SPI_HOST IP to connect to the same bus as other SPI controllers without interference. |
| 28:16 | Reserved | - | - | Reserved |
| 15:8 | TX_WATERMARK | RW | 0x0 | If !!EVENT_ENABLE.TXWM is set, the IP will send an interrupt when the depth of the TX FIFO drops below TX_WATERMARK words (32b each). |
| 7:0 | RX_WATERMARK | RW | 0x7F | If !!EVENT_ENABLE.RXWM is set, the IP will send an interrupt when the depth of the RX FIFO reaches RX_WATERMARK words (32b each). |
STATUS
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31 | READY | R | 0x0 | When high, indicates the SPI host is ready to receive commands. Writing to COMMAND when READY is low is an error, and will trigger an interrupt. |
| 30 | ACTIVE | R | 0x0 | When high, indicates the SPI host is processing a previously issued command. |
| 29 | TXFULL | R | 0x0 | When high, indicates that the transmit data fifo is full. Any further writes to !!TXDATA will create an error interrupt. |
| 28 | TXEMPTY | R | 0x0 | When high, indicates that the transmit data fifo is empty. |
| 27 | TXSTALL | R | 0x0 | If high, signifies that an ongoing transaction has stalled due to lack of data in the TX FIFO |
| 26 | TXWM | R | 0x0 | If high, the amount of data in the TX FIFO has fallen below the level of !!CONTROL.TX_WATERMARK words (32b each). |
| 25 | RXFULL | R | 0x0 | When high, indicates that the receive fifo is full. Any ongoing transactions will stall until firmware reads some data from !!RXDATA. |
| 24 | RXEMPTY | R | 0x0 | When high, indicates that the receive fifo is empty. Any reads from RX FIFO will cause an error interrupt. |
| 23 | RXSTALL | R | 0x0 | If high, signifies that an ongoing transaction has stalled due to lack of available space in the RX FIFO |
| 22 | BYTEORDER | R | 0x0 | The value of the ByteOrder parameter, provided so that firmware can confirm proper IP configuration. |
| 21 | Reserved | - | - | Reserved |
| 20 | RXWM | R | 0x0 | If high, the number of 32-bits in the RX FIFO now exceeds the !!CONTROL.RX_WATERMARK entries (32b each). |
| 19:16 | CMDQD | R | 0x0 | Command queue depth. Indicates how many unread 32-bit words are currently in the command segment queue. |
| 15:8 | RXQD | R | 0x0 | Receive queue depth. Indicates how many unread 32-bit words are currently in the RX FIFO. When active, this result may an underestimate due to synchronization delays. |
| 7:0 | TXQD | R | 0x0 | Transmit queue depth. Indicates how many unsent 32-bit words are currently in the TX FIFO. When active, this result may be an overestimate due to synchronization delays. |
CONFIGOPTS
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31 | CPOL | RW | 0x0 | The polarity of the sck clock signal. When CPOL is 0, sck is low when idle, and emits high pulses. When CPOL is 1, sck is high when idle, and emits a series of low pulses. |
| 30 | CPHA | RW | 0x0 | The phase of the sck clock signal relative to the data. When CPHA = 0, the data changes on the trailing edge of sck and is typically sampled on the leading edge. Conversely if CPHA = 1 high, data lines change on the leading edge of sck and are typically sampled on the trailing edge. CPHA should be chosen to match the phase of the selected device. The sampling behavior is modified by the !!CONFIGOPTS.FULLCYC bit. |
| 29 | FULLCYC | RW | 0x0 | Full cycle. Modifies the CPHA sampling behaviour to allow for longer device logic setup times. Rather than sampling the SD bus a half cycle after shifting out data, the data is sampled a full cycle after shifting data out. This means that if CPHA = 0, data is shifted out on the trailing edge, and sampled a full cycle later. If CPHA = 1, data is shifted and sampled with the trailing edge, also separated by a full cycle. |
| 28 | Reserved | - | - | Reserved |
| 27:24 | CSNLEAD | RW | 0x0 | CS_N Leading Time. Indicates the number of half sck cycles, CSNLEAD+1, to leave between the falling edge of cs_n and the first edge of sck. Setting this register to zero corresponds to the minimum delay of one-half sck cycle |
| 23:20 | CSNTRAIL | RW | 0x0 | CS_N Trailing Time. Indicates the number of half sck cycles, CSNTRAIL+1, to leave between last edge of sck and the rising edge of cs_n. Setting this register to zero corresponds to the minimum delay of one-half sck cycle. |
| 19:16 | CSNIDLE | RW | 0x0 | Minimum idle time between commands. Indicates the minimum number of sck half-cycles to hold cs_n high between commands. Setting this register to zero creates a minimally-wide CS_N-high pulse of one-half sck cycle. |
| 15:0 | CLKDIV | RW | 0x0 | Core clock divider. Slows down subsequent SPI transactions by a factor of (CLKDIV+1) relative to the core clock frequency. The period of sck, T(sck) then becomes `2*(CLK_DIV+1)*T(core)` |
CSID
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:0 | CSID | RW | 0x0 | Chip Select ID |
COMMAND
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:25 | Reserved | - | - | Reserved |
| 24:5 | LEN | W | 0x0 | Segment Length. For read or write segments, this field controls the number of 1-byte bursts to transmit and or receive in this command segment. The number of cycles required to send or received a byte will depend on !!COMMAND.SPEED. For dummy segments, (!!COMMAND.DIRECTION == 0), this register controls the number of dummy cycles to issue. The number of bytes (or dummy cycles) in the segment will be equal to !!COMMAND.LEN + 1. |
| 4:3 | DIRECTION | W | 0x0 | The direction for the following command: "0" = Dummy cycles (no TX/RX). "1" = Rx only, "2" = Tx only, "3" = Bidirectional Tx/Rx (Standard SPI mode only). |
| 2:1 | SPEED | W | 0x0 | The speed for this command segment: "0" = Standard SPI. "1" = Dual SPI. "2"=Quad SPI, "3": RESERVED. |
| 0 | CSAAT | W | 0x0 | **C**hip **S**elect **A**ctive **A**fter **T**ransaction. If !!COMMAND.CSAAT = 0, the chip select line is raised immediately at the end of the command segment. If !!COMMAND.CSAAT = 1, the chip select line is left low at the end of the current transaction segment. This allows the creation of longer, more complete SPI transactions, consisting of several separate segments for issuing instructions, pausing for dummy cycles, and transmitting or receiving data from the device. |
ERROR_ENABLE
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:5 | Reserved | - | - | Reserved |
| 4 | CSIDINVAL | RW | 0x1 | Invalid CSID: If this bit is set, the block sends an error interrupt whenever a command is submitted, but CSID exceeds NumCS. |
| 3 | CMDINVAL | RW | 0x1 | Invalid Command Errors: If this bit is set, the block sends an error interrupt whenever a command is sent with invalid values for !!COMMAND.SPEED or !!COMMAND.DIRECTION. |
| 2 | UNDERFLOW | RW | 0x1 | Underflow Errors: If this bit is set, the block sends an error interrupt whenever there is a read from !!RXDATA but the RX FIFO is empty. |
| 1 | OVERFLOW | RW | 0x1 | Overflow Errors: If this bit is set, the block sends an error interrupt whenever the TX FIFO overflows. |
| 0 | CMDBUSY | RW | 0x1 | Command Error: If this bit is set, the block sends an error interrupt whenever a command is issued while busy (i.e. a 1 is when !!STATUS.READY is not asserted.) |
ERROR_STATUS
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:6 | Reserved | - | - | Reserved |
| 5 | ACCESSINVAL | RW1C | 0x0 | Indicates that TLUL attempted to write to TXDATA with no bytes enabled. Such 'zero byte' writes are not supported. |
| 4 | CSIDINVAL | RW1C | 0x0 | Indicates a command was attempted with an invalid value for !!CSID. |
| 3 | CMDINVAL | RW1C | 0x0 | Indicates an invalid command segment, meaning either an invalid value of !!COMMAND.SPEED or a request for bidirectional data transfer at dual or quad speed |
| 2 | UNDERFLOW | RW1C | 0x0 | Indicates that firmware has attempted to read from !!RXDATA when the RX FIFO is empty. |
| 1 | OVERFLOW | RW1C | 0x0 | Indicates that firmware has overflowed the TX FIFO |
| 0 | CMDBUSY | RW1C | 0x0 | Indicates a write to !!COMMAND when !!STATUS.READY = 0. |
EVENT_ENABLE
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:6 | Reserved | - | - | Reserved |
| 5 | IDLE | RW | 0x0 | Assert to send a spi_event interrupt whenever !!STATUS.ACTIVE goes low |
| 4 | READY | RW | 0x0 | Assert to send a spi_event interrupt whenever !!STATUS.READY goes high |
| 3 | TXWM | RW | 0x0 | Assert to send a spi_event interrupt whenever the number of 32-bit words in the TX FIFO is less than !!CONTROL.TX_WATERMARK. To prevent the reassertion of this interrupt add more data to the TX FIFO, or reduce !!CONTROL.TX_WATERMARK. |
| 2 | RXWM | RW | 0x0 | Assert to send a spi_event interrupt whenever the number of 32-bit words in the RX FIFO is greater than !!CONTROL.RX_WATERMARK. To prevent the reassertion of this interrupt, read more data from the RX FIFO, or increase !!CONTROL.RX_WATERMARK. |
| 1 | TXEMPTY | RW | 0x0 | Assert to send a spi_event interrupt whenever !!STATUS.TXEMPTY goes high |
| 0 | RXFULL | RW | 0x0 | Assert to send a spi_event interrupt whenever !!STATUS.RXFULL goes high |