Software APIs
spi_device.h
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 #ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_SPI_DEVICE_H_
5 #define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_SPI_DEVICE_H_
6 
7 #include <stdalign.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include "sw/device/silicon_creator/lib/error.h"
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 /**
18  * Bit field definitions for JEDEC device ID.
19  *
20  * Note: spi_device sends bits 7:0 of the device ID first.
21  */
22 #define SPI_DEVICE_DEV_ID_CHIP_REV_FIELD \
23  ((bitfield_field32_t){.mask = 0x7, .index = 0})
24 #define SPI_DEVICE_DEV_ID_ROM_BOOTSTRAP_BIT 3
25 #define SPI_DEVICE_DEV_ID_CHIP_GEN_FIELD \
26  ((bitfield_field32_t){.mask = 0xf, .index = 4})
27 #define SPI_DEVICE_DEV_ID_DENSITY_FIELD \
28  ((bitfield_field32_t){.mask = 0xff, .index = 8})
29 
30 enum {
31  /**
32  * lowRISC's manufacturer ID from the JEDEC JEP106BE standard.
33  */
34  kSpiDeviceJedecContCode = 0x7f,
35  kSpiDeviceJedecContCodeCount = 12,
36  kSpiDeviceJedecManufId = 0xef,
37  /**
38  * LSB of the 2-byte device ID.
39  *
40  * Density is expressed as log2(flash size in bytes).
41  */
42  kSpiDeviceJedecDensity = 20,
43  /**
44  * Size of the JEDEC Basic Flash Parameter Table (BFPT) in words.
45  */
46  kSpiDeviceBfptNumWords = 23,
47  /**
48  * Size of the SFDP table in words.
49  */
50  kSpiDeviceSfdpTableNumWords = 27,
51  /**
52  * Address value used when a command does not have an address.
53  *
54  * Since the spi_device is configured to support only the 3-byte addressing
55  * mode this value is not a valid address.
56  */
57  kSpiDeviceNoAddress = UINT32_MAX,
58 };
59 
60 // TODO(#11740): Auto-generated macros for HW constants.
61 enum {
62  /**
63  * Size of the SFDP area in spi_device egress buffer in bytes.
64  *
65  * spi_device provides 256 bytes for the SFDP table.
66  */
67  kSpiDeviceSfdpAreaNumBytes = 256,
68  /**
69  * Offset of the SFDP area in spi_device egress buffer.
70  */
71  kSpiDeviceSfdpAreaOffset = 0xc00,
72  /**
73  * Offset of the payload area in spi_device ingress buffer.
74  */
75  kSpiDevicePayloadAreaOffset = 0x0,
76  /**
77  * Size of the payload area in spi_device ingress buffer in bytes.
78  */
79  kSpiDevicePayloadAreaNumBytes = 256,
80  /**
81  * Size of the payload area in spi_device ingress buffer in words.
82  */
83  kSpiDevicePayloadAreaNumWords =
84  kSpiDevicePayloadAreaNumBytes / sizeof(uint32_t),
85  /**
86  * Index of the WEL bit in flash status register.
87  */
88  kSpiDeviceWelBit = 1,
89 };
90 
91 /**
92  * Supported SPI flash command opcodes.
93  *
94  * SPI flash commands consist of a single byte of opcode followed by optional
95  * address (transmitted MSB-first by the host) and payload fields (transmitted
96  * LSB-first by the host).
97  *
98  * spi_device is configured to support only the 3-byte addressing mode and the
99  * maximum payload size is 256 bytes. If a command with a larger payload is
100  * received, spi_device overwrites the contents of the payload buffer.
101  */
102 typedef enum spi_device_opcode {
103  /**
104  * READ_STATUS command.
105  *
106  * This command is handled by the spi_device. Upon receiving this command,
107  * spi_device sends the bits of the status register.
108  */
109  kSpiDeviceOpcodeReadStatus = 0x05,
110  /**
111  * READ_JEDEC_ID command.
112  *
113  * This command is handled by the spi_device. Upon receiving this command,
114  * spi_device sends `kSpiDeviceJedecContCodeCount` repetitions of
115  * `kSpiDeviceJedecContCode`, followed by `kSpiDeviceJedecManufId` and 2 bytes
116  * of device id.
117  */
118  kSpiDeviceOpcodeReadJedecId = 0x9f,
119  /**
120  * READ_SFDP command.
121  *
122  * This commond is handled by the spi_device. Upon receiving this
123  * opcode, 3 bytes of address (all zeroes), and 8 dummy cycles;
124  * spi_device sends `kSpiDeviceSfdpTable` from its buffer.
125  */
126  kSpiDeviceOpcodeReadSfdp = 0x5a,
127  /**
128  * CHIP_ERASE command.
129  *
130  * This command should be handled in software. Upon receiving this command,
131  * all data partitions of the embedded flash should be erased.
132  */
133  kSpiDeviceOpcodeChipErase = 0xc7,
134  /**
135  * SECTOR_ERASE command.
136  *
137  * This command has a 3 byte address field and should be handled in software.
138  * Upon receiving this command, the corresponding 4 KiB in the embedded flash
139  * should be erased.
140  */
141  kSpiDeviceOpcodeSectorErase = 0x20,
142  /**
143  * PAGE_PROGRAM command.
144  *
145  * This command has a 3 byte address field followed by a variable length
146  * payload (max 256 bytes) and should be handled in software. Upon receiving
147  * this command, the corresponding area in the embedded flash should be
148  * programmed with the payload.
149  */
150  kSpiDeviceOpcodePageProgram = 0x02,
151  /**
152  * RESET command.
153  *
154  * This command should be handled in software. Upon receiving this command,
155  * the chip should be reset. Note that OpenTitan does not enforce the
156  * RESET_ENABLE (0x66) and RESET (0x99) sequence.
157  */
158  kSpiDeviceOpcodeReset = 0x99,
159  /**
160  * WRITE_ENABLE command.
161  *
162  * This command is handled by the spi_device. Upon receiving this command,
163  * spi_device sets the WEL (write enable latch) bit of the status register.
164  */
165  kSpiDeviceOpcodeWriteEnable = 0x06,
166  /**
167  * WRITE_DISABLE command.
168  *
169  * This command is handled by the spi_device. Upon receiving this command,
170  * spi_device clears the WEL (write enable latch) bit of the status register.
171  */
172  kSpiDeviceOpcodeWriteDisable = 0x04,
173 
174 } spi_device_opcode_t;
175 
176 /**
177  * SFDP header (JESD216F 6.2).
178  */
179 typedef struct spi_device_sfdp_header {
180  /**
181  * 32-bit SFDP signature that indicates the presence of a SFDP table
182  * (JESD216F 6.2.1).
183  */
184  uint32_t signature;
185  /**
186  * SFDP major revision number (JESD216F 6.2.2).
187  */
188  uint8_t minor_revision;
189  /**
190  * SFDP minor revision number (JESD216F 6.2.2).
191  */
192  uint8_t major_revision;
193  /**
194  * Number of parameter headers, zero-based (JESD216F 6.2.2).
195  */
196  uint8_t param_count;
197  /**
198  * SFDP access protocol (JESD216F 6.2.3).
199  */
208 
209 /**
210  * SFDP parameter header (JESD216F 6.3).
211  */
212 typedef struct spi_device_param_header {
213  /**
214  * LSB of the parameter ID that indicates parameter table ownership and type
215  * (JESD216F 6.3.1, 6.3.3).
216  */
217  uint8_t param_id_lsb;
218  /**
219  * Parameter table minor revision number (JESD216F 6.3.1).
220  */
221  uint8_t minor_revision;
222  /**
223  * Parameter table major revision number (JESD216F 6.3.1).
224  */
225  uint8_t major_revision;
226  /**
227  * Length of the parameter table in words, one-based (JESD216F 6.3.1).
228  */
230  /**
231  * Word-aligned byte offset of the corresponding parameter table from the
232  * start of the SFDP table (JESD216F 6.3.2).
233  */
234  uint8_t table_pointer[3];
235  /**
236  * MSB of the parameter ID that indicates parameter table ownership and type
237  * (JESD216F 6.3.2, 6.3.3).
238  */
239  uint8_t param_id_msb;
248 
249 /**
250  * Basic Flash Parameter Table (BFPT) (JESD216F 6.4).
251  *
252  * This is a mandatory table defined by JEDEC that identifies some of the basic
253  * features of a SPI protocol flash memory device.
254  */
255 typedef struct spi_device_bfpt {
256  uint32_t data[kSpiDeviceBfptNumWords];
259 static_assert(sizeof(spi_device_bfpt_t) ==
260  kSpiDeviceBfptNumWords * sizeof(uint32_t),
261  "`kSpiDeviceBfptNumWords` is incorrect");
262 
263 /**
264  * SFDP table.
265  */
266 typedef struct spi_device_sfdp_table {
267  /**
268  * SFDP header.
269  */
271  /**
272  * Parameter header for the Basic Flash Parameters Table (BFPT).
273  */
275  /**
276  * Basic Flash Parameters Table (BFPT).
277  */
284 static_assert(sizeof(spi_device_sfdp_table_t) <= kSpiDeviceSfdpAreaNumBytes,
285  "SFDP table must fit in the space provided by spi_device");
286 static_assert(sizeof(spi_device_sfdp_table_t) ==
287  kSpiDeviceSfdpTableNumWords * sizeof(uint32_t),
288  "`kSpiDeviceSfdpTableNumWords` is incorrect");
289 
290 // Note: Declared here to be able to use in tests.
291 extern const spi_device_sfdp_table_t kSpiDeviceSfdpTable;
292 
293 /**
294  * Initializes the spi_device in flash mode for bootstrap in ROM.
295  *
296  * This function initializes the spi_device in the following configuration:
297  * - CPOL = 0, CPHA = 0 (clock low in idle, data sampled on rising clock edge).
298  * - MSb-first bit order for RX and TX.
299  * - Flash mode with 3-byte addressing.
300  * - `kSpiDeviceSfdpTable` written to the SFDP area in the buffer.
301  * - Commands:
302  * - READ_JEDEC_ID
303  * - READ_SFDP
304  */
305 void spi_device_init(void);
306 
307 /**
308  * A SPI flash command.
309  */
310 typedef struct spi_device_cmd {
311  /**
312  * Command opcode.
313  *
314  * See `spi_device_opcode_t` for a list of command opcodes.
315  */
316  spi_device_opcode_t opcode;
317  /**
318  * Address.
319  *
320  * This field is set to `kSpiDeviceNoAddress` if the command does not have an
321  * address field.
322  */
323  uint32_t address;
324  /**
325  * Payload size in bytes.
326  *
327  * This value must never exceed `kSpiDevicePayloadAreaNumBytes`.
328  */
330  /**
331  * Payload.
332  */
333  alignas(uint32_t) uint8_t payload[kSpiDevicePayloadAreaNumBytes];
335 
336 /**
337  * Gets the SPI flash command received from the host.
338  *
339  * This function returns only the commands that are handled by software and
340  * blocks until the next command. The size of the payload is rounded up to the
341  * next word boundary.
342  *
343  * @param[out] cmd SPI flash command.
344  */
346 rom_error_t spi_device_cmd_get(spi_device_cmd_t *cmd);
347 
348 /**
349  * Clears the SPI flash status register.
350  *
351  * This function should be called after handling a SPI flash command in software
352  * to clear the WIP (busy) and WEL (write enable latch) bits.
353  */
354 void spi_device_flash_status_clear(void);
355 
356 /**
357  * Gets the SPI flash status register.
358  */
360 uint32_t spi_device_flash_status_get(void);
361 
362 #ifdef __cplusplus
363 }
364 #endif
365 
366 #endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_SPI_DEVICE_H_