From b7e5138eb4dc7f933eb4e8ba28e59983e421b7d2 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 11:00:46 +0000 Subject: [PATCH 01/10] [sw] Fix inline error when build optimized with O1 Signed-off-by: Douglas Reis --- sw/device/tests/axi_sram/smoketest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sw/device/tests/axi_sram/smoketest.c b/sw/device/tests/axi_sram/smoketest.c index cac2698f0..fc3b04bf8 100644 --- a/sw/device/tests/axi_sram/smoketest.c +++ b/sw/device/tests/axi_sram/smoketest.c @@ -5,7 +5,7 @@ #include #include -bool rapid_write_test() +static bool rapid_write_test() { uint64_t d1 = 0xB03747F359ABBCFEUL, res1; uint64_t d2 = 0x0A197F0071E028A1UL, res2; From f20411a9d883608cad76270add98b9fe3471e237 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 11:01:44 +0000 Subject: [PATCH 02/10] [sw,uart] Add functions to read the status register Signed-off-by: Douglas Reis --- sw/device/lib/hal/uart.c | 10 ++++++++++ sw/device/lib/hal/uart.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/sw/device/lib/hal/uart.c b/sw/device/lib/hal/uart.c index a9895df26..c392bd183 100644 --- a/sw/device/lib/hal/uart.c +++ b/sw/device/lib/hal/uart.c @@ -60,6 +60,16 @@ bool uart_interrupt_any_pending(uart_t uart, uart_intr intrs) return (VOLATILE_READ(uart->intr_state) & intrs) != 0u; } +bool uart_status_any(uart_t uart, uart_status status) +{ + return (VOLATILE_READ(uart->status) & status) != 0u; +} + +bool uart_status_all(uart_t uart, uart_status status) +{ + return (VOLATILE_READ(uart->status) & status) == status; +} + void uart_loopback_set(uart_t uart, bool system_enable, bool line_enable) { uart_ctrl ctrl = VOLATILE_READ(uart->ctrl); diff --git a/sw/device/lib/hal/uart.h b/sw/device/lib/hal/uart.h index b71433110..84fcfa612 100644 --- a/sw/device/lib/hal/uart.h +++ b/sw/device/lib/hal/uart.h @@ -22,6 +22,8 @@ void uart_interrupt_force(uart_t uart, uart_intr intrs); void uart_interrupt_clear(uart_t uart, uart_intr intrs); bool uart_interrupt_all_pending(uart_t uart, uart_intr intrs); bool uart_interrupt_any_pending(uart_t uart, uart_intr intrs); +bool uart_status_any(uart_t uart, uart_status status); +bool uart_status_all(uart_t uart, uart_status status); void uart_loopback_set(uart_t uart, bool system_enable, bool line_enable); char uart_in(uart_t uart); From 0d451c00ba5f43254981d511c514f00f9f5c38b4 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 11:03:16 +0000 Subject: [PATCH 03/10] [sw, test_framework] Flush the uart before and after the test This makes sure that bootrom logs don't interfer with tests. Also make sure that test logs are printed before the simulation is finished. Signed-off-by: Douglas Reis --- sw/device/lib/test_framework/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sw/device/lib/test_framework/main.c b/sw/device/lib/test_framework/main.c index b7167b2d5..0a8b4f6de 100644 --- a/sw/device/lib/test_framework/main.c +++ b/sw/device/lib/test_framework/main.c @@ -78,9 +78,15 @@ test_exception_handler(struct trap_registers *registers, struct trap_context *co void *dv_test_status = mocha_system_dv_test_status(); uart_init(console); + //Flush the uart + while (!uart_status_any(console, uart_status_txidle)) { + }; DEV_WRITE(dv_test_status, TEST_STATUS_IN_TEST); bool result = test_main(console); + //Flush the uart + while (!uart_status_any(console, uart_status_txidle)) { + }; test_exit(result); } From 313da1815bc45b410b31b8a190a6a0bbf14b20cb Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 11:05:06 +0000 Subject: [PATCH 04/10] [sw,uart] Refactor smoketest The test was sensitive to timing, when optimization was enabled it would fails as the loop back transmission would not have finished in time for checking. Signed-off-by: Douglas Reis --- sw/device/tests/uart/smoketest.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/sw/device/tests/uart/smoketest.c b/sw/device/tests/uart/smoketest.c index b05b2cf18..241ad3b8a 100644 --- a/sw/device/tests/uart/smoketest.c +++ b/sw/device/tests/uart/smoketest.c @@ -3,26 +3,38 @@ // SPDX-License-Identifier: Apache-2.0 #include "hal/uart.h" +#include "runtime/print.h" #include #include -const char uart_loopback_test_string[] = "Test String"; +const static char uart_loopback_test_string[] = "Test String"; static bool loopback_test(uart_t uart) { + // Flush the uart + while (!uart_status_any(uart, uart_status_txidle)) { + }; + uart_loopback_set(uart, true, true); for (uint32_t idx = 0; idx < sizeof(uart_loopback_test_string); idx++) { uart_out(uart, uart_loopback_test_string[idx]); } + // Wait for the transmission to finish + while (!uart_status_any(uart, uart_status_txidle)) { + }; + uart_loopback_set(uart, false, false); bool res = true; for (uint32_t idx = 0; idx < sizeof(uart_loopback_test_string); idx++) { - if (uart_in(uart) != uart_loopback_test_string[idx]) { + while (uart_status_any(uart, uart_status_rxempty)) { + }; + char rx = uart_in(uart); + if (rx != uart_loopback_test_string[idx]) { + uprintf(uart, "Expected: %c, got: %c\n", rx, uart_loopback_test_string[idx]); res = false; break; } } - uart_loopback_set(uart, false, false); return res; } From 926cdf3a25469fdd5b8f7c990531c482d9a51b95 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 11:20:24 +0000 Subject: [PATCH 05/10] [sw, spi_host] Add functions to read the status register Signed-off-by: Douglas Reis --- sw/device/lib/hal/spi_host.c | 11 +++++++++++ sw/device/lib/hal/spi_host.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/sw/device/lib/hal/spi_host.c b/sw/device/lib/hal/spi_host.c index 4ca1b8a28..560ad3952 100644 --- a/sw/device/lib/hal/spi_host.c +++ b/sw/device/lib/hal/spi_host.c @@ -25,3 +25,14 @@ uint32_t spi_host_read(spi_host_t spi_host) { return DEV_READ(spi_host + SPI_HOST_RXDATA_REG); } + +uint32_t spi_host_status(spi_host_t spi_host) +{ + return DEV_READ(spi_host + SPI_HOST_STATUS_REG); +} + +void spi_host_wait_for_idle(spi_host_t spi_host) +{ + while ((spi_host_status(spi_host) & SPI_HOST_STATUS_ACTIVE_MASK) != 0) { + }; +} diff --git a/sw/device/lib/hal/spi_host.h b/sw/device/lib/hal/spi_host.h index 5c806e5a0..aed807066 100644 --- a/sw/device/lib/hal/spi_host.h +++ b/sw/device/lib/hal/spi_host.h @@ -15,6 +15,7 @@ #define SPI_HOST_CONTROL_SPIEN_MASK (1u << 31) #define SPI_HOST_CONTROL_OUTPUTEN_MASK (1u << 29) #define SPI_HOST_STATUS_REG (0x14) +#define SPI_HOST_STATUS_ACTIVE_MASK (1u << 30) #define SPI_HOST_CONFIGOPTS_REG (0x18) #define SPI_HOST_CSID_REG (0x1C) #define SPI_HOST_COMMAND_REG (0x20) @@ -32,3 +33,5 @@ typedef void *spi_host_t; void spi_host_init(spi_host_t spi_host); void spi_host_write(spi_host_t spi_host, uint32_t data); uint32_t spi_host_read(spi_host_t spi_host); +uint32_t spi_host_status(spi_host_t spi_host); +void spi_host_wait_for_idle(spi_host_t spi_host); From 70d1d62d7c6a48f41825c24bcdc659c04b9fe976 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 11:21:21 +0000 Subject: [PATCH 06/10] [sw, spi_host] Fix timing error in smoketest The error manifest when optimization is enabled Signed-off-by: Douglas Reis --- sw/device/tests/spi_host/smoketest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sw/device/tests/spi_host/smoketest.c b/sw/device/tests/spi_host/smoketest.c index 658f22cdf..46ef6b0c2 100644 --- a/sw/device/tests/spi_host/smoketest.c +++ b/sw/device/tests/spi_host/smoketest.c @@ -16,6 +16,7 @@ bool test_main() spi_host = mocha_system_spi_host(); spi_host_init(spi_host); spi_host_write(spi_host, tx_data); + spi_host_wait_for_idle(spi_host); rx_data = spi_host_read(spi_host); return tx_data == rx_data; } From 06348c5f3b73d6f9911039cdcbef16f0524d3461 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 11:22:38 +0000 Subject: [PATCH 07/10] [sw, cmake] Enable optimization O1 This makes binaries smaller and faster to run tests Signed-off-by: Douglas Reis --- sw/cheri_toolchain.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sw/cheri_toolchain.cmake b/sw/cheri_toolchain.cmake index e084f1140..5d6df67f8 100644 --- a/sw/cheri_toolchain.cmake +++ b/sw/cheri_toolchain.cmake @@ -32,14 +32,14 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(LDS_DIR "${CMAKE_SOURCE_DIR}/device/lib/boot") string(CONCAT CMAKE_CXX_FLAGS_INIT - "-std=c++20 -O0 -g" + "-std=c++20 -O1 -g" " -ffreestanding -static" " -fno-builtin -fno-exceptions -fno-c++-static-destructors -fno-rtti" " -Wall -Wextra" ) string(CONCAT CMAKE_C_FLAGS_INIT - "-std=c99 -O0 -g" + "-std=c99 -O1 -g" " -ffreestanding -static" " -fno-builtin" " -Wall -Wextra" From 8e04cde2a5f401fc9c4ffe42e1ca0238d3969758 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 14:08:33 +0000 Subject: [PATCH 08/10] [rdlgenerator] Add none member to bitmask enums Signed-off-by: Douglas Reis --- sw/device/lib/hal/autogen/clkmgr.h | 3 +++ sw/device/lib/hal/autogen/entropy_src.h | 2 ++ sw/device/lib/hal/autogen/i2c.h | 6 ++++++ sw/device/lib/hal/autogen/kmac.h | 2 ++ sw/device/lib/hal/autogen/rom_ctrl.h | 1 + sw/device/lib/hal/autogen/rstmgr.h | 2 ++ sw/device/lib/hal/autogen/spi_device.h | 4 ++++ sw/device/lib/hal/autogen/uart.h | 3 +++ util/rdlgenerator.py | 4 ++-- 9 files changed, 25 insertions(+), 2 deletions(-) diff --git a/sw/device/lib/hal/autogen/clkmgr.h b/sw/device/lib/hal/autogen/clkmgr.h index 10c6630f5..65e5f03aa 100644 --- a/sw/device/lib/hal/autogen/clkmgr.h +++ b/sw/device/lib/hal/autogen/clkmgr.h @@ -9,6 +9,7 @@ #include typedef enum [[clang::flag_enum]] clkmgr_alert_test : uint32_t { + clkmgr_alert_test_none = 0, clkmgr_alert_test_recov_fault = (1u << 0), clkmgr_alert_test_fatal_fault = (1u << 1), } clkmgr_alert_test; @@ -66,6 +67,7 @@ typedef struct [[gnu::aligned(4)]] { } clkmgr_main_meas_ctrl_shadowed; typedef enum [[clang::flag_enum]] clkmgr_recov_err_code : uint32_t { + clkmgr_recov_err_code_none = 0, clkmgr_recov_err_code_shadow_update_err = (1u << 0), clkmgr_recov_err_code_io_measure_err = (1u << 1), clkmgr_recov_err_code_main_measure_err = (1u << 2), @@ -74,6 +76,7 @@ typedef enum [[clang::flag_enum]] clkmgr_recov_err_code : uint32_t { } clkmgr_recov_err_code; typedef enum [[clang::flag_enum]] clkmgr_fatal_err_code : uint32_t { + clkmgr_fatal_err_code_none = 0, clkmgr_fatal_err_code_reg_intg = (1u << 0), clkmgr_fatal_err_code_idle_cnt = (1u << 1), clkmgr_fatal_err_code_shadow_storage_err = (1u << 2), diff --git a/sw/device/lib/hal/autogen/entropy_src.h b/sw/device/lib/hal/autogen/entropy_src.h index c41b4ce64..c6e931f52 100644 --- a/sw/device/lib/hal/autogen/entropy_src.h +++ b/sw/device/lib/hal/autogen/entropy_src.h @@ -9,6 +9,7 @@ #include typedef enum [[clang::flag_enum]] entropy_src_intr : uint32_t { + entropy_src_intr_none = 0, entropy_src_intr_es_entropy_valid = (1u << 0), entropy_src_intr_es_health_test_failed = (1u << 1), entropy_src_intr_es_observe_fifo_ready = (1u << 2), @@ -16,6 +17,7 @@ typedef enum [[clang::flag_enum]] entropy_src_intr : uint32_t { } entropy_src_intr; typedef enum [[clang::flag_enum]] entropy_src_alert_test : uint32_t { + entropy_src_alert_test_none = 0, entropy_src_alert_test_recov_alert = (1u << 0), entropy_src_alert_test_fatal_alert = (1u << 1), } entropy_src_alert_test; diff --git a/sw/device/lib/hal/autogen/i2c.h b/sw/device/lib/hal/autogen/i2c.h index d656dec80..c0726c909 100644 --- a/sw/device/lib/hal/autogen/i2c.h +++ b/sw/device/lib/hal/autogen/i2c.h @@ -9,6 +9,7 @@ #include typedef enum [[clang::flag_enum]] i2c_intr : uint32_t { + i2c_intr_none = 0, i2c_intr_fmt_threshold = (1u << 0), i2c_intr_rx_threshold = (1u << 1), i2c_intr_acq_threshold = (1u << 2), @@ -32,6 +33,7 @@ typedef struct [[gnu::aligned(4)]] { } i2c_alert_test; typedef enum [[clang::flag_enum]] i2c_ctrl : uint32_t { + i2c_ctrl_none = 0, i2c_ctrl_enablehost = (1u << 0), i2c_ctrl_enabletarget = (1u << 1), i2c_ctrl_llpbk = (1u << 2), @@ -42,6 +44,7 @@ typedef enum [[clang::flag_enum]] i2c_ctrl : uint32_t { } i2c_ctrl; typedef enum [[clang::flag_enum]] i2c_status : uint32_t { + i2c_status_none = 0, i2c_status_fmtfull = (1u << 0), i2c_status_rxfull = (1u << 1), i2c_status_fmtempty = (1u << 2), @@ -108,6 +111,7 @@ typedef struct [[gnu::aligned(4)]] { } i2c_target_fifo_status; typedef enum [[clang::flag_enum]] i2c_ovrd : uint32_t { + i2c_ovrd_none = 0, i2c_ovrd_txovrden = (1u << 0), i2c_ovrd_sclval = (1u << 1), i2c_ovrd_sdaval = (1u << 2), @@ -210,6 +214,7 @@ typedef struct [[gnu::aligned(4)]] { } i2c_acq_fifo_next_data; typedef enum [[clang::flag_enum]] i2c_controller_events : uint32_t { + i2c_controller_events_none = 0, i2c_controller_events_nack = (1u << 0), i2c_controller_events_unhandled_nack_timeout = (1u << 1), i2c_controller_events_bus_timeout = (1u << 2), @@ -217,6 +222,7 @@ typedef enum [[clang::flag_enum]] i2c_controller_events : uint32_t { } i2c_controller_events; typedef enum [[clang::flag_enum]] i2c_target_events : uint32_t { + i2c_target_events_none = 0, i2c_target_events_tx_pending = (1u << 0), i2c_target_events_bus_timeout = (1u << 1), i2c_target_events_arbitration_lost = (1u << 2), diff --git a/sw/device/lib/hal/autogen/kmac.h b/sw/device/lib/hal/autogen/kmac.h index ea8a212a1..0d416b254 100644 --- a/sw/device/lib/hal/autogen/kmac.h +++ b/sw/device/lib/hal/autogen/kmac.h @@ -9,12 +9,14 @@ #include typedef enum [[clang::flag_enum]] kmac_intr : uint32_t { + kmac_intr_none = 0, kmac_intr_kmac_done = (1u << 0), kmac_intr_fifo_empty = (1u << 1), kmac_intr_kmac_err = (1u << 2), } kmac_intr; typedef enum [[clang::flag_enum]] kmac_alert_test : uint32_t { + kmac_alert_test_none = 0, kmac_alert_test_recov_operation_err = (1u << 0), kmac_alert_test_fatal_fault_err = (1u << 1), } kmac_alert_test; diff --git a/sw/device/lib/hal/autogen/rom_ctrl.h b/sw/device/lib/hal/autogen/rom_ctrl.h index b475c8b0c..983347d0c 100644 --- a/sw/device/lib/hal/autogen/rom_ctrl.h +++ b/sw/device/lib/hal/autogen/rom_ctrl.h @@ -14,6 +14,7 @@ typedef struct [[gnu::aligned(4)]] { } rom_ctrl_alert_test; typedef enum [[clang::flag_enum]] rom_ctrl_fatal_alert_cause : uint32_t { + rom_ctrl_fatal_alert_cause_none = 0, rom_ctrl_fatal_alert_cause_checker_error = (1u << 0), rom_ctrl_fatal_alert_cause_integrity_error = (1u << 1), } rom_ctrl_fatal_alert_cause; diff --git a/sw/device/lib/hal/autogen/rstmgr.h b/sw/device/lib/hal/autogen/rstmgr.h index 839e699a9..63f59d1e2 100644 --- a/sw/device/lib/hal/autogen/rstmgr.h +++ b/sw/device/lib/hal/autogen/rstmgr.h @@ -9,6 +9,7 @@ #include typedef enum [[clang::flag_enum]] rstmgr_alert_test : uint32_t { + rstmgr_alert_test_none = 0, rstmgr_alert_test_fatal_fault = (1u << 0), rstmgr_alert_test_fatal_cnsty_fault = (1u << 1), } rstmgr_alert_test; @@ -71,6 +72,7 @@ typedef struct [[gnu::aligned(4)]] { } rstmgr_sw_rst_ctrl_n; typedef enum [[clang::flag_enum]] rstmgr_err_code : uint32_t { + rstmgr_err_code_none = 0, rstmgr_err_code_reg_intg_err = (1u << 0), rstmgr_err_code_reset_consistency_err = (1u << 1), rstmgr_err_code_fsm_err = (1u << 2), diff --git a/sw/device/lib/hal/autogen/spi_device.h b/sw/device/lib/hal/autogen/spi_device.h index f22b56295..a05f8366d 100644 --- a/sw/device/lib/hal/autogen/spi_device.h +++ b/sw/device/lib/hal/autogen/spi_device.h @@ -9,6 +9,7 @@ #include typedef enum [[clang::flag_enum]] spi_device_intr : uint32_t { + spi_device_intr_none = 0, spi_device_intr_upload_cmdfifo_not_empty = (1u << 0), spi_device_intr_upload_payload_not_empty = (1u << 1), spi_device_intr_upload_payload_overflow = (1u << 2), @@ -49,6 +50,7 @@ typedef struct [[gnu::aligned(4)]] { } spi_device_status; typedef enum [[clang::flag_enum]] spi_device_intercept_en : uint32_t { + spi_device_intercept_en_none = 0, spi_device_intercept_en_status = (1u << 0), spi_device_intercept_en_jedec = (1u << 1), spi_device_intercept_en_sfdp = (1u << 2), @@ -163,6 +165,7 @@ typedef struct [[gnu::aligned(4)]] { } spi_device_tpm_cap; typedef enum [[clang::flag_enum]] spi_device_tpm_cfg : uint32_t { + spi_device_tpm_cfg_none = 0, spi_device_tpm_cfg_en = (1u << 0), spi_device_tpm_cfg_tpm_mode = (1u << 1), spi_device_tpm_cfg_hw_reg_dis = (1u << 2), @@ -171,6 +174,7 @@ typedef enum [[clang::flag_enum]] spi_device_tpm_cfg : uint32_t { } spi_device_tpm_cfg; typedef enum [[clang::flag_enum]] spi_device_tpm_status : uint32_t { + spi_device_tpm_status_none = 0, spi_device_tpm_status_cmdaddr_notempty = (1u << 0), spi_device_tpm_status_wrfifo_pending = (1u << 1), spi_device_tpm_status_rdfifo_aborted = (1u << 2), diff --git a/sw/device/lib/hal/autogen/uart.h b/sw/device/lib/hal/autogen/uart.h index 93b384510..ff4417b96 100644 --- a/sw/device/lib/hal/autogen/uart.h +++ b/sw/device/lib/hal/autogen/uart.h @@ -9,6 +9,7 @@ #include typedef enum [[clang::flag_enum]] uart_intr : uint32_t { + uart_intr_none = 0, uart_intr_tx_watermark = (1u << 0), uart_intr_rx_watermark = (1u << 1), uart_intr_tx_done = (1u << 2), @@ -40,6 +41,7 @@ typedef struct [[gnu::aligned(4)]] { } uart_ctrl; typedef enum [[clang::flag_enum]] uart_status : uint32_t { + uart_status_none = 0, uart_status_txfull = (1u << 0), uart_status_rxfull = (1u << 1), uart_status_txempty = (1u << 2), @@ -74,6 +76,7 @@ typedef struct [[gnu::aligned(4)]] { } uart_fifo_status; typedef enum [[clang::flag_enum]] uart_ovrd : uint32_t { + uart_ovrd_none = 0, uart_ovrd_txen = (1u << 0), uart_ovrd_txval = (1u << 1), } uart_ovrd; diff --git a/util/rdlgenerator.py b/util/rdlgenerator.py index cb9ac8249..1a197ed98 100755 --- a/util/rdlgenerator.py +++ b/util/rdlgenerator.py @@ -269,7 +269,7 @@ def emit_register_flag_enum(device_name: str, reg: dict) -> str: """ reg_name = reg["name"].lower() fully_qualified_type_name = "_".join([device_name, reg_name]) - enum_variants = [] + enum_variants = [f"{fully_qualified_type_name}_none = 0,"] for bit, field in enumerate(fields_ascending_by_lsb(reg)): field_name = field["name"].lower() fully_qualified_field_name = "_".join([device_name, reg_name, field_name]) @@ -288,7 +288,7 @@ def emit_common_device_register_declaration( ) -> tuple[str, str]: common_name = stripped_longest_common_prefix([x["name"] for x in register_set]) fully_qualified_type_name = "_".join([device_name, common_name]) - enum_variants = [] + enum_variants = [f"{fully_qualified_type_name}_none = 0,"] for bit, field in enumerate(fields_ascending_by_lsb(register_set[0])): field_name = field["name"].lower() fully_qualified_field_name = "_".join([device_name, common_name, field_name]) From a44038ac6a94d380dd699b45cd34335a2c512436 Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 13:17:36 +0000 Subject: [PATCH 09/10] [sw, spi_device] Refactor spi_device to use the autogenerated types Signed-off-by: Douglas Reis --- sw/device/lib/hal/spi_device.c | 382 ++++++++++++------------- sw/device/lib/hal/spi_device.h | 162 +++-------- sw/device/tests/spi_device/smoketest.c | 60 ++-- 3 files changed, 245 insertions(+), 359 deletions(-) diff --git a/sw/device/lib/hal/spi_device.c b/sw/device/lib/hal/spi_device.c index 6f21cc0bb..fd8ccd279 100644 --- a/sw/device/lib/hal/spi_device.c +++ b/sw/device/lib/hal/spi_device.c @@ -8,256 +8,267 @@ #include #include -bool spi_device_interrupt_is_pending(spi_device_t spi_device, uint8_t intr_id) +bool spi_device_interrupt_any_pending(spi_device_t spi_device, spi_device_intr intrs) { - if (intr_id > SPI_DEVICE_MAX_INTR) { - return false; - } - return ((DEV_READ(spi_device + SPI_DEVICE_INTR_STATE_REG) & (1 << intr_id)) != 0); + return (VOLATILE_READ(spi_device->intr_state) & intrs) != 0u; } -void spi_device_interrupt_clear(spi_device_t spi_device, uint8_t intr_id) +void spi_device_interrupt_clear(spi_device_t spi_device, spi_device_intr intrs) { - if (intr_id <= SPI_DEVICE_MAX_INTR) { - DEV_WRITE(spi_device + SPI_DEVICE_INTR_STATE_REG, 1 << intr_id); - } + VOLATILE_WRITE(spi_device->intr_state, intrs); } -void spi_device_interrupt_disable_all(spi_device_t spi_device) +void spi_device_interrupt_enable_write(spi_device_t spi_device, spi_device_intr intrs) { - DEV_WRITE(spi_device + SPI_DEVICE_INTR_ENABLE_REG, 0); + VOLATILE_WRITE(spi_device->intr_enable, intrs); } -void spi_device_interrupt_enable(spi_device_t spi_device, uint8_t intr_id) +void spi_device_interrupt_enable_set(spi_device_t spi_device, spi_device_intr intrs) { - if (intr_id <= SPI_DEVICE_MAX_INTR) { - DEV_WRITE(spi_device + SPI_DEVICE_INTR_ENABLE_REG, - DEV_READ(spi_device + SPI_DEVICE_INTR_ENABLE_REG) | (1 << intr_id)); - } + spi_device_intr intr_enable = VOLATILE_READ(spi_device->intr_enable); + intr_enable |= intrs; + VOLATILE_WRITE(spi_device->intr_enable, intr_enable); } -void spi_device_interrupt_disable(spi_device_t spi_device, uint8_t intr_id) +void spi_device_interrupt_enable_clear(spi_device_t spi_device, spi_device_intr intrs) { - if (intr_id <= SPI_DEVICE_MAX_INTR) { - DEV_WRITE(spi_device + SPI_DEVICE_INTR_ENABLE_REG, - DEV_READ(spi_device + SPI_DEVICE_INTR_ENABLE_REG) & ~(1 << intr_id)); - } + spi_device_intr intr_enable = VOLATILE_READ(spi_device->intr_enable); + intr_enable &= ~intrs; + VOLATILE_WRITE(spi_device->intr_enable, intr_enable); } -void spi_device_interrupt_trigger(spi_device_t spi_device, uint8_t intr_id) +void spi_device_interrupt_force(spi_device_t spi_device, spi_device_intr intrs) { - if (intr_id <= SPI_DEVICE_MAX_INTR) { - DEV_WRITE(spi_device + SPI_DEVICE_INTR_TEST_REG, 1 << intr_id); - } + VOLATILE_WRITE(spi_device->intr_test, intrs); } void spi_device_enable_set(spi_device_t spi_device, bool enable) { - DEV_WRITE(spi_device + SPI_DEVICE_CTRL_REG, enable << SPI_DEVICE_CTRL_MODE_OFFSET); + spi_device_control ctrl = { .mode = enable ? 1u : 0u }; + VOLATILE_WRITE(spi_device->control, ctrl); } void spi_device_4b_addr_mode_enable_set(spi_device_t spi_device, bool enable) { - DEV_WRITE(spi_device + SPI_DEVICE_ADDR_MODE_REG, (uint32_t)enable); + spi_device_addr_mode addr_mode = { .addr_4b_en = enable }; + VOLATILE_WRITE(spi_device->addr_mode, addr_mode); // Wait for change to take effect - while (DEV_READ(spi_device + SPI_DEVICE_ADDR_MODE_REG) & SPI_DEVICE_ADDR_MODE_PENDING_MASK) { + while (VOLATILE_READ(spi_device->addr_mode).pending) { } } bool spi_device_4b_addr_mode_enable_get(spi_device_t spi_device) { - return ((DEV_READ(spi_device + SPI_DEVICE_ADDR_MODE_REG) & SPI_DEVICE_ADDR_MODE_4B_EN_MASK) == - 1); + return VOLATILE_READ(spi_device->addr_mode).addr_4b_en; } void spi_device_flash_status_set(spi_device_t spi_device, uint32_t flash_status) { - DEV_WRITE(spi_device + SPI_DEVICE_FLASH_STATUS_REG, flash_status); + spi_device_flash_status s; + __builtin_memcpy(&s, &flash_status, sizeof(s)); + VOLATILE_WRITE(spi_device->flash_status, s); } uint32_t spi_device_flash_status_get(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_FLASH_STATUS_REG); + spi_device_flash_status s = VOLATILE_READ(spi_device->flash_status); + uint32_t raw; + __builtin_memcpy(&raw, &s, sizeof(raw)); + return raw; } void spi_device_jedec_cc_set(spi_device_t spi_device, uint8_t cc, uint8_t num_cc) { - DEV_WRITE(spi_device + SPI_DEVICE_JEDEC_CC_REG, - ((uint32_t)cc << SPI_DEVICE_JEDEC_CC) | - ((uint32_t)num_cc << SPI_DEVICE_JEDEC_NUM_CC)); + spi_device_jedec_cc jedec_cc = { .cc = cc, .num_cc = num_cc }; + VOLATILE_WRITE(spi_device->jedec_cc, jedec_cc); } uint16_t spi_device_jedec_cc_get(spi_device_t spi_device) { - return (uint16_t)DEV_READ(spi_device + SPI_DEVICE_JEDEC_CC_REG); + spi_device_jedec_cc jedec_cc = VOLATILE_READ(spi_device->jedec_cc); + return (uint16_t)(jedec_cc.cc | ((uint16_t)jedec_cc.num_cc << 8)); } void spi_device_jedec_id_set_raw(spi_device_t spi_device, uint32_t data) { - DEV_WRITE(spi_device + SPI_DEVICE_JEDEC_ID_REG, data); + spi_device_jedec_id jedec_id; + __builtin_memcpy(&jedec_id, &data, sizeof(jedec_id)); + VOLATILE_WRITE(spi_device->jedec_id, jedec_id); } void spi_device_jedec_id_set(spi_device_t spi_device, bool rom_bootstrap, uint8_t chip_rev, uint8_t chip_gen, uint8_t density, uint8_t manufacturer_id) { - uint32_t reg = ((uint32_t)rom_bootstrap) << SPI_DEVICE_ROM_BOOTSTRAP; - reg = reg | (((uint32_t)chip_rev & SPI_DEVICE_CHIP_REV_MASK) << SPI_DEVICE_CHIP_REV); - reg = reg | (((uint32_t)chip_gen & SPI_DEVICE_CHIP_GEN_MASK) << SPI_DEVICE_CHIP_GEN); - reg = reg | (((uint32_t)density) << SPI_DEVICE_DENSITY); - reg = reg | (((uint32_t)manufacturer_id) << SPI_DEVICE_MANUFACTURER_ID); - spi_device_jedec_id_set_raw(spi_device, reg); + uint16_t id = (uint16_t)((chip_rev & 0x7u) | ((uint16_t)rom_bootstrap << 3) | + ((uint16_t)(chip_gen & 0xFu) << 4) | ((uint16_t)density << 8)); + spi_device_jedec_id jedec_id = { .id = id, .mf = manufacturer_id }; + VOLATILE_WRITE(spi_device->jedec_id, jedec_id); } uint32_t spi_device_jedec_id_get(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_JEDEC_ID_REG); + spi_device_jedec_id jedec_id = VOLATILE_READ(spi_device->jedec_id); + uint32_t raw; + __builtin_memcpy(&raw, &jedec_id, sizeof(raw)); + return raw; } void spi_device_mailbox_addr_set(spi_device_t spi_device, uint32_t addr) { - DEV_WRITE(spi_device + SPI_DEVICE_MAILBOX_ADDR_REG, addr); + VOLATILE_WRITE(spi_device->mailbox_addr, addr); } uint32_t spi_device_mailbox_addr_get(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_MAILBOX_ADDR_REG); + return VOLATILE_READ(spi_device->mailbox_addr); } uint32_t spi_device_upload_status_get(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_UPLOAD_STATUS_REG); + spi_device_upload_status s = VOLATILE_READ(spi_device->upload_status); + uint32_t raw; + __builtin_memcpy(&raw, &s, sizeof(raw)); + return raw; } uint32_t spi_device_upload_status2_get(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_UPLOAD_STATUS2_REG); + spi_device_upload_status2 s = VOLATILE_READ(spi_device->upload_status2); + uint32_t raw; + __builtin_memcpy(&raw, &s, sizeof(raw)); + return raw; } uint32_t spi_device_upload_cmdfifo_read(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_UPLOAD_CMDFIFO_REG); + spi_device_upload_cmdfifo s = VOLATILE_READ(spi_device->upload_cmdfifo); + uint32_t raw; + __builtin_memcpy(&raw, &s, sizeof(raw)); + return raw; } uint32_t spi_device_upload_addrfifo_read(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_UPLOAD_ADDRFIFO_REG); + return VOLATILE_READ(spi_device->upload_addrfifo); } -void spi_device_cmd_filter_set(spi_device_t spi_device, uint32_t offset, uint32_t data) +void spi_device_cmd_filter_set(spi_device_t spi_device, uint8_t idx, uint32_t data) { - if (offset < SPI_DEVICE_CMD_FILTER_0_REG || offset > SPI_DEVICE_CMD_FILTER_7_REG) { + if (idx >= 8) { return; } - - DEV_WRITE(spi_device + offset, data); + VOLATILE_WRITE(spi_device->cmd_filter[idx], data); } -uint32_t spi_device_cmd_filter_get(spi_device_t spi_device, uint32_t offset) +uint32_t spi_device_cmd_filter_get(spi_device_t spi_device, uint8_t idx) { - if (offset < SPI_DEVICE_CMD_FILTER_0_REG || offset > SPI_DEVICE_CMD_FILTER_7_REG) { + if (idx >= 8) { return 0; } - - return DEV_READ(spi_device + offset); + return VOLATILE_READ(spi_device->cmd_filter[idx]); } -void spi_device_cmd_info_set_raw(spi_device_t spi_device, uint32_t offset, uint32_t data) +void spi_device_cmd_info_set_raw(spi_device_t spi_device, uint8_t idx, uint32_t data) { - if (offset < SPI_DEVICE_CMD_INFO_0_REG || offset > SPI_DEVICE_CMD_INFO_23_REG) { + if (idx >= 24) { return; } - - DEV_WRITE(spi_device + offset, data); + spi_device_cmd_info cmd_info; + __builtin_memcpy(&cmd_info, &data, sizeof(cmd_info)); + VOLATILE_WRITE(spi_device->cmd_info[idx], cmd_info); } -void spi_device_cmd_info_set(spi_device_t spi_device, uint32_t offset, uint8_t opcode, +void spi_device_cmd_info_set(spi_device_t spi_device, uint8_t idx, uint8_t opcode, uint8_t addr_mode, uint8_t dummy_cycles, bool handled_in_sw) { - if (offset < SPI_DEVICE_CMD_INFO_0_REG || offset > SPI_DEVICE_CMD_INFO_23_REG) { + if (idx >= 24) { return; } - uint32_t reg = 0; - reg = reg | (opcode << SPI_DEVICE_CMD_OPCODE); - - reg = reg | ((addr_mode & SPI_DEVICE_CMD_ADDR_MODE_MASK) << SPI_DEVICE_CMD_ADDR_MODE); + spi_device_cmd_info cmd_info = { 0 }; + cmd_info.opcode = opcode; + cmd_info.addr_mode = addr_mode; if (dummy_cycles > 0) { - reg = reg | - (((dummy_cycles - 1) & SPI_DEVICE_CMD_DUMMY_SIZE_MASK) << SPI_DEVICE_CMD_DUMMY_SIZE); - reg = reg | (1 << SPI_DEVICE_CMD_DUMMY_EN); + cmd_info.dummy_size = dummy_cycles - 1; + cmd_info.dummy_en = 1; } if (handled_in_sw) { - reg = reg | (1 << SPI_DEVICE_CMD_UPLOAD); - reg = reg | (1 << SPI_DEVICE_CMD_BUSY); + cmd_info.upload = 1; + cmd_info.busy = 1; } - reg = reg | (1 << SPI_DEVICE_CMD_VALID); + cmd_info.valid = 1; - spi_device_cmd_info_set_raw(spi_device, offset, reg); + VOLATILE_WRITE(spi_device->cmd_info[idx], cmd_info); } -uint32_t spi_device_cmd_info_get(spi_device_t spi_device, uint32_t offset) +uint32_t spi_device_cmd_info_get(spi_device_t spi_device, uint8_t idx) { - if (offset < SPI_DEVICE_CMD_INFO_0_REG || offset > SPI_DEVICE_CMD_INFO_23_REG) { + if (idx >= 24) { return 0; } - - return DEV_READ(spi_device + offset); + spi_device_cmd_info cmd_info = VOLATILE_READ(spi_device->cmd_info[idx]); + uint32_t raw; + __builtin_memcpy(&raw, &cmd_info, sizeof(raw)); + return raw; } void spi_device_cmd_info_4b_enable_set_raw(spi_device_t spi_device, uint32_t data) { - DEV_WRITE(spi_device + SPI_DEVICE_CMD_INFO_EN4B_REG, data); + spi_device_cmd_info_en4b en4b; + __builtin_memcpy(&en4b, &data, sizeof(en4b)); + VOLATILE_WRITE(spi_device->cmd_info_en4b, en4b); } void spi_device_cmd_info_4b_enable_set(spi_device_t spi_device, uint8_t opcode) { - uint32_t reg = 0; - reg = reg | (opcode << SPI_DEVICE_CMD_OPCODE); - reg = reg | (1 << SPI_DEVICE_CMD_VALID); - - spi_device_cmd_info_4b_enable_set_raw(spi_device, reg); + spi_device_cmd_info_en4b en4b = { .opcode = opcode, .valid = 1 }; + VOLATILE_WRITE(spi_device->cmd_info_en4b, en4b); } void spi_device_cmd_info_write_enable_set_raw(spi_device_t spi_device, uint32_t data) { - DEV_WRITE(spi_device + SPI_DEVICE_CMD_INFO_WREN_REG, data); + spi_device_cmd_info_wren wren; + __builtin_memcpy(&wren, &data, sizeof(wren)); + VOLATILE_WRITE(spi_device->cmd_info_wren, wren); } void spi_device_cmd_info_write_enable_set(spi_device_t spi_device, uint8_t opcode) { - uint32_t reg = 0; - reg = reg | (opcode << SPI_DEVICE_CMD_OPCODE); - reg = reg | (1 << SPI_DEVICE_CMD_VALID); - - spi_device_cmd_info_write_enable_set_raw(spi_device, reg); + spi_device_cmd_info_wren wren = { .opcode = opcode, .valid = 1 }; + VOLATILE_WRITE(spi_device->cmd_info_wren, wren); } uint32_t spi_device_cmd_info_write_enable_get(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_CMD_INFO_WREN_REG); + spi_device_cmd_info_wren wren = VOLATILE_READ(spi_device->cmd_info_wren); + uint32_t raw; + __builtin_memcpy(&raw, &wren, sizeof(raw)); + return raw; } void spi_device_cmd_info_write_disable_set_raw(spi_device_t spi_device, uint32_t data) { - DEV_WRITE(spi_device + SPI_DEVICE_CMD_INFO_WRDI_REG, data); + spi_device_cmd_info_wrdi wrdi; + __builtin_memcpy(&wrdi, &data, sizeof(wrdi)); + VOLATILE_WRITE(spi_device->cmd_info_wrdi, wrdi); } void spi_device_cmd_info_write_disable_set(spi_device_t spi_device, uint8_t opcode) { - uint32_t reg = 0; - reg = reg | (opcode << SPI_DEVICE_CMD_OPCODE); - reg = reg | (1 << SPI_DEVICE_CMD_VALID); - - spi_device_cmd_info_write_disable_set_raw(spi_device, reg); + spi_device_cmd_info_wrdi wrdi = { .opcode = opcode, .valid = 1 }; + VOLATILE_WRITE(spi_device->cmd_info_wrdi, wrdi); } uint32_t spi_device_cmd_info_write_disable_get(spi_device_t spi_device) { - return DEV_READ(spi_device + SPI_DEVICE_CMD_INFO_WRDI_REG); + spi_device_cmd_info_wrdi wrdi = VOLATILE_READ(spi_device->cmd_info_wrdi); + uint32_t raw; + __builtin_memcpy(&raw, &wrdi, sizeof(raw)); + return raw; } bool spi_device_flash_read_buffer_write(spi_device_t spi_device, uint32_t offset, uint32_t data) @@ -270,8 +281,7 @@ bool spi_device_flash_read_buffer_write(spi_device_t spi_device, uint32_t offset if (offset >= SPI_DEVICE_READ_BUFFER_NUM_BYTES) { return false; } - DEV_WRITE(spi_device + SPI_DEVICE_EGRESS_BUFFER_OFFSET + SPI_DEVICE_READ_BUFFER_OFFSET + offset, - data); + spi_device->egress_buffer[offset / sizeof(uint32_t)] = data; return true; } @@ -285,53 +295,50 @@ uint32_t spi_device_flash_payload_buffer_read(spi_device_t spi_device, uint32_t if (offset >= SPI_DEVICE_PAYLOAD_AREA_NUM_BYTES) { return 0; } - return DEV_READ( - spi_device + SPI_DEVICE_INGRESS_BUFFER_OFFSET + SPI_DEVICE_PAYLOAD_AREA_OFFSET + offset); + return spi_device->ingress_buffer[offset / sizeof(uint32_t)]; } void spi_device_sfdp_table_init(spi_device_t spi_device) { // Prepare pointer to SFDP area in egress buffer - void *buf_ptr = spi_device + SPI_DEVICE_EGRESS_BUFFER_OFFSET + SPI_DEVICE_SFDP_AREA_OFFSET; + volatile uint32_t *buf_ptr = + &spi_device->egress_buffer[SPI_DEVICE_SFDP_AREA_OFFSET / sizeof(uint32_t)]; + volatile uint32_t *const buf_end = buf_ptr + SPI_DEVICE_SFDP_AREA_NUM_BYTES / sizeof(uint32_t); // clang-format off // Write SFDP header 1st word // [31: 0]: SFDP signature that indicates the presence of a SFDP table (JESD216F 6.2.1) - DEV_WRITE(buf_ptr, SPI_DEVICE_SFDP_SIGNATURE); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = SPI_DEVICE_SFDP_SIGNATURE; // Write SFDP header 2nd word // [ 7: 0]: SFDP minor revision number (JESD216F 6.2.2) // [15: 8]: SFDP major revision number (JESD216F 6.2.2) // [23:16]: Number of parameter headers, zero-based (JESD216F 6.2.2) // [31:24]: SFDP access protocol (JESD216F 6.2.3) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field( 7, 0, SPI_DEVICE_SFDP_MINOR_REVISION) | reg32_field(15, 8, SPI_DEVICE_SFDP_MAJOR_REVISION) | reg32_field(23, 16, SPI_DEVICE_SFDP_PARAM_COUNT) | - reg32_field(31, 24, SPI_DEVICE_SFDP_ACCESS_PROTOCOL)); - buf_ptr += sizeof(uint32_t); + reg32_field(31, 24, SPI_DEVICE_SFDP_ACCESS_PROTOCOL); // Write Basic Flash Parameters Table (BFPT) parameter header 1st word // [ 7: 0]: LSB of the parameter ID that indicates parameter table ownership and type (JESD216F 6.3.1, 6.3.3) // [15: 8]: Parameter table minor revision number (JESD216F 6.3.1) // [23:16]: Parameter table major revision number (JESD216F 6.3.1) // [31:24]: Length of the parameter table in words, one-based (JESD216F 6.3.1) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field( 7, 0, SPI_DEVICE_BFPT_PARAM_ID_LSB) | reg32_field(15, 8, SPI_DEVICE_BFPT_MINOR_REVISION) | reg32_field(23, 16, SPI_DEVICE_BFPT_MAJOR_REVISION) | - reg32_field(31, 24, SPI_DEVICE_BFPT_NUM_WORDS)); - buf_ptr += sizeof(uint32_t); + reg32_field(31, 24, SPI_DEVICE_BFPT_NUM_WORDS); // Write BFPT parameter header 2nd word // [23: 0]: Word-aligned byte offset of the corresponding parameter table from the start of the SFDP table (JESD216F 6.3.2) // [31:24]: MSB of the parameter ID that indicates parameter table ownership and type (JESD216F 6.3.2, 6.3.3) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(23, 0, 4) | - reg32_field(31, 24, SPI_DEVICE_BFPT_PARAM_ID_MSB)); - buf_ptr += sizeof(uint32_t); + reg32_field(31, 24, SPI_DEVICE_BFPT_PARAM_ID_MSB); // Note: Words below are numbered starting from 1 to match JESD216F. Some fields // that are not supported by OpenTitan are merged for the sake of conciseness. @@ -347,7 +354,7 @@ void spi_device_sfdp_table_init(spi_device_t spi_device) // [ 3: 3]: Volatile block protect bits (solely volatile: 0x1) // [ 2: 2]: Write granularity (buffer >= 64 B: 0x1) // [ 1: 0]: Block/sector erase sizes (uniform 4 KiB erase: 0x1) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 23, UINT32_MAX) | reg32_field(22, 19, 0) | reg32_field(18, 17, 0x0) | @@ -357,69 +364,60 @@ void spi_device_sfdp_table_init(spi_device_t spi_device) reg32_field( 4, 4, 0x1) | reg32_field( 3, 3, 0x1) | reg32_field( 2, 2, 0x1) | - reg32_field( 1, 0, 0x1)); - buf_ptr += sizeof(uint32_t); + reg32_field( 1, 0, 0x1); // Write BFPT 2nd Word // [31:31]: Density greater than 2 Gib (0x0) // [30: 0]: Flash memory density in bits, zero-based (0x7fffff) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 31, 0x0) | - reg32_field(30, 0, MOCHA_SPI_DEVICE_DENSITY_BITS - 1)); - buf_ptr += sizeof(uint32_t); + reg32_field(30, 0, MOCHA_SPI_DEVICE_DENSITY_BITS - 1); // Write BFPT 3rd Word // [31: 0]: Fast read (1S-4S-4S) (1S-1S-4S) (not supported, 0x0) - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 4th Word // [31: 0]: Fast read (1S-1S-2S) (1S-2S-2S) (not supported, 0x0) - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 5th Word // [31: 5]: Reserved (all 1s) // [ 4: 4]: Fast read (4S-4S-4S) support (not supported, 0x0) // [ 3: 1]: Reserved (all 1s) // [ 0: 0]: Fast read (2S-2S-2S) support (not supported, 0x0) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 5, UINT32_MAX) | reg32_field( 4, 4, 0x0) | reg32_field( 3, 1, UINT32_MAX) | - reg32_field( 0, 0, 0x0)); - buf_ptr += sizeof(uint32_t); + reg32_field( 0, 0, 0x0); // Write BFPT 6th Word // [31:16]: Fast read (2S-2S-2S) (not supported, 0x0) // [15: 0]: Reserved (all 1s) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 16, 0x0) | - reg32_field(15, 0, UINT32_MAX)); - buf_ptr += sizeof(uint32_t); + reg32_field(15, 0, UINT32_MAX); // Write BFPT 7th Word // [31:16]: Fast read (4S-4S-4S) (not supported, 0x0) // [15: 0]: Reserved (all 1s) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 16, 0x0) | - reg32_field(15, 0, UINT32_MAX)); - buf_ptr += sizeof(uint32_t); + reg32_field(15, 0, UINT32_MAX); // Write BFPT 8th Word // [31:16]: Erase type 2 instruction and size (not supported, 0x0) // [15: 8]: Erase type 1 instruction (0x20) // [ 7: 0]: Erase type 1 size (4 KiB, 2^N bytes, N = 0x0c) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 16, 0x0) | reg32_field(15, 8, SPI_DEVICE_OPCODE_SECTOR_ERASE) | - reg32_field( 7, 0, 0x0C)); - buf_ptr += sizeof(uint32_t); + reg32_field( 7, 0, 0x0C); // Write BFPT 9th Word // [31: 0]: Erase type 4 and 3 (not supported, 0x0) - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 10th Word // [31:11]: Erase 4,3,2 typical time (not supported, 0x0) @@ -429,12 +427,11 @@ void spi_device_sfdp_table_init(spi_device_t spi_device) // (8 + 1) * 16 ms = 144 ms // [ 3: 0]: Max erase time multiplier, zero-based (0x6) // formula: 2 * (multiplier + 1) * erase_time - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 11, 0x0) | reg32_field(10, 9, 0x1) | reg32_field( 8, 4, 0x8) | - reg32_field( 3, 0, 0x6)); - buf_ptr += sizeof(uint32_t); + reg32_field( 3, 0, 0x6); // Write BFPT 11th Word // [31:31]: Reserved (all 1s) @@ -457,7 +454,7 @@ void spi_device_sfdp_table_init(spi_device_t spi_device) // [ 7: 4]: Page size, 2^N (0x8) // [ 3: 0]: Max program time multiplier, zero-based (0x0) // formula: 2 * (multiplier + 1) * program_time - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 31, UINT32_MAX) | reg32_field(30, 29, 0x0) | reg32_field(28, 24, 0xB) | @@ -468,107 +465,92 @@ void spi_device_sfdp_table_init(spi_device_t spi_device) reg32_field(13, 13, 0x1) | reg32_field(12, 8, 0xB) | reg32_field( 7, 4, 0x8) | - reg32_field( 3, 0, 0x0)); - buf_ptr += sizeof(uint32_t); + reg32_field( 3, 0, 0x0); // Write BFPT 12th Word // [31:31]: Suspend/Resume supported (not supported, 0x1) // [30: 9]: Suspend/Resume latencies for erase & program (not supported, 0x0) // [ 8: 8]: Reserved (all 1s) // [ 7: 0]: Prohibited ops during suspend (not supported, 0x0) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 31, 0x1) | reg32_field(30, 9, 0x0) | reg32_field( 8, 8, UINT32_MAX) | - reg32_field( 7, 0, 0x0)); - buf_ptr += sizeof(uint32_t); + reg32_field( 7, 0, 0x0); // Write BFPT 13th Word // [31: 0]: Erase/program suspend/resume instructions (not supported, 0x0) - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 14th Word // [31:31]: Deep powerdown support (not supported, 0x1) // [30: 8]: Deep powerdown instructions and delay (not supported, 0x0) // [ 7: 2]: Busy polling (bit 0 using 0x05 instruction, 0x1) // [ 1: 0]: Reserved (all 1s) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 31, 0x1) | reg32_field(30, 8, 0x0) | reg32_field( 7, 2, 0x1) | - reg32_field( 1, 0, UINT32_MAX)); - buf_ptr += sizeof(uint32_t); + reg32_field( 1, 0, UINT32_MAX); // Write BFPT 15th Word // [31:24]: Reserved (all 1s) // [23: 0]: Hold, QE, (4S-4S-4S), 0-4-4 (not supported, 0x0) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 24, UINT32_MAX) | - reg32_field(23, 0, 0x0)); - buf_ptr += sizeof(uint32_t); + reg32_field(23, 0, 0x0); // Write BFPT 16th Word // [31:14]: 4-Byte addressing (not supported, 0x0) // [13: 8]: Soft-reset (0x66/0x99 sequence, 0x10) // [ 7: 7]: Reserved // [ 6: 0]: Status register (read-only, 0x0) - DEV_WRITE(buf_ptr, + *buf_ptr++ = reg32_field(31, 14, 0x0) | reg32_field(13, 8, 0x10) | reg32_field( 7, 7, UINT32_MAX) | - reg32_field( 6, 0, 0x0)); - buf_ptr += sizeof(uint32_t); + reg32_field( 6, 0, 0x0); // Write BFPT 17th Word // [31: 0]: Fast read (1S-8S-8S) (1S-1S-8S) (not supported, 0x0) - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 18th Word // [31, 0]: Data strobe, SPI protocol reset, etc. (not supported, 0x0) // // Note: Reserved fields of this word should be 0 (JESD216F 6.4.21). - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 19th Word // [31, 0]: Octable enable, (8D-8D-8D), 0-8-8 mode (not suported, 0x0) // // Note: Reserved fields of this word should be 0 (JESD216F 6.4.22). - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 20th Word // [31, 0]: Max (8S-8S-8S) (4D-4D-4D) (4S-4S-4S) speed // (not supported, 0xffffffff) - DEV_WRITE(buf_ptr, UINT32_MAX); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = UINT32_MAX; // Write BFPT 21st Word // [31, 0]: Fast read support for various modes (not supported, 0x0) // // Note: Reserved fields of this word should be 0 (JESD216F 6.4.24). - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 22nd Word // [31, 0]: Fast read (1S-1D-1D) (1S-2D-2D) (not supported, 0x0) - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // Write BFPT 23rd Word // [31, 0]: Fast read (1S-4D-4D) (4S-2D-2D) (not supported, 0x0) - DEV_WRITE(buf_ptr, 0); - buf_ptr += sizeof(uint32_t); + *buf_ptr++ = 0; // clang-format on // Fill the remaining space with `0xff`s. - while (buf_ptr < spi_device + SPI_DEVICE_EGRESS_BUFFER_OFFSET + SPI_DEVICE_SFDP_AREA_OFFSET + - SPI_DEVICE_SFDP_AREA_NUM_BYTES) { - DEV_WRITE(buf_ptr, UINT32_MAX); - buf_ptr += sizeof(uint32_t); + while (buf_ptr < buf_end) { + *buf_ptr++ = UINT32_MAX; } } @@ -583,25 +565,20 @@ void spi_device_init(spi_device_t spi_device) spi_device_flash_status_set(spi_device, 0); // Configure commands - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_0_REG, SPI_DEVICE_OPCODE_READ_STATUS, 0, - 0, false); - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_3_REG, SPI_DEVICE_OPCODE_READ_JEDEC_ID, - 0, 0, false); - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_4_REG, SPI_DEVICE_OPCODE_READ_SFDP, + spi_device_cmd_info_set(spi_device, 0, SPI_DEVICE_OPCODE_READ_STATUS, 0, 0, false); + spi_device_cmd_info_set(spi_device, 3, SPI_DEVICE_OPCODE_READ_JEDEC_ID, 0, 0, false); + spi_device_cmd_info_set(spi_device, 4, SPI_DEVICE_OPCODE_READ_SFDP, SPI_DEVICE_CMD_ADDR_MODE_ADDR_3B, 8, false); - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_5_REG, SPI_DEVICE_OPCODE_READ_DATA, + spi_device_cmd_info_set(spi_device, 5, SPI_DEVICE_OPCODE_READ_DATA, SPI_DEVICE_CMD_ADDR_MODE_ADDR_3B, 0, false); - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_11_REG, SPI_DEVICE_OPCODE_CHIP_ERASE, 0, - 0, true); - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_12_REG, SPI_DEVICE_OPCODE_SECTOR_ERASE, + spi_device_cmd_info_set(spi_device, 11, SPI_DEVICE_OPCODE_CHIP_ERASE, 0, 0, true); + spi_device_cmd_info_set(spi_device, 12, SPI_DEVICE_OPCODE_SECTOR_ERASE, SPI_DEVICE_CMD_ADDR_MODE_ADDR_3B, 0, true); - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_13_REG, SPI_DEVICE_OPCODE_PAGE_PROGRAM, + spi_device_cmd_info_set(spi_device, 13, SPI_DEVICE_OPCODE_PAGE_PROGRAM, SPI_DEVICE_CMD_ADDR_MODE_ADDR_3B, 0, true); - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_14_REG, SPI_DEVICE_OPCODE_RESET, 0, 0, - true); - spi_device_cmd_info_set(spi_device, SPI_DEVICE_CMD_INFO_15_REG, - SPI_DEVICE_OPCODE_PAGE_PROGRAM4B, SPI_DEVICE_CMD_ADDR_MODE_ADDR_4B, 0, - true); + spi_device_cmd_info_set(spi_device, 14, SPI_DEVICE_OPCODE_RESET, 0, 0, true); + spi_device_cmd_info_set(spi_device, 15, SPI_DEVICE_OPCODE_PAGE_PROGRAM4B, + SPI_DEVICE_CMD_ADDR_MODE_ADDR_4B, 0, true); // Configure WRITE_ENABLE and WRITE_DISABLE commands spi_device_cmd_info_write_enable_set(spi_device, SPI_DEVICE_OPCODE_WRITE_ENABLE); spi_device_cmd_info_write_disable_set(spi_device, SPI_DEVICE_OPCODE_WRITE_DISABLE); @@ -617,43 +594,42 @@ spi_device_cmd_t spi_device_cmd_get_non_blocking(spi_device_t spi_device) .payload_byte_count = 0 }; // Check for software-handled command - if (!spi_device_interrupt_is_pending(spi_device, SPI_DEVICE_INTR_UPLOAD_CMDFIFO_NOT_EMPTY)) { + if (!spi_device_interrupt_any_pending(spi_device, spi_device_intr_upload_cmdfifo_not_empty)) { cmd.status = spi_device_status_empty; return cmd; } // Clear interrupt - spi_device_interrupt_clear(spi_device, SPI_DEVICE_INTR_UPLOAD_CMDFIFO_NOT_EMPTY); + spi_device_interrupt_clear(spi_device, spi_device_intr_upload_cmdfifo_not_empty); // Check for payload overflow - if (spi_device_interrupt_is_pending(spi_device, SPI_DEVICE_INTR_UPLOAD_PAYLOAD_OVERFLOW)) { + if (spi_device_interrupt_any_pending(spi_device, spi_device_intr_upload_payload_overflow)) { cmd.status = spi_device_status_overflow; - spi_device_interrupt_clear(spi_device, SPI_DEVICE_INTR_UPLOAD_PAYLOAD_OVERFLOW); + spi_device_interrupt_clear(spi_device, spi_device_intr_upload_payload_overflow); return cmd; } // Get opcode - cmd.opcode = (uint8_t)spi_device_upload_cmdfifo_read(spi_device); + cmd.opcode = (uint8_t)VOLATILE_READ(spi_device->upload_cmdfifo).data; // Get address - if ((spi_device_upload_status_get(spi_device) & - SPI_DEVICE_UPLOAD_STATUS_ADDRFIFO_NOTEMPTY_MASK) != 0) { - cmd.address = spi_device_upload_addrfifo_read(spi_device); + if (VOLATILE_READ(spi_device->upload_status).addrfifo_notempty) { + cmd.address = VOLATILE_READ(spi_device->upload_addrfifo); } else { // No address cmd.address = UINT32_MAX; } // Get payload size - cmd.payload_byte_count = (uint16_t)(spi_device_upload_status2_get(spi_device) & - SPI_DEVICE_UPLOAD_STATUS2_PAYLOAD_DEPTH_MASK); + cmd.payload_byte_count = (uint16_t)VOLATILE_READ(spi_device->upload_status2).payload_depth; return cmd; } spi_device_cmd_t spi_device_cmd_get(spi_device_t spi_device) { // Wait for software-handled command - while (!spi_device_interrupt_is_pending(spi_device, SPI_DEVICE_INTR_UPLOAD_CMDFIFO_NOT_EMPTY)) { + while ( + !spi_device_interrupt_any_pending(spi_device, spi_device_intr_upload_cmdfifo_not_empty)) { } return spi_device_cmd_get_non_blocking(spi_device); diff --git a/sw/device/lib/hal/spi_device.h b/sw/device/lib/hal/spi_device.h index 76e48f975..c6b85a88c 100644 --- a/sw/device/lib/hal/spi_device.h +++ b/sw/device/lib/hal/spi_device.h @@ -4,121 +4,21 @@ #pragma once -#include "hal/mmio.h" +#include "autogen/spi_device.h" #include #include -#define SPI_DEVICE_INTR_STATE_REG (0x0) -#define SPI_DEVICE_INTR_ENABLE_REG (0x4) -#define SPI_DEVICE_INTR_TEST_REG (0x8) -#define SPI_DEVICE_INTR_UPLOAD_CMDFIFO_NOT_EMPTY (0) -#define SPI_DEVICE_INTR_UPLOAD_PAYLOAD_NOT_EMPTY (1) -#define SPI_DEVICE_INTR_UPLOAD_PAYLOAD_OVERFLOW (2) -#define SPI_DEVICE_INTR_READBUF_WATERMARK (3) -#define SPI_DEVICE_INTR_READBUF_FLIP (4) -#define SPI_DEVICE_INTR_TPM_HEADER_NOT_EMPTY (5) -#define SPI_DEVICE_INTR_TPM_RDFIFO_CMD_END (6) -#define SPI_DEVICE_INTR_TPM_RDFIFO_DROP (7) -#define SPI_DEVICE_MAX_INTR (7) - -#define SPI_DEVICE_CTRL_REG (0x10) -#define SPI_DEVICE_CTRL_MODE_OFFSET (4) -#define SPI_DEVICE_CTRL_MODE_MASK (0x1 << 4) - -#define SPI_DEVICE_ADDR_MODE_REG (0x20) -#define SPI_DEVICE_ADDR_MODE_4B_EN_MASK (0x1) -#define SPI_DEVICE_ADDR_MODE_PENDING_MASK (0x70000000) - -#define SPI_DEVICE_FLASH_STATUS_REG (0x28) -#define SPI_DEVICE_FLASH_STATUS_BUSY_MASK (0x1) -#define SPI_DEVICE_FLASH_STATUS_WEL_MASK (0x2) - -#define SPI_DEVICE_JEDEC_CC_REG (0x2C) -#define SPI_DEVICE_JEDEC_CC (0) -#define SPI_DEVICE_JEDEC_NUM_CC (8) - -#define SPI_DEVICE_JEDEC_ID_REG (0x30) -#define SPI_DEVICE_CHIP_REV (0) -#define SPI_DEVICE_CHIP_REV_MASK (0x7) -#define SPI_DEVICE_ROM_BOOTSTRAP (3) -#define SPI_DEVICE_CHIP_GEN (4) -#define SPI_DEVICE_CHIP_GEN_MASK (0xF) -#define SPI_DEVICE_DENSITY (8) -#define SPI_DEVICE_MANUFACTURER_ID (16) - -#define SPI_DEVICE_MAILBOX_ADDR_REG (0x38) - -#define SPI_DEVICE_UPLOAD_STATUS_REG (0x3C) -#define SPI_DEVICE_UPLOAD_STATUS_CMDFIFO_NOTEMPTY_MASK (0x80) -#define SPI_DEVICE_UPLOAD_STATUS_ADDRFIFO_NOTEMPTY_MASK (0x8000) - -#define SPI_DEVICE_UPLOAD_STATUS2_REG (0x40) -#define SPI_DEVICE_UPLOAD_STATUS2_PAYLOAD_DEPTH_MASK (0x1FF) - -#define SPI_DEVICE_UPLOAD_CMDFIFO_REG (0x44) -#define SPI_DEVICE_UPLOAD_ADDRFIFO_REG (0x48) - -#define SPI_DEVICE_CMD_FILTER_0_REG (0x4C) -#define SPI_DEVICE_CMD_FILTER_1_REG (0x50) -#define SPI_DEVICE_CMD_FILTER_2_REG (0x54) -#define SPI_DEVICE_CMD_FILTER_3_REG (0x58) -#define SPI_DEVICE_CMD_FILTER_4_REG (0x5C) -#define SPI_DEVICE_CMD_FILTER_5_REG (0x60) -#define SPI_DEVICE_CMD_FILTER_6_REG (0x64) -#define SPI_DEVICE_CMD_FILTER_7_REG (0x68) - -#define SPI_DEVICE_CMD_INFO_0_REG (0x7C) -#define SPI_DEVICE_CMD_INFO_1_REG (0x80) -#define SPI_DEVICE_CMD_INFO_2_REG (0x84) -#define SPI_DEVICE_CMD_INFO_3_REG (0x88) -#define SPI_DEVICE_CMD_INFO_4_REG (0x8C) -#define SPI_DEVICE_CMD_INFO_5_REG (0x90) -#define SPI_DEVICE_CMD_INFO_6_REG (0x94) -#define SPI_DEVICE_CMD_INFO_7_REG (0x98) -#define SPI_DEVICE_CMD_INFO_8_REG (0x9C) -#define SPI_DEVICE_CMD_INFO_9_REG (0xA0) -#define SPI_DEVICE_CMD_INFO_10_REG (0xA4) -#define SPI_DEVICE_CMD_INFO_11_REG (0xA8) -#define SPI_DEVICE_CMD_INFO_12_REG (0xAC) -#define SPI_DEVICE_CMD_INFO_13_REG (0xB0) -#define SPI_DEVICE_CMD_INFO_14_REG (0xB4) -#define SPI_DEVICE_CMD_INFO_15_REG (0xB8) -#define SPI_DEVICE_CMD_INFO_16_REG (0xBC) -#define SPI_DEVICE_CMD_INFO_17_REG (0xC0) -#define SPI_DEVICE_CMD_INFO_18_REG (0xC4) -#define SPI_DEVICE_CMD_INFO_19_REG (0xC8) -#define SPI_DEVICE_CMD_INFO_20_REG (0xCC) -#define SPI_DEVICE_CMD_INFO_21_REG (0xD0) -#define SPI_DEVICE_CMD_INFO_22_REG (0xD4) -#define SPI_DEVICE_CMD_INFO_23_REG (0xD8) -#define SPI_DEVICE_CMD_OPCODE (0) -#define SPI_DEVICE_CMD_ADDR_MODE (8) -#define SPI_DEVICE_CMD_ADDR_MODE_MASK (0x3) -#define SPI_DEVICE_CMD_ADDR_MODE_ADDR_DISABLED (0x0) -#define SPI_DEVICE_CMD_ADDR_MODE_ADDR_CFG (0x1) -#define SPI_DEVICE_CMD_ADDR_MODE_ADDR_3B (0x2) -#define SPI_DEVICE_CMD_ADDR_MODE_ADDR_4B (0x3) -#define SPI_DEVICE_CMD_DUMMY_SIZE (12) -#define SPI_DEVICE_CMD_DUMMY_SIZE_MASK (0x7) -#define SPI_DEVICE_CMD_DUMMY_EN (15) -#define SPI_DEVICE_CMD_UPLOAD (24) -#define SPI_DEVICE_CMD_BUSY (25) -#define SPI_DEVICE_CMD_VALID (31) - -#define SPI_DEVICE_CMD_INFO_EN4B_REG (0xDC) -#define SPI_DEVICE_CMD_INFO_WREN_REG (0xE4) -#define SPI_DEVICE_CMD_INFO_WRDI_REG (0xE8) - -#define SPI_DEVICE_EGRESS_BUFFER_OFFSET (0x1000) -#define SPI_DEVICE_READ_BUFFER_OFFSET (0x0) #define SPI_DEVICE_READ_BUFFER_NUM_BYTES (2048) #define SPI_DEVICE_SFDP_AREA_OFFSET (0xC00) #define SPI_DEVICE_SFDP_AREA_NUM_BYTES (256) -#define SPI_DEVICE_INGRESS_BUFFER_OFFSET (0x1E00) -#define SPI_DEVICE_PAYLOAD_AREA_OFFSET (0x0) #define SPI_DEVICE_PAYLOAD_AREA_NUM_BYTES (256) +#define SPI_DEVICE_CMD_ADDR_MODE_ADDR_DISABLED (0x0) +#define SPI_DEVICE_CMD_ADDR_MODE_ADDR_CFG (0x1) +#define SPI_DEVICE_CMD_ADDR_MODE_ADDR_3B (0x2) +#define SPI_DEVICE_CMD_ADDR_MODE_ADDR_4B (0x3) + #define SPI_DEVICE_SFDP_SIGNATURE (0x50444653) #define SPI_DEVICE_SFDP_MINOR_REVISION (0x0A) #define SPI_DEVICE_SFDP_MAJOR_REVISION (0x01) @@ -155,8 +55,6 @@ #define MOCHA_SPI_DEVICE_DENSITY_BYTES_LOG2 (20) #define MOCHA_SPI_DEVICE_MANUFACTURER_ID (0xef) -typedef void *spi_device_t; - typedef enum spi_device_status { spi_device_status_ready = 0, spi_device_status_empty = 1, @@ -170,53 +68,73 @@ typedef struct spi_device_cmd { uint32_t address; } spi_device_cmd_t; -bool spi_device_interrupt_is_pending(spi_device_t spi_device, uint8_t intr_id); -void spi_device_interrupt_clear(spi_device_t spi_device, uint8_t intr_id); -void spi_device_interrupt_disable_all(spi_device_t spi_device); -void spi_device_interrupt_enable(spi_device_t spi_device, uint8_t intr_id); -void spi_device_interrupt_disable(spi_device_t spi_device, uint8_t intr_id); -void spi_device_interrupt_trigger(spi_device_t spi_device, uint8_t intr_id); +/* interrupts */ +bool spi_device_interrupt_any_pending(spi_device_t spi_device, spi_device_intr intrs); +void spi_device_interrupt_clear(spi_device_t spi_device, spi_device_intr intrs); +void spi_device_interrupt_enable_write(spi_device_t spi_device, spi_device_intr intrs); +void spi_device_interrupt_enable_set(spi_device_t spi_device, spi_device_intr intrs); +void spi_device_interrupt_enable_clear(spi_device_t spi_device, spi_device_intr intrs); +void spi_device_interrupt_force(spi_device_t spi_device, spi_device_intr intrs); + +/* control */ void spi_device_enable_set(spi_device_t spi_device, bool enable); void spi_device_4b_addr_mode_enable_set(spi_device_t spi_device, bool enable); bool spi_device_4b_addr_mode_enable_get(spi_device_t spi_device); + +/* flash status */ void spi_device_flash_status_set(spi_device_t spi_device, uint32_t flash_status); uint32_t spi_device_flash_status_get(spi_device_t spi_device); + +/* JEDEC */ void spi_device_jedec_cc_set(spi_device_t spi_device, uint8_t cc, uint8_t num_cc); uint16_t spi_device_jedec_cc_get(spi_device_t spi_device); void spi_device_jedec_id_set_raw(spi_device_t spi_device, uint32_t data); void spi_device_jedec_id_set(spi_device_t spi_device, bool rom_bootstrap, uint8_t chip_rev, uint8_t chip_gen, uint8_t density, uint8_t manufacturer_id); uint32_t spi_device_jedec_id_get(spi_device_t spi_device); + +/* mailbox */ void spi_device_mailbox_addr_set(spi_device_t spi_device, uint32_t addr); uint32_t spi_device_mailbox_addr_get(spi_device_t spi_device); + +/* upload */ uint32_t spi_device_upload_status_get(spi_device_t spi_device); uint32_t spi_device_upload_status2_get(spi_device_t spi_device); uint32_t spi_device_upload_cmdfifo_read(spi_device_t spi_device); uint32_t spi_device_upload_addrfifo_read(spi_device_t spi_device); -void spi_device_cmd_filter_set(spi_device_t spi_device, uint32_t offset, uint32_t data); -uint32_t spi_device_cmd_filter_get(spi_device_t spi_device, uint32_t offset); -void spi_device_cmd_info_set_raw(spi_device_t spi_device, uint32_t offset, uint32_t data); -void spi_device_cmd_info_set(spi_device_t spi_device, uint32_t offset, uint8_t opcode, + +/* cmd filter - idx is 0-based array index (0..7) */ +void spi_device_cmd_filter_set(spi_device_t spi_device, uint8_t idx, uint32_t data); +uint32_t spi_device_cmd_filter_get(spi_device_t spi_device, uint8_t idx); + +/* cmd info - idx is 0-based array index (0..23) */ +void spi_device_cmd_info_set_raw(spi_device_t spi_device, uint8_t idx, uint32_t data); +void spi_device_cmd_info_set(spi_device_t spi_device, uint8_t idx, uint8_t opcode, uint8_t addr_mode, uint8_t dummy_cycles, bool handled_in_sw); -uint32_t spi_device_cmd_info_get(spi_device_t spi_device, uint32_t offset); +uint32_t spi_device_cmd_info_get(spi_device_t spi_device, uint8_t idx); +void spi_device_cmd_info_4b_enable_set_raw(spi_device_t spi_device, uint32_t data); +void spi_device_cmd_info_4b_enable_set(spi_device_t spi_device, uint8_t opcode); void spi_device_cmd_info_write_enable_set_raw(spi_device_t spi_device, uint32_t data); void spi_device_cmd_info_write_enable_set(spi_device_t spi_device, uint8_t opcode); uint32_t spi_device_cmd_info_write_enable_get(spi_device_t spi_device); void spi_device_cmd_info_write_disable_set_raw(spi_device_t spi_device, uint32_t data); void spi_device_cmd_info_write_disable_set(spi_device_t spi_device, uint8_t opcode); uint32_t spi_device_cmd_info_write_disable_get(spi_device_t spi_device); + +/* buffers */ bool spi_device_flash_read_buffer_write(spi_device_t spi_device, uint32_t offset, uint32_t data); uint32_t spi_device_flash_payload_buffer_read(spi_device_t spi_device, uint32_t offset); static inline uint64_t spi_device_flash_payload_buffer_read64(spi_device_t spi_device, uint32_t offset) { - uintptr_t addr = (uintptr_t)spi_device + SPI_DEVICE_INGRESS_BUFFER_OFFSET + - SPI_DEVICE_PAYLOAD_AREA_OFFSET + offset; - return DEV_READ64(addr); + return *((volatile uint64_t *)&spi_device->ingress_buffer[offset / sizeof(uint32_t)]); } +/* initialisation */ void spi_device_sfdp_table_init(spi_device_t spi_device); void spi_device_init(spi_device_t spi_device); + +/* command receive */ spi_device_cmd_t spi_device_cmd_get(spi_device_t spi_device); spi_device_cmd_t spi_device_cmd_get_non_blocking(spi_device_t spi_device); diff --git a/sw/device/tests/spi_device/smoketest.c b/sw/device/tests/spi_device/smoketest.c index a4b81cf09..752928d9e 100644 --- a/sw/device/tests/spi_device/smoketest.c +++ b/sw/device/tests/spi_device/smoketest.c @@ -13,32 +13,32 @@ enum { mip_read_retry_count = 20u, }; -bool cmd_filter_readback_test(spi_device_t spi_device, uint32_t offset) +bool cmd_filter_readback_test(spi_device_t spi_device, uint8_t idx) { - spi_device_cmd_filter_set(spi_device, offset, 0x55555555); - if (spi_device_cmd_filter_get(spi_device, offset) != 0x55555555) { + spi_device_cmd_filter_set(spi_device, idx, 0x55555555); + if (spi_device_cmd_filter_get(spi_device, idx) != 0x55555555) { return false; } - spi_device_cmd_filter_set(spi_device, offset, 0xAAAAAAAA); - if (spi_device_cmd_filter_get(spi_device, offset) != 0xAAAAAAAA) { + spi_device_cmd_filter_set(spi_device, idx, 0xAAAAAAAA); + if (spi_device_cmd_filter_get(spi_device, idx) != 0xAAAAAAAA) { return false; } return true; } -bool cmd_info_readback_test(spi_device_t spi_device, uint32_t offset) +bool cmd_info_readback_test(spi_device_t spi_device, uint8_t idx) { const uint32_t CMD_INFO_RESET_MASK = 0x83FFFFFF; - spi_device_cmd_info_set_raw(spi_device, offset, 0xAAAAAAAA & CMD_INFO_RESET_MASK); - if ((spi_device_cmd_info_get(spi_device, offset) & CMD_INFO_RESET_MASK) != + spi_device_cmd_info_set_raw(spi_device, idx, 0xAAAAAAAA & CMD_INFO_RESET_MASK); + if ((spi_device_cmd_info_get(spi_device, idx) & CMD_INFO_RESET_MASK) != (0xAAAAAAAA & CMD_INFO_RESET_MASK)) { return false; } - spi_device_cmd_info_set_raw(spi_device, offset, 0x55555555 & CMD_INFO_RESET_MASK); - if ((spi_device_cmd_info_get(spi_device, offset) & CMD_INFO_RESET_MASK) != + spi_device_cmd_info_set_raw(spi_device, idx, 0x55555555 & CMD_INFO_RESET_MASK); + if ((spi_device_cmd_info_get(spi_device, idx) & CMD_INFO_RESET_MASK) != (0x55555555 & CMD_INFO_RESET_MASK)) { return false; } @@ -83,25 +83,17 @@ bool reg_test(spi_device_t spi_device) return false; } - if (!(cmd_filter_readback_test(spi_device, SPI_DEVICE_CMD_FILTER_0_REG) && - cmd_filter_readback_test(spi_device, SPI_DEVICE_CMD_FILTER_1_REG) && - cmd_filter_readback_test(spi_device, SPI_DEVICE_CMD_FILTER_2_REG) && - cmd_filter_readback_test(spi_device, SPI_DEVICE_CMD_FILTER_3_REG) && - cmd_filter_readback_test(spi_device, SPI_DEVICE_CMD_FILTER_4_REG) && - cmd_filter_readback_test(spi_device, SPI_DEVICE_CMD_FILTER_5_REG) && - cmd_filter_readback_test(spi_device, SPI_DEVICE_CMD_FILTER_6_REG) && - cmd_filter_readback_test(spi_device, SPI_DEVICE_CMD_FILTER_7_REG))) { + if (!(cmd_filter_readback_test(spi_device, 0) && cmd_filter_readback_test(spi_device, 1) && + cmd_filter_readback_test(spi_device, 2) && cmd_filter_readback_test(spi_device, 3) && + cmd_filter_readback_test(spi_device, 4) && cmd_filter_readback_test(spi_device, 5) && + cmd_filter_readback_test(spi_device, 6) && cmd_filter_readback_test(spi_device, 7))) { return false; } - if (!(cmd_info_readback_test(spi_device, SPI_DEVICE_CMD_INFO_0_REG) && - cmd_info_readback_test(spi_device, SPI_DEVICE_CMD_INFO_1_REG) && - cmd_info_readback_test(spi_device, SPI_DEVICE_CMD_INFO_2_REG) && - cmd_info_readback_test(spi_device, SPI_DEVICE_CMD_INFO_3_REG) && - cmd_info_readback_test(spi_device, SPI_DEVICE_CMD_INFO_20_REG) && - cmd_info_readback_test(spi_device, SPI_DEVICE_CMD_INFO_21_REG) && - cmd_info_readback_test(spi_device, SPI_DEVICE_CMD_INFO_22_REG) && - cmd_info_readback_test(spi_device, SPI_DEVICE_CMD_INFO_23_REG))) { + if (!(cmd_info_readback_test(spi_device, 0) && cmd_info_readback_test(spi_device, 1) && + cmd_info_readback_test(spi_device, 2) && cmd_info_readback_test(spi_device, 3) && + cmd_info_readback_test(spi_device, 20) && cmd_info_readback_test(spi_device, 21) && + cmd_info_readback_test(spi_device, 22) && cmd_info_readback_test(spi_device, 23))) { return false; } @@ -116,8 +108,8 @@ bool machine_irq_test(spi_device_t spi_device, plic_t plic) plic_interrupt_priority_write(plic, mocha_system_irq_spi_device, 3); plic_machine_priority_threshold_write(plic, 0); - spi_device_interrupt_disable_all(spi_device); - spi_device_interrupt_enable(spi_device, SPI_DEVICE_INTR_UPLOAD_PAYLOAD_OVERFLOW); + spi_device_interrupt_enable_write(spi_device, spi_device_intr_none); + spi_device_interrupt_enable_set(spi_device, spi_device_intr_upload_payload_overflow); plic_machine_interrupt_enable_set(plic, mocha_system_irq_spi_device); @@ -126,7 +118,7 @@ bool machine_irq_test(spi_device_t spi_device, plic_t plic) return false; } - spi_device_interrupt_trigger(spi_device, SPI_DEVICE_INTR_UPLOAD_PAYLOAD_OVERFLOW); + spi_device_interrupt_force(spi_device, spi_device_intr_upload_payload_overflow); // Check that mip MEIP is set following the triggered interrupt for (size_t i = 0; i < mip_read_retry_count; i++) { @@ -140,7 +132,7 @@ bool machine_irq_test(spi_device_t spi_device, plic_t plic) } intr_id = plic_machine_interrupt_claim(plic); - spi_device_interrupt_clear(spi_device, SPI_DEVICE_INTR_UPLOAD_PAYLOAD_OVERFLOW); + spi_device_interrupt_clear(spi_device, spi_device_intr_upload_payload_overflow); plic_machine_interrupt_complete(plic, intr_id); // Check that mip MEIP is clear @@ -159,8 +151,8 @@ bool supervisor_irq_test(spi_device_t spi_device, plic_t plic) plic_interrupt_priority_write(plic, mocha_system_irq_spi_device, 3); plic_supervisor_priority_threshold_write(plic, 0); - spi_device_interrupt_disable_all(spi_device); - spi_device_interrupt_enable(spi_device, SPI_DEVICE_INTR_READBUF_FLIP); + spi_device_interrupt_enable_write(spi_device, spi_device_intr_none); + spi_device_interrupt_enable_set(spi_device, spi_device_intr_readbuf_flip); plic_supervisor_interrupt_enable_set(plic, mocha_system_irq_spi_device); @@ -169,7 +161,7 @@ bool supervisor_irq_test(spi_device_t spi_device, plic_t plic) return false; } - spi_device_interrupt_trigger(spi_device, SPI_DEVICE_INTR_READBUF_FLIP); + spi_device_interrupt_force(spi_device, spi_device_intr_readbuf_flip); // Check that mip SEIP is set following the triggered interrupt for (size_t i = 0; i < mip_read_retry_count; i++) { @@ -183,7 +175,7 @@ bool supervisor_irq_test(spi_device_t spi_device, plic_t plic) } intr_id = plic_supervisor_interrupt_claim(plic); - spi_device_interrupt_clear(spi_device, SPI_DEVICE_INTR_READBUF_FLIP); + spi_device_interrupt_clear(spi_device, spi_device_intr_readbuf_flip); plic_supervisor_interrupt_complete(plic, intr_id); // Check that mip SEIP is clear From cd76d12fcab1c52440bc0c2b782c6b38f63eb76b Mon Sep 17 00:00:00 2001 From: Douglas Reis Date: Wed, 13 May 2026 16:22:38 +0000 Subject: [PATCH 10/10] fixup Signed-off-by: Douglas Reis --- sw/device/lib/hal/spi_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sw/device/lib/hal/spi_device.c b/sw/device/lib/hal/spi_device.c index fd8ccd279..1ad923cd6 100644 --- a/sw/device/lib/hal/spi_device.c +++ b/sw/device/lib/hal/spi_device.c @@ -54,8 +54,8 @@ void spi_device_4b_addr_mode_enable_set(spi_device_t spi_device, bool enable) VOLATILE_WRITE(spi_device->addr_mode, addr_mode); // Wait for change to take effect - while (VOLATILE_READ(spi_device->addr_mode).pending) { - } + // while (VOLATILE_READ(spi_device->addr_mode).pending) { + // } } bool spi_device_4b_addr_mode_enable_get(spi_device_t spi_device)