2 * QEMU model of the Ibex SPI Controller
3 * SPEC Reference: https://docs.opentitan.org/hw/ip/spi_host/doc/
5 * Copyright (C) 2022 Western Digital
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
26 #include "qemu/osdep.h"
28 #include "qemu/module.h"
29 #include "hw/registerfields.h"
30 #include "hw/ssi/ibex_spi_host.h"
32 #include "hw/qdev-properties.h"
33 #include "hw/qdev-properties-system.h"
34 #include "migration/vmstate.h"
37 REG32(INTR_STATE
, 0x00)
38 FIELD(INTR_STATE
, ERROR
, 0, 1)
39 FIELD(INTR_STATE
, SPI_EVENT
, 1, 1)
40 REG32(INTR_ENABLE
, 0x04)
41 FIELD(INTR_ENABLE
, ERROR
, 0, 1)
42 FIELD(INTR_ENABLE
, SPI_EVENT
, 1, 1)
43 REG32(INTR_TEST
, 0x08)
44 FIELD(INTR_TEST
, ERROR
, 0, 1)
45 FIELD(INTR_TEST
, SPI_EVENT
, 1, 1)
46 REG32(ALERT_TEST
, 0x0c)
47 FIELD(ALERT_TEST
, FETAL_TEST
, 0, 1)
49 FIELD(CONTROL
, RX_WATERMARK
, 0, 8)
50 FIELD(CONTROL
, TX_WATERMARK
, 1, 8)
51 FIELD(CONTROL
, OUTPUT_EN
, 29, 1)
52 FIELD(CONTROL
, SW_RST
, 30, 1)
53 FIELD(CONTROL
, SPIEN
, 31, 1)
55 FIELD(STATUS
, TXQD
, 0, 8)
56 FIELD(STATUS
, RXQD
, 18, 8)
57 FIELD(STATUS
, CMDQD
, 16, 3)
58 FIELD(STATUS
, RXWM
, 20, 1)
59 FIELD(STATUS
, BYTEORDER
, 22, 1)
60 FIELD(STATUS
, RXSTALL
, 23, 1)
61 FIELD(STATUS
, RXEMPTY
, 24, 1)
62 FIELD(STATUS
, RXFULL
, 25, 1)
63 FIELD(STATUS
, TXWM
, 26, 1)
64 FIELD(STATUS
, TXSTALL
, 27, 1)
65 FIELD(STATUS
, TXEMPTY
, 28, 1)
66 FIELD(STATUS
, TXFULL
, 29, 1)
67 FIELD(STATUS
, ACTIVE
, 30, 1)
68 FIELD(STATUS
, READY
, 31, 1)
69 REG32(CONFIGOPTS
, 0x18)
70 FIELD(CONFIGOPTS
, CLKDIV_0
, 0, 16)
71 FIELD(CONFIGOPTS
, CSNIDLE_0
, 16, 4)
72 FIELD(CONFIGOPTS
, CSNTRAIL_0
, 20, 4)
73 FIELD(CONFIGOPTS
, CSNLEAD_0
, 24, 4)
74 FIELD(CONFIGOPTS
, FULLCYC_0
, 29, 1)
75 FIELD(CONFIGOPTS
, CPHA_0
, 30, 1)
76 FIELD(CONFIGOPTS
, CPOL_0
, 31, 1)
78 FIELD(CSID
, CSID
, 0, 32)
80 FIELD(COMMAND
, LEN
, 0, 8)
81 FIELD(COMMAND
, CSAAT
, 9, 1)
82 FIELD(COMMAND
, SPEED
, 10, 2)
83 FIELD(COMMAND
, DIRECTION
, 12, 2)
84 REG32(ERROR_ENABLE
, 0x2c)
85 FIELD(ERROR_ENABLE
, CMDBUSY
, 0, 1)
86 FIELD(ERROR_ENABLE
, OVERFLOW
, 1, 1)
87 FIELD(ERROR_ENABLE
, UNDERFLOW
, 2, 1)
88 FIELD(ERROR_ENABLE
, CMDINVAL
, 3, 1)
89 FIELD(ERROR_ENABLE
, CSIDINVAL
, 4, 1)
90 REG32(ERROR_STATUS
, 0x30)
91 FIELD(ERROR_STATUS
, CMDBUSY
, 0, 1)
92 FIELD(ERROR_STATUS
, OVERFLOW
, 1, 1)
93 FIELD(ERROR_STATUS
, UNDERFLOW
, 2, 1)
94 FIELD(ERROR_STATUS
, CMDINVAL
, 3, 1)
95 FIELD(ERROR_STATUS
, CSIDINVAL
, 4, 1)
96 FIELD(ERROR_STATUS
, ACCESSINVAL
, 5, 1)
97 REG32(EVENT_ENABLE
, 0x34)
98 FIELD(EVENT_ENABLE
, RXFULL
, 0, 1)
99 FIELD(EVENT_ENABLE
, TXEMPTY
, 1, 1)
100 FIELD(EVENT_ENABLE
, RXWM
, 2, 1)
101 FIELD(EVENT_ENABLE
, TXWM
, 3, 1)
102 FIELD(EVENT_ENABLE
, READY
, 4, 1)
103 FIELD(EVENT_ENABLE
, IDLE
, 5, 1)
105 static inline uint8_t div4_round_up(uint8_t dividend
)
107 return (dividend
+ 3) / 4;
110 static void ibex_spi_rxfifo_reset(IbexSPIHostState
*s
)
112 uint32_t data
= s
->regs
[IBEX_SPI_HOST_STATUS
];
113 /* Empty the RX FIFO and assert RXEMPTY */
114 fifo8_reset(&s
->rx_fifo
);
115 data
= FIELD_DP32(data
, STATUS
, RXFULL
, 0);
116 data
= FIELD_DP32(data
, STATUS
, RXEMPTY
, 1);
117 s
->regs
[IBEX_SPI_HOST_STATUS
] = data
;
120 static void ibex_spi_txfifo_reset(IbexSPIHostState
*s
)
122 uint32_t data
= s
->regs
[IBEX_SPI_HOST_STATUS
];
123 /* Empty the TX FIFO and assert TXEMPTY */
124 fifo8_reset(&s
->tx_fifo
);
125 data
= FIELD_DP32(data
, STATUS
, TXFULL
, 0);
126 data
= FIELD_DP32(data
, STATUS
, TXEMPTY
, 1);
127 s
->regs
[IBEX_SPI_HOST_STATUS
] = data
;
130 static void ibex_spi_host_reset(DeviceState
*dev
)
132 IbexSPIHostState
*s
= IBEX_SPI_HOST(dev
);
133 trace_ibex_spi_host_reset("Resetting Ibex SPI");
135 /* SPI Host Register Reset */
136 s
->regs
[IBEX_SPI_HOST_INTR_STATE
] = 0x00;
137 s
->regs
[IBEX_SPI_HOST_INTR_ENABLE
] = 0x00;
138 s
->regs
[IBEX_SPI_HOST_INTR_TEST
] = 0x00;
139 s
->regs
[IBEX_SPI_HOST_ALERT_TEST
] = 0x00;
140 s
->regs
[IBEX_SPI_HOST_CONTROL
] = 0x7f;
141 s
->regs
[IBEX_SPI_HOST_STATUS
] = 0x00;
142 s
->regs
[IBEX_SPI_HOST_CONFIGOPTS
] = 0x00;
143 s
->regs
[IBEX_SPI_HOST_CSID
] = 0x00;
144 s
->regs
[IBEX_SPI_HOST_COMMAND
] = 0x00;
145 /* RX/TX Modelled by FIFO */
146 s
->regs
[IBEX_SPI_HOST_RXDATA
] = 0x00;
147 s
->regs
[IBEX_SPI_HOST_TXDATA
] = 0x00;
149 s
->regs
[IBEX_SPI_HOST_ERROR_ENABLE
] = 0x1F;
150 s
->regs
[IBEX_SPI_HOST_ERROR_STATUS
] = 0x00;
151 s
->regs
[IBEX_SPI_HOST_EVENT_ENABLE
] = 0x00;
153 ibex_spi_rxfifo_reset(s
);
154 ibex_spi_txfifo_reset(s
);
156 s
->init_status
= true;
161 * Check if we need to trigger an interrupt.
162 * The two interrupts lines (host_err and event) can
163 * be enabled separately in 'IBEX_SPI_HOST_INTR_ENABLE'.
165 * Interrupts are triggered based on the ones
166 * enabled in the `IBEX_SPI_HOST_EVENT_ENABLE` and `IBEX_SPI_HOST_ERROR_ENABLE`.
168 static void ibex_spi_host_irq(IbexSPIHostState
*s
)
170 uint32_t intr_test_reg
= s
->regs
[IBEX_SPI_HOST_INTR_TEST
];
171 uint32_t intr_en_reg
= s
->regs
[IBEX_SPI_HOST_INTR_ENABLE
];
172 uint32_t intr_state_reg
= s
->regs
[IBEX_SPI_HOST_INTR_STATE
];
174 uint32_t err_en_reg
= s
->regs
[IBEX_SPI_HOST_ERROR_ENABLE
];
175 uint32_t event_en_reg
= s
->regs
[IBEX_SPI_HOST_EVENT_ENABLE
];
176 uint32_t err_status_reg
= s
->regs
[IBEX_SPI_HOST_ERROR_STATUS
];
177 uint32_t status_reg
= s
->regs
[IBEX_SPI_HOST_STATUS
];
180 bool error_en
= FIELD_EX32(intr_en_reg
, INTR_ENABLE
, ERROR
);
181 bool event_en
= FIELD_EX32(intr_en_reg
, INTR_ENABLE
, SPI_EVENT
);
182 bool err_pending
= FIELD_EX32(intr_state_reg
, INTR_STATE
, ERROR
);
183 bool status_pending
= FIELD_EX32(intr_state_reg
, INTR_STATE
, SPI_EVENT
);
185 int err_irq
= 0, event_irq
= 0;
187 /* Error IRQ enabled and Error IRQ Cleared */
188 if (error_en
&& !err_pending
) {
189 /* Event enabled, Interrupt Test Error */
190 if (FIELD_EX32(intr_test_reg
, INTR_TEST
, ERROR
)) {
192 } else if (FIELD_EX32(err_en_reg
, ERROR_ENABLE
, CMDBUSY
) &&
193 FIELD_EX32(err_status_reg
, ERROR_STATUS
, CMDBUSY
)) {
194 /* Wrote to COMMAND when not READY */
196 } else if (FIELD_EX32(err_en_reg
, ERROR_ENABLE
, CMDINVAL
) &&
197 FIELD_EX32(err_status_reg
, ERROR_STATUS
, CMDINVAL
)) {
198 /* Invalid command segment */
200 } else if (FIELD_EX32(err_en_reg
, ERROR_ENABLE
, CSIDINVAL
) &&
201 FIELD_EX32(err_status_reg
, ERROR_STATUS
, CSIDINVAL
)) {
202 /* Invalid value for CSID */
206 s
->regs
[IBEX_SPI_HOST_INTR_STATE
] |= R_INTR_STATE_ERROR_MASK
;
210 qemu_set_irq(s
->host_err
, err_irq
);
212 /* Event IRQ Enabled and Event IRQ Cleared */
213 if (event_en
&& !status_pending
) {
214 if (FIELD_EX32(intr_test_reg
, INTR_STATE
, SPI_EVENT
)) {
215 /* Event enabled, Interrupt Test Event */
217 } else if (FIELD_EX32(event_en_reg
, EVENT_ENABLE
, READY
) &&
218 FIELD_EX32(status_reg
, STATUS
, READY
)) {
219 /* SPI Host ready for next command */
221 } else if (FIELD_EX32(event_en_reg
, EVENT_ENABLE
, TXEMPTY
) &&
222 FIELD_EX32(status_reg
, STATUS
, TXEMPTY
)) {
223 /* SPI TXEMPTY, TXFIFO drained */
225 } else if (FIELD_EX32(event_en_reg
, EVENT_ENABLE
, RXFULL
) &&
226 FIELD_EX32(status_reg
, STATUS
, RXFULL
)) {
227 /* SPI RXFULL, RXFIFO full */
231 s
->regs
[IBEX_SPI_HOST_INTR_STATE
] |= R_INTR_STATE_SPI_EVENT_MASK
;
235 qemu_set_irq(s
->event
, event_irq
);
238 static void ibex_spi_host_transfer(IbexSPIHostState
*s
)
240 uint32_t rx
, tx
, data
;
241 /* Get num of one byte transfers */
242 uint8_t segment_len
= FIELD_EX32(s
->regs
[IBEX_SPI_HOST_COMMAND
],
245 while (segment_len
> 0) {
246 if (fifo8_is_empty(&s
->tx_fifo
)) {
248 s
->regs
[IBEX_SPI_HOST_STATUS
] |= R_STATUS_TXSTALL_MASK
;
250 } else if (fifo8_is_full(&s
->rx_fifo
)) {
252 s
->regs
[IBEX_SPI_HOST_STATUS
] |= R_STATUS_RXSTALL_MASK
;
255 tx
= fifo8_pop(&s
->tx_fifo
);
258 rx
= ssi_transfer(s
->ssi
, tx
);
260 trace_ibex_spi_host_transfer(tx
, rx
);
262 if (!fifo8_is_full(&s
->rx_fifo
)) {
263 fifo8_push(&s
->rx_fifo
, rx
);
266 s
->regs
[IBEX_SPI_HOST_STATUS
] |= R_STATUS_RXFULL_MASK
;
271 data
= s
->regs
[IBEX_SPI_HOST_STATUS
];
273 data
= FIELD_DP32(data
, STATUS
, READY
, 1);
275 data
= FIELD_DP32(data
, STATUS
, RXQD
, div4_round_up(segment_len
));
277 data
= FIELD_DP32(data
, STATUS
, TXQD
, fifo8_num_used(&s
->tx_fifo
) / 4);
279 data
= FIELD_DP32(data
, STATUS
, TXFULL
, 0);
281 data
= FIELD_DP32(data
, STATUS
, RXEMPTY
, 0);
282 /* Update register status */
283 s
->regs
[IBEX_SPI_HOST_STATUS
] = data
;
284 /* Drop remaining bytes that exceed segment_len */
285 ibex_spi_txfifo_reset(s
);
287 ibex_spi_host_irq(s
);
290 static uint64_t ibex_spi_host_read(void *opaque
, hwaddr addr
,
293 IbexSPIHostState
*s
= opaque
;
297 trace_ibex_spi_host_read(addr
, size
);
299 /* Match reg index */
302 /* Skipping any W/O registers */
303 case IBEX_SPI_HOST_INTR_STATE
...IBEX_SPI_HOST_INTR_ENABLE
:
304 case IBEX_SPI_HOST_CONTROL
...IBEX_SPI_HOST_STATUS
:
307 case IBEX_SPI_HOST_CSID
:
310 case IBEX_SPI_HOST_CONFIGOPTS
:
311 rc
= s
->config_opts
[s
->regs
[IBEX_SPI_HOST_CSID
]];
313 case IBEX_SPI_HOST_TXDATA
:
316 case IBEX_SPI_HOST_RXDATA
:
318 s
->regs
[IBEX_SPI_HOST_STATUS
] &= ~R_STATUS_RXFULL_MASK
;
320 for (int i
= 0; i
< 4; ++i
) {
321 if (fifo8_is_empty(&s
->rx_fifo
)) {
322 /* Assert RXEMPTY, no IRQ */
323 s
->regs
[IBEX_SPI_HOST_STATUS
] |= R_STATUS_RXEMPTY_MASK
;
324 s
->regs
[IBEX_SPI_HOST_ERROR_STATUS
] |=
325 R_ERROR_STATUS_UNDERFLOW_MASK
;
328 rx_byte
= fifo8_pop(&s
->rx_fifo
);
329 rc
|= rx_byte
<< (i
* 8);
332 case IBEX_SPI_HOST_ERROR_ENABLE
...IBEX_SPI_HOST_EVENT_ENABLE
:
336 qemu_log_mask(LOG_GUEST_ERROR
, "Bad offset 0x%" HWADDR_PRIx
"\n",
343 static void ibex_spi_host_write(void *opaque
, hwaddr addr
,
344 uint64_t val64
, unsigned int size
)
346 IbexSPIHostState
*s
= opaque
;
347 uint32_t val32
= val64
;
348 uint32_t shift_mask
= 0xff, status
= 0, data
= 0;
351 trace_ibex_spi_host_write(addr
, size
, val64
);
353 /* Match reg index */
357 /* Skipping any R/O registers */
358 case IBEX_SPI_HOST_INTR_STATE
:
359 /* rw1c status register */
360 if (FIELD_EX32(val32
, INTR_STATE
, ERROR
)) {
361 data
= FIELD_DP32(data
, INTR_STATE
, ERROR
, 0);
363 if (FIELD_EX32(val32
, INTR_STATE
, SPI_EVENT
)) {
364 data
= FIELD_DP32(data
, INTR_STATE
, SPI_EVENT
, 0);
366 s
->regs
[addr
] = data
;
368 case IBEX_SPI_HOST_INTR_ENABLE
:
369 s
->regs
[addr
] = val32
;
371 case IBEX_SPI_HOST_INTR_TEST
:
372 s
->regs
[addr
] = val32
;
373 ibex_spi_host_irq(s
);
375 case IBEX_SPI_HOST_ALERT_TEST
:
376 s
->regs
[addr
] = val32
;
377 qemu_log_mask(LOG_UNIMP
,
378 "%s: SPI_ALERT_TEST is not supported\n", __func__
);
380 case IBEX_SPI_HOST_CONTROL
:
381 s
->regs
[addr
] = val32
;
383 if (val32
& R_CONTROL_SW_RST_MASK
) {
384 ibex_spi_host_reset((DeviceState
*)s
);
385 /* Clear active if any */
386 s
->regs
[IBEX_SPI_HOST_STATUS
] &= ~R_STATUS_ACTIVE_MASK
;
389 if (val32
& R_CONTROL_OUTPUT_EN_MASK
) {
390 qemu_log_mask(LOG_UNIMP
,
391 "%s: CONTROL_OUTPUT_EN is not supported\n", __func__
);
394 case IBEX_SPI_HOST_CONFIGOPTS
:
395 /* Update the respective config-opts register based on CSIDth index */
396 s
->config_opts
[s
->regs
[IBEX_SPI_HOST_CSID
]] = val32
;
397 qemu_log_mask(LOG_UNIMP
,
398 "%s: CONFIGOPTS Hardware settings not supported\n",
401 case IBEX_SPI_HOST_CSID
:
402 if (val32
>= s
->num_cs
) {
403 /* CSID exceeds max num_cs */
404 s
->regs
[IBEX_SPI_HOST_ERROR_STATUS
] |=
405 R_ERROR_STATUS_CSIDINVAL_MASK
;
406 ibex_spi_host_irq(s
);
409 s
->regs
[addr
] = val32
;
411 case IBEX_SPI_HOST_COMMAND
:
412 s
->regs
[addr
] = val32
;
414 /* STALL, IP not enabled */
415 if (!(FIELD_EX32(s
->regs
[IBEX_SPI_HOST_CONTROL
],
420 /* SPI not ready, IRQ Error */
421 if (!(FIELD_EX32(s
->regs
[IBEX_SPI_HOST_STATUS
],
423 s
->regs
[IBEX_SPI_HOST_ERROR_STATUS
] |= R_ERROR_STATUS_CMDBUSY_MASK
;
424 ibex_spi_host_irq(s
);
428 /* Assert Not Ready */
429 s
->regs
[IBEX_SPI_HOST_STATUS
] &= ~R_STATUS_READY_MASK
;
431 if (FIELD_EX32(val32
, COMMAND
, DIRECTION
) != BIDIRECTIONAL_TRANSFER
) {
432 qemu_log_mask(LOG_UNIMP
,
433 "%s: Rx Only/Tx Only are not supported\n", __func__
);
436 if (val32
& R_COMMAND_CSAAT_MASK
) {
437 qemu_log_mask(LOG_UNIMP
,
438 "%s: CSAAT is not supported\n", __func__
);
440 if (val32
& R_COMMAND_SPEED_MASK
) {
441 qemu_log_mask(LOG_UNIMP
,
442 "%s: SPEED is not supported\n", __func__
);
445 /* Set Transfer Callback */
446 timer_mod(s
->fifo_trigger_handle
,
447 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) +
448 (TX_INTERRUPT_TRIGGER_DELAY_NS
));
451 case IBEX_SPI_HOST_TXDATA
:
453 * This is a hardware `feature` where
454 * the first word written to TXDATA after init is omitted entirely
456 if (s
->init_status
) {
457 s
->init_status
= false;
461 for (int i
= 0; i
< 4; ++i
) {
462 /* Attempting to write when TXFULL */
463 if (fifo8_is_full(&s
->tx_fifo
)) {
464 /* Assert RXEMPTY, no IRQ */
465 s
->regs
[IBEX_SPI_HOST_STATUS
] |= R_STATUS_TXFULL_MASK
;
466 s
->regs
[IBEX_SPI_HOST_ERROR_STATUS
] |=
467 R_ERROR_STATUS_OVERFLOW_MASK
;
468 ibex_spi_host_irq(s
);
471 /* Byte ordering is set by the IP */
472 status
= s
->regs
[IBEX_SPI_HOST_STATUS
];
473 if (FIELD_EX32(status
, STATUS
, BYTEORDER
) == 0) {
474 /* LE: LSB transmitted first (default for ibex processor) */
475 shift_mask
= 0xff << (i
* 8);
477 /* BE: MSB transmitted first */
478 qemu_log_mask(LOG_UNIMP
,
479 "%s: Big endian is not supported\n", __func__
);
482 fifo8_push(&s
->tx_fifo
, (val32
& shift_mask
) >> (i
* 8));
484 status
= s
->regs
[IBEX_SPI_HOST_STATUS
];
486 status
= FIELD_DP32(status
, STATUS
, TXEMPTY
, 0);
488 txqd_len
= FIELD_EX32(status
, STATUS
, TXQD
);
489 /* Partial bytes (size < 4) are padded, in words. */
491 status
= FIELD_DP32(status
, STATUS
, TXQD
, txqd_len
);
493 status
= FIELD_DP32(status
, STATUS
, READY
, 1);
494 /* Update register status */
495 s
->regs
[IBEX_SPI_HOST_STATUS
] = status
;
497 case IBEX_SPI_HOST_ERROR_ENABLE
:
498 s
->regs
[addr
] = val32
;
500 if (val32
& R_ERROR_ENABLE_CMDINVAL_MASK
) {
501 qemu_log_mask(LOG_UNIMP
,
502 "%s: Segment Length is not supported\n", __func__
);
505 case IBEX_SPI_HOST_ERROR_STATUS
:
507 * Indicates any errors that have occurred.
508 * When an error occurs, the corresponding bit must be cleared
509 * here before issuing any further commands
511 status
= s
->regs
[addr
];
512 /* rw1c status register */
513 if (FIELD_EX32(val32
, ERROR_STATUS
, CMDBUSY
)) {
514 status
= FIELD_DP32(status
, ERROR_STATUS
, CMDBUSY
, 0);
516 if (FIELD_EX32(val32
, ERROR_STATUS
, OVERFLOW
)) {
517 status
= FIELD_DP32(status
, ERROR_STATUS
, OVERFLOW
, 0);
519 if (FIELD_EX32(val32
, ERROR_STATUS
, UNDERFLOW
)) {
520 status
= FIELD_DP32(status
, ERROR_STATUS
, UNDERFLOW
, 0);
522 if (FIELD_EX32(val32
, ERROR_STATUS
, CMDINVAL
)) {
523 status
= FIELD_DP32(status
, ERROR_STATUS
, CMDINVAL
, 0);
525 if (FIELD_EX32(val32
, ERROR_STATUS
, CSIDINVAL
)) {
526 status
= FIELD_DP32(status
, ERROR_STATUS
, CSIDINVAL
, 0);
528 if (FIELD_EX32(val32
, ERROR_STATUS
, ACCESSINVAL
)) {
529 status
= FIELD_DP32(status
, ERROR_STATUS
, ACCESSINVAL
, 0);
531 s
->regs
[addr
] = status
;
533 case IBEX_SPI_HOST_EVENT_ENABLE
:
534 /* Controls which classes of SPI events raise an interrupt. */
535 s
->regs
[addr
] = val32
;
537 if (val32
& R_EVENT_ENABLE_RXWM_MASK
) {
538 qemu_log_mask(LOG_UNIMP
,
539 "%s: RXWM is not supported\n", __func__
);
541 if (val32
& R_EVENT_ENABLE_TXWM_MASK
) {
542 qemu_log_mask(LOG_UNIMP
,
543 "%s: TXWM is not supported\n", __func__
);
546 if (val32
& R_EVENT_ENABLE_IDLE_MASK
) {
547 qemu_log_mask(LOG_UNIMP
,
548 "%s: IDLE is not supported\n", __func__
);
552 qemu_log_mask(LOG_GUEST_ERROR
, "Bad offset 0x%" HWADDR_PRIx
"\n",
557 static const MemoryRegionOps ibex_spi_ops
= {
558 .read
= ibex_spi_host_read
,
559 .write
= ibex_spi_host_write
,
560 /* Ibex default LE */
561 .endianness
= DEVICE_LITTLE_ENDIAN
,
564 static Property ibex_spi_properties
[] = {
565 DEFINE_PROP_UINT32("num_cs", IbexSPIHostState
, num_cs
, 1),
566 DEFINE_PROP_END_OF_LIST(),
569 static const VMStateDescription vmstate_ibex
= {
570 .name
= TYPE_IBEX_SPI_HOST
,
572 .minimum_version_id
= 1,
573 .fields
= (const VMStateField
[]) {
574 VMSTATE_UINT32_ARRAY(regs
, IbexSPIHostState
, IBEX_SPI_HOST_MAX_REGS
),
575 VMSTATE_VARRAY_UINT32(config_opts
, IbexSPIHostState
,
576 num_cs
, 0, vmstate_info_uint32
, uint32_t),
577 VMSTATE_FIFO8(rx_fifo
, IbexSPIHostState
),
578 VMSTATE_FIFO8(tx_fifo
, IbexSPIHostState
),
579 VMSTATE_TIMER_PTR(fifo_trigger_handle
, IbexSPIHostState
),
580 VMSTATE_BOOL(init_status
, IbexSPIHostState
),
581 VMSTATE_END_OF_LIST()
585 static void fifo_trigger_update(void *opaque
)
587 IbexSPIHostState
*s
= opaque
;
588 ibex_spi_host_transfer(s
);
591 static void ibex_spi_host_realize(DeviceState
*dev
, Error
**errp
)
593 IbexSPIHostState
*s
= IBEX_SPI_HOST(dev
);
596 s
->ssi
= ssi_create_bus(dev
, "ssi");
597 s
->cs_lines
= g_new0(qemu_irq
, s
->num_cs
);
599 for (i
= 0; i
< s
->num_cs
; ++i
) {
600 sysbus_init_irq(SYS_BUS_DEVICE(dev
), &s
->cs_lines
[i
]);
603 /* Setup CONFIGOPTS Multi-register */
604 s
->config_opts
= g_new0(uint32_t, s
->num_cs
);
606 /* Setup FIFO Interrupt Timer */
607 s
->fifo_trigger_handle
= timer_new_ns(QEMU_CLOCK_VIRTUAL
,
608 fifo_trigger_update
, s
);
610 /* FIFO sizes as per OT Spec */
611 fifo8_create(&s
->tx_fifo
, IBEX_SPI_HOST_TXFIFO_LEN
);
612 fifo8_create(&s
->rx_fifo
, IBEX_SPI_HOST_RXFIFO_LEN
);
615 static void ibex_spi_host_init(Object
*obj
)
617 IbexSPIHostState
*s
= IBEX_SPI_HOST(obj
);
619 sysbus_init_irq(SYS_BUS_DEVICE(obj
), &s
->host_err
);
620 sysbus_init_irq(SYS_BUS_DEVICE(obj
), &s
->event
);
622 memory_region_init_io(&s
->mmio
, obj
, &ibex_spi_ops
, s
,
623 TYPE_IBEX_SPI_HOST
, 0x1000);
624 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &s
->mmio
);
627 static void ibex_spi_host_class_init(ObjectClass
*klass
, void *data
)
629 DeviceClass
*dc
= DEVICE_CLASS(klass
);
630 dc
->realize
= ibex_spi_host_realize
;
631 dc
->reset
= ibex_spi_host_reset
;
632 dc
->vmsd
= &vmstate_ibex
;
633 device_class_set_props(dc
, ibex_spi_properties
);
636 static const TypeInfo ibex_spi_host_info
= {
637 .name
= TYPE_IBEX_SPI_HOST
,
638 .parent
= TYPE_SYS_BUS_DEVICE
,
639 .instance_size
= sizeof(IbexSPIHostState
),
640 .instance_init
= ibex_spi_host_init
,
641 .class_init
= ibex_spi_host_class_init
,
644 static void ibex_spi_host_register_types(void)
646 type_register_static(&ibex_spi_host_info
);
649 type_init(ibex_spi_host_register_types
)