Software APIs
spi_device_flash_smoketest.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 
5 #include <stdbool.h>
6 #include <stdint.h>
7 
9 #include "sw/device/lib/base/status.h"
12 #include "sw/device/lib/testing/spi_device_testutils.h"
13 #include "sw/device/lib/testing/spi_flash_emulator.h"
14 #include "sw/device/lib/testing/spi_flash_testutils.h"
15 #include "sw/device/lib/testing/test_framework/check.h"
17 
19 
20 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true);
21 
22 enum {
23  kSpiDeviceDatasetSize = 128,
24  kSpiDeviceFlashAddress = 0x00,
25 };
26 
27 // A set of bytes to be send out by spi_device.
28 const uint8_t kSpiTxData[kSpiDeviceDatasetSize] = {
29  0xe8, 0x50, 0xc6, 0xb4, 0xbe, 0x16, 0xed, 0x55, 0x16, 0x1d, 0xe6, 0x1c,
30  0xde, 0x9f, 0xfd, 0x24, 0x89, 0x81, 0x4d, 0x0d, 0x1a, 0x12, 0x4f, 0x57,
31  0xea, 0xd6, 0x6f, 0xc0, 0x7d, 0x46, 0xe7, 0x37, 0x81, 0xd3, 0x8e, 0x16,
32  0xad, 0x7b, 0xd0, 0xe2, 0x4f, 0xff, 0x39, 0xe6, 0x71, 0x3c, 0x82, 0x04,
33  0xec, 0x3a, 0x27, 0xcc, 0x3d, 0x58, 0x0e, 0x56, 0xd2, 0xd2, 0xb9, 0xa3,
34  0xb5, 0x3d, 0xc0, 0x40, 0xba, 0x90, 0x16, 0xd8, 0xe3, 0xa4, 0x22, 0x74,
35  0x80, 0xcb, 0x7b, 0xde, 0xd7, 0x3f, 0x4d, 0x93, 0x4d, 0x59, 0x79, 0x88,
36  0x24, 0xe7, 0x68, 0x8b, 0x7a, 0x78, 0xb7, 0x07, 0x09, 0x26, 0xcf, 0x6b,
37  0x52, 0xd9, 0x4c, 0xd3, 0x33, 0xdf, 0x2e, 0x0d, 0x3b, 0xab, 0x45, 0x85,
38  0xc2, 0xc2, 0x19, 0xe5, 0xc7, 0x2b, 0xb0, 0xf6, 0xcb, 0x06, 0xf6, 0xe2,
39  0xf5, 0xb1, 0xab, 0xef, 0x6f, 0xd8, 0x23, 0xfd,
40 };
41 
42 static status_t configure_jedec_id(dif_spi_device_handle_t *spid) {
44  .device_id = 0x2298,
45  .manufacturer_id = 0x74,
46  .continuation_code = 0x17,
47  .num_continuation_code = 2,
48  };
49  TRY(dif_spi_device_set_flash_id(spid, id));
50  return OK_STATUS();
51 }
52 
53 static status_t configure_flash_mode(dif_spi_device_handle_t *spid) {
54  dif_spi_device_config_t spi_device_config = {
57  .device_mode = kDifSpiDeviceModeFlashEmulation,
58  };
59  TRY(dif_spi_device_configure(spid, spi_device_config));
60 
61  dif_spi_device_flash_command_t read_commands[] = {
62  {
63  // Slot 0: ReadStatus1
64  .opcode = kSpiDeviceFlashOpReadStatus1,
65  .address_type = kDifSpiDeviceFlashAddrDisabled,
66  .dummy_cycles = 0,
67  .payload_io_type = kDifSpiDevicePayloadIoSingle,
68  .payload_dir_to_host = true,
69  },
70  {
71  // Slot 1: ReadStatus2
72  .opcode = kSpiDeviceFlashOpReadStatus2,
73  .address_type = kDifSpiDeviceFlashAddrDisabled,
74  .dummy_cycles = 0,
75  .payload_io_type = kDifSpiDevicePayloadIoSingle,
76  .payload_dir_to_host = true,
77  },
78  {
79  // Slot 2: ReadStatus3
80  .opcode = kSpiDeviceFlashOpReadStatus3,
81  .address_type = kDifSpiDeviceFlashAddrDisabled,
82  .dummy_cycles = 0,
83  .payload_io_type = kDifSpiDevicePayloadIoSingle,
84  .payload_dir_to_host = true,
85  },
86  {
87  // Slot 3: ReadJedecID
88  .opcode = kSpiDeviceFlashOpReadJedec,
89  .address_type = kDifSpiDeviceFlashAddrDisabled,
90  .dummy_cycles = 0,
91  .payload_io_type = kDifSpiDevicePayloadIoSingle,
92  .payload_dir_to_host = true,
93  },
94  {
95  // Slot 4: ReadSfdp
96  .opcode = kSpiDeviceFlashOpReadSfdp,
97  .address_type = kDifSpiDeviceFlashAddr3Byte,
98  .dummy_cycles = 8,
99  .payload_io_type = kDifSpiDevicePayloadIoSingle,
100  .payload_dir_to_host = true,
101  },
102  {
103  // Slot 1: ReadNormal
104  .opcode = kSpiDeviceFlashOpReadNormal,
105  .address_type = kDifSpiDeviceFlashAddr3Byte,
106  .dummy_cycles = 0,
107  .payload_io_type = kDifSpiDevicePayloadIoSingle,
108  .payload_dir_to_host = true,
109  },
110  };
111 
112  for (uint8_t i = 0; i < ARRAYSIZE(read_commands); ++i) {
113  uint8_t slot = i + kSpiDeviceReadCommandSlotBase;
115  read_commands[i]));
116  }
117 
118  dif_spi_device_flash_command_t write_commands[] = {
119  {
120  // Slot 1: PageProgram
121  .opcode = kSpiDeviceFlashOpPageProgram,
122  .address_type = kDifSpiDeviceFlashAddrCfg,
123  .payload_io_type = kDifSpiDevicePayloadIoSingle,
124  .payload_dir_to_host = false,
125  .upload = true,
126  .set_busy_status = true,
127  },
128  };
129 
130  for (uint8_t i = 0; i < ARRAYSIZE(write_commands); ++i) {
131  uint8_t slot = i + (uint8_t)kSpiDeviceWriteCommandSlotBase;
133  write_commands[i]));
134  }
135  return OK_STATUS();
136 }
137 
138 bool test_main(void) {
140  CHECK_DIF_OK(dif_spi_device_init_handle(
142 
143  CHECK_STATUS_OK(configure_flash_mode(&spid));
144 
145  LOG_INFO("SYNC: Waiting for write page");
146  upload_info_t info;
147  CHECK_STATUS_OK(spi_device_testutils_wait_for_upload(&spid, &info));
148 
149  CHECK_ARRAYS_EQ(info.data, kSpiTxData, ARRAYSIZE(kSpiTxData));
150 
152  &spid, kDifSpiDeviceFlashBufferTypeEFlash, 0, ARRAYSIZE(kSpiTxData),
153  kSpiTxData));
154 
155  LOG_INFO("Waiting for read");
156  CHECK_DIF_OK(dif_spi_device_set_flash_status_registers(&spid, 0x00));
157 
158  busy_spin_micros(500000);
159  uint32_t address;
160  CHECK_DIF_OK(dif_spi_device_get_last_read_address(&spid, &address));
161  CHECK(address == (kSpiDeviceFlashAddress + kSpiDeviceDatasetSize - 1));
162 
163  return true;
164 }