From 10139a7cb0f5075f572b35c0bb056cf9caf60a13 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Mon, 19 Jun 2023 17:41:09 +0100 Subject: [PATCH] [spi_host, flash] Add test for a macronix flash Signed-off-by: Douglas Reis --- sw/device/tests/BUILD | 28 +++++ .../tests/spi_host_macronix_flash_test.c | 115 ++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 sw/device/tests/spi_host_macronix_flash_test.c diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD index 33b7db2bc41c12..62a29eaccdf0f3 100644 --- a/sw/device/tests/BUILD +++ b/sw/device/tests/BUILD @@ -1775,6 +1775,34 @@ opentitan_functest( ], ) +opentitan_functest( + name = "spi_host_macronix_flash_test", + srcs = ["spi_host_macronix_flash_test.c"], + cw310 = cw310_params( + tags = [ + "bob", + "manual", + ], # Requires the BoB in CI. + ), + targets = ["cw310_test_rom"], # Can only run on CW310 board right now. + deps = [ + ":spi_host_flash_test_impl", + "//hw/top_earlgrey/sw/autogen:top_earlgrey", + "//sw/device/lib/arch:device", + "//sw/device/lib/base:memory", + "//sw/device/lib/base:mmio", + "//sw/device/lib/dif:pinmux", + "//sw/device/lib/dif:spi_host", + "//sw/device/lib/runtime:hart", + "//sw/device/lib/runtime:log", + "//sw/device/lib/runtime:print", + "//sw/device/lib/testing:spi_device_testutils", + "//sw/device/lib/testing:spi_flash_testutils", + "//sw/device/lib/testing:spi_host_testutils", + "//sw/device/lib/testing/test_framework:ottf_main", + ], +) + opentitan_functest( name = "spi_host_irq_test", srcs = ["spi_host_irq_test.c"], diff --git a/sw/device/tests/spi_host_macronix_flash_test.c b/sw/device/tests/spi_host_macronix_flash_test.c new file mode 100644 index 00000000000000..79930d1561c2cb --- /dev/null +++ b/sw/device/tests/spi_host_macronix_flash_test.c @@ -0,0 +1,115 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +#include + +#include "spi_host_flash_test_impl.h" +#include "sw/device/lib/arch/device.h" +#include "sw/device/lib/base/macros.h" +#include "sw/device/lib/base/memory.h" +#include "sw/device/lib/base/mmio.h" +#include "sw/device/lib/dif/dif_pinmux.h" +#include "sw/device/lib/dif/dif_spi_host.h" +#include "sw/device/lib/runtime/hart.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/runtime/print.h" +#include "sw/device/lib/testing/spi_device_testutils.h" +#include "sw/device/lib/testing/spi_flash_testutils.h" +#include "sw/device/lib/testing/test_framework/check.h" +#include "sw/device/lib/testing/test_framework/ottf_main.h" + +#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" + +static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__, + "This test assumes the target platform is little endian."); + +OTTF_DEFINE_TEST_CONFIG(); + +static status_t pinmux_connect_spi_host1_to_bob(const dif_pinmux_t *pinmux) { + // CSB. + TRY(dif_pinmux_output_select(pinmux, kTopEarlgreyPinmuxMioOutIob7, + kTopEarlgreyPinmuxOutselSpiHost1Csb)); + // SCLK. + TRY(dif_pinmux_output_select(pinmux, kTopEarlgreyPinmuxMioOutIoa3, + kTopEarlgreyPinmuxOutselSpiHost1Sck)); + // SD0. + TRY(dif_pinmux_input_select(pinmux, kTopEarlgreyPinmuxPeripheralInSpiHost1Sd0, + kTopEarlgreyPinmuxInselIoa5)); + TRY(dif_pinmux_output_select(pinmux, kTopEarlgreyPinmuxMioOutIoa5, + kTopEarlgreyPinmuxOutselSpiHost1Sd0)); + + // SD1. + TRY(dif_pinmux_input_select(pinmux, kTopEarlgreyPinmuxPeripheralInSpiHost1Sd1, + kTopEarlgreyPinmuxInselIoa4)); + TRY(dif_pinmux_output_select(pinmux, kTopEarlgreyPinmuxMioOutIoa4, + kTopEarlgreyPinmuxOutselSpiHost1Sd1)); + // SD2. + TRY(dif_pinmux_input_select(pinmux, kTopEarlgreyPinmuxPeripheralInSpiHost1Sd2, + kTopEarlgreyPinmuxInselIoa8)); + TRY(dif_pinmux_output_select(pinmux, kTopEarlgreyPinmuxMioOutIoa8, + kTopEarlgreyPinmuxOutselSpiHost1Sd2)); + // SD3. + TRY(dif_pinmux_input_select(pinmux, kTopEarlgreyPinmuxPeripheralInSpiHost1Sd3, + kTopEarlgreyPinmuxInselIoa7)); + TRY(dif_pinmux_output_select(pinmux, kTopEarlgreyPinmuxMioOutIoa7, + kTopEarlgreyPinmuxOutselSpiHost1Sd3)); + return OK_STATUS(); +} + +static void init_test(dif_spi_host_t *spi_host) { + dif_pinmux_t pinmux; + mmio_region_t base_addr = + mmio_region_from_addr(TOP_EARLGREY_PINMUX_AON_BASE_ADDR); + CHECK_DIF_OK(dif_pinmux_init(base_addr, &pinmux)); + pinmux_connect_spi_host1_to_bob(&pinmux); + + base_addr = mmio_region_from_addr(TOP_EARLGREY_SPI_HOST1_BASE_ADDR); + CHECK_DIF_OK(dif_spi_host_init(base_addr, spi_host)); + + CHECK(kClockFreqPeripheralHz <= UINT32_MAX, + "kClockFreqPeripheralHz must fit in uint32_t"); + + CHECK_DIF_OK(dif_spi_host_configure(spi_host, + (dif_spi_host_config_t){ + .spi_clock = 1000000, + .peripheral_clock_freq_hz = + (uint32_t)kClockFreqPeripheralHz, + }), + "SPI_HOST config failed!"); + + CHECK_DIF_OK(dif_spi_host_output_set_enabled(spi_host, true)); +} + +bool test_main(void) { + dif_spi_host_t spi_host; + + init_test(&spi_host); + enum MacronixVendorSpecific { + kDeviceId = 0x1B20, + kManufactureId = 0xC2, + kPageQuadProgramOpcode = 0x38, + // The Macronix flash requires that the addr in sent using 4 lanes as the + // data when issuing the `kPageQuadProgramOpcode` operation. + kPageQuadProgramAddrWidth = 4, + }; + + status_t result = OK_STATUS(); + EXECUTE_TEST(result, test_software_reset, &spi_host); + EXECUTE_TEST(result, test_read_sfdp, &spi_host); + EXECUTE_TEST(result, test_sector_erase, &spi_host); + EXECUTE_TEST(result, test_read_jedec, &spi_host, kDeviceId, kManufactureId); + EXECUTE_TEST(result, test_enable_quad_mode, &spi_host); + EXECUTE_TEST(result, test_page_program, &spi_host); + if (is_4_bytes_address_mode_supported()) { + EXECUTE_TEST(result, test_4bytes_address, &spi_host); + } + EXECUTE_TEST(result, test_fast_read, &spi_host); + EXECUTE_TEST(result, test_dual_read, &spi_host); + EXECUTE_TEST(result, test_quad_read, &spi_host); + EXECUTE_TEST(result, test_page_program_quad, &spi_host, + kPageQuadProgramOpcode, kPageQuadProgramAddrWidth); + EXECUTE_TEST(result, test_erase_32k_block, &spi_host); + EXECUTE_TEST(result, test_erase_64k_block, &spi_host); + + return status_ok(result); +}