5#include "sw/device/lib/testing/spi_device_testutils.h" 
    7#include "hw/top/dt/dt_spi_device.h" 
    9#include "sw/device/lib/testing/test_framework/check.h" 
   11#define MODULE_ID MAKE_MODULE_ID('s', 'd', 't') 
   17static const dt_pad_t kSpiDeviceDirectPads[4] = {
 
   24status_t spi_device_testutils_configure_passthrough(
 
   26    bool upload_write_commands) {
 
   32  TRY(dif_spi_device_configure(spi_device, spi_device_config));
 
   35      .status = upload_write_commands,
 
   40  TRY(dif_spi_device_set_passthrough_intercept_config(spi_device,
 
   44  TRY(dif_spi_device_set_all_passthrough_command_filters(spi_device,
 
   47  dif_spi_device_flash_command_t read_commands[] = {
 
   50          .opcode = kSpiDeviceFlashOpReadStatus1,
 
   54          .payload_dir_to_host = 
true,
 
   58          .opcode = kSpiDeviceFlashOpReadStatus2,
 
   62          .payload_dir_to_host = 
true,
 
   66          .opcode = kSpiDeviceFlashOpReadStatus3,
 
   70          .payload_dir_to_host = 
true,
 
   74          .opcode = kSpiDeviceFlashOpReadJedec,
 
   78          .payload_dir_to_host = 
true,
 
   82          .opcode = kSpiDeviceFlashOpReadSfdp,
 
   86          .payload_dir_to_host = 
true,
 
   90          .opcode = kSpiDeviceFlashOpReadNormal,
 
   92          .passthrough_swap_address = 
true,
 
   95          .payload_dir_to_host = 
true,
 
   99          .opcode = kSpiDeviceFlashOpReadFast,
 
  101          .passthrough_swap_address = 
true,
 
  104          .payload_dir_to_host = 
true,
 
  108          .opcode = kSpiDeviceFlashOpReadDual,
 
  110          .passthrough_swap_address = 
true,
 
  113          .payload_dir_to_host = 
true,
 
  117          .opcode = kSpiDeviceFlashOpReadQuad,
 
  119          .passthrough_swap_address = 
true,
 
  122          .payload_dir_to_host = 
true,
 
  126          .opcode = kSpiDeviceFlashOpRead4b,
 
  128          .passthrough_swap_address = 
true,
 
  131          .payload_dir_to_host = 
true,
 
  135          .opcode = kSpiDeviceFlashOpReadFast4b,
 
  137          .passthrough_swap_address = 
true,
 
  140          .payload_dir_to_host = 
true,
 
  143  static_assert(
ARRAYSIZE(read_commands) <= UINT8_MAX,
 
  144                "Length of read_commands must fit in uint8_t or we must change " 
  146  for (uint8_t i = 0; i < 
ARRAYSIZE(read_commands); ++i) {
 
  147    uint8_t slot = i + kSpiDeviceReadCommandSlotBase;
 
  148    if (bitfield_bit32_read(filters, slot)) {
 
  149      TRY(dif_spi_device_set_passthrough_command_filter(
 
  152    TRY(dif_spi_device_set_flash_command_slot(
 
  155  dif_spi_device_flash_command_t write_commands[] = {
 
  158          .opcode = kSpiDeviceFlashOpWriteStatus1,
 
  161          .payload_dir_to_host = 
false,
 
  162          .upload = upload_write_commands,
 
  163          .set_busy_status = upload_write_commands,
 
  167          .opcode = kSpiDeviceFlashOpWriteStatus2,
 
  170          .payload_dir_to_host = 
false,
 
  171          .upload = upload_write_commands,
 
  172          .set_busy_status = upload_write_commands,
 
  176          .opcode = kSpiDeviceFlashOpWriteStatus3,
 
  179          .payload_dir_to_host = 
false,
 
  180          .upload = upload_write_commands,
 
  181          .set_busy_status = upload_write_commands,
 
  185          .opcode = kSpiDeviceFlashOpChipErase,
 
  188          .upload = upload_write_commands,
 
  189          .set_busy_status = upload_write_commands,
 
  193          .opcode = kSpiDeviceFlashOpSectorErase,
 
  196          .upload = upload_write_commands,
 
  197          .set_busy_status = upload_write_commands,
 
  201          .opcode = kSpiDeviceFlashOpBlockErase32k,
 
  204          .upload = upload_write_commands,
 
  205          .set_busy_status = upload_write_commands,
 
  209          .opcode = kSpiDeviceFlashOpBlockErase64k,
 
  212          .upload = upload_write_commands,
 
  213          .set_busy_status = upload_write_commands,
 
  217          .opcode = kSpiDeviceFlashOpPageProgram,
 
  220          .payload_dir_to_host = 
false,
 
  221          .upload = upload_write_commands,
 
  222          .set_busy_status = upload_write_commands,
 
  226          .opcode = kSpiDeviceFlashOpSectorErase4b,
 
  229          .upload = upload_write_commands,
 
  230          .set_busy_status = upload_write_commands,
 
  234          .opcode = kSpiDeviceFlashOpBlockErase32k4b,
 
  237          .upload = upload_write_commands,
 
  238          .set_busy_status = upload_write_commands,
 
  242          .opcode = kSpiDeviceFlashOpBlockErase64k4b,
 
  245          .upload = upload_write_commands,
 
  246          .set_busy_status = upload_write_commands,
 
  250          .opcode = kSpiDeviceFlashOpPageProgram4b,
 
  253          .payload_dir_to_host = 
false,
 
  254          .upload = upload_write_commands,
 
  255          .set_busy_status = upload_write_commands,
 
  259          .opcode = kSpiDeviceFlashOpReset,
 
  262          .upload = upload_write_commands,
 
  263          .set_busy_status = upload_write_commands,
 
  267  static_assert(
ARRAYSIZE(write_commands) <= UINT8_MAX,
 
  268                "Length of write_commands must fit into uint8_t");
 
  269  for (uint8_t i = 0; i < 
ARRAYSIZE(write_commands); ++i) {
 
  270    uint8_t slot = i + (uint8_t)kSpiDeviceWriteCommandSlotBase;
 
  271    if (bitfield_bit32_read(filters, slot) || upload_write_commands) {
 
  272      TRY(dif_spi_device_set_passthrough_command_filter(
 
  275    TRY(dif_spi_device_set_flash_command_slot(
 
  281  TRY(dif_spi_device_configure_flash_wren_command(
 
  283  TRY(dif_spi_device_configure_flash_wrdi_command(
 
  285  TRY(dif_spi_device_configure_flash_en4b_command(
 
  288                                                  kSpiDeviceFlashOpExit4bAddr));
 
  290  if (upload_write_commands) {
 
  291    TRY(dif_spi_device_set_passthrough_command_filter(
 
  293    TRY(dif_spi_device_set_passthrough_command_filter(
 
  295    TRY(dif_spi_device_set_passthrough_command_filter(
 
  297    TRY(dif_spi_device_set_passthrough_command_filter(
 
  299    TRY(dif_spi_device_set_passthrough_command_filter(
 
  305status_t spi_device_testutils_configure_read_pipeline(
 
  307    dif_spi_device_read_pipeline_mode_t dual_mode,
 
  308    dif_spi_device_read_pipeline_mode_t quad_mode) {
 
  309  if (spi_device == NULL || dual_mode >= kDifSpiDeviceReadPipelineModeCount ||
 
  310      quad_mode >= kDifSpiDeviceReadPipelineModeCount) {
 
  311    return INVALID_ARGUMENT();
 
  314  const dif_spi_device_flash_command_t normal_read_cmd = {
 
  316      .opcode = kSpiDeviceFlashOpReadNormal,
 
  318      .passthrough_swap_address = 
true,
 
  321      .payload_dir_to_host = 
true,
 
  322      .read_pipeline_mode = dual_mode,
 
  324  const dif_spi_device_flash_command_t fast_read_cmd = {
 
  326      .opcode = kSpiDeviceFlashOpReadFast,
 
  328      .passthrough_swap_address = 
true,
 
  331      .payload_dir_to_host = 
true,
 
  332      .read_pipeline_mode = dual_mode,
 
  334  const dif_spi_device_flash_command_t dual_read_cmd = {
 
  336      .opcode = kSpiDeviceFlashOpReadDual,
 
  338      .passthrough_swap_address = 
true,
 
  341      .payload_dir_to_host = 
true,
 
  342      .read_pipeline_mode = dual_mode,
 
  344  const dif_spi_device_flash_command_t quad_read_cmd = {
 
  346      .opcode = kSpiDeviceFlashOpReadQuad,
 
  348      .passthrough_swap_address = 
true,
 
  351      .payload_dir_to_host = 
true,
 
  352      .read_pipeline_mode = quad_mode,
 
  354  TRY(dif_spi_device_set_flash_command_slot(
 
  356  TRY(dif_spi_device_set_flash_command_slot(spi_device, 6,
 
  358  TRY(dif_spi_device_set_flash_command_slot(spi_device, 7,
 
  360  TRY(dif_spi_device_set_flash_command_slot(spi_device, 8,
 
  365status_t spi_device_testutils_configure_pad_attrs(
dif_pinmux_t *pinmux) {
 
  369  for (uint32_t i = 0; i < 
ARRAYSIZE(kSpiDeviceDirectPads); ++i) {
 
  370    dt_pad_t pad = kSpiDeviceDirectPads[i];
 
  371    res = dif_pinmux_pad_write_attrs_dt(pinmux, pad, in_attr, &out_attr);
 
  378            "Specified slew rate not supported, trying supported slew rate");
 
  383            "Specified drive strength not supported, trying supported drive " 
  387      TRY(dif_pinmux_pad_write_attrs_dt(pinmux, pad, in_attr, &out_attr));
 
  396                                              upload_info_t *info) {
 
  402    TRY(dif_spi_device_irq_is_pending(
 
  404  } 
while (!upload_pending);
 
  409  TRY(dif_spi_device_get_flash_command_fifo_occupancy(spid, &occupancy));
 
  410  if (occupancy != 1) {
 
  414  TRY(dif_spi_device_pop_flash_command_fifo(spid, &info->opcode));
 
  416  TRY(dif_spi_device_get_flash_status_registers(spid, &info->flash_status));
 
  419  TRY(dif_spi_device_get_flash_address_fifo_occupancy(spid, &occupancy));
 
  422    TRY(dif_spi_device_get_4b_address_mode(spid, &addr_4b));
 
  423    info->addr_4b = addr_4b;
 
  424    TRY(dif_spi_device_pop_flash_address_fifo(spid, &info->address));
 
  425    info->has_address = 
true;
 
  430  TRY(dif_spi_device_get_flash_payload_fifo_occupancy(spid, &info->data_len,
 
  432  if (info->data_len) {
 
  433    if (info->data_len > 
sizeof(info->data)) {
 
  435      return INVALID_ARGUMENT();
 
  437    TRY(dif_spi_device_read_flash_payload_buffer(spid, start, info->data_len,
 
  442  TRY(dif_spi_device_irq_acknowledge(&spid->
dev,