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