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 
15 enum {
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 
27 enum {
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  */
44 static 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  */
60 static 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 
77  if (spi == NULL) {
78  return kDifBadArg;
79  }
80  return dif_spi_device_init(base_addr, &spi->dev);
81 }
82 
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 
91  dif_spi_device_config_t config) {
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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  */
580 static 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 
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 
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 
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 
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 
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 
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 
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 
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 
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?
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 
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;
722 
723 static dif_result_t dif_spi_device_get_flash_buffer_info(
724  dif_spi_device_flash_buffer_type_t buffer_type,
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 
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 
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  }
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 
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 
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 
826  dif_spi_device_handle_t *spi, dif_toggle_t enable) {
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 
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 
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 
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 
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 
893  dif_toggle_t enable,
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,
921  config.disable_locality_check);
922  }
923  mmio_region_write32(spi->dev.base_addr, SPI_DEVICE_TPM_CFG_REG_OFFSET,
924  reg_val);
925  return kDifOk;
926 }
927 
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 
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 
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  */
1020 static 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  */
1037 static 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 
1047  uint32_t value) {
1048  return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_STS_REG_OFFSET);
1049 }
1050 
1052  uint32_t *value) {
1053  return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_STS_REG_OFFSET);
1054 }
1055 
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 
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 
1067  uint32_t value) {
1068  return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_INT_ENABLE_REG_OFFSET);
1069 }
1070 
1072  uint32_t *value) {
1073  return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_INT_ENABLE_REG_OFFSET);
1074 }
1075 
1077  uint32_t value) {
1078  return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_INT_VECTOR_REG_OFFSET);
1079 }
1080 
1082  uint32_t *value) {
1083  return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_INT_VECTOR_REG_OFFSET);
1084 }
1085 
1087  uint32_t value) {
1088  return tpm_reg_write32(spi, value, SPI_DEVICE_TPM_INT_STATUS_REG_OFFSET);
1089 }
1090 
1092  uint32_t *value) {
1093  return tpm_reg_read32(spi, value, SPI_DEVICE_TPM_INT_STATUS_REG_OFFSET);
1094 }
1095 
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 
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 
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 
1146  size_t length, uint8_t *buf) {
1147  if (spi == NULL || buf == NULL) {
1148  return kDifBadArg;
1149  }
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 
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 
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 }