• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisioncbb45ff038cdbfcc8af158191405e2597f28c562 (tree)
Time2022-01-28 23:29:46
AuthorFrancisco Iglesias <francisco.iglesias@xili...>
CommiterPeter Maydell

Log Message

hw/ssi: Add a model of Xilinx Versal's OSPI flash memory controller

Add a model of Xilinx Versal's OSPI flash memory controller.

Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
Reviewed-by: Luc Michel <luc@lmichel.fr>
Message-id: 20220121161141.14389-7-francisco.iglesias@xilinx.com
[PMM: fixed indent]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Change Summary

Incremental Difference

--- a/hw/ssi/meson.build
+++ b/hw/ssi/meson.build
@@ -7,5 +7,6 @@ softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c'))
77 softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c'))
88 softmmu_ss.add(when: 'CONFIG_XILINX_SPI', if_true: files('xilinx_spi.c'))
99 softmmu_ss.add(when: 'CONFIG_XILINX_SPIPS', if_true: files('xilinx_spips.c'))
10+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-ospi.c'))
1011 softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_spi.c'))
1112 softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_spi.c'))
--- /dev/null
+++ b/hw/ssi/xlnx-versal-ospi.c
@@ -0,0 +1,1853 @@
1+/*
2+ * QEMU model of Xilinx Versal's OSPI controller.
3+ *
4+ * Copyright (c) 2021 Xilinx Inc.
5+ * Written by Francisco Iglesias <francisco.iglesias@xilinx.com>
6+ *
7+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8+ * of this software and associated documentation files (the "Software"), to deal
9+ * in the Software without restriction, including without limitation the rights
10+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+ * copies of the Software, and to permit persons to whom the Software is
12+ * furnished to do so, subject to the following conditions:
13+ *
14+ * The above copyright notice and this permission notice shall be included in
15+ * all copies or substantial portions of the Software.
16+ *
17+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+ * THE SOFTWARE.
24+ */
25+#include "qemu/osdep.h"
26+#include "hw/sysbus.h"
27+#include "migration/vmstate.h"
28+#include "hw/qdev-properties.h"
29+#include "qemu/bitops.h"
30+#include "qemu/log.h"
31+#include "hw/irq.h"
32+#include "hw/ssi/xlnx-versal-ospi.h"
33+
34+#ifndef XILINX_VERSAL_OSPI_ERR_DEBUG
35+#define XILINX_VERSAL_OSPI_ERR_DEBUG 0
36+#endif
37+
38+REG32(CONFIG_REG, 0x0)
39+ FIELD(CONFIG_REG, IDLE_FLD, 31, 1)
40+ FIELD(CONFIG_REG, DUAL_BYTE_OPCODE_EN_FLD, 30, 1)
41+ FIELD(CONFIG_REG, CRC_ENABLE_FLD, 29, 1)
42+ FIELD(CONFIG_REG, CONFIG_RESV2_FLD, 26, 3)
43+ FIELD(CONFIG_REG, PIPELINE_PHY_FLD, 25, 1)
44+ FIELD(CONFIG_REG, ENABLE_DTR_PROTOCOL_FLD, 24, 1)
45+ FIELD(CONFIG_REG, ENABLE_AHB_DECODER_FLD, 23, 1)
46+ FIELD(CONFIG_REG, MSTR_BAUD_DIV_FLD, 19, 4)
47+ FIELD(CONFIG_REG, ENTER_XIP_MODE_IMM_FLD, 18, 1)
48+ FIELD(CONFIG_REG, ENTER_XIP_MODE_FLD, 17, 1)
49+ FIELD(CONFIG_REG, ENB_AHB_ADDR_REMAP_FLD, 16, 1)
50+ FIELD(CONFIG_REG, ENB_DMA_IF_FLD, 15, 1)
51+ FIELD(CONFIG_REG, WR_PROT_FLASH_FLD, 14, 1)
52+ FIELD(CONFIG_REG, PERIPH_CS_LINES_FLD, 10, 4)
53+ FIELD(CONFIG_REG, PERIPH_SEL_DEC_FLD, 9, 1)
54+ FIELD(CONFIG_REG, ENB_LEGACY_IP_MODE_FLD, 8, 1)
55+ FIELD(CONFIG_REG, ENB_DIR_ACC_CTLR_FLD, 7, 1)
56+ FIELD(CONFIG_REG, RESET_CFG_FLD, 6, 1)
57+ FIELD(CONFIG_REG, RESET_PIN_FLD, 5, 1)
58+ FIELD(CONFIG_REG, HOLD_PIN_FLD, 4, 1)
59+ FIELD(CONFIG_REG, PHY_MODE_ENABLE_FLD, 3, 1)
60+ FIELD(CONFIG_REG, SEL_CLK_PHASE_FLD, 2, 1)
61+ FIELD(CONFIG_REG, SEL_CLK_POL_FLD, 1, 1)
62+ FIELD(CONFIG_REG, ENB_SPI_FLD, 0, 1)
63+REG32(DEV_INSTR_RD_CONFIG_REG, 0x4)
64+ FIELD(DEV_INSTR_RD_CONFIG_REG, RD_INSTR_RESV5_FLD, 29, 3)
65+ FIELD(DEV_INSTR_RD_CONFIG_REG, DUMMY_RD_CLK_CYCLES_FLD, 24, 5)
66+ FIELD(DEV_INSTR_RD_CONFIG_REG, RD_INSTR_RESV4_FLD, 21, 3)
67+ FIELD(DEV_INSTR_RD_CONFIG_REG, MODE_BIT_ENABLE_FLD, 20, 1)
68+ FIELD(DEV_INSTR_RD_CONFIG_REG, RD_INSTR_RESV3_FLD, 18, 2)
69+ FIELD(DEV_INSTR_RD_CONFIG_REG, DATA_XFER_TYPE_EXT_MODE_FLD, 16, 2)
70+ FIELD(DEV_INSTR_RD_CONFIG_REG, RD_INSTR_RESV2_FLD, 14, 2)
71+ FIELD(DEV_INSTR_RD_CONFIG_REG, ADDR_XFER_TYPE_STD_MODE_FLD, 12, 2)
72+ FIELD(DEV_INSTR_RD_CONFIG_REG, PRED_DIS_FLD, 11, 1)
73+ FIELD(DEV_INSTR_RD_CONFIG_REG, DDR_EN_FLD, 10, 1)
74+ FIELD(DEV_INSTR_RD_CONFIG_REG, INSTR_TYPE_FLD, 8, 2)
75+ FIELD(DEV_INSTR_RD_CONFIG_REG, RD_OPCODE_NON_XIP_FLD, 0, 8)
76+REG32(DEV_INSTR_WR_CONFIG_REG, 0x8)
77+ FIELD(DEV_INSTR_WR_CONFIG_REG, WR_INSTR_RESV4_FLD, 29, 3)
78+ FIELD(DEV_INSTR_WR_CONFIG_REG, DUMMY_WR_CLK_CYCLES_FLD, 24, 5)
79+ FIELD(DEV_INSTR_WR_CONFIG_REG, WR_INSTR_RESV3_FLD, 18, 6)
80+ FIELD(DEV_INSTR_WR_CONFIG_REG, DATA_XFER_TYPE_EXT_MODE_FLD, 16, 2)
81+ FIELD(DEV_INSTR_WR_CONFIG_REG, WR_INSTR_RESV2_FLD, 14, 2)
82+ FIELD(DEV_INSTR_WR_CONFIG_REG, ADDR_XFER_TYPE_STD_MODE_FLD, 12, 2)
83+ FIELD(DEV_INSTR_WR_CONFIG_REG, WR_INSTR_RESV1_FLD, 9, 3)
84+ FIELD(DEV_INSTR_WR_CONFIG_REG, WEL_DIS_FLD, 8, 1)
85+ FIELD(DEV_INSTR_WR_CONFIG_REG, WR_OPCODE_FLD, 0, 8)
86+REG32(DEV_DELAY_REG, 0xc)
87+ FIELD(DEV_DELAY_REG, D_NSS_FLD, 24, 8)
88+ FIELD(DEV_DELAY_REG, D_BTWN_FLD, 16, 8)
89+ FIELD(DEV_DELAY_REG, D_AFTER_FLD, 8, 8)
90+ FIELD(DEV_DELAY_REG, D_INIT_FLD, 0, 8)
91+REG32(RD_DATA_CAPTURE_REG, 0x10)
92+ FIELD(RD_DATA_CAPTURE_REG, RD_DATA_RESV3_FLD, 20, 12)
93+ FIELD(RD_DATA_CAPTURE_REG, DDR_READ_DELAY_FLD, 16, 4)
94+ FIELD(RD_DATA_CAPTURE_REG, RD_DATA_RESV2_FLD, 9, 7)
95+ FIELD(RD_DATA_CAPTURE_REG, DQS_ENABLE_FLD, 8, 1)
96+ FIELD(RD_DATA_CAPTURE_REG, RD_DATA_RESV1_FLD, 6, 2)
97+ FIELD(RD_DATA_CAPTURE_REG, SAMPLE_EDGE_SEL_FLD, 5, 1)
98+ FIELD(RD_DATA_CAPTURE_REG, DELAY_FLD, 1, 4)
99+ FIELD(RD_DATA_CAPTURE_REG, BYPASS_FLD, 0, 1)
100+REG32(DEV_SIZE_CONFIG_REG, 0x14)
101+ FIELD(DEV_SIZE_CONFIG_REG, DEV_SIZE_RESV_FLD, 29, 3)
102+ FIELD(DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS3_FLD, 27, 2)
103+ FIELD(DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS2_FLD, 25, 2)
104+ FIELD(DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS1_FLD, 23, 2)
105+ FIELD(DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS0_FLD, 21, 2)
106+ FIELD(DEV_SIZE_CONFIG_REG, BYTES_PER_SUBSECTOR_FLD, 16, 5)
107+ FIELD(DEV_SIZE_CONFIG_REG, BYTES_PER_DEVICE_PAGE_FLD, 4, 12)
108+ FIELD(DEV_SIZE_CONFIG_REG, NUM_ADDR_BYTES_FLD, 0, 4)
109+REG32(SRAM_PARTITION_CFG_REG, 0x18)
110+ FIELD(SRAM_PARTITION_CFG_REG, SRAM_PARTITION_RESV_FLD, 8, 24)
111+ FIELD(SRAM_PARTITION_CFG_REG, ADDR_FLD, 0, 8)
112+REG32(IND_AHB_ADDR_TRIGGER_REG, 0x1c)
113+REG32(DMA_PERIPH_CONFIG_REG, 0x20)
114+ FIELD(DMA_PERIPH_CONFIG_REG, DMA_PERIPH_RESV2_FLD, 12, 20)
115+ FIELD(DMA_PERIPH_CONFIG_REG, NUM_BURST_REQ_BYTES_FLD, 8, 4)
116+ FIELD(DMA_PERIPH_CONFIG_REG, DMA_PERIPH_RESV1_FLD, 4, 4)
117+ FIELD(DMA_PERIPH_CONFIG_REG, NUM_SINGLE_REQ_BYTES_FLD, 0, 4)
118+REG32(REMAP_ADDR_REG, 0x24)
119+REG32(MODE_BIT_CONFIG_REG, 0x28)
120+ FIELD(MODE_BIT_CONFIG_REG, RX_CRC_DATA_LOW_FLD, 24, 8)
121+ FIELD(MODE_BIT_CONFIG_REG, RX_CRC_DATA_UP_FLD, 16, 8)
122+ FIELD(MODE_BIT_CONFIG_REG, CRC_OUT_ENABLE_FLD, 15, 1)
123+ FIELD(MODE_BIT_CONFIG_REG, MODE_BIT_RESV1_FLD, 11, 4)
124+ FIELD(MODE_BIT_CONFIG_REG, CHUNK_SIZE_FLD, 8, 3)
125+ FIELD(MODE_BIT_CONFIG_REG, MODE_FLD, 0, 8)
126+REG32(SRAM_FILL_REG, 0x2c)
127+ FIELD(SRAM_FILL_REG, SRAM_FILL_INDAC_WRITE_FLD, 16, 16)
128+ FIELD(SRAM_FILL_REG, SRAM_FILL_INDAC_READ_FLD, 0, 16)
129+REG32(TX_THRESH_REG, 0x30)
130+ FIELD(TX_THRESH_REG, TX_THRESH_RESV_FLD, 5, 27)
131+ FIELD(TX_THRESH_REG, LEVEL_FLD, 0, 5)
132+REG32(RX_THRESH_REG, 0x34)
133+ FIELD(RX_THRESH_REG, RX_THRESH_RESV_FLD, 5, 27)
134+ FIELD(RX_THRESH_REG, LEVEL_FLD, 0, 5)
135+REG32(WRITE_COMPLETION_CTRL_REG, 0x38)
136+ FIELD(WRITE_COMPLETION_CTRL_REG, POLL_REP_DELAY_FLD, 24, 8)
137+ FIELD(WRITE_COMPLETION_CTRL_REG, POLL_COUNT_FLD, 16, 8)
138+ FIELD(WRITE_COMPLETION_CTRL_REG, ENABLE_POLLING_EXP_FLD, 15, 1)
139+ FIELD(WRITE_COMPLETION_CTRL_REG, DISABLE_POLLING_FLD, 14, 1)
140+ FIELD(WRITE_COMPLETION_CTRL_REG, POLLING_POLARITY_FLD, 13, 1)
141+ FIELD(WRITE_COMPLETION_CTRL_REG, WR_COMP_CTRL_RESV1_FLD, 12, 1)
142+ FIELD(WRITE_COMPLETION_CTRL_REG, POLLING_ADDR_EN_FLD, 11, 1)
143+ FIELD(WRITE_COMPLETION_CTRL_REG, POLLING_BIT_INDEX_FLD, 8, 3)
144+ FIELD(WRITE_COMPLETION_CTRL_REG, OPCODE_FLD, 0, 8)
145+REG32(NO_OF_POLLS_BEF_EXP_REG, 0x3c)
146+REG32(IRQ_STATUS_REG, 0x40)
147+ FIELD(IRQ_STATUS_REG, IRQ_STAT_RESV_FLD, 20, 12)
148+ FIELD(IRQ_STATUS_REG, ECC_FAIL_FLD, 19, 1)
149+ FIELD(IRQ_STATUS_REG, TX_CRC_CHUNK_BRK_FLD, 18, 1)
150+ FIELD(IRQ_STATUS_REG, RX_CRC_DATA_VAL_FLD, 17, 1)
151+ FIELD(IRQ_STATUS_REG, RX_CRC_DATA_ERR_FLD, 16, 1)
152+ FIELD(IRQ_STATUS_REG, IRQ_STAT_RESV1_FLD, 15, 1)
153+ FIELD(IRQ_STATUS_REG, STIG_REQ_INT_FLD, 14, 1)
154+ FIELD(IRQ_STATUS_REG, POLL_EXP_INT_FLD, 13, 1)
155+ FIELD(IRQ_STATUS_REG, INDRD_SRAM_FULL_FLD, 12, 1)
156+ FIELD(IRQ_STATUS_REG, RX_FIFO_FULL_FLD, 11, 1)
157+ FIELD(IRQ_STATUS_REG, RX_FIFO_NOT_EMPTY_FLD, 10, 1)
158+ FIELD(IRQ_STATUS_REG, TX_FIFO_FULL_FLD, 9, 1)
159+ FIELD(IRQ_STATUS_REG, TX_FIFO_NOT_FULL_FLD, 8, 1)
160+ FIELD(IRQ_STATUS_REG, RECV_OVERFLOW_FLD, 7, 1)
161+ FIELD(IRQ_STATUS_REG, INDIRECT_XFER_LEVEL_BREACH_FLD, 6, 1)
162+ FIELD(IRQ_STATUS_REG, ILLEGAL_ACCESS_DET_FLD, 5, 1)
163+ FIELD(IRQ_STATUS_REG, PROT_WR_ATTEMPT_FLD, 4, 1)
164+ FIELD(IRQ_STATUS_REG, INDIRECT_TRANSFER_REJECT_FLD, 3, 1)
165+ FIELD(IRQ_STATUS_REG, INDIRECT_OP_DONE_FLD, 2, 1)
166+ FIELD(IRQ_STATUS_REG, UNDERFLOW_DET_FLD, 1, 1)
167+ FIELD(IRQ_STATUS_REG, MODE_M_FAIL_FLD, 0, 1)
168+REG32(IRQ_MASK_REG, 0x44)
169+ FIELD(IRQ_MASK_REG, IRQ_MASK_RESV_FLD, 20, 12)
170+ FIELD(IRQ_MASK_REG, ECC_FAIL_MASK_FLD, 19, 1)
171+ FIELD(IRQ_MASK_REG, TX_CRC_CHUNK_BRK_MASK_FLD, 18, 1)
172+ FIELD(IRQ_MASK_REG, RX_CRC_DATA_VAL_MASK_FLD, 17, 1)
173+ FIELD(IRQ_MASK_REG, RX_CRC_DATA_ERR_MASK_FLD, 16, 1)
174+ FIELD(IRQ_MASK_REG, IRQ_MASK_RESV1_FLD, 15, 1)
175+ FIELD(IRQ_MASK_REG, STIG_REQ_MASK_FLD, 14, 1)
176+ FIELD(IRQ_MASK_REG, POLL_EXP_INT_MASK_FLD, 13, 1)
177+ FIELD(IRQ_MASK_REG, INDRD_SRAM_FULL_MASK_FLD, 12, 1)
178+ FIELD(IRQ_MASK_REG, RX_FIFO_FULL_MASK_FLD, 11, 1)
179+ FIELD(IRQ_MASK_REG, RX_FIFO_NOT_EMPTY_MASK_FLD, 10, 1)
180+ FIELD(IRQ_MASK_REG, TX_FIFO_FULL_MASK_FLD, 9, 1)
181+ FIELD(IRQ_MASK_REG, TX_FIFO_NOT_FULL_MASK_FLD, 8, 1)
182+ FIELD(IRQ_MASK_REG, RECV_OVERFLOW_MASK_FLD, 7, 1)
183+ FIELD(IRQ_MASK_REG, INDIRECT_XFER_LEVEL_BREACH_MASK_FLD, 6, 1)
184+ FIELD(IRQ_MASK_REG, ILLEGAL_ACCESS_DET_MASK_FLD, 5, 1)
185+ FIELD(IRQ_MASK_REG, PROT_WR_ATTEMPT_MASK_FLD, 4, 1)
186+ FIELD(IRQ_MASK_REG, INDIRECT_TRANSFER_REJECT_MASK_FLD, 3, 1)
187+ FIELD(IRQ_MASK_REG, INDIRECT_OP_DONE_MASK_FLD, 2, 1)
188+ FIELD(IRQ_MASK_REG, UNDERFLOW_DET_MASK_FLD, 1, 1)
189+ FIELD(IRQ_MASK_REG, MODE_M_FAIL_MASK_FLD, 0, 1)
190+REG32(LOWER_WR_PROT_REG, 0x50)
191+REG32(UPPER_WR_PROT_REG, 0x54)
192+REG32(WR_PROT_CTRL_REG, 0x58)
193+ FIELD(WR_PROT_CTRL_REG, WR_PROT_CTRL_RESV_FLD, 2, 30)
194+ FIELD(WR_PROT_CTRL_REG, ENB_FLD, 1, 1)
195+ FIELD(WR_PROT_CTRL_REG, INV_FLD, 0, 1)
196+REG32(INDIRECT_READ_XFER_CTRL_REG, 0x60)
197+ FIELD(INDIRECT_READ_XFER_CTRL_REG, INDIR_RD_XFER_RESV_FLD, 8, 24)
198+ FIELD(INDIRECT_READ_XFER_CTRL_REG, NUM_IND_OPS_DONE_FLD, 6, 2)
199+ FIELD(INDIRECT_READ_XFER_CTRL_REG, IND_OPS_DONE_STATUS_FLD, 5, 1)
200+ FIELD(INDIRECT_READ_XFER_CTRL_REG, RD_QUEUED_FLD, 4, 1)
201+ FIELD(INDIRECT_READ_XFER_CTRL_REG, SRAM_FULL_FLD, 3, 1)
202+ FIELD(INDIRECT_READ_XFER_CTRL_REG, RD_STATUS_FLD, 2, 1)
203+ FIELD(INDIRECT_READ_XFER_CTRL_REG, CANCEL_FLD, 1, 1)
204+ FIELD(INDIRECT_READ_XFER_CTRL_REG, START_FLD, 0, 1)
205+REG32(INDIRECT_READ_XFER_WATERMARK_REG, 0x64)
206+REG32(INDIRECT_READ_XFER_START_REG, 0x68)
207+REG32(INDIRECT_READ_XFER_NUM_BYTES_REG, 0x6c)
208+REG32(INDIRECT_WRITE_XFER_CTRL_REG, 0x70)
209+ FIELD(INDIRECT_WRITE_XFER_CTRL_REG, INDIR_WR_XFER_RESV2_FLD, 8, 24)
210+ FIELD(INDIRECT_WRITE_XFER_CTRL_REG, NUM_IND_OPS_DONE_FLD, 6, 2)
211+ FIELD(INDIRECT_WRITE_XFER_CTRL_REG, IND_OPS_DONE_STATUS_FLD, 5, 1)
212+ FIELD(INDIRECT_WRITE_XFER_CTRL_REG, WR_QUEUED_FLD, 4, 1)
213+ FIELD(INDIRECT_WRITE_XFER_CTRL_REG, INDIR_WR_XFER_RESV1_FLD, 3, 1)
214+ FIELD(INDIRECT_WRITE_XFER_CTRL_REG, WR_STATUS_FLD, 2, 1)
215+ FIELD(INDIRECT_WRITE_XFER_CTRL_REG, CANCEL_FLD, 1, 1)
216+ FIELD(INDIRECT_WRITE_XFER_CTRL_REG, START_FLD, 0, 1)
217+REG32(INDIRECT_WRITE_XFER_WATERMARK_REG, 0x74)
218+REG32(INDIRECT_WRITE_XFER_START_REG, 0x78)
219+REG32(INDIRECT_WRITE_XFER_NUM_BYTES_REG, 0x7c)
220+REG32(INDIRECT_TRIGGER_ADDR_RANGE_REG, 0x80)
221+ FIELD(INDIRECT_TRIGGER_ADDR_RANGE_REG, IND_RANGE_RESV1_FLD, 4, 28)
222+ FIELD(INDIRECT_TRIGGER_ADDR_RANGE_REG, IND_RANGE_WIDTH_FLD, 0, 4)
223+REG32(FLASH_COMMAND_CTRL_MEM_REG, 0x8c)
224+ FIELD(FLASH_COMMAND_CTRL_MEM_REG, FLASH_COMMAND_CTRL_MEM_RESV1_FLD, 29, 3)
225+ FIELD(FLASH_COMMAND_CTRL_MEM_REG, MEM_BANK_ADDR_FLD, 20, 9)
226+ FIELD(FLASH_COMMAND_CTRL_MEM_REG, FLASH_COMMAND_CTRL_MEM_RESV2_FLD, 19, 1)
227+ FIELD(FLASH_COMMAND_CTRL_MEM_REG, NB_OF_STIG_READ_BYTES_FLD, 16, 3)
228+ FIELD(FLASH_COMMAND_CTRL_MEM_REG, MEM_BANK_READ_DATA_FLD, 8, 8)
229+ FIELD(FLASH_COMMAND_CTRL_MEM_REG, FLASH_COMMAND_CTRL_MEM_RESV3_FLD, 2, 6)
230+ FIELD(FLASH_COMMAND_CTRL_MEM_REG, MEM_BANK_REQ_IN_PROGRESS_FLD, 1, 1)
231+ FIELD(FLASH_COMMAND_CTRL_MEM_REG, TRIGGER_MEM_BANK_REQ_FLD, 0, 1)
232+REG32(FLASH_CMD_CTRL_REG, 0x90)
233+ FIELD(FLASH_CMD_CTRL_REG, CMD_OPCODE_FLD, 24, 8)
234+ FIELD(FLASH_CMD_CTRL_REG, ENB_READ_DATA_FLD, 23, 1)
235+ FIELD(FLASH_CMD_CTRL_REG, NUM_RD_DATA_BYTES_FLD, 20, 3)
236+ FIELD(FLASH_CMD_CTRL_REG, ENB_COMD_ADDR_FLD, 19, 1)
237+ FIELD(FLASH_CMD_CTRL_REG, ENB_MODE_BIT_FLD, 18, 1)
238+ FIELD(FLASH_CMD_CTRL_REG, NUM_ADDR_BYTES_FLD, 16, 2)
239+ FIELD(FLASH_CMD_CTRL_REG, ENB_WRITE_DATA_FLD, 15, 1)
240+ FIELD(FLASH_CMD_CTRL_REG, NUM_WR_DATA_BYTES_FLD, 12, 3)
241+ FIELD(FLASH_CMD_CTRL_REG, NUM_DUMMY_CYCLES_FLD, 7, 5)
242+ FIELD(FLASH_CMD_CTRL_REG, FLASH_CMD_CTRL_RESV1_FLD, 3, 4)
243+ FIELD(FLASH_CMD_CTRL_REG, STIG_MEM_BANK_EN_FLD, 2, 1)
244+ FIELD(FLASH_CMD_CTRL_REG, CMD_EXEC_STATUS_FLD, 1, 1)
245+ FIELD(FLASH_CMD_CTRL_REG, CMD_EXEC_FLD, 0, 1)
246+REG32(FLASH_CMD_ADDR_REG, 0x94)
247+REG32(FLASH_RD_DATA_LOWER_REG, 0xa0)
248+REG32(FLASH_RD_DATA_UPPER_REG, 0xa4)
249+REG32(FLASH_WR_DATA_LOWER_REG, 0xa8)
250+REG32(FLASH_WR_DATA_UPPER_REG, 0xac)
251+REG32(POLLING_FLASH_STATUS_REG, 0xb0)
252+ FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_RSVD_FLD2, 21, 11)
253+ FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_NB_DUMMY, 16, 5)
254+ FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_RSVD_FLD1, 9, 7)
255+ FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_VALID_FLD, 8, 1)
256+ FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_FLD, 0, 8)
257+REG32(PHY_CONFIGURATION_REG, 0xb4)
258+ FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RESYNC_FLD, 31, 1)
259+ FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RESET_FLD, 30, 1)
260+ FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RX_DLL_BYPASS_FLD, 29, 1)
261+ FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RESV2_FLD, 23, 6)
262+ FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_TX_DLL_DELAY_FLD, 16, 7)
263+ FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RESV1_FLD, 7, 9)
264+ FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RX_DLL_DELAY_FLD, 0, 7)
265+REG32(PHY_MASTER_CONTROL_REG, 0xb8)
266+ FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_CONTROL_RESV3_FLD, 25, 7)
267+ FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_LOCK_MODE_FLD, 24, 1)
268+ FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_BYPASS_MODE_FLD, 23, 1)
269+ FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_PHASE_DETECT_SELECTOR_FLD, 20, 3)
270+ FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_CONTROL_RESV2_FLD, 19, 1)
271+ FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_NB_INDICATIONS_FLD, 16, 3)
272+ FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_CONTROL_RESV1_FLD, 7, 9)
273+ FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_INITIAL_DELAY_FLD, 0, 7)
274+REG32(DLL_OBSERVABLE_LOWER_REG, 0xbc)
275+ FIELD(DLL_OBSERVABLE_LOWER_REG,
276+ DLL_OBSERVABLE_LOWER_DLL_LOCK_INC_FLD, 24, 8)
277+ FIELD(DLL_OBSERVABLE_LOWER_REG,
278+ DLL_OBSERVABLE_LOWER_DLL_LOCK_DEC_FLD, 16, 8)
279+ FIELD(DLL_OBSERVABLE_LOWER_REG,
280+ DLL_OBSERVABLE_LOWER_LOOPBACK_LOCK_FLD, 15, 1)
281+ FIELD(DLL_OBSERVABLE_LOWER_REG,
282+ DLL_OBSERVABLE_LOWER_LOCK_VALUE_FLD, 8, 7)
283+ FIELD(DLL_OBSERVABLE_LOWER_REG,
284+ DLL_OBSERVABLE_LOWER_UNLOCK_COUNTER_FLD, 3, 5)
285+ FIELD(DLL_OBSERVABLE_LOWER_REG,
286+ DLL_OBSERVABLE_LOWER_LOCK_MODE_FLD, 1, 2)
287+ FIELD(DLL_OBSERVABLE_LOWER_REG,
288+ DLL_OBSERVABLE_LOWER_DLL_LOCK_FLD, 0, 1)
289+REG32(DLL_OBSERVABLE_UPPER_REG, 0xc0)
290+ FIELD(DLL_OBSERVABLE_UPPER_REG,
291+ DLL_OBSERVABLE_UPPER_RESV2_FLD, 23, 9)
292+ FIELD(DLL_OBSERVABLE_UPPER_REG,
293+ DLL_OBSERVABLE_UPPER_TX_DECODER_OUTPUT_FLD, 16, 7)
294+ FIELD(DLL_OBSERVABLE_UPPER_REG,
295+ DLL_OBSERVABLE_UPPER_RESV1_FLD, 7, 9)
296+ FIELD(DLL_OBSERVABLE_UPPER_REG,
297+ DLL_OBSERVABLE__UPPER_RX_DECODER_OUTPUT_FLD, 0, 7)
298+REG32(OPCODE_EXT_LOWER_REG, 0xe0)
299+ FIELD(OPCODE_EXT_LOWER_REG, EXT_READ_OPCODE_FLD, 24, 8)
300+ FIELD(OPCODE_EXT_LOWER_REG, EXT_WRITE_OPCODE_FLD, 16, 8)
301+ FIELD(OPCODE_EXT_LOWER_REG, EXT_POLL_OPCODE_FLD, 8, 8)
302+ FIELD(OPCODE_EXT_LOWER_REG, EXT_STIG_OPCODE_FLD, 0, 8)
303+REG32(OPCODE_EXT_UPPER_REG, 0xe4)
304+ FIELD(OPCODE_EXT_UPPER_REG, WEL_OPCODE_FLD, 24, 8)
305+ FIELD(OPCODE_EXT_UPPER_REG, EXT_WEL_OPCODE_FLD, 16, 8)
306+ FIELD(OPCODE_EXT_UPPER_REG, OPCODE_EXT_UPPER_RESV1_FLD, 0, 16)
307+REG32(MODULE_ID_REG, 0xfc)
308+ FIELD(MODULE_ID_REG, FIX_PATCH_FLD, 24, 8)
309+ FIELD(MODULE_ID_REG, MODULE_ID_FLD, 8, 16)
310+ FIELD(MODULE_ID_REG, MODULE_ID_RESV_FLD, 2, 6)
311+ FIELD(MODULE_ID_REG, CONF_FLD, 0, 2)
312+
313+#define RXFF_SZ 1024
314+#define TXFF_SZ 1024
315+
316+#define MAX_RX_DEC_OUT 8
317+
318+#define SZ_512MBIT (512 * 1024 * 1024)
319+#define SZ_1GBIT (1024 * 1024 * 1024)
320+#define SZ_2GBIT (2ULL * SZ_1GBIT)
321+#define SZ_4GBIT (4ULL * SZ_1GBIT)
322+
323+#define IS_IND_DMA_START(op) (op->done_bytes == 0)
324+/*
325+ * Bit field size of R_INDIRECT_WRITE_XFER_CTRL_REG_NUM_IND_OPS_DONE_FLD
326+ * is 2 bits, which can record max of 3 indac operations.
327+ */
328+#define IND_OPS_DONE_MAX 3
329+
330+typedef enum {
331+ WREN = 0x6,
332+} FlashCMD;
333+
334+static unsigned int ospi_stig_addr_len(XlnxVersalOspi *s)
335+{
336+ /* Num address bytes is NUM_ADDR_BYTES_FLD + 1 */
337+ return ARRAY_FIELD_EX32(s->regs,
338+ FLASH_CMD_CTRL_REG, NUM_ADDR_BYTES_FLD) + 1;
339+}
340+
341+static unsigned int ospi_stig_wr_data_len(XlnxVersalOspi *s)
342+{
343+ /* Num write data bytes is NUM_WR_DATA_BYTES_FLD + 1 */
344+ return ARRAY_FIELD_EX32(s->regs,
345+ FLASH_CMD_CTRL_REG, NUM_WR_DATA_BYTES_FLD) + 1;
346+}
347+
348+static unsigned int ospi_stig_rd_data_len(XlnxVersalOspi *s)
349+{
350+ /* Num read data bytes is NUM_RD_DATA_BYTES_FLD + 1 */
351+ return ARRAY_FIELD_EX32(s->regs,
352+ FLASH_CMD_CTRL_REG, NUM_RD_DATA_BYTES_FLD) + 1;
353+}
354+
355+/*
356+ * Status bits in R_IRQ_STATUS_REG are set when the event occurs and the
357+ * interrupt is enabled in the mask register ([1] Section 2.3.17)
358+ */
359+static void set_irq(XlnxVersalOspi *s, uint32_t set_mask)
360+{
361+ s->regs[R_IRQ_STATUS_REG] |= s->regs[R_IRQ_MASK_REG] & set_mask;
362+}
363+
364+static void ospi_update_irq_line(XlnxVersalOspi *s)
365+{
366+ qemu_set_irq(s->irq, !!(s->regs[R_IRQ_STATUS_REG] &
367+ s->regs[R_IRQ_MASK_REG]));
368+}
369+
370+static uint8_t ospi_get_wr_opcode(XlnxVersalOspi *s)
371+{
372+ return ARRAY_FIELD_EX32(s->regs,
373+ DEV_INSTR_WR_CONFIG_REG, WR_OPCODE_FLD);
374+}
375+
376+static uint8_t ospi_get_rd_opcode(XlnxVersalOspi *s)
377+{
378+ return ARRAY_FIELD_EX32(s->regs,
379+ DEV_INSTR_RD_CONFIG_REG, RD_OPCODE_NON_XIP_FLD);
380+}
381+
382+static uint32_t ospi_get_num_addr_bytes(XlnxVersalOspi *s)
383+{
384+ /* Num address bytes is NUM_ADDR_BYTES_FLD + 1 */
385+ return ARRAY_FIELD_EX32(s->regs,
386+ DEV_SIZE_CONFIG_REG, NUM_ADDR_BYTES_FLD) + 1;
387+}
388+
389+static void ospi_stig_membank_req(XlnxVersalOspi *s)
390+{
391+ int idx = ARRAY_FIELD_EX32(s->regs,
392+ FLASH_COMMAND_CTRL_MEM_REG, MEM_BANK_ADDR_FLD);
393+
394+ ARRAY_FIELD_DP32(s->regs, FLASH_COMMAND_CTRL_MEM_REG,
395+ MEM_BANK_READ_DATA_FLD, s->stig_membank[idx]);
396+}
397+
398+static int ospi_stig_membank_rd_bytes(XlnxVersalOspi *s)
399+{
400+ int rd_data_fld = ARRAY_FIELD_EX32(s->regs, FLASH_COMMAND_CTRL_MEM_REG,
401+ NB_OF_STIG_READ_BYTES_FLD);
402+ static const int sizes[6] = { 16, 32, 64, 128, 256, 512 };
403+ return (rd_data_fld < 6) ? sizes[rd_data_fld] : 0;
404+}
405+
406+static uint32_t ospi_get_page_sz(XlnxVersalOspi *s)
407+{
408+ return ARRAY_FIELD_EX32(s->regs,
409+ DEV_SIZE_CONFIG_REG, BYTES_PER_DEVICE_PAGE_FLD);
410+}
411+
412+static bool ospi_ind_rd_watermark_enabled(XlnxVersalOspi *s)
413+{
414+ return s->regs[R_INDIRECT_READ_XFER_WATERMARK_REG];
415+}
416+
417+static void ind_op_advance(IndOp *op, unsigned int len)
418+{
419+ op->done_bytes += len;
420+ assert(op->done_bytes <= op->num_bytes);
421+ if (op->done_bytes == op->num_bytes) {
422+ op->completed = true;
423+ }
424+}
425+
426+static uint32_t ind_op_next_byte(IndOp *op)
427+{
428+ return op->flash_addr + op->done_bytes;
429+}
430+
431+static uint32_t ind_op_end_byte(IndOp *op)
432+{
433+ return op->flash_addr + op->num_bytes;
434+}
435+
436+static void ospi_ind_op_next(IndOp *op)
437+{
438+ op[0] = op[1];
439+ op[1].completed = true;
440+}
441+
442+static void ind_op_setup(IndOp *op, uint32_t flash_addr, uint32_t num_bytes)
443+{
444+ if (num_bytes & 0x3) {
445+ qemu_log_mask(LOG_GUEST_ERROR,
446+ "OSPI indirect op num bytes not word aligned\n");
447+ }
448+ op->flash_addr = flash_addr;
449+ op->num_bytes = num_bytes;
450+ op->done_bytes = 0;
451+ op->completed = false;
452+}
453+
454+static bool ospi_ind_op_completed(IndOp *op)
455+{
456+ return op->completed;
457+}
458+
459+static bool ospi_ind_op_all_completed(XlnxVersalOspi *s)
460+{
461+ return s->rd_ind_op[0].completed && s->wr_ind_op[0].completed;
462+}
463+
464+static void ospi_ind_op_cancel(IndOp *op)
465+{
466+ op[0].completed = true;
467+ op[1].completed = true;
468+}
469+
470+static bool ospi_ind_op_add(IndOp *op, Fifo8 *fifo,
471+ uint32_t flash_addr, uint32_t num_bytes)
472+{
473+ /* Check if first indirect op has been completed */
474+ if (op->completed) {
475+ fifo8_reset(fifo);
476+ ind_op_setup(op, flash_addr, num_bytes);
477+ return false;
478+ }
479+
480+ /* Check if second indirect op has been completed */
481+ op++;
482+ if (op->completed) {
483+ ind_op_setup(op, flash_addr, num_bytes);
484+ return false;
485+ }
486+ return true;
487+}
488+
489+static void ospi_ind_op_queue_up_rd(XlnxVersalOspi *s)
490+{
491+ uint32_t num_bytes = s->regs[R_INDIRECT_READ_XFER_NUM_BYTES_REG];
492+ uint32_t flash_addr = s->regs[R_INDIRECT_READ_XFER_START_REG];
493+ bool failed;
494+
495+ failed = ospi_ind_op_add(s->rd_ind_op, &s->rx_sram, flash_addr, num_bytes);
496+ /* If two already queued set rd reject interrupt */
497+ if (failed) {
498+ set_irq(s, R_IRQ_STATUS_REG_INDIRECT_TRANSFER_REJECT_FLD_MASK);
499+ }
500+}
501+
502+static void ospi_ind_op_queue_up_wr(XlnxVersalOspi *s)
503+{
504+ uint32_t num_bytes = s->regs[R_INDIRECT_WRITE_XFER_NUM_BYTES_REG];
505+ uint32_t flash_addr = s->regs[R_INDIRECT_WRITE_XFER_START_REG];
506+ bool failed;
507+
508+ failed = ospi_ind_op_add(s->wr_ind_op, &s->tx_sram, flash_addr, num_bytes);
509+ /* If two already queued set rd reject interrupt */
510+ if (failed) {
511+ set_irq(s, R_IRQ_STATUS_REG_INDIRECT_TRANSFER_REJECT_FLD_MASK);
512+ }
513+}
514+
515+static uint64_t flash_sz(XlnxVersalOspi *s, unsigned int cs)
516+{
517+ /* Flash sizes in MB */
518+ static const uint64_t sizes[4] = { SZ_512MBIT / 8, SZ_1GBIT / 8,
519+ SZ_2GBIT / 8, SZ_4GBIT / 8 };
520+ uint32_t v = s->regs[R_DEV_SIZE_CONFIG_REG];
521+
522+ v >>= cs * R_DEV_SIZE_CONFIG_REG_MEM_SIZE_ON_CS0_FLD_LENGTH;
523+ return sizes[FIELD_EX32(v, DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS0_FLD)];
524+}
525+
526+static unsigned int ospi_get_block_sz(XlnxVersalOspi *s)
527+{
528+ unsigned int block_fld = ARRAY_FIELD_EX32(s->regs,
529+ DEV_SIZE_CONFIG_REG,
530+ BYTES_PER_SUBSECTOR_FLD);
531+ return 1 << block_fld;
532+}
533+
534+static unsigned int flash_blocks(XlnxVersalOspi *s, unsigned int cs)
535+{
536+ unsigned int b_sz = ospi_get_block_sz(s);
537+ unsigned int f_sz = flash_sz(s, cs);
538+
539+ return f_sz / b_sz;
540+}
541+
542+static int ospi_ahb_decoder_cs(XlnxVersalOspi *s, hwaddr addr)
543+{
544+ uint64_t end_addr = 0;
545+ int cs;
546+
547+ for (cs = 0; cs < s->num_cs; cs++) {
548+ end_addr += flash_sz(s, cs);
549+ if (addr < end_addr) {
550+ break;
551+ }
552+ }
553+
554+ if (cs == s->num_cs) {
555+ /* Address is out of range */
556+ qemu_log_mask(LOG_GUEST_ERROR,
557+ "OSPI flash address does not fit in configuration\n");
558+ return -1;
559+ }
560+ return cs;
561+}
562+
563+static void ospi_ahb_decoder_enable_cs(XlnxVersalOspi *s, hwaddr addr)
564+{
565+ int cs = ospi_ahb_decoder_cs(s, addr);
566+
567+ if (cs >= 0) {
568+ for (int i = 0; i < s->num_cs; i++) {
569+ qemu_set_irq(s->cs_lines[i], cs != i);
570+ }
571+ }
572+}
573+
574+static unsigned int single_cs(XlnxVersalOspi *s)
575+{
576+ unsigned int field = ARRAY_FIELD_EX32(s->regs,
577+ CONFIG_REG, PERIPH_CS_LINES_FLD);
578+
579+ /*
580+ * Below one liner is a trick that finds the rightmost zero and makes sure
581+ * all other bits are turned to 1. It is a variant of the 'Isolate the
582+ * rightmost 0-bit' trick found below at the time of writing:
583+ *
584+ * https://emre.me/computer-science/bit-manipulation-tricks/
585+ *
586+ * 4'bXXX0 -> 4'b1110
587+ * 4'bXX01 -> 4'b1101
588+ * 4'bX011 -> 4'b1011
589+ * 4'b0111 -> 4'b0111
590+ * 4'b1111 -> 4'b1111
591+ */
592+ return (field | ~(field + 1)) & 0xf;
593+}
594+
595+static void ospi_update_cs_lines(XlnxVersalOspi *s)
596+{
597+ unsigned int all_cs;
598+ int i;
599+
600+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, PERIPH_SEL_DEC_FLD)) {
601+ all_cs = ARRAY_FIELD_EX32(s->regs, CONFIG_REG, PERIPH_CS_LINES_FLD);
602+ } else {
603+ all_cs = single_cs(s);
604+ }
605+
606+ for (i = 0; i < s->num_cs; i++) {
607+ bool cs = (all_cs >> i) & 1;
608+
609+ qemu_set_irq(s->cs_lines[i], cs);
610+ }
611+}
612+
613+static void ospi_dac_cs(XlnxVersalOspi *s, hwaddr addr)
614+{
615+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENABLE_AHB_DECODER_FLD)) {
616+ ospi_ahb_decoder_enable_cs(s, addr);
617+ } else {
618+ ospi_update_cs_lines(s);
619+ }
620+}
621+
622+static void ospi_disable_cs(XlnxVersalOspi *s)
623+{
624+ int i;
625+
626+ for (i = 0; i < s->num_cs; i++) {
627+ qemu_set_irq(s->cs_lines[i], 1);
628+ }
629+}
630+
631+static void ospi_flush_txfifo(XlnxVersalOspi *s)
632+{
633+ while (!fifo8_is_empty(&s->tx_fifo)) {
634+ uint32_t tx_rx = fifo8_pop(&s->tx_fifo);
635+
636+ tx_rx = ssi_transfer(s->spi, tx_rx);
637+ fifo8_push(&s->rx_fifo, tx_rx);
638+ }
639+}
640+
641+static void ospi_tx_fifo_push_address_raw(XlnxVersalOspi *s,
642+ uint32_t flash_addr,
643+ unsigned int addr_bytes)
644+{
645+ /* Push write address */
646+ if (addr_bytes == 4) {
647+ fifo8_push(&s->tx_fifo, flash_addr >> 24);
648+ }
649+ if (addr_bytes >= 3) {
650+ fifo8_push(&s->tx_fifo, flash_addr >> 16);
651+ }
652+ if (addr_bytes >= 2) {
653+ fifo8_push(&s->tx_fifo, flash_addr >> 8);
654+ }
655+ fifo8_push(&s->tx_fifo, flash_addr);
656+}
657+
658+static void ospi_tx_fifo_push_address(XlnxVersalOspi *s, uint32_t flash_addr)
659+{
660+ /* Push write address */
661+ int addr_bytes = ospi_get_num_addr_bytes(s);
662+
663+ ospi_tx_fifo_push_address_raw(s, flash_addr, addr_bytes);
664+}
665+
666+static void ospi_tx_fifo_push_stig_addr(XlnxVersalOspi *s)
667+{
668+ uint32_t flash_addr = s->regs[R_FLASH_CMD_ADDR_REG];
669+ unsigned int addr_bytes = ospi_stig_addr_len(s);
670+
671+ ospi_tx_fifo_push_address_raw(s, flash_addr, addr_bytes);
672+}
673+
674+static void ospi_tx_fifo_push_rd_op_addr(XlnxVersalOspi *s, uint32_t flash_addr)
675+{
676+ uint8_t inst_code = ospi_get_rd_opcode(s);
677+
678+ fifo8_reset(&s->tx_fifo);
679+
680+ /* Push read opcode */
681+ fifo8_push(&s->tx_fifo, inst_code);
682+
683+ /* Push read address */
684+ ospi_tx_fifo_push_address(s, flash_addr);
685+}
686+
687+static void ospi_tx_fifo_push_stig_wr_data(XlnxVersalOspi *s)
688+{
689+ uint64_t data = s->regs[R_FLASH_WR_DATA_LOWER_REG];
690+ int wr_data_len = ospi_stig_wr_data_len(s);
691+ int i;
692+
693+ data |= (uint64_t) s->regs[R_FLASH_WR_DATA_UPPER_REG] << 32;
694+ for (i = 0; i < wr_data_len; i++) {
695+ int shift = i * 8;
696+ fifo8_push(&s->tx_fifo, data >> shift);
697+ }
698+}
699+
700+static void ospi_tx_fifo_push_stig_rd_data(XlnxVersalOspi *s)
701+{
702+ int rd_data_len;
703+ int i;
704+
705+ if (ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, STIG_MEM_BANK_EN_FLD)) {
706+ rd_data_len = ospi_stig_membank_rd_bytes(s);
707+ } else {
708+ rd_data_len = ospi_stig_rd_data_len(s);
709+ }
710+
711+ /* transmit second part (data) */
712+ for (i = 0; i < rd_data_len; ++i) {
713+ fifo8_push(&s->tx_fifo, 0);
714+ }
715+}
716+
717+static void ospi_rx_fifo_pop_stig_rd_data(XlnxVersalOspi *s)
718+{
719+ int size = ospi_stig_rd_data_len(s);
720+ uint8_t bytes[8] = {};
721+ int i;
722+
723+ size = MIN(fifo8_num_used(&s->rx_fifo), size);
724+
725+ assert(size <= 8);
726+
727+ for (i = 0; i < size; i++) {
728+ bytes[i] = fifo8_pop(&s->rx_fifo);
729+ }
730+
731+ s->regs[R_FLASH_RD_DATA_LOWER_REG] = ldl_le_p(bytes);
732+ s->regs[R_FLASH_RD_DATA_UPPER_REG] = ldl_le_p(bytes + 4);
733+}
734+
735+static void ospi_ind_read(XlnxVersalOspi *s, uint32_t flash_addr, uint32_t len)
736+{
737+ int i;
738+
739+ /* Create first section of read cmd */
740+ ospi_tx_fifo_push_rd_op_addr(s, flash_addr);
741+
742+ /* transmit first part */
743+ ospi_update_cs_lines(s);
744+ ospi_flush_txfifo(s);
745+
746+ fifo8_reset(&s->rx_fifo);
747+
748+ /* transmit second part (data) */
749+ for (i = 0; i < len; ++i) {
750+ fifo8_push(&s->tx_fifo, 0);
751+ }
752+ ospi_flush_txfifo(s);
753+
754+ for (i = 0; i < len; ++i) {
755+ fifo8_push(&s->rx_sram, fifo8_pop(&s->rx_fifo));
756+ }
757+
758+ /* done */
759+ ospi_disable_cs(s);
760+}
761+
762+static unsigned int ospi_dma_burst_size(XlnxVersalOspi *s)
763+{
764+ return 1 << ARRAY_FIELD_EX32(s->regs,
765+ DMA_PERIPH_CONFIG_REG,
766+ NUM_BURST_REQ_BYTES_FLD);
767+}
768+
769+static unsigned int ospi_dma_single_size(XlnxVersalOspi *s)
770+{
771+ return 1 << ARRAY_FIELD_EX32(s->regs,
772+ DMA_PERIPH_CONFIG_REG,
773+ NUM_SINGLE_REQ_BYTES_FLD);
774+}
775+
776+static void ind_rd_inc_num_done(XlnxVersalOspi *s)
777+{
778+ unsigned int done = ARRAY_FIELD_EX32(s->regs,
779+ INDIRECT_READ_XFER_CTRL_REG,
780+ NUM_IND_OPS_DONE_FLD);
781+ if (done < IND_OPS_DONE_MAX) {
782+ done++;
783+ }
784+ done &= 0x3;
785+ ARRAY_FIELD_DP32(s->regs, INDIRECT_READ_XFER_CTRL_REG,
786+ NUM_IND_OPS_DONE_FLD, done);
787+}
788+
789+static void ospi_ind_rd_completed(XlnxVersalOspi *s)
790+{
791+ ARRAY_FIELD_DP32(s->regs, INDIRECT_READ_XFER_CTRL_REG,
792+ IND_OPS_DONE_STATUS_FLD, 1);
793+
794+ ind_rd_inc_num_done(s);
795+ ospi_ind_op_next(s->rd_ind_op);
796+ if (ospi_ind_op_all_completed(s)) {
797+ set_irq(s, R_IRQ_STATUS_REG_INDIRECT_OP_DONE_FLD_MASK);
798+ }
799+}
800+
801+static void ospi_dma_read(XlnxVersalOspi *s)
802+{
803+ IndOp *op = s->rd_ind_op;
804+ uint32_t dma_len = op->num_bytes;
805+ uint32_t burst_sz = ospi_dma_burst_size(s);
806+ uint32_t single_sz = ospi_dma_single_size(s);
807+ uint32_t ind_trig_range;
808+ uint32_t remainder;
809+ XlnxCSUDMAClass *xcdc = XLNX_CSU_DMA_GET_CLASS(s->dma_src);
810+
811+ ind_trig_range = (1 << ARRAY_FIELD_EX32(s->regs,
812+ INDIRECT_TRIGGER_ADDR_RANGE_REG,
813+ IND_RANGE_WIDTH_FLD));
814+ remainder = dma_len % burst_sz;
815+ remainder = remainder % single_sz;
816+ if (burst_sz > ind_trig_range || single_sz > ind_trig_range ||
817+ remainder != 0) {
818+ qemu_log_mask(LOG_GUEST_ERROR,
819+ "OSPI DMA burst size / single size config error\n");
820+ }
821+
822+ s->src_dma_inprog = true;
823+ if (xcdc->read(s->dma_src, 0, dma_len) != MEMTX_OK) {
824+ qemu_log_mask(LOG_GUEST_ERROR, "OSPI DMA configuration error\n");
825+ }
826+ s->src_dma_inprog = false;
827+}
828+
829+static void ospi_do_ind_read(XlnxVersalOspi *s)
830+{
831+ IndOp *op = s->rd_ind_op;
832+ uint32_t next_b;
833+ uint32_t end_b;
834+ uint32_t len;
835+ bool start_dma = IS_IND_DMA_START(op) && !s->src_dma_inprog;
836+
837+ /* Continue to read flash until we run out of space in sram */
838+ while (!ospi_ind_op_completed(op) &&
839+ !fifo8_is_full(&s->rx_sram)) {
840+ /* Read reqested number of bytes, max bytes limited to size of sram */
841+ next_b = ind_op_next_byte(op);
842+ end_b = next_b + fifo8_num_free(&s->rx_sram);
843+ end_b = MIN(end_b, ind_op_end_byte(op));
844+
845+ len = end_b - next_b;
846+ ospi_ind_read(s, next_b, len);
847+ ind_op_advance(op, len);
848+
849+ if (ospi_ind_rd_watermark_enabled(s)) {
850+ ARRAY_FIELD_DP32(s->regs, IRQ_STATUS_REG,
851+ INDIRECT_XFER_LEVEL_BREACH_FLD, 1);
852+ set_irq(s,
853+ R_IRQ_STATUS_REG_INDIRECT_XFER_LEVEL_BREACH_FLD_MASK);
854+ }
855+
856+ if (!s->src_dma_inprog &&
857+ ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DMA_IF_FLD)) {
858+ ospi_dma_read(s);
859+ }
860+ }
861+
862+ /* Set sram full */
863+ if (fifo8_num_used(&s->rx_sram) == RXFF_SZ) {
864+ ARRAY_FIELD_DP32(s->regs,
865+ INDIRECT_READ_XFER_CTRL_REG, SRAM_FULL_FLD, 1);
866+ set_irq(s, R_IRQ_STATUS_REG_INDRD_SRAM_FULL_FLD_MASK);
867+ }
868+
869+ /* Signal completion if done, unless inside recursion via ospi_dma_read */
870+ if (!ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DMA_IF_FLD) || start_dma) {
871+ if (ospi_ind_op_completed(op)) {
872+ ospi_ind_rd_completed(s);
873+ }
874+ }
875+}
876+
877+/* Transmit write enable instruction */
878+static void ospi_transmit_wel(XlnxVersalOspi *s, bool ahb_decoder_cs,
879+ hwaddr addr)
880+{
881+ fifo8_reset(&s->tx_fifo);
882+ fifo8_push(&s->tx_fifo, WREN);
883+
884+ if (ahb_decoder_cs) {
885+ ospi_ahb_decoder_enable_cs(s, addr);
886+ } else {
887+ ospi_update_cs_lines(s);
888+ }
889+
890+ ospi_flush_txfifo(s);
891+ ospi_disable_cs(s);
892+
893+ fifo8_reset(&s->rx_fifo);
894+}
895+
896+static void ospi_ind_write(XlnxVersalOspi *s, uint32_t flash_addr, uint32_t len)
897+{
898+ bool ahb_decoder_cs = false;
899+ uint8_t inst_code;
900+ int i;
901+
902+ assert(fifo8_num_used(&s->tx_sram) >= len);
903+
904+ if (!ARRAY_FIELD_EX32(s->regs, DEV_INSTR_WR_CONFIG_REG, WEL_DIS_FLD)) {
905+ ospi_transmit_wel(s, ahb_decoder_cs, 0);
906+ }
907+
908+ /* reset fifos */
909+ fifo8_reset(&s->tx_fifo);
910+ fifo8_reset(&s->rx_fifo);
911+
912+ /* Push write opcode */
913+ inst_code = ospi_get_wr_opcode(s);
914+ fifo8_push(&s->tx_fifo, inst_code);
915+
916+ /* Push write address */
917+ ospi_tx_fifo_push_address(s, flash_addr);
918+
919+ /* data */
920+ for (i = 0; i < len; i++) {
921+ fifo8_push(&s->tx_fifo, fifo8_pop(&s->tx_sram));
922+ }
923+
924+ /* transmit */
925+ ospi_update_cs_lines(s);
926+ ospi_flush_txfifo(s);
927+
928+ /* done */
929+ ospi_disable_cs(s);
930+ fifo8_reset(&s->rx_fifo);
931+}
932+
933+static void ind_wr_inc_num_done(XlnxVersalOspi *s)
934+{
935+ unsigned int done = ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG,
936+ NUM_IND_OPS_DONE_FLD);
937+ if (done < IND_OPS_DONE_MAX) {
938+ done++;
939+ }
940+ done &= 0x3;
941+ ARRAY_FIELD_DP32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG,
942+ NUM_IND_OPS_DONE_FLD, done);
943+}
944+
945+static void ospi_ind_wr_completed(XlnxVersalOspi *s)
946+{
947+ ARRAY_FIELD_DP32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG,
948+ IND_OPS_DONE_STATUS_FLD, 1);
949+ ind_wr_inc_num_done(s);
950+ ospi_ind_op_next(s->wr_ind_op);
951+ /* Set indirect op done interrupt if enabled */
952+ if (ospi_ind_op_all_completed(s)) {
953+ set_irq(s, R_IRQ_STATUS_REG_INDIRECT_OP_DONE_FLD_MASK);
954+ }
955+}
956+
957+static void ospi_do_indirect_write(XlnxVersalOspi *s)
958+{
959+ uint32_t write_watermark = s->regs[R_INDIRECT_WRITE_XFER_WATERMARK_REG];
960+ uint32_t pagesz = ospi_get_page_sz(s);
961+ uint32_t page_mask = ~(pagesz - 1);
962+ IndOp *op = s->wr_ind_op;
963+ uint32_t next_b;
964+ uint32_t end_b;
965+ uint32_t len;
966+
967+ /* Write out tx_fifo in maximum page sz chunks */
968+ while (!ospi_ind_op_completed(op) && fifo8_num_used(&s->tx_sram) > 0) {
969+ next_b = ind_op_next_byte(op);
970+ end_b = next_b + MIN(fifo8_num_used(&s->tx_sram), pagesz);
971+
972+ /* Dont cross page boundary */
973+ if ((end_b & page_mask) > next_b) {
974+ end_b &= page_mask;
975+ }
976+
977+ len = end_b - next_b;
978+ len = MIN(len, op->num_bytes - op->done_bytes);
979+ ospi_ind_write(s, next_b, len);
980+ ind_op_advance(op, len);
981+ }
982+
983+ /*
984+ * Always set indirect transfer level breached interrupt if enabled
985+ * (write watermark > 0) since the tx_sram always will be emptied
986+ */
987+ if (write_watermark > 0) {
988+ set_irq(s, R_IRQ_STATUS_REG_INDIRECT_XFER_LEVEL_BREACH_FLD_MASK);
989+ }
990+
991+ /* Signal completions if done */
992+ if (ospi_ind_op_completed(op)) {
993+ ospi_ind_wr_completed(s);
994+ }
995+}
996+
997+static void ospi_stig_fill_membank(XlnxVersalOspi *s)
998+{
999+ int num_rd_bytes = ospi_stig_membank_rd_bytes(s);
1000+ int idx = num_rd_bytes - 8; /* first of last 8 */
1001+ int i;
1002+
1003+ for (i = 0; i < num_rd_bytes; i++) {
1004+ s->stig_membank[i] = fifo8_pop(&s->rx_fifo);
1005+ }
1006+
1007+ g_assert((idx + 4) < ARRAY_SIZE(s->stig_membank));
1008+
1009+ /* Fill in lower upper regs */
1010+ s->regs[R_FLASH_RD_DATA_LOWER_REG] = ldl_le_p(&s->stig_membank[idx]);
1011+ s->regs[R_FLASH_RD_DATA_UPPER_REG] = ldl_le_p(&s->stig_membank[idx + 4]);
1012+}
1013+
1014+static void ospi_stig_cmd_exec(XlnxVersalOspi *s)
1015+{
1016+ uint8_t inst_code;
1017+
1018+ /* Reset fifos */
1019+ fifo8_reset(&s->tx_fifo);
1020+ fifo8_reset(&s->rx_fifo);
1021+
1022+ /* Push write opcode */
1023+ inst_code = ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, CMD_OPCODE_FLD);
1024+ fifo8_push(&s->tx_fifo, inst_code);
1025+
1026+ /* Push address if enabled */
1027+ if (ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, ENB_COMD_ADDR_FLD)) {
1028+ ospi_tx_fifo_push_stig_addr(s);
1029+ }
1030+
1031+ /* Enable cs */
1032+ ospi_update_cs_lines(s);
1033+
1034+ /* Data */
1035+ if (ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, ENB_WRITE_DATA_FLD)) {
1036+ ospi_tx_fifo_push_stig_wr_data(s);
1037+ } else if (ARRAY_FIELD_EX32(s->regs,
1038+ FLASH_CMD_CTRL_REG, ENB_READ_DATA_FLD)) {
1039+ /* transmit first part */
1040+ ospi_flush_txfifo(s);
1041+ fifo8_reset(&s->rx_fifo);
1042+ ospi_tx_fifo_push_stig_rd_data(s);
1043+ }
1044+
1045+ /* Transmit */
1046+ ospi_flush_txfifo(s);
1047+ ospi_disable_cs(s);
1048+
1049+ if (ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, ENB_READ_DATA_FLD)) {
1050+ if (ARRAY_FIELD_EX32(s->regs,
1051+ FLASH_CMD_CTRL_REG, STIG_MEM_BANK_EN_FLD)) {
1052+ ospi_stig_fill_membank(s);
1053+ } else {
1054+ ospi_rx_fifo_pop_stig_rd_data(s);
1055+ }
1056+ }
1057+}
1058+
1059+static uint32_t ospi_block_address(XlnxVersalOspi *s, unsigned int block)
1060+{
1061+ unsigned int block_sz = ospi_get_block_sz(s);
1062+ unsigned int cs = 0;
1063+ uint32_t addr = 0;
1064+
1065+ while (cs < s->num_cs && block >= flash_blocks(s, cs)) {
1066+ block -= flash_blocks(s, 0);
1067+ addr += flash_sz(s, cs);
1068+ }
1069+ addr += block * block_sz;
1070+ return addr;
1071+}
1072+
1073+static uint32_t ospi_get_wr_prot_addr_low(XlnxVersalOspi *s)
1074+{
1075+ unsigned int block = s->regs[R_LOWER_WR_PROT_REG];
1076+
1077+ return ospi_block_address(s, block);
1078+}
1079+
1080+static uint32_t ospi_get_wr_prot_addr_upper(XlnxVersalOspi *s)
1081+{
1082+ unsigned int block = s->regs[R_UPPER_WR_PROT_REG];
1083+
1084+ /* Get address of first block out of defined range */
1085+ return ospi_block_address(s, block + 1);
1086+}
1087+
1088+static bool ospi_is_write_protected(XlnxVersalOspi *s, hwaddr addr)
1089+{
1090+ uint32_t wr_prot_addr_upper = ospi_get_wr_prot_addr_upper(s);
1091+ uint32_t wr_prot_addr_low = ospi_get_wr_prot_addr_low(s);
1092+ bool in_range = false;
1093+
1094+ if (addr >= wr_prot_addr_low && addr < wr_prot_addr_upper) {
1095+ in_range = true;
1096+ }
1097+
1098+ if (ARRAY_FIELD_EX32(s->regs, WR_PROT_CTRL_REG, INV_FLD)) {
1099+ in_range = !in_range;
1100+ }
1101+ return in_range;
1102+}
1103+
1104+static uint64_t ospi_rx_sram_read(XlnxVersalOspi *s, unsigned int size)
1105+{
1106+ uint8_t bytes[8] = {};
1107+ int i;
1108+
1109+ if (size < 4 && fifo8_num_used(&s->rx_sram) >= 4) {
1110+ qemu_log_mask(LOG_GUEST_ERROR,
1111+ "OSPI only last read of internal "
1112+ "sram is allowed to be < 32 bits\n");
1113+ }
1114+
1115+ size = MIN(fifo8_num_used(&s->rx_sram), size);
1116+
1117+ assert(size <= 8);
1118+
1119+ for (i = 0; i < size; i++) {
1120+ bytes[i] = fifo8_pop(&s->rx_sram);
1121+ }
1122+
1123+ return ldq_le_p(bytes);
1124+}
1125+
1126+static void ospi_tx_sram_write(XlnxVersalOspi *s, uint64_t value,
1127+ unsigned int size)
1128+{
1129+ int i;
1130+ for (i = 0; i < size && !fifo8_is_full(&s->tx_sram); i++) {
1131+ fifo8_push(&s->tx_sram, value >> 8 * i);
1132+ }
1133+}
1134+
1135+static uint64_t ospi_do_dac_read(void *opaque, hwaddr addr, unsigned int size)
1136+{
1137+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque);
1138+ uint8_t bytes[8] = {};
1139+ int i;
1140+
1141+ /* Create first section of read cmd */
1142+ ospi_tx_fifo_push_rd_op_addr(s, (uint32_t) addr);
1143+
1144+ /* Enable cs and transmit first part */
1145+ ospi_dac_cs(s, addr);
1146+ ospi_flush_txfifo(s);
1147+
1148+ fifo8_reset(&s->rx_fifo);
1149+
1150+ /* transmit second part (data) */
1151+ for (i = 0; i < size; ++i) {
1152+ fifo8_push(&s->tx_fifo, 0);
1153+ }
1154+ ospi_flush_txfifo(s);
1155+
1156+ /* fill in result */
1157+ size = MIN(fifo8_num_used(&s->rx_fifo), size);
1158+
1159+ assert(size <= 8);
1160+
1161+ for (i = 0; i < size; i++) {
1162+ bytes[i] = fifo8_pop(&s->rx_fifo);
1163+ }
1164+
1165+ /* done */
1166+ ospi_disable_cs(s);
1167+
1168+ return ldq_le_p(bytes);
1169+}
1170+
1171+static void ospi_do_dac_write(void *opaque,
1172+ hwaddr addr,
1173+ uint64_t value,
1174+ unsigned int size)
1175+{
1176+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque);
1177+ bool ahb_decoder_cs = ARRAY_FIELD_EX32(s->regs, CONFIG_REG,
1178+ ENABLE_AHB_DECODER_FLD);
1179+ uint8_t inst_code;
1180+ unsigned int i;
1181+
1182+ if (!ARRAY_FIELD_EX32(s->regs, DEV_INSTR_WR_CONFIG_REG, WEL_DIS_FLD)) {
1183+ ospi_transmit_wel(s, ahb_decoder_cs, addr);
1184+ }
1185+
1186+ /* reset fifos */
1187+ fifo8_reset(&s->tx_fifo);
1188+ fifo8_reset(&s->rx_fifo);
1189+
1190+ /* Push write opcode */
1191+ inst_code = ospi_get_wr_opcode(s);
1192+ fifo8_push(&s->tx_fifo, inst_code);
1193+
1194+ /* Push write address */
1195+ ospi_tx_fifo_push_address(s, addr);
1196+
1197+ /* data */
1198+ for (i = 0; i < size; i++) {
1199+ fifo8_push(&s->tx_fifo, value >> 8 * i);
1200+ }
1201+
1202+ /* Enable cs and transmit */
1203+ ospi_dac_cs(s, addr);
1204+ ospi_flush_txfifo(s);
1205+ ospi_disable_cs(s);
1206+
1207+ fifo8_reset(&s->rx_fifo);
1208+}
1209+
1210+static void flash_cmd_ctrl_mem_reg_post_write(RegisterInfo *reg,
1211+ uint64_t val)
1212+{
1213+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1214+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_SPI_FLD)) {
1215+ if (ARRAY_FIELD_EX32(s->regs,
1216+ FLASH_COMMAND_CTRL_MEM_REG,
1217+ TRIGGER_MEM_BANK_REQ_FLD)) {
1218+ ospi_stig_membank_req(s);
1219+ ARRAY_FIELD_DP32(s->regs, FLASH_COMMAND_CTRL_MEM_REG,
1220+ TRIGGER_MEM_BANK_REQ_FLD, 0);
1221+ }
1222+ }
1223+}
1224+
1225+static void flash_cmd_ctrl_reg_post_write(RegisterInfo *reg, uint64_t val)
1226+{
1227+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1228+
1229+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_SPI_FLD) &&
1230+ ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, CMD_EXEC_FLD)) {
1231+ ospi_stig_cmd_exec(s);
1232+ set_irq(s, R_IRQ_STATUS_REG_STIG_REQ_INT_FLD_MASK);
1233+ ARRAY_FIELD_DP32(s->regs, FLASH_CMD_CTRL_REG, CMD_EXEC_FLD, 0);
1234+ }
1235+}
1236+
1237+static uint64_t ind_wr_dec_num_done(XlnxVersalOspi *s, uint64_t val)
1238+{
1239+ unsigned int done = ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG,
1240+ NUM_IND_OPS_DONE_FLD);
1241+ done--;
1242+ done &= 0x3;
1243+ val = FIELD_DP32(val, INDIRECT_WRITE_XFER_CTRL_REG,
1244+ NUM_IND_OPS_DONE_FLD, done);
1245+ return val;
1246+}
1247+
1248+static bool ind_wr_clearing_op_done(XlnxVersalOspi *s, uint64_t new_val)
1249+{
1250+ bool set_in_reg = ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG,
1251+ IND_OPS_DONE_STATUS_FLD);
1252+ bool set_in_new_val = FIELD_EX32(new_val, INDIRECT_WRITE_XFER_CTRL_REG,
1253+ IND_OPS_DONE_STATUS_FLD);
1254+ /* return true if clearing bit */
1255+ return set_in_reg && !set_in_new_val;
1256+}
1257+
1258+static uint64_t ind_wr_xfer_ctrl_reg_pre_write(RegisterInfo *reg,
1259+ uint64_t val)
1260+{
1261+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1262+
1263+ if (ind_wr_clearing_op_done(s, val)) {
1264+ val = ind_wr_dec_num_done(s, val);
1265+ }
1266+ return val;
1267+}
1268+
1269+static void ind_wr_xfer_ctrl_reg_post_write(RegisterInfo *reg, uint64_t val)
1270+{
1271+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1272+
1273+ if (s->ind_write_disabled) {
1274+ return;
1275+ }
1276+
1277+ if (ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, START_FLD)) {
1278+ ospi_ind_op_queue_up_wr(s);
1279+ ospi_do_indirect_write(s);
1280+ ARRAY_FIELD_DP32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, START_FLD, 0);
1281+ }
1282+
1283+ if (ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, CANCEL_FLD)) {
1284+ ospi_ind_op_cancel(s->wr_ind_op);
1285+ fifo8_reset(&s->tx_sram);
1286+ ARRAY_FIELD_DP32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, CANCEL_FLD, 0);
1287+ }
1288+}
1289+
1290+static uint64_t ind_wr_xfer_ctrl_reg_post_read(RegisterInfo *reg,
1291+ uint64_t val)
1292+{
1293+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1294+ IndOp *op = s->wr_ind_op;
1295+
1296+ /* Check if ind ops is ongoing */
1297+ if (!ospi_ind_op_completed(&op[0])) {
1298+ /* Check if two ind ops are queued */
1299+ if (!ospi_ind_op_completed(&op[1])) {
1300+ val = FIELD_DP32(val, INDIRECT_WRITE_XFER_CTRL_REG,
1301+ WR_QUEUED_FLD, 1);
1302+ }
1303+ val = FIELD_DP32(val, INDIRECT_WRITE_XFER_CTRL_REG, WR_STATUS_FLD, 1);
1304+ }
1305+ return val;
1306+}
1307+
1308+static uint64_t ind_rd_dec_num_done(XlnxVersalOspi *s, uint64_t val)
1309+{
1310+ unsigned int done = ARRAY_FIELD_EX32(s->regs, INDIRECT_READ_XFER_CTRL_REG,
1311+ NUM_IND_OPS_DONE_FLD);
1312+ done--;
1313+ done &= 0x3;
1314+ val = FIELD_DP32(val, INDIRECT_READ_XFER_CTRL_REG,
1315+ NUM_IND_OPS_DONE_FLD, done);
1316+ return val;
1317+}
1318+
1319+static uint64_t ind_rd_xfer_ctrl_reg_pre_write(RegisterInfo *reg,
1320+ uint64_t val)
1321+{
1322+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1323+
1324+ if (FIELD_EX32(val, INDIRECT_READ_XFER_CTRL_REG,
1325+ IND_OPS_DONE_STATUS_FLD)) {
1326+ val = ind_rd_dec_num_done(s, val);
1327+ val &= ~R_INDIRECT_READ_XFER_CTRL_REG_IND_OPS_DONE_STATUS_FLD_MASK;
1328+ }
1329+ return val;
1330+}
1331+
1332+static void ind_rd_xfer_ctrl_reg_post_write(RegisterInfo *reg, uint64_t val)
1333+{
1334+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1335+
1336+ if (ARRAY_FIELD_EX32(s->regs, INDIRECT_READ_XFER_CTRL_REG, START_FLD)) {
1337+ ospi_ind_op_queue_up_rd(s);
1338+ ospi_do_ind_read(s);
1339+ ARRAY_FIELD_DP32(s->regs, INDIRECT_READ_XFER_CTRL_REG, START_FLD, 0);
1340+ }
1341+
1342+ if (ARRAY_FIELD_EX32(s->regs, INDIRECT_READ_XFER_CTRL_REG, CANCEL_FLD)) {
1343+ ospi_ind_op_cancel(s->rd_ind_op);
1344+ fifo8_reset(&s->rx_sram);
1345+ ARRAY_FIELD_DP32(s->regs, INDIRECT_READ_XFER_CTRL_REG, CANCEL_FLD, 0);
1346+ }
1347+}
1348+
1349+static uint64_t ind_rd_xfer_ctrl_reg_post_read(RegisterInfo *reg,
1350+ uint64_t val)
1351+{
1352+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1353+ IndOp *op = s->rd_ind_op;
1354+
1355+ /* Check if ind ops is ongoing */
1356+ if (!ospi_ind_op_completed(&op[0])) {
1357+ /* Check if two ind ops are queued */
1358+ if (!ospi_ind_op_completed(&op[1])) {
1359+ val = FIELD_DP32(val, INDIRECT_READ_XFER_CTRL_REG,
1360+ RD_QUEUED_FLD, 1);
1361+ }
1362+ val = FIELD_DP32(val, INDIRECT_READ_XFER_CTRL_REG, RD_STATUS_FLD, 1);
1363+ }
1364+ return val;
1365+}
1366+
1367+static uint64_t sram_fill_reg_post_read(RegisterInfo *reg, uint64_t val)
1368+{
1369+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1370+ val = ((fifo8_num_used(&s->tx_sram) & 0xFFFF) << 16) |
1371+ (fifo8_num_used(&s->rx_sram) & 0xFFFF);
1372+ return val;
1373+}
1374+
1375+static uint64_t dll_obs_upper_reg_post_read(RegisterInfo *reg, uint64_t val)
1376+{
1377+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque);
1378+ uint32_t rx_dec_out;
1379+
1380+ rx_dec_out = FIELD_EX32(val, DLL_OBSERVABLE_UPPER_REG,
1381+ DLL_OBSERVABLE__UPPER_RX_DECODER_OUTPUT_FLD);
1382+
1383+ if (rx_dec_out < MAX_RX_DEC_OUT) {
1384+ ARRAY_FIELD_DP32(s->regs, DLL_OBSERVABLE_UPPER_REG,
1385+ DLL_OBSERVABLE__UPPER_RX_DECODER_OUTPUT_FLD,
1386+ rx_dec_out + 1);
1387+ }
1388+
1389+ return val;
1390+}
1391+
1392+
1393+static void xlnx_versal_ospi_reset(DeviceState *dev)
1394+{
1395+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(dev);
1396+ unsigned int i;
1397+
1398+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
1399+ register_reset(&s->regs_info[i]);
1400+ }
1401+
1402+ fifo8_reset(&s->rx_fifo);
1403+ fifo8_reset(&s->tx_fifo);
1404+ fifo8_reset(&s->rx_sram);
1405+ fifo8_reset(&s->tx_sram);
1406+
1407+ s->rd_ind_op[0].completed = true;
1408+ s->rd_ind_op[1].completed = true;
1409+ s->wr_ind_op[0].completed = true;
1410+ s->wr_ind_op[1].completed = true;
1411+ ARRAY_FIELD_DP32(s->regs, DLL_OBSERVABLE_LOWER_REG,
1412+ DLL_OBSERVABLE_LOWER_DLL_LOCK_FLD, 1);
1413+ ARRAY_FIELD_DP32(s->regs, DLL_OBSERVABLE_LOWER_REG,
1414+ DLL_OBSERVABLE_LOWER_LOOPBACK_LOCK_FLD, 1);
1415+}
1416+
1417+static RegisterAccessInfo ospi_regs_info[] = {
1418+ { .name = "CONFIG_REG",
1419+ .addr = A_CONFIG_REG,
1420+ .reset = 0x80780081,
1421+ .ro = 0x9c000000,
1422+ },{ .name = "DEV_INSTR_RD_CONFIG_REG",
1423+ .addr = A_DEV_INSTR_RD_CONFIG_REG,
1424+ .reset = 0x3,
1425+ .ro = 0xe0ecc800,
1426+ },{ .name = "DEV_INSTR_WR_CONFIG_REG",
1427+ .addr = A_DEV_INSTR_WR_CONFIG_REG,
1428+ .reset = 0x2,
1429+ .ro = 0xe0fcce00,
1430+ },{ .name = "DEV_DELAY_REG",
1431+ .addr = A_DEV_DELAY_REG,
1432+ },{ .name = "RD_DATA_CAPTURE_REG",
1433+ .addr = A_RD_DATA_CAPTURE_REG,
1434+ .reset = 0x1,
1435+ .ro = 0xfff0fec0,
1436+ },{ .name = "DEV_SIZE_CONFIG_REG",
1437+ .addr = A_DEV_SIZE_CONFIG_REG,
1438+ .reset = 0x101002,
1439+ .ro = 0xe0000000,
1440+ },{ .name = "SRAM_PARTITION_CFG_REG",
1441+ .addr = A_SRAM_PARTITION_CFG_REG,
1442+ .reset = 0x80,
1443+ .ro = 0xffffff00,
1444+ },{ .name = "IND_AHB_ADDR_TRIGGER_REG",
1445+ .addr = A_IND_AHB_ADDR_TRIGGER_REG,
1446+ },{ .name = "DMA_PERIPH_CONFIG_REG",
1447+ .addr = A_DMA_PERIPH_CONFIG_REG,
1448+ .ro = 0xfffff0f0,
1449+ },{ .name = "REMAP_ADDR_REG",
1450+ .addr = A_REMAP_ADDR_REG,
1451+ },{ .name = "MODE_BIT_CONFIG_REG",
1452+ .addr = A_MODE_BIT_CONFIG_REG,
1453+ .reset = 0x200,
1454+ .ro = 0xffff7800,
1455+ },{ .name = "SRAM_FILL_REG",
1456+ .addr = A_SRAM_FILL_REG,
1457+ .ro = 0xffffffff,
1458+ .post_read = sram_fill_reg_post_read,
1459+ },{ .name = "TX_THRESH_REG",
1460+ .addr = A_TX_THRESH_REG,
1461+ .reset = 0x1,
1462+ .ro = 0xffffffe0,
1463+ },{ .name = "RX_THRESH_REG",
1464+ .addr = A_RX_THRESH_REG,
1465+ .reset = 0x1,
1466+ .ro = 0xffffffe0,
1467+ },{ .name = "WRITE_COMPLETION_CTRL_REG",
1468+ .addr = A_WRITE_COMPLETION_CTRL_REG,
1469+ .reset = 0x10005,
1470+ .ro = 0x1800,
1471+ },{ .name = "NO_OF_POLLS_BEF_EXP_REG",
1472+ .addr = A_NO_OF_POLLS_BEF_EXP_REG,
1473+ .reset = 0xffffffff,
1474+ },{ .name = "IRQ_STATUS_REG",
1475+ .addr = A_IRQ_STATUS_REG,
1476+ .ro = 0xfff08000,
1477+ .w1c = 0xf7fff,
1478+ },{ .name = "IRQ_MASK_REG",
1479+ .addr = A_IRQ_MASK_REG,
1480+ .ro = 0xfff08000,
1481+ },{ .name = "LOWER_WR_PROT_REG",
1482+ .addr = A_LOWER_WR_PROT_REG,
1483+ },{ .name = "UPPER_WR_PROT_REG",
1484+ .addr = A_UPPER_WR_PROT_REG,
1485+ },{ .name = "WR_PROT_CTRL_REG",
1486+ .addr = A_WR_PROT_CTRL_REG,
1487+ .ro = 0xfffffffc,
1488+ },{ .name = "INDIRECT_READ_XFER_CTRL_REG",
1489+ .addr = A_INDIRECT_READ_XFER_CTRL_REG,
1490+ .ro = 0xffffffd4,
1491+ .w1c = 0x08,
1492+ .pre_write = ind_rd_xfer_ctrl_reg_pre_write,
1493+ .post_write = ind_rd_xfer_ctrl_reg_post_write,
1494+ .post_read = ind_rd_xfer_ctrl_reg_post_read,
1495+ },{ .name = "INDIRECT_READ_XFER_WATERMARK_REG",
1496+ .addr = A_INDIRECT_READ_XFER_WATERMARK_REG,
1497+ },{ .name = "INDIRECT_READ_XFER_START_REG",
1498+ .addr = A_INDIRECT_READ_XFER_START_REG,
1499+ },{ .name = "INDIRECT_READ_XFER_NUM_BYTES_REG",
1500+ .addr = A_INDIRECT_READ_XFER_NUM_BYTES_REG,
1501+ },{ .name = "INDIRECT_WRITE_XFER_CTRL_REG",
1502+ .addr = A_INDIRECT_WRITE_XFER_CTRL_REG,
1503+ .ro = 0xffffffdc,
1504+ .w1c = 0x20,
1505+ .pre_write = ind_wr_xfer_ctrl_reg_pre_write,
1506+ .post_write = ind_wr_xfer_ctrl_reg_post_write,
1507+ .post_read = ind_wr_xfer_ctrl_reg_post_read,
1508+ },{ .name = "INDIRECT_WRITE_XFER_WATERMARK_REG",
1509+ .addr = A_INDIRECT_WRITE_XFER_WATERMARK_REG,
1510+ .reset = 0xffffffff,
1511+ },{ .name = "INDIRECT_WRITE_XFER_START_REG",
1512+ .addr = A_INDIRECT_WRITE_XFER_START_REG,
1513+ },{ .name = "INDIRECT_WRITE_XFER_NUM_BYTES_REG",
1514+ .addr = A_INDIRECT_WRITE_XFER_NUM_BYTES_REG,
1515+ },{ .name = "INDIRECT_TRIGGER_ADDR_RANGE_REG",
1516+ .addr = A_INDIRECT_TRIGGER_ADDR_RANGE_REG,
1517+ .reset = 0x4,
1518+ .ro = 0xfffffff0,
1519+ },{ .name = "FLASH_COMMAND_CTRL_MEM_REG",
1520+ .addr = A_FLASH_COMMAND_CTRL_MEM_REG,
1521+ .ro = 0xe008fffe,
1522+ .post_write = flash_cmd_ctrl_mem_reg_post_write,
1523+ },{ .name = "FLASH_CMD_CTRL_REG",
1524+ .addr = A_FLASH_CMD_CTRL_REG,
1525+ .ro = 0x7a,
1526+ .post_write = flash_cmd_ctrl_reg_post_write,
1527+ },{ .name = "FLASH_CMD_ADDR_REG",
1528+ .addr = A_FLASH_CMD_ADDR_REG,
1529+ },{ .name = "FLASH_RD_DATA_LOWER_REG",
1530+ .addr = A_FLASH_RD_DATA_LOWER_REG,
1531+ .ro = 0xffffffff,
1532+ },{ .name = "FLASH_RD_DATA_UPPER_REG",
1533+ .addr = A_FLASH_RD_DATA_UPPER_REG,
1534+ .ro = 0xffffffff,
1535+ },{ .name = "FLASH_WR_DATA_LOWER_REG",
1536+ .addr = A_FLASH_WR_DATA_LOWER_REG,
1537+ },{ .name = "FLASH_WR_DATA_UPPER_REG",
1538+ .addr = A_FLASH_WR_DATA_UPPER_REG,
1539+ },{ .name = "POLLING_FLASH_STATUS_REG",
1540+ .addr = A_POLLING_FLASH_STATUS_REG,
1541+ .ro = 0xfff0ffff,
1542+ },{ .name = "PHY_CONFIGURATION_REG",
1543+ .addr = A_PHY_CONFIGURATION_REG,
1544+ .reset = 0x40000000,
1545+ .ro = 0x1f80ff80,
1546+ },{ .name = "PHY_MASTER_CONTROL_REG",
1547+ .addr = A_PHY_MASTER_CONTROL_REG,
1548+ .reset = 0x800000,
1549+ .ro = 0xfe08ff80,
1550+ },{ .name = "DLL_OBSERVABLE_LOWER_REG",
1551+ .addr = A_DLL_OBSERVABLE_LOWER_REG,
1552+ .ro = 0xffffffff,
1553+ },{ .name = "DLL_OBSERVABLE_UPPER_REG",
1554+ .addr = A_DLL_OBSERVABLE_UPPER_REG,
1555+ .ro = 0xffffffff,
1556+ .post_read = dll_obs_upper_reg_post_read,
1557+ },{ .name = "OPCODE_EXT_LOWER_REG",
1558+ .addr = A_OPCODE_EXT_LOWER_REG,
1559+ .reset = 0x13edfa00,
1560+ },{ .name = "OPCODE_EXT_UPPER_REG",
1561+ .addr = A_OPCODE_EXT_UPPER_REG,
1562+ .reset = 0x6f90000,
1563+ .ro = 0xffff,
1564+ },{ .name = "MODULE_ID_REG",
1565+ .addr = A_MODULE_ID_REG,
1566+ .reset = 0x300,
1567+ .ro = 0xffffffff,
1568+ }
1569+};
1570+
1571+/* Return dev-obj from reg-region created by register_init_block32 */
1572+static XlnxVersalOspi *xilinx_ospi_of_mr(void *mr_accessor)
1573+{
1574+ RegisterInfoArray *reg_array = mr_accessor;
1575+ Object *dev;
1576+
1577+ dev = reg_array->mem.owner;
1578+ assert(dev);
1579+
1580+ return XILINX_VERSAL_OSPI(dev);
1581+}
1582+
1583+static void ospi_write(void *opaque, hwaddr addr, uint64_t value,
1584+ unsigned int size)
1585+{
1586+ XlnxVersalOspi *s = xilinx_ospi_of_mr(opaque);
1587+
1588+ register_write_memory(opaque, addr, value, size);
1589+ ospi_update_irq_line(s);
1590+}
1591+
1592+static const MemoryRegionOps ospi_ops = {
1593+ .read = register_read_memory,
1594+ .write = ospi_write,
1595+ .endianness = DEVICE_LITTLE_ENDIAN,
1596+ .valid = {
1597+ .min_access_size = 4,
1598+ .max_access_size = 4,
1599+ },
1600+};
1601+
1602+static uint64_t ospi_indac_read(void *opaque, unsigned int size)
1603+{
1604+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque);
1605+ uint64_t ret = ospi_rx_sram_read(s, size);
1606+
1607+ if (!ospi_ind_op_completed(s->rd_ind_op)) {
1608+ ospi_do_ind_read(s);
1609+ }
1610+ return ret;
1611+}
1612+
1613+static void ospi_indac_write(void *opaque, uint64_t value, unsigned int size)
1614+{
1615+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque);
1616+
1617+ g_assert(!s->ind_write_disabled);
1618+
1619+ if (!ospi_ind_op_completed(s->wr_ind_op)) {
1620+ ospi_tx_sram_write(s, value, size);
1621+ ospi_do_indirect_write(s);
1622+ } else {
1623+ qemu_log_mask(LOG_GUEST_ERROR,
1624+ "OSPI wr into indac area while no ongoing indac wr\n");
1625+ }
1626+}
1627+
1628+static bool is_inside_indac_range(XlnxVersalOspi *s, hwaddr addr)
1629+{
1630+ uint32_t range_start;
1631+ uint32_t range_end;
1632+
1633+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DMA_IF_FLD)) {
1634+ return true;
1635+ }
1636+
1637+ range_start = s->regs[R_IND_AHB_ADDR_TRIGGER_REG];
1638+ range_end = range_start +
1639+ (1 << ARRAY_FIELD_EX32(s->regs,
1640+ INDIRECT_TRIGGER_ADDR_RANGE_REG,
1641+ IND_RANGE_WIDTH_FLD));
1642+
1643+ addr += s->regs[R_IND_AHB_ADDR_TRIGGER_REG] & 0xF0000000;
1644+
1645+ return addr >= range_start && addr < range_end;
1646+}
1647+
1648+static bool ospi_is_indac_active(XlnxVersalOspi *s)
1649+{
1650+ /*
1651+ * When dac and indac cannot be active at the same time,
1652+ * return true when dac is disabled.
1653+ */
1654+ return s->dac_with_indac || !s->dac_enable;
1655+}
1656+
1657+static uint64_t ospi_dac_read(void *opaque, hwaddr addr, unsigned int size)
1658+{
1659+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque);
1660+
1661+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_SPI_FLD)) {
1662+ if (ospi_is_indac_active(s) &&
1663+ is_inside_indac_range(s, addr)) {
1664+ return ospi_indac_read(s, size);
1665+ }
1666+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DIR_ACC_CTLR_FLD)
1667+ && s->dac_enable) {
1668+ if (ARRAY_FIELD_EX32(s->regs,
1669+ CONFIG_REG, ENB_AHB_ADDR_REMAP_FLD)) {
1670+ addr += s->regs[R_REMAP_ADDR_REG];
1671+ }
1672+ return ospi_do_dac_read(opaque, addr, size);
1673+ } else {
1674+ qemu_log_mask(LOG_GUEST_ERROR, "OSPI AHB rd while DAC disabled\n");
1675+ }
1676+ } else {
1677+ qemu_log_mask(LOG_GUEST_ERROR, "OSPI AHB rd while OSPI disabled\n");
1678+ }
1679+
1680+ return 0;
1681+}
1682+
1683+static void ospi_dac_write(void *opaque, hwaddr addr, uint64_t value,
1684+ unsigned int size)
1685+{
1686+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque);
1687+
1688+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_SPI_FLD)) {
1689+ if (ospi_is_indac_active(s) &&
1690+ !s->ind_write_disabled &&
1691+ is_inside_indac_range(s, addr)) {
1692+ return ospi_indac_write(s, value, size);
1693+ }
1694+ if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DIR_ACC_CTLR_FLD) &&
1695+ s->dac_enable) {
1696+ if (ARRAY_FIELD_EX32(s->regs,
1697+ CONFIG_REG, ENB_AHB_ADDR_REMAP_FLD)) {
1698+ addr += s->regs[R_REMAP_ADDR_REG];
1699+ }
1700+ /* Check if addr is write protected */
1701+ if (ARRAY_FIELD_EX32(s->regs, WR_PROT_CTRL_REG, ENB_FLD) &&
1702+ ospi_is_write_protected(s, addr)) {
1703+ set_irq(s, R_IRQ_STATUS_REG_PROT_WR_ATTEMPT_FLD_MASK);
1704+ ospi_update_irq_line(s);
1705+ qemu_log_mask(LOG_GUEST_ERROR,
1706+ "OSPI writing into write protected area\n");
1707+ return;
1708+ }
1709+ ospi_do_dac_write(opaque, addr, value, size);
1710+ } else {
1711+ qemu_log_mask(LOG_GUEST_ERROR, "OSPI AHB wr while DAC disabled\n");
1712+ }
1713+ } else {
1714+ qemu_log_mask(LOG_GUEST_ERROR, "OSPI AHB wr while OSPI disabled\n");
1715+ }
1716+}
1717+
1718+static const MemoryRegionOps ospi_dac_ops = {
1719+ .read = ospi_dac_read,
1720+ .write = ospi_dac_write,
1721+ .endianness = DEVICE_LITTLE_ENDIAN,
1722+ .valid = {
1723+ .min_access_size = 4,
1724+ .max_access_size = 4,
1725+ },
1726+};
1727+
1728+static void ospi_update_dac_status(void *opaque, int n, int level)
1729+{
1730+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque);
1731+
1732+ s->dac_enable = level;
1733+}
1734+
1735+static void xlnx_versal_ospi_realize(DeviceState *dev, Error **errp)
1736+{
1737+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(dev);
1738+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1739+
1740+ s->num_cs = 4;
1741+ s->spi = ssi_create_bus(dev, "spi0");
1742+ s->cs_lines = g_new0(qemu_irq, s->num_cs);
1743+ for (int i = 0; i < s->num_cs; ++i) {
1744+ sysbus_init_irq(sbd, &s->cs_lines[i]);
1745+ }
1746+
1747+ fifo8_create(&s->rx_fifo, RXFF_SZ);
1748+ fifo8_create(&s->tx_fifo, TXFF_SZ);
1749+ fifo8_create(&s->rx_sram, RXFF_SZ);
1750+ fifo8_create(&s->tx_sram, TXFF_SZ);
1751+}
1752+
1753+static void xlnx_versal_ospi_init(Object *obj)
1754+{
1755+ XlnxVersalOspi *s = XILINX_VERSAL_OSPI(obj);
1756+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1757+ DeviceState *dev = DEVICE(obj);
1758+ RegisterInfoArray *reg_array;
1759+
1760+ memory_region_init(&s->iomem, obj, TYPE_XILINX_VERSAL_OSPI,
1761+ XILINX_VERSAL_OSPI_R_MAX * 4);
1762+ reg_array =
1763+ register_init_block32(DEVICE(obj), ospi_regs_info,
1764+ ARRAY_SIZE(ospi_regs_info),
1765+ s->regs_info, s->regs,
1766+ &ospi_ops,
1767+ XILINX_VERSAL_OSPI_ERR_DEBUG,
1768+ XILINX_VERSAL_OSPI_R_MAX * 4);
1769+ memory_region_add_subregion(&s->iomem, 0x0, &reg_array->mem);
1770+ sysbus_init_mmio(sbd, &s->iomem);
1771+
1772+ memory_region_init_io(&s->iomem_dac, obj, &ospi_dac_ops, s,
1773+ TYPE_XILINX_VERSAL_OSPI "-dac", 0x20000000);
1774+ sysbus_init_mmio(sbd, &s->iomem_dac);
1775+
1776+ sysbus_init_irq(sbd, &s->irq);
1777+
1778+ object_property_add_link(obj, "dma-src", TYPE_XLNX_CSU_DMA,
1779+ (Object **)&s->dma_src,
1780+ object_property_allow_set_link,
1781+ OBJ_PROP_LINK_STRONG);
1782+
1783+ qdev_init_gpio_in_named(dev, ospi_update_dac_status, "ospi-mux-sel", 1);
1784+}
1785+
1786+static const VMStateDescription vmstate_ind_op = {
1787+ .name = "OSPIIndOp",
1788+ .version_id = 1,
1789+ .minimum_version_id = 1,
1790+ .fields = (VMStateField[]) {
1791+ VMSTATE_UINT32(flash_addr, IndOp),
1792+ VMSTATE_UINT32(num_bytes, IndOp),
1793+ VMSTATE_UINT32(done_bytes, IndOp),
1794+ VMSTATE_BOOL(completed, IndOp),
1795+ VMSTATE_END_OF_LIST()
1796+ }
1797+};
1798+
1799+static const VMStateDescription vmstate_xlnx_versal_ospi = {
1800+ .name = TYPE_XILINX_VERSAL_OSPI,
1801+ .version_id = 1,
1802+ .minimum_version_id = 1,
1803+ .minimum_version_id_old = 1,
1804+ .fields = (VMStateField[]) {
1805+ VMSTATE_FIFO8(rx_fifo, XlnxVersalOspi),
1806+ VMSTATE_FIFO8(tx_fifo, XlnxVersalOspi),
1807+ VMSTATE_FIFO8(rx_sram, XlnxVersalOspi),
1808+ VMSTATE_FIFO8(tx_sram, XlnxVersalOspi),
1809+ VMSTATE_BOOL(ind_write_disabled, XlnxVersalOspi),
1810+ VMSTATE_BOOL(dac_with_indac, XlnxVersalOspi),
1811+ VMSTATE_BOOL(dac_enable, XlnxVersalOspi),
1812+ VMSTATE_BOOL(src_dma_inprog, XlnxVersalOspi),
1813+ VMSTATE_STRUCT_ARRAY(rd_ind_op, XlnxVersalOspi, 2, 1,
1814+ vmstate_ind_op, IndOp),
1815+ VMSTATE_STRUCT_ARRAY(wr_ind_op, XlnxVersalOspi, 2, 1,
1816+ vmstate_ind_op, IndOp),
1817+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalOspi, XILINX_VERSAL_OSPI_R_MAX),
1818+ VMSTATE_UINT8_ARRAY(stig_membank, XlnxVersalOspi, 512),
1819+ VMSTATE_END_OF_LIST(),
1820+ }
1821+};
1822+
1823+static Property xlnx_versal_ospi_properties[] = {
1824+ DEFINE_PROP_BOOL("dac-with-indac", XlnxVersalOspi, dac_with_indac, false),
1825+ DEFINE_PROP_BOOL("indac-write-disabled", XlnxVersalOspi,
1826+ ind_write_disabled, false),
1827+ DEFINE_PROP_END_OF_LIST(),
1828+};
1829+
1830+static void xlnx_versal_ospi_class_init(ObjectClass *klass, void *data)
1831+{
1832+ DeviceClass *dc = DEVICE_CLASS(klass);
1833+
1834+ dc->reset = xlnx_versal_ospi_reset;
1835+ dc->realize = xlnx_versal_ospi_realize;
1836+ dc->vmsd = &vmstate_xlnx_versal_ospi;
1837+ device_class_set_props(dc, xlnx_versal_ospi_properties);
1838+}
1839+
1840+static const TypeInfo xlnx_versal_ospi_info = {
1841+ .name = TYPE_XILINX_VERSAL_OSPI,
1842+ .parent = TYPE_SYS_BUS_DEVICE,
1843+ .instance_size = sizeof(XlnxVersalOspi),
1844+ .class_init = xlnx_versal_ospi_class_init,
1845+ .instance_init = xlnx_versal_ospi_init,
1846+};
1847+
1848+static void xlnx_versal_ospi_register_types(void)
1849+{
1850+ type_register_static(&xlnx_versal_ospi_info);
1851+}
1852+
1853+type_init(xlnx_versal_ospi_register_types)
--- /dev/null
+++ b/include/hw/ssi/xlnx-versal-ospi.h
@@ -0,0 +1,111 @@
1+/*
2+ * Header file for the Xilinx Versal's OSPI controller
3+ *
4+ * Copyright (C) 2021 Xilinx Inc
5+ * Written by Francisco Iglesias <francisco.iglesias@xilinx.com>
6+ *
7+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8+ * of this software and associated documentation files (the "Software"), to deal
9+ * in the Software without restriction, including without limitation the rights
10+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+ * copies of the Software, and to permit persons to whom the Software is
12+ * furnished to do so, subject to the following conditions:
13+ *
14+ * The above copyright notice and this permission notice shall be included in
15+ * all copies or substantial portions of the Software.
16+ *
17+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+ * THE SOFTWARE.
24+ */
25+
26+/*
27+ * This is a model of Xilinx Versal's Octal SPI flash memory controller
28+ * documented in Versal's Technical Reference manual [1] and the Versal ACAP
29+ * Register reference [2].
30+ *
31+ * References:
32+ *
33+ * [1] Versal ACAP Technical Reference Manual,
34+ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
35+ *
36+ * [2] Versal ACAP Register Reference,
37+ * https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___ospi.html
38+ *
39+ *
40+ * QEMU interface:
41+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
42+ * + sysbus MMIO region 1: MemoryRegion for flash memory linear address space
43+ * (data transfer).
44+ * + sysbus IRQ 0: Device interrupt.
45+ * + Named GPIO input "ospi-mux-sel": 0: enables indirect access mode
46+ * and 1: enables direct access mode.
47+ * + Property "dac-with-indac": Allow both direct accesses and indirect
48+ * accesses simultaneously.
49+ * + Property "indac-write-disabled": Disable indirect access writes.
50+ */
51+
52+#ifndef XILINX_VERSAL_OSPI_H
53+#define XILINX_VERSAL_OSPI_H
54+
55+#include "hw/register.h"
56+#include "hw/ssi/ssi.h"
57+#include "qemu/fifo8.h"
58+#include "hw/dma/xlnx_csu_dma.h"
59+
60+#define TYPE_XILINX_VERSAL_OSPI "xlnx.versal-ospi"
61+
62+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalOspi, XILINX_VERSAL_OSPI)
63+
64+#define XILINX_VERSAL_OSPI_R_MAX (0xfc / 4 + 1)
65+
66+/*
67+ * Indirect operations
68+ */
69+typedef struct IndOp {
70+ uint32_t flash_addr;
71+ uint32_t num_bytes;
72+ uint32_t done_bytes;
73+ bool completed;
74+} IndOp;
75+
76+struct XlnxVersalOspi {
77+ SysBusDevice parent_obj;
78+
79+ MemoryRegion iomem;
80+ MemoryRegion iomem_dac;
81+
82+ uint8_t num_cs;
83+ qemu_irq *cs_lines;
84+
85+ SSIBus *spi;
86+
87+ Fifo8 rx_fifo;
88+ Fifo8 tx_fifo;
89+
90+ Fifo8 rx_sram;
91+ Fifo8 tx_sram;
92+
93+ qemu_irq irq;
94+
95+ XlnxCSUDMA *dma_src;
96+ bool ind_write_disabled;
97+ bool dac_with_indac;
98+ bool dac_enable;
99+ bool src_dma_inprog;
100+
101+ IndOp rd_ind_op[2];
102+ IndOp wr_ind_op[2];
103+
104+ uint32_t regs[XILINX_VERSAL_OSPI_R_MAX];
105+ RegisterInfo regs_info[XILINX_VERSAL_OSPI_R_MAX];
106+
107+ /* Maximum inferred membank size is 512 bytes */
108+ uint8_t stig_membank[512];
109+};
110+
111+#endif /* XILINX_VERSAL_OSPI_H */