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 NUM_CS supports other counts, but sep_io instantiates it with NUM_CS = 1.

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

ERROR

Latched event. An enabled error event or an INTR_TEST write sets it. It remains set after the cause disappears or INTR_TEST is written back to zero. Clear it by writing 1 to the state bit; clearing ERROR_STATUS alone does not clear it.

SPI_EVENT

Level-sensitive status of the conditions selected by EVENT_ENABLE. Service the condition or change its selection to remove the source; it is not a latched error event.

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:

AddressNameAccessDescription
0x0INTR_STATERW-
0x4INTR_ENABLERW-
0x8INTR_TESTW-
0xCALERT_TESTW-
0x10CONTROLRW-
0x14STATUSR-
0x18CONFIGOPTSRW-
0x1CCSIDRW-
0x20COMMANDW-
0x2CERROR_ENABLERW-
0x30ERROR_STATUSRW-
0x34EVENT_ENABLERW-

Register Details:

INTR_STATE

BitsFieldAccessResetDescription
31:2Reserved--Reserved
1SPI_EVENTR0x0Event-related interrupts, see !!EVENT_ENABLE register for more
information.
0ERRORRW1C0x0Error-related interrupts, see !!ERROR_ENABLE register for more
information.

INTR_ENABLE

BitsFieldAccessResetDescription
31:2Reserved--Reserved
1SPI_EVENTRW0x0Enable interrupt when !!INTR_STATE.spi_event is set.
0ERRORRW0x0Enable interrupt when !!INTR_STATE.error is set.

INTR_TEST

BitsFieldAccessResetDescription
31:2Reserved--Reserved
1SPI_EVENTW0x0Write 1 to force !!INTR_STATE.spi_event to 1.
0ERRORW0x0Write 1 to force !!INTR_STATE.error to 1.

ALERT_TEST

BitsFieldAccessResetDescription
31:1Reserved--Reserved
0FATAL_FAULTW0x0Write 1 to trigger one alert event of this kind.

CONTROL

BitsFieldAccessResetDescription
31SPIENRW0x0Enables the SPI host. On reset, this field is 0, meaning
that no transactions can proceed.
30SW_RSTRW0x0Clears 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.
29OUTPUT_ENRW0x0Enable 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:16Reserved--Reserved
15:8TX_WATERMARKRW0x0If !!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:0RX_WATERMARKRW0x7FIf !!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

BitsFieldAccessResetDescription
31READYR0x0When 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.
30ACTIVER0x0When high, indicates the SPI host is processing a previously
issued command.
29TXFULLR0x0When high, indicates that the transmit data fifo is full.
Any further writes to !!TXDATA will create an error interrupt.
28TXEMPTYR0x0When high, indicates that the transmit data fifo is empty.
27TXSTALLR0x0If high, signifies that an ongoing transaction has stalled
due to lack of data in the TX FIFO
26TXWMR0x0If high, the amount of data in the TX FIFO has fallen below the
level of !!CONTROL.TX_WATERMARK words (32b each).
25RXFULLR0x0When high, indicates that the receive fifo is full. Any
ongoing transactions will stall until firmware reads some
data from !!RXDATA.
24RXEMPTYR0x0When high, indicates that the receive fifo is empty.
Any reads from RX FIFO will cause an error interrupt.
23RXSTALLR0x0If high, signifies that an ongoing transaction has stalled
due to lack of available space in the RX FIFO
22BYTEORDERR0x0The value of the ByteOrder parameter, provided so that firmware
can confirm proper IP configuration.
21Reserved--Reserved
20RXWMR0x0If high, the number of 32-bits in the RX FIFO now exceeds the
!!CONTROL.RX_WATERMARK entries (32b each).
19:16CMDQDR0x0Command queue depth. Indicates how many unread 32-bit words are
currently in the command segment queue.
15:8RXQDR0x0Receive 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:0TXQDR0x0Transmit 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

BitsFieldAccessResetDescription
31CPOLRW0x0The 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.
30CPHARW0x0The 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.
29FULLCYCRW0x0Full 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.
28Reserved--Reserved
27:24CSNLEADRW0x0CS_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:20CSNTRAILRW0x0CS_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:16CSNIDLERW0x0Minimum 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:0CLKDIVRW0x0Core 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

BitsFieldAccessResetDescription
31:0CSIDRW0x0Chip Select ID

COMMAND

BitsFieldAccessResetDescription
31:25Reserved--Reserved
24:5LENW0x0Segment 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:3DIRECTIONW0x0The 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:1SPEEDW0x0The speed for this command segment: "0" = Standard SPI. "1" = Dual SPI.
"2"=Quad SPI, "3": RESERVED.
0CSAATW0x0**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

BitsFieldAccessResetDescription
31:5Reserved--Reserved
4CSIDINVALRW0x1Invalid CSID: If this bit is set, the block sends an error interrupt whenever
a command is submitted, but CSID exceeds NumCS.
3CMDINVALRW0x1Invalid 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.
2UNDERFLOWRW0x1Underflow 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.
1OVERFLOWRW0x1Overflow Errors: If this bit is set, the block sends an
error interrupt whenever the TX FIFO overflows.
0CMDBUSYRW0x1Command 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

BitsFieldAccessResetDescription
31:6Reserved--Reserved
5ACCESSINVALRW1C0x0Indicates that TLUL attempted to write to TXDATA with no bytes enabled. Such
'zero byte' writes are not supported.
4CSIDINVALRW1C0x0Indicates a command was attempted with an invalid value for !!CSID.
3CMDINVALRW1C0x0Indicates an invalid command segment, meaning either an invalid value of
!!COMMAND.SPEED or a request for bidirectional data transfer at dual or quad
speed
2UNDERFLOWRW1C0x0Indicates that firmware has attempted to read from
!!RXDATA when the RX FIFO is empty.
1OVERFLOWRW1C0x0Indicates that firmware has overflowed the TX FIFO
0CMDBUSYRW1C0x0Indicates a write to !!COMMAND when !!STATUS.READY = 0.

EVENT_ENABLE

BitsFieldAccessResetDescription
31:6Reserved--Reserved
5IDLERW0x0Assert to send a spi_event interrupt whenever !!STATUS.ACTIVE
goes low
4READYRW0x0Assert to send a spi_event interrupt whenever !!STATUS.READY
goes high
3TXWMRW0x0Assert 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.
2RXWMRW0x0Assert 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.
1TXEMPTYRW0x0Assert to send a spi_event interrupt whenever !!STATUS.TXEMPTY
goes high
0RXFULLRW0x0Assert to send a spi_event interrupt whenever !!STATUS.RXFULL
goes high