Software APIs
dif_spi_device.c
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
6
10
11#include "spi_device_regs.h" // Generated.
12
13#define DIF_SPI_DEVICE_TPM_FIFO_DEPTH 16
14
15enum {
16 kDifSpiDeviceEFlashLen =
17 SPI_DEVICE_PARAM_SRAM_READ_BUFFER_DEPTH * sizeof(uint32_t),
18 kDifSpiDeviceMailboxLen =
19 SPI_DEVICE_PARAM_SRAM_MAILBOX_DEPTH * sizeof(uint32_t),
20 kDifSpiDeviceSfdpLen = SPI_DEVICE_PARAM_SRAM_SFDP_DEPTH * sizeof(uint32_t),
21 kDifSpiDevicePayloadLen =
22 SPI_DEVICE_PARAM_SRAM_PAYLOAD_DEPTH * sizeof(uint32_t),
23 kDifSpiDeviceTpmWriteFifoLen =
24 SPI_DEVICE_PARAM_SRAM_TPM_WR_FIFO_DEPTH * sizeof(uint32_t),
25};
26
27enum {
28 kDifSpiDeviceEFlashOffset =
29 SPI_DEVICE_PARAM_SRAM_READ_BUFFER_OFFSET * sizeof(uint32_t),
30 kDifSpiDeviceMailboxOffset =
31 SPI_DEVICE_PARAM_SRAM_MAILBOX_OFFSET * sizeof(uint32_t),
32 kDifSpiDeviceSfdpOffset =
33 SPI_DEVICE_PARAM_SRAM_SFDP_OFFSET * sizeof(uint32_t),
34 kDifSpiDevicePayloadOffset =
35 SPI_DEVICE_PARAM_SRAM_PAYLOAD_OFFSET * sizeof(uint32_t),
36 kDifSpiDeviceTpmWriteFifoOffset =
37 SPI_DEVICE_PARAM_SRAM_TPM_WR_FIFO_OFFSET * sizeof(uint32_t),
38};
39
40/**
41 * Computes the required value of the control register from a given
42 * configuration.
43 */
44static inline uint32_t build_control_word(
45 const dif_spi_device_config_t config) {
46 uint32_t val = 0;
47
48 val = bitfield_bit32_write(val, SPI_DEVICE_CFG_TX_ORDER_BIT,
49 config.tx_order == kDifSpiDeviceBitOrderLsbToMsb);
50 val = bitfield_bit32_write(val, SPI_DEVICE_CFG_RX_ORDER_BIT,
51 config.rx_order == kDifSpiDeviceBitOrderLsbToMsb);
52
53 return val;
54}
55
56/**
57 * Extracts the mode value from the given configuration. Return all ones if the
58 * configuration is invalid.
59 */
60static inline uint32_t extract_mode_from_config(
61 const dif_spi_device_config_t config) {
62 switch (config.device_mode) {
64 return SPI_DEVICE_CONTROL_MODE_VALUE_DISABLED;
66 return SPI_DEVICE_CONTROL_MODE_VALUE_FLASHMODE;
68 return SPI_DEVICE_CONTROL_MODE_VALUE_PASSTHROUGH;
69 default:
70 return -1u;
71 }
72 return -1u;
73}
74
75dif_result_t dif_spi_device_init_handle(mmio_region_t base_addr,
77 if (spi == NULL) {
78 return kDifBadArg;
79 }
80 return dif_spi_device_init(base_addr, &spi->dev);
81}
82
83dif_result_t dif_spi_device_init_handle_from_dt(dt_spi_device_t dt,
85 mmio_region_t addr =
86 mmio_region_from_addr(dt_spi_device_primary_reg_block(dt));
87 return dif_spi_device_init_handle(addr, spi);
88}
89
90dif_result_t dif_spi_device_configure(dif_spi_device_handle_t *spi,
92 if (spi == NULL) {
93 return kDifBadArg;
94 }
95
96 uint32_t device_mode = extract_mode_from_config(config);
97 if (device_mode == -1u) {
98 return kDifBadArg;
99 }
100
101 uint32_t device_config = build_control_word(config);
102 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_CFG_REG_OFFSET,
103 device_config);
104
105 uint32_t control =
106 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_CONTROL_REG_OFFSET);
107 // Change mode.
108 control = bitfield_field32_write(control, SPI_DEVICE_CONTROL_MODE_FIELD,
109 device_mode);
110 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_CONTROL_REG_OFFSET,
111 control);
112
113 spi->config = config;
114 return kDifOk;
115}
116
117dif_result_t dif_spi_device_set_passthrough_mode(dif_spi_device_handle_t *spi,
118 dif_toggle_t enable) {
119 if (spi == NULL || !dif_is_valid_toggle(enable)) {
120 return kDifBadArg;
121 }
122 uint32_t control =
123 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_CONTROL_REG_OFFSET);
124 uint32_t mode = bitfield_field32_read(control, SPI_DEVICE_CONTROL_MODE_FIELD);
125 if (mode != SPI_DEVICE_CONTROL_MODE_VALUE_FLASHMODE &&
126 mode != SPI_DEVICE_CONTROL_MODE_VALUE_PASSTHROUGH) {
127 return kDifBadArg;
128 }
129 if (dif_toggle_to_bool(enable)) {
130 control = bitfield_field32_write(control, SPI_DEVICE_CONTROL_MODE_FIELD,
131 SPI_DEVICE_CONTROL_MODE_VALUE_PASSTHROUGH);
132 } else {
133 control = bitfield_field32_write(control, SPI_DEVICE_CONTROL_MODE_FIELD,
134 SPI_DEVICE_CONTROL_MODE_VALUE_FLASHMODE);
135 }
136 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_CONTROL_REG_OFFSET,
137 control);
138 return kDifOk;
139}
140
141dif_result_t dif_spi_device_get_csb_status(dif_spi_device_handle_t *spi,
142 bool *csb) {
143 if (spi == NULL || csb == NULL) {
144 return kDifBadArg;
145 }
146 uint32_t reg_val =
147 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_STATUS_REG_OFFSET);
148 *csb = bitfield_bit32_read(reg_val, SPI_DEVICE_STATUS_CSB_BIT);
149 return kDifOk;
150}
151
152dif_result_t dif_spi_device_enable_mailbox(dif_spi_device_handle_t *spi,
153 uint32_t address) {
154 if (spi == NULL) {
155 return kDifBadArg;
156 }
157 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_MAILBOX_ADDR_REG_OFFSET,
158 address);
159 uint32_t cfg_reg =
160 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_CFG_REG_OFFSET);
161 cfg_reg = bitfield_bit32_write(cfg_reg, SPI_DEVICE_CFG_MAILBOX_EN_BIT, 1);
162 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_CFG_REG_OFFSET, cfg_reg);
163 return kDifOk;
164}
165
166dif_result_t dif_spi_device_disable_mailbox(dif_spi_device_handle_t *spi) {
167 if (spi == NULL) {
168 return kDifBadArg;
169 }
170 uint32_t cfg_reg =
171 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_CFG_REG_OFFSET);
172 cfg_reg = bitfield_bit32_write(cfg_reg, SPI_DEVICE_CFG_MAILBOX_EN_BIT, 0);
173 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_CFG_REG_OFFSET, cfg_reg);
174 return kDifOk;
175}
176
177dif_result_t dif_spi_device_get_mailbox_configuration(
178 dif_spi_device_handle_t *spi, dif_toggle_t *is_enabled, uint32_t *address) {
179 if (spi == NULL || is_enabled == NULL || address == NULL) {
180 return kDifBadArg;
181 }
182 uint32_t cfg_reg =
183 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_CFG_REG_OFFSET);
184 bool mailbox_enabled =
185 bitfield_bit32_read(cfg_reg, SPI_DEVICE_CFG_MAILBOX_EN_BIT);
186 *is_enabled = dif_bool_to_toggle(mailbox_enabled);
187 *address = mmio_region_read32(spi->dev.base_addr,
188 SPI_DEVICE_MAILBOX_ADDR_REG_OFFSET);
189 return kDifOk;
190}
191
192dif_result_t dif_spi_device_set_4b_address_mode(dif_spi_device_handle_t *spi,
193 dif_toggle_t addr_4b) {
194 if (spi == NULL || !dif_is_valid_toggle(addr_4b)) {
195 return kDifBadArg;
196 }
197 uint32_t cfg_reg = 0;
198 if (addr_4b == kDifToggleEnabled) {
199 cfg_reg = bitfield_bit32_write(cfg_reg, SPI_DEVICE_ADDR_MODE_ADDR_4B_EN_BIT,
200 true);
201 } else {
202 cfg_reg = bitfield_bit32_write(cfg_reg, SPI_DEVICE_ADDR_MODE_ADDR_4B_EN_BIT,
203 false);
204 }
205 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_ADDR_MODE_REG_OFFSET,
206 cfg_reg);
207 return kDifOk;
208}
209
210dif_result_t dif_spi_device_get_4b_address_mode(dif_spi_device_handle_t *spi,
211 dif_toggle_t *addr_4b) {
212 if (spi == NULL || addr_4b == NULL) {
213 return kDifBadArg;
214 }
215 uint32_t cfg_reg =
216 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_ADDR_MODE_REG_OFFSET);
217 if (bitfield_bit32_read(cfg_reg, SPI_DEVICE_ADDR_MODE_ADDR_4B_EN_BIT)) {
218 *addr_4b = kDifToggleEnabled;
219 } else {
220 *addr_4b = kDifToggleDisabled;
221 }
222 return kDifOk;
223}
224
225dif_result_t dif_spi_device_clear_flash_status_request(
227 if (spi == NULL) {
228 return kDifBadArg;
229 }
230
231 uint32_t device_mode = extract_mode_from_config(spi->config);
232 if (device_mode == -1u) {
233 return kDifBadArg;
234 }
235
236 uint32_t control =
237 bitfield_field32_write(0, SPI_DEVICE_CONTROL_MODE_FIELD, device_mode);
238 control = bitfield_bit32_write(
239 control, SPI_DEVICE_CONTROL_FLASH_STATUS_FIFO_CLR_BIT, true);
240 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_CONTROL_REG_OFFSET,
241 control);
242
243 return kDifOk;
244}
245
246dif_result_t dif_spi_device_get_flash_id(dif_spi_device_handle_t *spi,
247 dif_spi_device_flash_id_t *id) {
248 if (spi == NULL || id == NULL) {
249 return kDifBadArg;
250 }
251 uint32_t cc_reg =
252 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_JEDEC_CC_REG_OFFSET);
253 uint32_t id_reg =
254 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_JEDEC_ID_REG_OFFSET);
255 id->num_continuation_code =
256 (uint8_t)bitfield_field32_read(cc_reg, SPI_DEVICE_JEDEC_CC_NUM_CC_FIELD);
257 id->continuation_code =
258 (uint8_t)bitfield_field32_read(cc_reg, SPI_DEVICE_JEDEC_CC_CC_FIELD);
259 id->manufacturer_id =
260 (uint8_t)bitfield_field32_read(id_reg, SPI_DEVICE_JEDEC_ID_MF_FIELD);
261 id->device_id =
262 (uint16_t)bitfield_field32_read(id_reg, SPI_DEVICE_JEDEC_ID_ID_FIELD);
263 return kDifOk;
264}
265
266dif_result_t dif_spi_device_set_flash_id(dif_spi_device_handle_t *spi,
267 dif_spi_device_flash_id_t id) {
268 if (spi == NULL) {
269 return kDifBadArg;
270 }
271 uint32_t cc_reg = bitfield_field32_write(0, SPI_DEVICE_JEDEC_CC_NUM_CC_FIELD,
272 id.num_continuation_code);
273 cc_reg = bitfield_field32_write(cc_reg, SPI_DEVICE_JEDEC_CC_CC_FIELD,
274 id.continuation_code);
275 uint32_t id_reg = bitfield_field32_write(0, SPI_DEVICE_JEDEC_ID_MF_FIELD,
276 id.manufacturer_id);
277 id_reg = bitfield_field32_write(id_reg, SPI_DEVICE_JEDEC_ID_ID_FIELD,
278 id.device_id);
279 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_JEDEC_CC_REG_OFFSET,
280 cc_reg);
281 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_JEDEC_ID_REG_OFFSET,
282 id_reg);
283 return kDifOk;
284}
285
286dif_result_t dif_spi_device_set_passthrough_intercept_config(
289 if (spi == NULL) {
290 return kDifBadArg;
291 }
292 uint32_t reg_val = bitfield_bit32_write(0, SPI_DEVICE_INTERCEPT_EN_STATUS_BIT,
293 config.status);
294 reg_val = bitfield_bit32_write(reg_val, SPI_DEVICE_INTERCEPT_EN_JEDEC_BIT,
295 config.jedec_id);
296 reg_val = bitfield_bit32_write(reg_val, SPI_DEVICE_INTERCEPT_EN_SFDP_BIT,
297 config.sfdp);
298 reg_val = bitfield_bit32_write(reg_val, SPI_DEVICE_INTERCEPT_EN_MBX_BIT,
299 config.mailbox);
300 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_INTERCEPT_EN_REG_OFFSET,
301 reg_val);
302 return kDifOk;
303}
304
305dif_result_t dif_spi_device_get_last_read_address(dif_spi_device_handle_t *spi,
306 uint32_t *address) {
307 if (spi == NULL || address == NULL) {
308 return kDifBadArg;
309 }
310 *address = mmio_region_read32(spi->dev.base_addr,
311 SPI_DEVICE_LAST_READ_ADDR_REG_OFFSET);
312 return kDifOk;
313}
314
315dif_result_t dif_spi_device_set_eflash_read_threshold(
316 dif_spi_device_handle_t *spi, uint32_t address) {
317 if (spi == NULL || address > SPI_DEVICE_READ_THRESHOLD_THRESHOLD_MASK) {
318 return kDifBadArg;
319 }
320 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_READ_THRESHOLD_REG_OFFSET,
321 address);
322 return kDifOk;
323}
324
325dif_result_t dif_spi_device_reset_eflash_buffer(dif_spi_device_handle_t *spi) {
326 if (spi == NULL) {
327 return kDifBadArg;
328 }
329
330 uint32_t device_mode = extract_mode_from_config(spi->config);
331 if (device_mode == -1u) {
332 return kDifBadArg;
333 }
334
335 uint32_t control =
336 bitfield_field32_write(0, SPI_DEVICE_CONTROL_MODE_FIELD, device_mode);
337 control = bitfield_bit32_write(
338 control, SPI_DEVICE_CONTROL_FLASH_READ_BUFFER_CLR_BIT, true);
339 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_CONTROL_REG_OFFSET,
340 control);
341
342 return kDifOk;
343}
344
345dif_result_t dif_spi_device_set_flash_command_slot(
346 dif_spi_device_handle_t *spi, uint8_t slot, dif_toggle_t enable,
347 dif_spi_device_flash_command_t command_info) {
348 if (spi == NULL || slot >= SPI_DEVICE_PARAM_NUM_CMD_INFO ||
349 !dif_is_valid_toggle(enable)) {
350 return kDifBadArg;
351 }
352 ptrdiff_t reg_offset =
353 SPI_DEVICE_CMD_INFO_0_REG_OFFSET + slot * sizeof(uint32_t);
354 uint32_t reg_val = 0;
355 if (enable == kDifToggleDisabled) {
356 reg_val =
357 bitfield_bit32_write(reg_val, SPI_DEVICE_CMD_INFO_0_VALID_0_BIT, false);
358 } else {
359 // Validate command info parameters.
360 uint32_t address_mode;
361 switch (command_info.address_type) {
363 address_mode = SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDRDISABLED;
364 break;
366 address_mode = SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDRCFG;
367 break;
369 address_mode = SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDR3B;
370 break;
372 address_mode = SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDR4B;
373 break;
374 default:
375 return kDifBadArg;
376 }
377 if (command_info.dummy_cycles >
378 (1u + SPI_DEVICE_CMD_INFO_0_DUMMY_SIZE_0_MASK)) {
379 return kDifBadArg;
380 }
381
382 uint32_t payload_en;
383 switch (command_info.payload_io_type) {
385 payload_en = 0x0;
386 break;
388 if (command_info.payload_dir_to_host) {
389 payload_en = 0x2;
390 } else {
391 payload_en = 0x1;
392 }
393 break;
395 payload_en = 0x3;
396 break;
398 payload_en = 0xf;
399 break;
400 default:
401 return kDifBadArg;
402 }
403
404 uint32_t read_pipeline_mode;
405 switch (command_info.read_pipeline_mode) {
407 read_pipeline_mode =
408 SPI_DEVICE_CMD_INFO_0_READ_PIPELINE_MODE_0_VALUE_ZERO_STAGES;
409 break;
411 read_pipeline_mode =
412 SPI_DEVICE_CMD_INFO_0_READ_PIPELINE_MODE_0_VALUE_TWO_STAGES_HALF_CYCLE;
413 break;
415 read_pipeline_mode =
416 SPI_DEVICE_CMD_INFO_0_READ_PIPELINE_MODE_0_VALUE_TWO_STAGES_FULL_CYCLE;
417 break;
418 default:
419 return kDifBadArg;
420 }
421
422 // Check for invalid argument combinations.
423 if (command_info.payload_swap_enable &&
424 (command_info.payload_dir_to_host ||
426 return kDifBadArg;
427 }
428 if (command_info.passthrough_swap_address &&
429 command_info.address_type == kDifSpiDeviceFlashAddrDisabled) {
430 return kDifBadArg;
431 }
432
433 // Write the command info values.
434 reg_val = bitfield_field32_write(
435 reg_val, SPI_DEVICE_CMD_INFO_0_OPCODE_0_FIELD, command_info.opcode);
436 reg_val = bitfield_field32_write(
437 reg_val, SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_FIELD, address_mode);
438 reg_val =
439 bitfield_bit32_write(reg_val, SPI_DEVICE_CMD_INFO_0_ADDR_SWAP_EN_0_BIT,
440 command_info.passthrough_swap_address);
441 if (command_info.dummy_cycles > 0) {
442 reg_val = bitfield_field32_write(reg_val,
443 SPI_DEVICE_CMD_INFO_0_DUMMY_SIZE_0_FIELD,
444 command_info.dummy_cycles - 1);
445 reg_val = bitfield_bit32_write(
446 reg_val, SPI_DEVICE_CMD_INFO_0_DUMMY_EN_0_BIT, true);
447 }
448 reg_val = bitfield_field32_write(
449 reg_val, SPI_DEVICE_CMD_INFO_0_PAYLOAD_EN_0_FIELD, payload_en);
450 reg_val =
451 bitfield_bit32_write(reg_val, SPI_DEVICE_CMD_INFO_0_PAYLOAD_DIR_0_BIT,
452 command_info.payload_dir_to_host);
453 reg_val = bitfield_bit32_write(reg_val,
454 SPI_DEVICE_CMD_INFO_0_PAYLOAD_SWAP_EN_0_BIT,
455 command_info.payload_swap_enable);
456 reg_val = bitfield_field32_write(
457 reg_val, SPI_DEVICE_CMD_INFO_0_READ_PIPELINE_MODE_0_FIELD,
458 read_pipeline_mode);
459 reg_val = bitfield_bit32_write(reg_val, SPI_DEVICE_CMD_INFO_0_UPLOAD_0_BIT,
460 command_info.upload);
461 reg_val = bitfield_bit32_write(reg_val, SPI_DEVICE_CMD_INFO_0_BUSY_0_BIT,
462 command_info.set_busy_status);
463 reg_val =
464 bitfield_bit32_write(reg_val, SPI_DEVICE_CMD_INFO_0_VALID_0_BIT, true);
465 }
466 mmio_region_write32(spi->dev.base_addr, reg_offset, reg_val);
467 return kDifOk;
468}
469
470dif_result_t dif_spi_device_get_flash_command_slot(
471 dif_spi_device_handle_t *spi, uint8_t slot, dif_toggle_t *enabled,
472 dif_spi_device_flash_command_t *command_info) {
473 if (spi == NULL || enabled == NULL || command_info == NULL ||
474 slot >= SPI_DEVICE_PARAM_NUM_CMD_INFO) {
475 return kDifBadArg;
476 }
477 ptrdiff_t reg_offset =
478 SPI_DEVICE_CMD_INFO_0_REG_OFFSET + slot * sizeof(uint32_t);
479 uint32_t reg_val = mmio_region_read32(spi->dev.base_addr, reg_offset);
480
481 dif_spi_device_flash_address_type_t address_type;
482 uint32_t reg_val_address_mode =
483 bitfield_field32_read(reg_val, SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_FIELD);
484 switch (reg_val_address_mode) {
485 case SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDRDISABLED:
486 address_type = kDifSpiDeviceFlashAddrDisabled;
487 break;
488 case SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDRCFG:
489 address_type = kDifSpiDeviceFlashAddrCfg;
490 break;
491 case SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDR3B:
492 address_type = kDifSpiDeviceFlashAddr3Byte;
493 break;
494 case SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDR4B:
495 address_type = kDifSpiDeviceFlashAddr4Byte;
496 break;
497 default:
498 address_type = kDifSpiDeviceFlashAddrCount;
499 break;
500 }
501
502 uint32_t dummy_cycles = 0;
503 if (bitfield_bit32_read(reg_val, SPI_DEVICE_CMD_INFO_0_DUMMY_EN_0_BIT)) {
504 dummy_cycles = 1 + bitfield_field32_read(
505 reg_val, SPI_DEVICE_CMD_INFO_0_DUMMY_SIZE_0_FIELD);
506 } else {
507 dummy_cycles = 0;
508 }
509
510 uint32_t payload_en =
511 bitfield_field32_read(reg_val, SPI_DEVICE_CMD_INFO_0_PAYLOAD_EN_0_FIELD);
512 bool payload_dir_to_host =
513 bitfield_bit32_read(reg_val, SPI_DEVICE_CMD_INFO_0_PAYLOAD_DIR_0_BIT);
514 dif_spi_device_payload_io_t payload_io_type;
515 switch (payload_en) {
516 case 0x0:
517 payload_io_type = kDifSpiDevicePayloadIoNone;
518 break;
519 case 0x1:
520 if (payload_dir_to_host) {
521 payload_io_type = kDifSpiDevicePayloadIoInvalid;
522 } else {
523 payload_io_type = kDifSpiDevicePayloadIoSingle;
524 }
525 break;
526 case 0x2:
527 if (!payload_dir_to_host) {
528 payload_io_type = kDifSpiDevicePayloadIoInvalid;
529 } else {
530 payload_io_type = kDifSpiDevicePayloadIoSingle;
531 }
532 break;
533 case 0x3:
534 payload_io_type = kDifSpiDevicePayloadIoDual;
535 break;
536 case 0xf:
537 payload_io_type = kDifSpiDevicePayloadIoQuad;
538 break;
539 default:
540 payload_io_type = kDifSpiDevicePayloadIoInvalid;
541 break;
542 }
543
544 dif_spi_device_flash_command_t cmd = {
545 .opcode = (uint8_t)bitfield_field32_read(
546 reg_val, SPI_DEVICE_CMD_INFO_0_OPCODE_0_FIELD),
547 .address_type = address_type,
548 .dummy_cycles = (uint8_t)dummy_cycles,
549 .payload_io_type = payload_io_type,
550 .passthrough_swap_address = bitfield_bit32_read(
551 reg_val, SPI_DEVICE_CMD_INFO_0_PAYLOAD_SWAP_EN_0_BIT),
552 .payload_dir_to_host = payload_dir_to_host,
553 .payload_swap_enable = bitfield_bit32_read(
554 reg_val, SPI_DEVICE_CMD_INFO_0_PAYLOAD_SWAP_EN_0_BIT),
555 .upload =
556 bitfield_bit32_read(reg_val, SPI_DEVICE_CMD_INFO_0_UPLOAD_0_BIT),
557 .set_busy_status =
558 bitfield_bit32_read(reg_val, SPI_DEVICE_CMD_INFO_0_BUSY_0_BIT),
559 };
560 *command_info = cmd;
561
562 if (bitfield_bit32_read(reg_val, SPI_DEVICE_CMD_INFO_0_VALID_0_BIT)) {
563 *enabled = kDifToggleEnabled;
564 } else {
565 *enabled = kDifToggleDisabled;
566 }
567 return kDifOk;
568}
569
570/**
571 * Write cmd_info register that is a separate CSR for a specific opcode (not
572 * attached to a numbered slot).
573 *
574 * @param spi A handle to a spi_device.
575 * @param enable Whether to enable the function.
576 * @param opcode Which opcode activates the function.
577 * @param reg_offset The register offset for the function's cmd_info CSR.
578 * @return The result of the operation.
579 */
580static dif_result_t write_special_cmd_info(dif_spi_device_handle_t *spi,
581 dif_toggle_t enable, uint8_t opcode,
582 ptrdiff_t reg_offset) {
583 if (spi == NULL || !dif_is_valid_toggle(enable)) {
584 return kDifBadArg;
585 }
586 bool valid = dif_toggle_to_bool(enable);
587 uint32_t reg_val =
588 bitfield_field32_write(0, SPI_DEVICE_CMD_INFO_EN4B_OPCODE_FIELD, opcode);
589 reg_val =
590 bitfield_bit32_write(reg_val, SPI_DEVICE_CMD_INFO_EN4B_VALID_BIT, valid);
591 mmio_region_write32(spi->dev.base_addr, reg_offset, reg_val);
592 return kDifOk;
593}
594
595dif_result_t dif_spi_device_configure_flash_en4b_command(
596 dif_spi_device_handle_t *spi, dif_toggle_t enable, uint8_t opcode) {
597 return write_special_cmd_info(spi, enable, opcode,
598 SPI_DEVICE_CMD_INFO_EN4B_REG_OFFSET);
599}
600
601dif_result_t dif_spi_device_configure_flash_ex4b_command(
602 dif_spi_device_handle_t *spi, dif_toggle_t enable, uint8_t opcode) {
603 return write_special_cmd_info(spi, enable, opcode,
604 SPI_DEVICE_CMD_INFO_EX4B_REG_OFFSET);
605}
606
607dif_result_t dif_spi_device_configure_flash_wren_command(
608 dif_spi_device_handle_t *spi, dif_toggle_t enable, uint8_t opcode) {
609 return write_special_cmd_info(spi, enable, opcode,
610 SPI_DEVICE_CMD_INFO_WREN_REG_OFFSET);
611}
612
613dif_result_t dif_spi_device_configure_flash_wrdi_command(
614 dif_spi_device_handle_t *spi, dif_toggle_t enable, uint8_t opcode) {
615 return write_special_cmd_info(spi, enable, opcode,
616 SPI_DEVICE_CMD_INFO_WRDI_REG_OFFSET);
617}
618
619dif_result_t dif_spi_device_set_flash_address_swap(dif_spi_device_handle_t *spi,
620 uint32_t mask,
621 uint32_t replacement) {
622 if (spi == NULL) {
623 return kDifBadArg;
624 }
625 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_ADDR_SWAP_MASK_REG_OFFSET,
626 mask);
627 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_ADDR_SWAP_DATA_REG_OFFSET,
628 replacement);
629 return kDifOk;
630}
631
632dif_result_t dif_spi_device_set_flash_payload_swap(dif_spi_device_handle_t *spi,
633 uint32_t mask,
634 uint32_t replacement) {
635 if (spi == NULL) {
636 return kDifBadArg;
637 }
638 mmio_region_write32(spi->dev.base_addr,
639 SPI_DEVICE_PAYLOAD_SWAP_MASK_REG_OFFSET, mask);
640 mmio_region_write32(spi->dev.base_addr,
641 SPI_DEVICE_PAYLOAD_SWAP_DATA_REG_OFFSET, replacement);
642 return kDifOk;
643}
644
645dif_result_t dif_spi_device_get_flash_command_fifo_occupancy(
646 dif_spi_device_handle_t *spi, uint8_t *occupancy) {
647 if (spi == NULL || occupancy == NULL) {
648 return kDifBadArg;
649 }
650 uint32_t reg_val = mmio_region_read32(spi->dev.base_addr,
651 SPI_DEVICE_UPLOAD_STATUS_REG_OFFSET);
652 *occupancy = (uint8_t)bitfield_field32_read(
653 reg_val, SPI_DEVICE_UPLOAD_STATUS_CMDFIFO_DEPTH_FIELD);
654 return kDifOk;
655}
656
657dif_result_t dif_spi_device_get_flash_address_fifo_occupancy(
658 dif_spi_device_handle_t *spi, uint8_t *occupancy) {
659 if (spi == NULL || occupancy == NULL) {
660 return kDifBadArg;
661 }
662 uint32_t reg_val = mmio_region_read32(spi->dev.base_addr,
663 SPI_DEVICE_UPLOAD_STATUS_REG_OFFSET);
664 *occupancy = (uint8_t)bitfield_field32_read(
665 reg_val, SPI_DEVICE_UPLOAD_STATUS_ADDRFIFO_DEPTH_FIELD);
666 return kDifOk;
667}
668
669dif_result_t dif_spi_device_get_flash_payload_fifo_occupancy(
670 dif_spi_device_handle_t *spi, uint16_t *occupancy, uint32_t *start_offset) {
671 if (spi == NULL || occupancy == NULL || start_offset == NULL) {
672 return kDifBadArg;
673 }
674 uint32_t reg_val = mmio_region_read32(spi->dev.base_addr,
675 SPI_DEVICE_UPLOAD_STATUS2_REG_OFFSET);
676 *occupancy = (uint16_t)bitfield_field32_read(
677 reg_val, SPI_DEVICE_UPLOAD_STATUS2_PAYLOAD_DEPTH_FIELD);
678 *start_offset = bitfield_field32_read(
679 reg_val, SPI_DEVICE_UPLOAD_STATUS2_PAYLOAD_START_IDX_FIELD);
680 return kDifOk;
681}
682
683// TODO: Does the IP handle overrun / underrun correctly?
684dif_result_t dif_spi_device_pop_flash_command_fifo(dif_spi_device_handle_t *spi,
685 uint8_t *command) {
686 if (spi == NULL || command == NULL) {
687 return kDifBadArg;
688 }
689 uint32_t upload_status = mmio_region_read32(
690 spi->dev.base_addr, SPI_DEVICE_UPLOAD_STATUS_REG_OFFSET);
691 if (!bitfield_bit32_read(upload_status,
692 SPI_DEVICE_UPLOAD_STATUS_CMDFIFO_NOTEMPTY_BIT)) {
693 return kDifUnavailable;
694 }
695 uint32_t cmd_item = mmio_region_read32(spi->dev.base_addr,
696 SPI_DEVICE_UPLOAD_CMDFIFO_REG_OFFSET);
697 *command = (uint8_t)bitfield_field32_read(
698 cmd_item, SPI_DEVICE_UPLOAD_CMDFIFO_DATA_FIELD);
699 return kDifOk;
700}
701
702dif_result_t dif_spi_device_pop_flash_address_fifo(dif_spi_device_handle_t *spi,
703 uint32_t *address) {
704 if (spi == NULL || address == NULL) {
705 return kDifBadArg;
706 }
707 uint32_t upload_status = mmio_region_read32(
708 spi->dev.base_addr, SPI_DEVICE_UPLOAD_STATUS_REG_OFFSET);
709 if (!bitfield_bit32_read(upload_status,
710 SPI_DEVICE_UPLOAD_STATUS_ADDRFIFO_NOTEMPTY_BIT)) {
711 return kDifUnavailable;
712 }
713 *address = mmio_region_read32(spi->dev.base_addr,
714 SPI_DEVICE_UPLOAD_ADDRFIFO_REG_OFFSET);
715 return kDifOk;
716}
717
719 size_t buffer_len;
720 ptrdiff_t buffer_offset;
721} dif_spi_device_buffer_info_t;
722
723static dif_result_t dif_spi_device_get_flash_buffer_info(
724 dif_spi_device_flash_buffer_type_t buffer_type,
725 dif_spi_device_buffer_info_t *info) {
726 switch (buffer_type) {
728 info->buffer_len = kDifSpiDeviceEFlashLen;
729 info->buffer_offset = kDifSpiDeviceEFlashOffset;
730 break;
732 info->buffer_len = kDifSpiDeviceMailboxLen;
733 info->buffer_offset = kDifSpiDeviceMailboxOffset;
734 break;
736 info->buffer_len = kDifSpiDeviceSfdpLen;
737 info->buffer_offset = kDifSpiDeviceSfdpOffset;
738 break;
739 default:
740 return kDifBadArg;
741 }
742 return kDifOk;
743}
744
745dif_result_t dif_spi_device_read_flash_payload_buffer(
746 dif_spi_device_handle_t *spi, uint32_t offset, size_t length,
747 uint8_t *buf) {
748 if (spi == NULL || buf == NULL) {
749 return kDifBadArg;
750 }
751 const dif_spi_device_buffer_info_t info = {
752 .buffer_len = kDifSpiDevicePayloadLen,
753 .buffer_offset = kDifSpiDevicePayloadOffset,
754 };
755 if (offset >= (info.buffer_offset + (ptrdiff_t)info.buffer_len) ||
756 length > (info.buffer_offset + (ptrdiff_t)info.buffer_len -
757 (ptrdiff_t)offset)) {
758 return kDifBadArg;
759 }
760 ptrdiff_t offset_from_base = SPI_DEVICE_INGRESS_BUFFER_REG_OFFSET +
761 info.buffer_offset + (ptrdiff_t)offset;
762 mmio_region_memcpy_from_mmio32(spi->dev.base_addr, (uint32_t)offset_from_base,
763 buf, length);
764 return kDifOk;
765}
766
767dif_result_t dif_spi_device_write_flash_buffer(
769 dif_spi_device_flash_buffer_type_t buffer_type, uint32_t offset,
770 size_t length, const uint8_t *buf) {
771 if (spi == NULL || buf == NULL) {
772 return kDifBadArg;
773 }
774 dif_spi_device_buffer_info_t info;
776 dif_spi_device_get_flash_buffer_info(buffer_type, &info);
777 if (status != kDifOk) {
778 return status;
779 }
780 if (offset >= (info.buffer_offset + (ptrdiff_t)info.buffer_len) ||
781 length > (info.buffer_offset + (ptrdiff_t)info.buffer_len -
782 (ptrdiff_t)offset)) {
783 return kDifBadArg;
784 }
785 ptrdiff_t offset_from_base = SPI_DEVICE_EGRESS_BUFFER_REG_OFFSET +
786 info.buffer_offset + (ptrdiff_t)offset;
787 mmio_region_memcpy_to_mmio32(spi->dev.base_addr, (uint32_t)offset_from_base,
788 buf, length);
789 return kDifOk;
790}
791
792dif_result_t dif_spi_device_get_passthrough_command_filter(
793 dif_spi_device_handle_t *spi, uint8_t command, dif_toggle_t *enabled) {
794 if (spi == NULL || enabled == NULL) {
795 return kDifBadArg;
796 }
797 ptrdiff_t reg_offset =
798 SPI_DEVICE_CMD_FILTER_0_REG_OFFSET + (command >> 5) * sizeof(uint32_t);
799 uint32_t command_index = command & 0x1fu;
800 uint32_t reg_value = mmio_region_read32(spi->dev.base_addr, reg_offset);
801 bool filtered = bitfield_bit32_read(reg_value, command_index);
802 if (filtered) {
803 *enabled = kDifToggleEnabled;
804 } else {
805 *enabled = kDifToggleDisabled;
806 }
807 return kDifOk;
808}
809
810dif_result_t dif_spi_device_set_passthrough_command_filter(
811 dif_spi_device_handle_t *spi, uint8_t command, dif_toggle_t enabled) {
812 if (spi == NULL || !dif_is_valid_toggle(enabled)) {
813 return kDifBadArg;
814 }
815 bool enable_filter = dif_toggle_to_bool(enabled);
816 ptrdiff_t reg_offset =
817 SPI_DEVICE_CMD_FILTER_0_REG_OFFSET + (command >> 5) * sizeof(uint32_t);
818 uint32_t command_index = command & 0x1fu;
819 uint32_t reg_value = mmio_region_read32(spi->dev.base_addr, reg_offset);
820 reg_value = bitfield_bit32_write(reg_value, command_index, enable_filter);
821 mmio_region_write32(spi->dev.base_addr, reg_offset, reg_value);
822 return kDifOk;
823}
824
825dif_result_t dif_spi_device_set_all_passthrough_command_filters(
827 if (spi == NULL || !dif_is_valid_toggle(enable)) {
828 return kDifBadArg;
829 }
830 uint32_t reg_value = dif_toggle_to_bool(enable) ? UINT32_MAX : 0;
831 for (int i = 0; i < SPI_DEVICE_CMD_FILTER_MULTIREG_COUNT; i++) {
832 ptrdiff_t reg_offset =
833 SPI_DEVICE_CMD_FILTER_0_REG_OFFSET + i * (ptrdiff_t)sizeof(uint32_t);
834 mmio_region_write32(spi->dev.base_addr, reg_offset, reg_value);
835 }
836 return kDifOk;
837}
838
839dif_result_t dif_spi_device_clear_flash_busy_bit(dif_spi_device_handle_t *spi) {
840 if (spi == NULL) {
841 return kDifBadArg;
842 }
843 uint32_t reg_val = mmio_region_read32(spi->dev.base_addr,
844 SPI_DEVICE_FLASH_STATUS_REG_OFFSET);
845 reg_val =
846 bitfield_bit32_write(reg_val, SPI_DEVICE_FLASH_STATUS_WEL_BIT, false);
847 reg_val =
848 bitfield_bit32_write(reg_val, SPI_DEVICE_FLASH_STATUS_BUSY_BIT, false);
849 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_FLASH_STATUS_REG_OFFSET,
850 reg_val);
851 return kDifOk;
852}
853
854dif_result_t dif_spi_device_set_flash_status_registers(
855 dif_spi_device_handle_t *spi, uint32_t value) {
856 if (spi == NULL) {
857 return kDifBadArg;
858 }
859 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_FLASH_STATUS_REG_OFFSET,
860 value);
861 return kDifOk;
862}
863
864dif_result_t dif_spi_device_get_flash_status_registers(
865 dif_spi_device_handle_t *spi, uint32_t *value) {
866 if (spi == NULL || value == NULL) {
867 return kDifBadArg;
868 }
869 *value = mmio_region_read32(spi->dev.base_addr,
870 SPI_DEVICE_FLASH_STATUS_REG_OFFSET);
871 return kDifOk;
872}
873
874dif_result_t dif_spi_device_get_tpm_capabilities(
875 dif_spi_device_handle_t *spi, dif_spi_device_tpm_caps_t *caps) {
876 if (spi == NULL || caps == NULL) {
877 return kDifBadArg;
878 }
879 uint32_t reg_val =
880 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_TPM_CAP_REG_OFFSET);
881 caps->revision =
882 (uint8_t)bitfield_field32_read(reg_val, SPI_DEVICE_TPM_CAP_REV_FIELD);
883 caps->multi_locality =
884 bitfield_bit32_read(reg_val, SPI_DEVICE_TPM_CAP_LOCALITY_BIT);
885 caps->max_write_size = (uint8_t)bitfield_field32_read(
886 reg_val, SPI_DEVICE_TPM_CAP_MAX_WR_SIZE_FIELD);
887 caps->max_read_size = (uint8_t)bitfield_field32_read(
888 reg_val, SPI_DEVICE_TPM_CAP_MAX_RD_SIZE_FIELD);
889 return kDifOk;
890}
891
892dif_result_t dif_spi_device_tpm_configure(dif_spi_device_handle_t *spi,
893 dif_toggle_t enable,
894 dif_spi_device_tpm_config_t config) {
895 if (spi == NULL || !dif_is_valid_toggle(enable)) {
896 return kDifBadArg;
897 }
898 bool tpm_en = dif_toggle_to_bool(enable);
899 uint32_t reg_val = bitfield_bit32_write(0, SPI_DEVICE_TPM_CFG_EN_BIT, tpm_en);
900 if (tpm_en) {
901 bool use_crb;
902 switch (config.interface) {
904 use_crb = false;
905 break;
907 use_crb = true;
908 break;
909 default:
910 return kDifBadArg;
911 }
912 reg_val =
913 bitfield_bit32_write(reg_val, SPI_DEVICE_TPM_CFG_TPM_MODE_BIT, use_crb);
914 reg_val = bitfield_bit32_write(reg_val, SPI_DEVICE_TPM_CFG_HW_REG_DIS_BIT,
916 reg_val =
917 bitfield_bit32_write(reg_val, SPI_DEVICE_TPM_CFG_TPM_REG_CHK_DIS_BIT,
919 reg_val =
920 bitfield_bit32_write(reg_val, SPI_DEVICE_TPM_CFG_INVALID_LOCALITY_BIT,
922 }
923 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_TPM_CFG_REG_OFFSET,
924 reg_val);
925 return kDifOk;
926}
927
928dif_result_t dif_spi_device_tpm_get_data_status(
929 dif_spi_device_handle_t *spi, dif_spi_device_tpm_data_status_t *status) {
930 if (spi == NULL || status == NULL) {
931 return kDifBadArg;
932 }
933 uint32_t reg_val =
934 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_TPM_STATUS_REG_OFFSET);
935 status->cmd_addr_valid =
936 bitfield_bit32_read(reg_val, SPI_DEVICE_TPM_STATUS_CMDADDR_NOTEMPTY_BIT);
937 status->wrfifo_acquired =
938 bitfield_bit32_read(reg_val, SPI_DEVICE_TPM_STATUS_WRFIFO_PENDING_BIT);
939 status->rdfifo_aborted =
940 bitfield_bit32_read(reg_val, SPI_DEVICE_TPM_STATUS_RDFIFO_ABORTED_BIT);
941 return kDifOk;
942}
943
944dif_result_t dif_spi_device_tpm_set_access_reg(dif_spi_device_handle_t *spi,
945 uint8_t locality,
946 uint8_t value) {
947 if (spi == NULL || locality >= SPI_DEVICE_PARAM_NUM_LOCALITY) {
948 return kDifBadArg;
949 }
950 // There is one 8-bit TPM_ACCESS register per locality, but bus accesses are
951 // 32 bits.
952 ptrdiff_t reg_offset = SPI_DEVICE_TPM_ACCESS_0_REG_OFFSET + (locality & 0xfc);
953 uint32_t reg_val = mmio_region_read32(spi->dev.base_addr, reg_offset);
954 switch (locality & 0x03) {
955 case 0:
956 reg_val = bitfield_field32_write(
957 reg_val, SPI_DEVICE_TPM_ACCESS_0_ACCESS_0_FIELD, value);
958 break;
959 case 1:
960 reg_val = bitfield_field32_write(
961 reg_val, SPI_DEVICE_TPM_ACCESS_0_ACCESS_1_FIELD, value);
962 break;
963 case 2:
964 reg_val = bitfield_field32_write(
965 reg_val, SPI_DEVICE_TPM_ACCESS_0_ACCESS_2_FIELD, value);
966 break;
967 case 3:
968 reg_val = bitfield_field32_write(
969 reg_val, SPI_DEVICE_TPM_ACCESS_0_ACCESS_3_FIELD, value);
970 break;
971 default:
972 break;
973 }
974 mmio_region_write32(spi->dev.base_addr, reg_offset, reg_val);
975 return kDifOk;
976}
977
978dif_result_t dif_spi_device_tpm_get_access_reg(dif_spi_device_handle_t *spi,
979 uint8_t locality,
980 uint8_t *value) {
981 if (spi == NULL || locality >= SPI_DEVICE_PARAM_NUM_LOCALITY ||
982 value == NULL) {
983 return kDifBadArg;
984 }
985 // There is one 8-bit TPM_ACCESS register per locality, but bus accesses are
986 // 32 bits.
987 ptrdiff_t reg_offset = SPI_DEVICE_TPM_ACCESS_0_REG_OFFSET + (locality & 0xfc);
988 uint32_t reg_val = mmio_region_read32(spi->dev.base_addr, reg_offset);
989 switch (locality & 0x03) {
990 case 0:
991 *value = (uint8_t)bitfield_field32_read(
992 reg_val, SPI_DEVICE_TPM_ACCESS_0_ACCESS_0_FIELD);
993 break;
994 case 1:
995 *value = (uint8_t)bitfield_field32_read(
996 reg_val, SPI_DEVICE_TPM_ACCESS_0_ACCESS_1_FIELD);
997 break;
998 case 2:
999 *value = (uint8_t)bitfield_field32_read(
1000 reg_val, SPI_DEVICE_TPM_ACCESS_0_ACCESS_2_FIELD);
1001 break;
1002 case 3:
1003 *value = (uint8_t)bitfield_field32_read(
1004 reg_val, SPI_DEVICE_TPM_ACCESS_0_ACCESS_3_FIELD);
1005 break;
1006 default:
1007 break;
1008 }
1009 return kDifOk;
1010}
1011
1012/**
1013 * Write a TPM register used with the return-by-hardware logic.
1014 *
1015 * @param spi A handle to a spi device.
1016 * @param value The value to write.
1017 * @param reg_offset The offset of the related CSR from the spi device's base.
1018 * @return The result of the operation.
1019 */
1020static dif_result_t tpm_reg_write32(dif_spi_device_handle_t *spi,
1021 uint32_t value, ptrdiff_t reg_offset) {
1022 if (spi == NULL) {
1023 return kDifBadArg;
1024 }
1025 mmio_region_write32(spi->dev.base_addr, reg_offset, value);
1026 return kDifOk;
1027}
1028
1029/**
1030 * Read from a TPM register used with the return-by-hardware logic.
1031 *
1032 * @param spi A handle to a spi device.
1033 * @param value The value read.
1034 * @param reg_offset The offset of the related CSR from the spi device's base.
1035 * @return The result of the operation.
1036 */
1037static dif_result_t tpm_reg_read32(dif_spi_device_handle_t *spi,
1038 uint32_t *value, ptrdiff_t reg_offset) {
1039 if (spi == NULL || value == NULL) {
1040 return kDifBadArg;
1041 }
1042 *value = mmio_region_read32(spi->dev.base_addr, reg_offset);
1043 return kDifOk;
1044}
1045
1046dif_result_t dif_spi_device_tpm_set_sts_reg(dif_spi_device_handle_t *spi,
1047 uint32_t value) {
1048 return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_STS_REG_OFFSET);
1049}
1050
1051dif_result_t dif_spi_device_tpm_get_sts_reg(dif_spi_device_handle_t *spi,
1052 uint32_t *value) {
1053 return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_STS_REG_OFFSET);
1054}
1055
1056dif_result_t dif_spi_device_tpm_set_intf_capability_reg(
1057 dif_spi_device_handle_t *spi, uint32_t value) {
1058 return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_INTF_CAPABILITY_REG_OFFSET);
1059}
1060
1061dif_result_t dif_spi_device_tpm_get_intf_capability_reg(
1062 dif_spi_device_handle_t *spi, uint32_t *value) {
1063 return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_INTF_CAPABILITY_REG_OFFSET);
1064}
1065
1066dif_result_t dif_spi_device_tpm_set_int_enable_reg(dif_spi_device_handle_t *spi,
1067 uint32_t value) {
1068 return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_INT_ENABLE_REG_OFFSET);
1069}
1070
1071dif_result_t dif_spi_device_tpm_get_int_enable_reg(dif_spi_device_handle_t *spi,
1072 uint32_t *value) {
1073 return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_INT_ENABLE_REG_OFFSET);
1074}
1075
1076dif_result_t dif_spi_device_tpm_set_int_vector_reg(dif_spi_device_handle_t *spi,
1077 uint32_t value) {
1078 return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_INT_VECTOR_REG_OFFSET);
1079}
1080
1081dif_result_t dif_spi_device_tpm_get_int_vector_reg(dif_spi_device_handle_t *spi,
1082 uint32_t *value) {
1083 return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_INT_VECTOR_REG_OFFSET);
1084}
1085
1086dif_result_t dif_spi_device_tpm_set_int_status_reg(dif_spi_device_handle_t *spi,
1087 uint32_t value) {
1088 return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_INT_STATUS_REG_OFFSET);
1089}
1090
1091dif_result_t dif_spi_device_tpm_get_int_status_reg(dif_spi_device_handle_t *spi,
1092 uint32_t *value) {
1093 return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_INT_STATUS_REG_OFFSET);
1094}
1095
1096dif_result_t dif_spi_device_tpm_set_id(dif_spi_device_handle_t *spi,
1097 dif_spi_device_tpm_id_t id) {
1098 if (spi == NULL) {
1099 return kDifBadArg;
1100 }
1101 uint32_t reg_val;
1102 reg_val =
1103 bitfield_field32_write(0, SPI_DEVICE_TPM_DID_VID_VID_FIELD, id.vendor_id);
1104 reg_val = bitfield_field32_write(reg_val, SPI_DEVICE_TPM_DID_VID_DID_FIELD,
1105 id.device_id);
1106 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_TPM_DID_VID_REG_OFFSET,
1107 reg_val);
1108 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_TPM_RID_REG_OFFSET,
1109 id.revision);
1110 return kDifOk;
1111}
1112
1113dif_result_t dif_spi_device_tpm_get_id(dif_spi_device_handle_t *spi,
1114 dif_spi_device_tpm_id_t *value) {
1115 if (spi == NULL || value == NULL) {
1116 return kDifBadArg;
1117 }
1118 uint32_t did_vid =
1119 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_TPM_DID_VID_REG_OFFSET);
1120 uint32_t rid =
1121 mmio_region_read32(spi->dev.base_addr, SPI_DEVICE_TPM_RID_REG_OFFSET);
1122 value->vendor_id = (uint16_t)bitfield_field32_read(
1123 did_vid, SPI_DEVICE_TPM_DID_VID_VID_FIELD);
1124 value->device_id = (uint16_t)bitfield_field32_read(
1125 did_vid, SPI_DEVICE_TPM_DID_VID_DID_FIELD);
1126 value->revision =
1127 (uint8_t)bitfield_field32_read(rid, SPI_DEVICE_TPM_RID_RID_FIELD);
1128 return kDifOk;
1129}
1130
1131dif_result_t dif_spi_device_tpm_get_command(dif_spi_device_handle_t *spi,
1132 uint8_t *command,
1133 uint32_t *address) {
1134 if (spi == NULL || command == NULL || address == NULL) {
1135 return kDifBadArg;
1136 }
1137 uint32_t reg_val = mmio_region_read32(spi->dev.base_addr,
1138 SPI_DEVICE_TPM_CMD_ADDR_REG_OFFSET);
1139 *command = (uint8_t)bitfield_field32_read(reg_val,
1140 SPI_DEVICE_TPM_CMD_ADDR_CMD_FIELD);
1141 *address = bitfield_field32_read(reg_val, SPI_DEVICE_TPM_CMD_ADDR_ADDR_FIELD);
1142 return kDifOk;
1143}
1144
1145dif_result_t dif_spi_device_tpm_write_data(dif_spi_device_handle_t *spi,
1146 size_t length, uint8_t *buf) {
1147 if (spi == NULL || buf == NULL) {
1148 return kDifBadArg;
1149 }
1150 dif_spi_device_tpm_data_status_t status;
1151 dif_result_t result = dif_spi_device_tpm_get_data_status(spi, &status);
1152 uint8_t offset = length & 0x3; // lower two bits of length
1153 uint32_t rdfifo_wdata;
1154
1155 DIF_RETURN_IF_ERROR(result);
1156
1157 // TODO: Ensure the received length is greater than FIFO SIZE
1158 if (DIF_SPI_DEVICE_TPM_FIFO_DEPTH * sizeof(uint32_t) < length) {
1159 return kDifOutOfRange;
1160 }
1161 for (int i = 0; i < length; i += 4) {
1162 if (i + 4 > length) {
1163 // Send partial
1164 rdfifo_wdata = 0;
1165 for (int j = 0; j <= offset; j++) {
1166 rdfifo_wdata |= (uint32_t)(buf[i + j]) << (8 * j);
1167 }
1168 } else {
1169 // Type casting to uint32_t then fetch
1170 rdfifo_wdata = *((uint32_t *)buf + (i >> 2));
1171 }
1172 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_TPM_READ_FIFO_REG_OFFSET,
1173 rdfifo_wdata);
1174 }
1175 return kDifOk;
1176}
1177
1178dif_result_t dif_spi_device_tpm_read_data(dif_spi_device_handle_t *spi,
1179 size_t length, uint8_t *buf) {
1180 if (spi == NULL || buf == NULL) {
1181 return kDifBadArg;
1182 }
1183 const uint32_t kOffset = 0;
1184 const dif_spi_device_buffer_info_t kInfo = {
1185 .buffer_len = kDifSpiDeviceTpmWriteFifoLen,
1186 .buffer_offset = kDifSpiDeviceTpmWriteFifoOffset,
1187 };
1188 if (kOffset >= (kInfo.buffer_offset + (ptrdiff_t)kInfo.buffer_len) ||
1189 length > (kInfo.buffer_offset + (ptrdiff_t)kInfo.buffer_len -
1190 (ptrdiff_t)kOffset)) {
1191 return kDifBadArg;
1192 }
1193 ptrdiff_t offset_from_base = SPI_DEVICE_INGRESS_BUFFER_REG_OFFSET +
1194 kInfo.buffer_offset + (ptrdiff_t)kOffset;
1195 mmio_region_memcpy_from_mmio32(spi->dev.base_addr, (uint32_t)offset_from_base,
1196 buf, length);
1197 return kDifOk;
1198}
1199
1200dif_result_t dif_spi_device_tpm_free_write_fifo(dif_spi_device_handle_t *spi) {
1201 if (spi == NULL) {
1202 return kDifBadArg;
1203 }
1204 // TPM_STATUS.wrfifo_pending is the only writeable CSR, and it's RW0C.
1205 mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_TPM_STATUS_REG_OFFSET, 0);
1206 return kDifOk;
1207}