This is mostly a stub which completes SPI transactions as noops
by masking out the error interrupts and never clearing the IPCMDDONE
interrupt.
Although incomplete, this allows software that uses NXP's mcuxpresso
SDK to run the SDK board initialization functions.
It also supports AHB memory access, aka XIP, for now as simple RAM
memory regions.
The patch includes an automatically generated header which contains
the register layout and helpers.
The header can be regenerated with the svd-flexspi target when the
build is configured with --enable-mcux-soc-svd.
Signed-off-by: Octavian Purdila <tavip@google.com>
---
include/hw/arm/svd/flexspi.h | 1085 ++++++++++++++++++++++++++++++++++
include/hw/ssi/flexspi.h | 31 +
hw/ssi/flexspi.c | 181 ++++++
hw/arm/svd/meson.build | 4 +
hw/ssi/Kconfig | 4 +
hw/ssi/meson.build | 1 +
hw/ssi/trace-events | 4 +
7 files changed, 1310 insertions(+)
create mode 100644 include/hw/arm/svd/flexspi.h
create mode 100644 include/hw/ssi/flexspi.h
create mode 100644 hw/ssi/flexspi.c
diff --git a/include/hw/arm/svd/flexspi.h b/include/hw/arm/svd/flexspi.h
new file mode 100644
index 0000000000..6e7e715d51
--- /dev/null
+++ b/include/hw/arm/svd/flexspi.h
@@ -0,0 +1,1085 @@
+/*
+ * Copyright 2016-2023 NXP SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Automatically generated by svd-gen-header.py from MIMXRT595S_cm33.xml
+ */
+#pragma once
+
+#include "hw/register.h"
+
+/* FlexSPI */
+#define FLEXSPI_REGS_NO (267)
+
+/* Module Control Register 0 */
+REG32(FLEXSPI_MCR0, 0x0);
+/* Software Reset */
+FIELD(FLEXSPI_MCR0, SWRESET, 0, 1);
+
+/* Interrupt Register */
+REG32(FLEXSPI_INTR, 0x14);
+/*
+ * IP triggered Command Sequences Execution finished interrupt. This interrupt
+ * is also generated when there is IPCMDGE or IPCMDERR interrupt generated.
+ */
+FIELD(FLEXSPI_INTR, IPCMDDONE, 0, 1);
+
+/* Status Register 0 */
+REG32(FLEXSPI_STS0, 0xE0);
+/*
+ * This status bit indicates the state machine in SEQ_CTL is idle and there is
+ * command sequence executing on FlexSPI interface.
+ */
+FIELD(FLEXSPI_STS0, SEQIDLE, 0, 1);
+
+
+#define FLEXSPI_REGISTER_ACCESS_INFO_ARRAY(_name) \
+ struct RegisterAccessInfo _name[FLEXSPI_REGS_NO] = { \
+ [0 ... FLEXSPI_REGS_NO - 1] = { \
+ .name = "", \
+ .addr = -1, \
+ }, \
+ [0x0] = { \
+ .name = "MCR0", \
+ .addr = 0x0, \
+ .ro = 0x20CC, \
+ .reset = 0xFFFF80C2, \
+ }, \
+ [0x1] = { \
+ .name = "MCR1", \
+ .addr = 0x4, \
+ .ro = 0x0, \
+ .reset = 0xFFFFFFFF, \
+ }, \
+ [0x2] = { \
+ .name = "MCR2", \
+ .addr = 0x8, \
+ .ro = 0xFF37FF, \
+ .reset = 0x200081F7, \
+ }, \
+ [0x3] = { \
+ .name = "AHBCR", \
+ .addr = 0xC, \
+ .ro = 0xFFFFFB02, \
+ .reset = 0x18, \
+ }, \
+ [0x4] = { \
+ .name = "INTEN", \
+ .addr = 0x10, \
+ .ro = 0xFFFFC000, \
+ .reset = 0x0, \
+ }, \
+ [0x5] = { \
+ .name = "INTR", \
+ .addr = 0x14, \
+ .ro = 0xFFFFE000, \
+ .reset = 0x0, \
+ }, \
+ [0x6] = { \
+ .name = "LUTKEY", \
+ .addr = 0x18, \
+ .ro = 0x0, \
+ .reset = 0x5AF05AF0, \
+ }, \
+ [0x7] = { \
+ .name = "LUTCR", \
+ .addr = 0x1C, \
+ .ro = 0xFFFFFFFC, \
+ .reset = 0x2, \
+ }, \
+ [0x8] = { \
+ .name = "AHBRXBUF0CR0", \
+ .addr = 0x20, \
+ .ro = 0x78F0FF00, \
+ .reset = 0x80000010, \
+ }, \
+ [0x9] = { \
+ .name = "AHBRXBUF1CR0", \
+ .addr = 0x24, \
+ .ro = 0x78F0FF00, \
+ .reset = 0x80010010, \
+ }, \
+ [0xA] = { \
+ .name = "AHBRXBUF2CR0", \
+ .addr = 0x28, \
+ .ro = 0x78F0FF00, \
+ .reset = 0x80020010, \
+ }, \
+ [0xB] = { \
+ .name = "AHBRXBUF3CR0", \
+ .addr = 0x2C, \
+ .ro = 0x78F0FF00, \
+ .reset = 0x80030010, \
+ }, \
+ [0xC] = { \
+ .name = "AHBRXBUF4CR0", \
+ .addr = 0x30, \
+ .ro = 0x78F0FF00, \
+ .reset = 0x80040010, \
+ }, \
+ [0xD] = { \
+ .name = "AHBRXBUF5CR0", \
+ .addr = 0x34, \
+ .ro = 0x78F0FF00, \
+ .reset = 0x80050010, \
+ }, \
+ [0xE] = { \
+ .name = "AHBRXBUF6CR0", \
+ .addr = 0x38, \
+ .ro = 0x78F0FF00, \
+ .reset = 0x80060010, \
+ }, \
+ [0xF] = { \
+ .name = "AHBRXBUF7CR0", \
+ .addr = 0x3C, \
+ .ro = 0x78F0FF00, \
+ .reset = 0x80070010, \
+ }, \
+ [0x18] = { \
+ .name = "FLSHA1CR0", \
+ .addr = 0x60, \
+ .ro = 0xFF800000, \
+ .reset = 0x10000, \
+ }, \
+ [0x19] = { \
+ .name = "FLSHA2CR0", \
+ .addr = 0x64, \
+ .ro = 0xFF800000, \
+ .reset = 0x10000, \
+ }, \
+ [0x1A] = { \
+ .name = "FLSHB1CR0", \
+ .addr = 0x68, \
+ .ro = 0xFF800000, \
+ .reset = 0x10000, \
+ }, \
+ [0x1B] = { \
+ .name = "FLSHB2CR0", \
+ .addr = 0x6C, \
+ .ro = 0xFF800000, \
+ .reset = 0x10000, \
+ }, \
+ [0x1C] = { \
+ .name = "FLSHCR1A1", \
+ .addr = 0x70, \
+ .ro = 0x0, \
+ .reset = 0x63, \
+ }, \
+ [0x1D] = { \
+ .name = "FLSHCR1A2", \
+ .addr = 0x74, \
+ .ro = 0x0, \
+ .reset = 0x63, \
+ }, \
+ [0x1E] = { \
+ .name = "FLSHCR1B1", \
+ .addr = 0x78, \
+ .ro = 0x0, \
+ .reset = 0x63, \
+ }, \
+ [0x1F] = { \
+ .name = "FLSHCR1B2", \
+ .addr = 0x7C, \
+ .ro = 0x0, \
+ .reset = 0x63, \
+ }, \
+ [0x20] = { \
+ .name = "FLSHCR2A1", \
+ .addr = 0x80, \
+ .ro = 0x1010, \
+ .reset = 0x0, \
+ }, \
+ [0x21] = { \
+ .name = "FLSHCR2A2", \
+ .addr = 0x84, \
+ .ro = 0x1010, \
+ .reset = 0x0, \
+ }, \
+ [0x22] = { \
+ .name = "FLSHCR2B1", \
+ .addr = 0x88, \
+ .ro = 0x1010, \
+ .reset = 0x0, \
+ }, \
+ [0x23] = { \
+ .name = "FLSHCR2B2", \
+ .addr = 0x8C, \
+ .ro = 0x1010, \
+ .reset = 0x0, \
+ }, \
+ [0x25] = { \
+ .name = "FLSHCR4", \
+ .addr = 0x94, \
+ .ro = 0xFFFFFFFA, \
+ .reset = 0x0, \
+ }, \
+ [0x28] = { \
+ .name = "IPCR0", \
+ .addr = 0xA0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x29] = { \
+ .name = "IPCR1", \
+ .addr = 0xA4, \
+ .ro = 0x78F00000, \
+ .reset = 0x0, \
+ }, \
+ [0x2C] = { \
+ .name = "IPCMD", \
+ .addr = 0xB0, \
+ .ro = 0xFFFFFFFE, \
+ .reset = 0x0, \
+ }, \
+ [0x2D] = { \
+ .name = "DLPR", \
+ .addr = 0xB4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x2E] = { \
+ .name = "IPRXFCR", \
+ .addr = 0xB8, \
+ .ro = 0xFFFFFE00, \
+ .reset = 0x0, \
+ }, \
+ [0x2F] = { \
+ .name = "IPTXFCR", \
+ .addr = 0xBC, \
+ .ro = 0xFFFFFE00, \
+ .reset = 0x0, \
+ }, \
+ [0x30] = { \
+ .name = "DLLCRA", \
+ .addr = 0xC0, \
+ .ro = 0xFFFF8084, \
+ .reset = 0x100, \
+ }, \
+ [0x31] = { \
+ .name = "DLLCRB", \
+ .addr = 0xC4, \
+ .ro = 0xFFFF8084, \
+ .reset = 0x100, \
+ }, \
+ [0x38] = { \
+ .name = "STS0", \
+ .addr = 0xE0, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x2, \
+ }, \
+ [0x39] = { \
+ .name = "STS1", \
+ .addr = 0xE4, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x3A] = { \
+ .name = "STS2", \
+ .addr = 0xE8, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x1000100, \
+ }, \
+ [0x3B] = { \
+ .name = "AHBSPNDSTS", \
+ .addr = 0xEC, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x3C] = { \
+ .name = "IPRXFSTS", \
+ .addr = 0xF0, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x3D] = { \
+ .name = "IPTXFSTS", \
+ .addr = 0xF4, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x40] = { \
+ .name = "RFDR0", \
+ .addr = 0x100, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x41] = { \
+ .name = "RFDR1", \
+ .addr = 0x104, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x42] = { \
+ .name = "RFDR2", \
+ .addr = 0x108, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x43] = { \
+ .name = "RFDR3", \
+ .addr = 0x10C, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x44] = { \
+ .name = "RFDR4", \
+ .addr = 0x110, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x45] = { \
+ .name = "RFDR5", \
+ .addr = 0x114, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x46] = { \
+ .name = "RFDR6", \
+ .addr = 0x118, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x47] = { \
+ .name = "RFDR7", \
+ .addr = 0x11C, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x48] = { \
+ .name = "RFDR8", \
+ .addr = 0x120, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x49] = { \
+ .name = "RFDR9", \
+ .addr = 0x124, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x4A] = { \
+ .name = "RFDR10", \
+ .addr = 0x128, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x4B] = { \
+ .name = "RFDR11", \
+ .addr = 0x12C, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x4C] = { \
+ .name = "RFDR12", \
+ .addr = 0x130, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x4D] = { \
+ .name = "RFDR13", \
+ .addr = 0x134, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x4E] = { \
+ .name = "RFDR14", \
+ .addr = 0x138, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x4F] = { \
+ .name = "RFDR15", \
+ .addr = 0x13C, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x50] = { \
+ .name = "RFDR16", \
+ .addr = 0x140, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x51] = { \
+ .name = "RFDR17", \
+ .addr = 0x144, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x52] = { \
+ .name = "RFDR18", \
+ .addr = 0x148, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x53] = { \
+ .name = "RFDR19", \
+ .addr = 0x14C, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x54] = { \
+ .name = "RFDR20", \
+ .addr = 0x150, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x55] = { \
+ .name = "RFDR21", \
+ .addr = 0x154, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x56] = { \
+ .name = "RFDR22", \
+ .addr = 0x158, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x57] = { \
+ .name = "RFDR23", \
+ .addr = 0x15C, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x58] = { \
+ .name = "RFDR24", \
+ .addr = 0x160, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x59] = { \
+ .name = "RFDR25", \
+ .addr = 0x164, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x5A] = { \
+ .name = "RFDR26", \
+ .addr = 0x168, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x5B] = { \
+ .name = "RFDR27", \
+ .addr = 0x16C, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x5C] = { \
+ .name = "RFDR28", \
+ .addr = 0x170, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x5D] = { \
+ .name = "RFDR29", \
+ .addr = 0x174, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x5E] = { \
+ .name = "RFDR30", \
+ .addr = 0x178, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x5F] = { \
+ .name = "RFDR31", \
+ .addr = 0x17C, \
+ .ro = 0xFFFFFFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x60] = { \
+ .name = "TFDR0", \
+ .addr = 0x180, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x61] = { \
+ .name = "TFDR1", \
+ .addr = 0x184, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x62] = { \
+ .name = "TFDR2", \
+ .addr = 0x188, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x63] = { \
+ .name = "TFDR3", \
+ .addr = 0x18C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x64] = { \
+ .name = "TFDR4", \
+ .addr = 0x190, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x65] = { \
+ .name = "TFDR5", \
+ .addr = 0x194, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x66] = { \
+ .name = "TFDR6", \
+ .addr = 0x198, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x67] = { \
+ .name = "TFDR7", \
+ .addr = 0x19C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x68] = { \
+ .name = "TFDR8", \
+ .addr = 0x1A0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x69] = { \
+ .name = "TFDR9", \
+ .addr = 0x1A4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x6A] = { \
+ .name = "TFDR10", \
+ .addr = 0x1A8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x6B] = { \
+ .name = "TFDR11", \
+ .addr = 0x1AC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x6C] = { \
+ .name = "TFDR12", \
+ .addr = 0x1B0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x6D] = { \
+ .name = "TFDR13", \
+ .addr = 0x1B4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x6E] = { \
+ .name = "TFDR14", \
+ .addr = 0x1B8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x6F] = { \
+ .name = "TFDR15", \
+ .addr = 0x1BC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x70] = { \
+ .name = "TFDR16", \
+ .addr = 0x1C0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x71] = { \
+ .name = "TFDR17", \
+ .addr = 0x1C4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x72] = { \
+ .name = "TFDR18", \
+ .addr = 0x1C8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x73] = { \
+ .name = "TFDR19", \
+ .addr = 0x1CC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x74] = { \
+ .name = "TFDR20", \
+ .addr = 0x1D0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x75] = { \
+ .name = "TFDR21", \
+ .addr = 0x1D4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x76] = { \
+ .name = "TFDR22", \
+ .addr = 0x1D8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x77] = { \
+ .name = "TFDR23", \
+ .addr = 0x1DC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x78] = { \
+ .name = "TFDR24", \
+ .addr = 0x1E0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x79] = { \
+ .name = "TFDR25", \
+ .addr = 0x1E4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x7A] = { \
+ .name = "TFDR26", \
+ .addr = 0x1E8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x7B] = { \
+ .name = "TFDR27", \
+ .addr = 0x1EC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x7C] = { \
+ .name = "TFDR28", \
+ .addr = 0x1F0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x7D] = { \
+ .name = "TFDR29", \
+ .addr = 0x1F4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x7E] = { \
+ .name = "TFDR30", \
+ .addr = 0x1F8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x7F] = { \
+ .name = "TFDR31", \
+ .addr = 0x1FC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x80] = { \
+ .name = "LUT0", \
+ .addr = 0x200, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x81] = { \
+ .name = "LUT1", \
+ .addr = 0x204, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x82] = { \
+ .name = "LUT2", \
+ .addr = 0x208, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x83] = { \
+ .name = "LUT3", \
+ .addr = 0x20C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x84] = { \
+ .name = "LUT4", \
+ .addr = 0x210, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x85] = { \
+ .name = "LUT5", \
+ .addr = 0x214, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x86] = { \
+ .name = "LUT6", \
+ .addr = 0x218, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x87] = { \
+ .name = "LUT7", \
+ .addr = 0x21C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x88] = { \
+ .name = "LUT8", \
+ .addr = 0x220, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x89] = { \
+ .name = "LUT9", \
+ .addr = 0x224, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x8A] = { \
+ .name = "LUT10", \
+ .addr = 0x228, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x8B] = { \
+ .name = "LUT11", \
+ .addr = 0x22C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x8C] = { \
+ .name = "LUT12", \
+ .addr = 0x230, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x8D] = { \
+ .name = "LUT13", \
+ .addr = 0x234, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x8E] = { \
+ .name = "LUT14", \
+ .addr = 0x238, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x8F] = { \
+ .name = "LUT15", \
+ .addr = 0x23C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x90] = { \
+ .name = "LUT16", \
+ .addr = 0x240, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x91] = { \
+ .name = "LUT17", \
+ .addr = 0x244, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x92] = { \
+ .name = "LUT18", \
+ .addr = 0x248, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x93] = { \
+ .name = "LUT19", \
+ .addr = 0x24C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x94] = { \
+ .name = "LUT20", \
+ .addr = 0x250, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x95] = { \
+ .name = "LUT21", \
+ .addr = 0x254, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x96] = { \
+ .name = "LUT22", \
+ .addr = 0x258, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x97] = { \
+ .name = "LUT23", \
+ .addr = 0x25C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x98] = { \
+ .name = "LUT24", \
+ .addr = 0x260, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x99] = { \
+ .name = "LUT25", \
+ .addr = 0x264, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x9A] = { \
+ .name = "LUT26", \
+ .addr = 0x268, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x9B] = { \
+ .name = "LUT27", \
+ .addr = 0x26C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x9C] = { \
+ .name = "LUT28", \
+ .addr = 0x270, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x9D] = { \
+ .name = "LUT29", \
+ .addr = 0x274, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x9E] = { \
+ .name = "LUT30", \
+ .addr = 0x278, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x9F] = { \
+ .name = "LUT31", \
+ .addr = 0x27C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA0] = { \
+ .name = "LUT32", \
+ .addr = 0x280, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA1] = { \
+ .name = "LUT33", \
+ .addr = 0x284, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA2] = { \
+ .name = "LUT34", \
+ .addr = 0x288, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA3] = { \
+ .name = "LUT35", \
+ .addr = 0x28C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA4] = { \
+ .name = "LUT36", \
+ .addr = 0x290, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA5] = { \
+ .name = "LUT37", \
+ .addr = 0x294, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA6] = { \
+ .name = "LUT38", \
+ .addr = 0x298, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA7] = { \
+ .name = "LUT39", \
+ .addr = 0x29C, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA8] = { \
+ .name = "LUT40", \
+ .addr = 0x2A0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xA9] = { \
+ .name = "LUT41", \
+ .addr = 0x2A4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xAA] = { \
+ .name = "LUT42", \
+ .addr = 0x2A8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xAB] = { \
+ .name = "LUT43", \
+ .addr = 0x2AC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xAC] = { \
+ .name = "LUT44", \
+ .addr = 0x2B0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xAD] = { \
+ .name = "LUT45", \
+ .addr = 0x2B4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xAE] = { \
+ .name = "LUT46", \
+ .addr = 0x2B8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xAF] = { \
+ .name = "LUT47", \
+ .addr = 0x2BC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB0] = { \
+ .name = "LUT48", \
+ .addr = 0x2C0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB1] = { \
+ .name = "LUT49", \
+ .addr = 0x2C4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB2] = { \
+ .name = "LUT50", \
+ .addr = 0x2C8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB3] = { \
+ .name = "LUT51", \
+ .addr = 0x2CC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB4] = { \
+ .name = "LUT52", \
+ .addr = 0x2D0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB5] = { \
+ .name = "LUT53", \
+ .addr = 0x2D4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB6] = { \
+ .name = "LUT54", \
+ .addr = 0x2D8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB7] = { \
+ .name = "LUT55", \
+ .addr = 0x2DC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB8] = { \
+ .name = "LUT56", \
+ .addr = 0x2E0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xB9] = { \
+ .name = "LUT57", \
+ .addr = 0x2E4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xBA] = { \
+ .name = "LUT58", \
+ .addr = 0x2E8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xBB] = { \
+ .name = "LUT59", \
+ .addr = 0x2EC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xBC] = { \
+ .name = "LUT60", \
+ .addr = 0x2F0, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xBD] = { \
+ .name = "LUT61", \
+ .addr = 0x2F4, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xBE] = { \
+ .name = "LUT62", \
+ .addr = 0x2F8, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0xBF] = { \
+ .name = "LUT63", \
+ .addr = 0x2FC, \
+ .ro = 0x0, \
+ .reset = 0x0, \
+ }, \
+ [0x108] = { \
+ .name = "HADDRSTART", \
+ .addr = 0x420, \
+ .ro = 0xFFE, \
+ .reset = 0x0, \
+ }, \
+ [0x109] = { \
+ .name = "HADDREND", \
+ .addr = 0x424, \
+ .ro = 0xFFF, \
+ .reset = 0x0, \
+ }, \
+ [0x10A] = { \
+ .name = "HADDROFFSET", \
+ .addr = 0x428, \
+ .ro = 0xFFF, \
+ .reset = 0x0, \
+ }, \
+ }
diff --git a/include/hw/ssi/flexspi.h b/include/hw/ssi/flexspi.h
new file mode 100644
index 0000000000..51699e1ceb
--- /dev/null
+++ b/include/hw/ssi/flexspi.h
@@ -0,0 +1,31 @@
+/*
+ * QEMU model for FLEXSPI
+ *
+ * Copyright (c) 2024 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_RT500_FLEXSPI_H
+#define HW_RT500_FLEXSPI_H
+
+#include "hw/sysbus.h"
+#include "hw/ssi/ssi.h"
+#include "hw/arm/svd/flexspi.h"
+
+#define TYPE_FLEXSPI "flexspi"
+#define FLEXSPI(obj) OBJECT_CHECK(FlexSpiState, (obj), TYPE_FLEXSPI)
+
+typedef struct {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+ uint32_t regs[FLEXSPI_REGS_NO];
+ MemoryRegion mem;
+ uint64_t mmap_size;
+} FlexSpiState;
+
+#endif /* HW_RT500_FLEXSPI_H */
diff --git a/hw/ssi/flexspi.c b/hw/ssi/flexspi.c
new file mode 100644
index 0000000000..d5d9e4f098
--- /dev/null
+++ b/hw/ssi/flexspi.c
@@ -0,0 +1,181 @@
+/*
+ * QEMU model for FLEXSPI
+ *
+ * Copyright (c) 2024 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/mmap-alloc.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "migration/vmstate.h"
+#include "exec/address-spaces.h"
+#include "hw/ssi/flexspi.h"
+#include "hw/arm/svd/flexspi.h"
+
+#include "trace.h"
+
+#define REG(s, reg) (s->regs[R_FLEXSPI_##reg])
+#define RF_WR(s, reg, field, val) \
+ ARRAY_FIELD_DP32(s->regs, FLEXSPI_##reg, field, val)
+#define RF_RD(s, reg, field) \
+ ARRAY_FIELD_EX32(s->regs, FLEXSPI_##reg, field)
+
+static FLEXSPI_REGISTER_ACCESS_INFO_ARRAY(reg_info);
+
+static void flexspi_reset_enter(Object *obj, ResetType type)
+{
+ FlexSpiState *s = FLEXSPI(obj);
+
+ for (int i = 0; i < FLEXSPI_REGS_NO; i++) {
+ hwaddr addr = reg_info[i].addr;
+
+ if (addr != -1) {
+ struct RegisterInfo ri = {
+ .data = &s->regs[addr / 4],
+ .data_size = 4,
+ .access = ®_info[i],
+ };
+
+ register_reset(&ri);
+ }
+ }
+
+ /* idle immediately after reset */
+ RF_WR(s, STS0, SEQIDLE, 1);
+}
+
+static MemTxResult flexspi_read(void *opaque, hwaddr addr,
+ uint64_t *data, unsigned size,
+ MemTxAttrs attrs)
+{
+ FlexSpiState *s = opaque;
+ const struct RegisterAccessInfo *rai = ®_info[addr / 4];
+ MemTxResult ret = MEMTX_OK;
+
+ switch (addr) {
+ default:
+ *data = s->regs[addr / 4];
+ break;
+ }
+
+ trace_flexspi_reg_read(DEVICE(s)->id, rai->name, addr, *data);
+ return ret;
+}
+
+
+static MemTxResult flexspi_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size,
+ MemTxAttrs attrs)
+{
+ FlexSpiState *s = opaque;
+ const struct RegisterAccessInfo *rai = ®_info[addr / 4];
+ struct RegisterInfo ri = {
+ .data = &s->regs[addr / 4],
+ .data_size = 4,
+ .access = rai,
+ };
+
+ trace_flexspi_reg_write(DEVICE(s)->id, rai->name, addr, value);
+
+ switch (addr) {
+ case A_FLEXSPI_MCR0:
+ {
+ register_write(&ri, value, ~0, NULL, false);
+
+ if (RF_RD(s, MCR0, SWRESET)) {
+ RF_WR(s, MCR0, SWRESET, 0);
+ }
+ break;
+ }
+ case A_FLEXSPI_INTR:
+ {
+ /* fake SPI transfer completion */
+ RF_WR(s, INTR, IPCMDDONE, 1);
+ break;
+ }
+ default:
+ register_write(&ri, value, ~0, NULL, false);
+ break;
+ }
+
+ return MEMTX_OK;
+}
+
+static const MemoryRegionOps flexspi_ops = {
+ .read_with_attrs = flexspi_read,
+ .write_with_attrs = flexspi_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static Property flexspi_properties[] = {
+ DEFINE_PROP_UINT64("mmap_size", FlexSpiState, mmap_size, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void flexspi_init(Object *obj)
+{
+ FlexSpiState *s = FLEXSPI(obj);
+
+ memory_region_init_io(&s->mmio, obj, &flexspi_ops, s, TYPE_FLEXSPI,
+ sizeof(s->regs));
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void flexspi_realize(DeviceState *dev, Error **errp)
+{
+ FlexSpiState *s = FLEXSPI(dev);
+
+ if (s->mmap_size) {
+ memory_region_init_ram(&s->mem, OBJECT(s), DEVICE(s)->id, s->mmap_size,
+ NULL);
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mem);
+ }
+}
+
+static const VMStateDescription vmstate_flexspi = {
+ .name = "flexspi",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, FlexSpiState, FLEXSPI_REGS_NO),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void flexspi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ rc->phases.enter = flexspi_reset_enter;
+ dc->realize = flexspi_realize;
+ dc->vmsd = &vmstate_flexspi;
+ device_class_set_props(dc, flexspi_properties);
+}
+
+static const TypeInfo flexspi_types[] = {
+ {
+ .name = TYPE_FLEXSPI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(FlexSpiState),
+ .instance_init = flexspi_init,
+ .class_init = flexspi_class_init,
+ },
+};
+
+DEFINE_TYPES(flexspi_types);
diff --git a/hw/arm/svd/meson.build b/hw/arm/svd/meson.build
index 9c458b314c..adf0f8327a 100644
--- a/hw/arm/svd/meson.build
+++ b/hw/arm/svd/meson.build
@@ -24,4 +24,8 @@ if get_option('mcux-soc-svd')
[ '-i', rt595, '-o', '@SOURCE_ROOT@/include/hw/arm/svd/rt500_clkctl1.h',
'-p', 'CLKCTL1', '-t', 'RT500_CLKCTL1',
'--fields', 'PSCCTL*:FlexIO AUDIOPLL0PFD OSEVENTTFCLKSEL'])
+ run_target('svd-flexspi', command: svd_gen_header +
+ [ '-i', rt595, '-o', '@SOURCE_ROOT@/include/hw/arm/svd/flexspi.h',
+ '-p', 'FLEXSPI0', '-t', 'FLEXSPI',
+ '--fields', 'STS0:SEQIDLE MCR0:SWRESET INTR:IPCMDDONE'])
endif
diff --git a/hw/ssi/Kconfig b/hw/ssi/Kconfig
index 8d180de7cf..e3de40e6b6 100644
--- a/hw/ssi/Kconfig
+++ b/hw/ssi/Kconfig
@@ -28,3 +28,7 @@ config BCM2835_SPI
config PNV_SPI
bool
select SSI
+
+config FLEXSPI
+ bool
+ select SSI
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
index 58e0d14b37..31a2618d52 100644
--- a/hw/ssi/meson.build
+++ b/hw/ssi/meson.build
@@ -13,3 +13,4 @@ system_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_spi_host.c'))
system_ss.add(when: 'CONFIG_BCM2835_SPI', if_true: files('bcm2835_spi.c'))
system_ss.add(when: 'CONFIG_PNV_SPI', if_true: files('pnv_spi.c'))
system_ss.add(when: 'CONFIG_FLEXCOMM', if_true: files('flexcomm_spi.c'))
+system_ss.add(when: 'CONFIG_FLEXSPI', if_true: files('flexspi.c'))
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
index f849f1f8be..dd2f04cb22 100644
--- a/hw/ssi/trace-events
+++ b/hw/ssi/trace-events
@@ -58,3 +58,7 @@ pnv_spi_RDR_match(const char* result) "%s"
flexcomm_spi_reg_read(const char *id, const char *reg_name, uint32_t addr, uint32_t val) " %s: %s[0x%04x] -> 0x%08x"
flexcomm_spi_reg_write(const char *id, const char *reg_name, uint32_t addr, uint32_t val) "%s: %s[0x%04x] <- 0x%08x"
flexcomm_spi_irq(const char *id, bool irq, bool fifoirqs, bool perirqs, bool enabled) "%s: %d %d %d %d"
+
+# flexspi.c
+flexspi_reg_read(const char *id, const char *reg_name, uint32_t addr, uint32_t val) " %s: %s[0x%04x] -> 0x%08x"
+flexspi_reg_write(const char *id, const char *reg_name, uint32_t addr, uint32_t val) "%s: %s[0x%04x] <- 0x%08x"
--
2.47.0.rc0.187.ge670bccf7e-goog
© 2016 - 2024 Red Hat, Inc.