129318db1SChalapathi V /*
229318db1SChalapathi V * QEMU PowerPC SPI model
329318db1SChalapathi V *
429318db1SChalapathi V * Copyright (c) 2024, IBM Corporation.
529318db1SChalapathi V *
629318db1SChalapathi V * SPDX-License-Identifier: GPL-2.0-or-later
729318db1SChalapathi V */
829318db1SChalapathi V
929318db1SChalapathi V #include "qemu/osdep.h"
1029318db1SChalapathi V #include "qemu/log.h"
1129318db1SChalapathi V #include "hw/qdev-properties.h"
1229318db1SChalapathi V #include "hw/ppc/pnv_xscom.h"
1329318db1SChalapathi V #include "hw/ssi/pnv_spi.h"
1429318db1SChalapathi V #include "hw/ssi/pnv_spi_regs.h"
1529318db1SChalapathi V #include "hw/ssi/ssi.h"
1629318db1SChalapathi V #include <libfdt.h>
1729318db1SChalapathi V #include "hw/irq.h"
1829318db1SChalapathi V #include "trace.h"
1929318db1SChalapathi V
20b4cb930eSChalapathi V #define PNV_SPI_OPCODE_LO_NIBBLE(x) (x & 0x0F)
21b4cb930eSChalapathi V #define PNV_SPI_MASKED_OPCODE(x) (x & 0xF0)
22b4cb930eSChalapathi V
2329318db1SChalapathi V /*
2429318db1SChalapathi V * Macro from include/hw/ppc/fdt.h
2529318db1SChalapathi V * fdt.h cannot be included here as it contain ppc target specific dependency.
2629318db1SChalapathi V */
2729318db1SChalapathi V #define _FDT(exp) \
2829318db1SChalapathi V do { \
2929318db1SChalapathi V int _ret = (exp); \
3029318db1SChalapathi V if (_ret < 0) { \
3129318db1SChalapathi V qemu_log_mask(LOG_GUEST_ERROR, \
3229318db1SChalapathi V "error creating device tree: %s: %s", \
3329318db1SChalapathi V #exp, fdt_strerror(_ret)); \
3429318db1SChalapathi V exit(1); \
3529318db1SChalapathi V } \
3629318db1SChalapathi V } while (0)
3729318db1SChalapathi V
38b4cb930eSChalapathi V /* PnvXferBuffer */
39b4cb930eSChalapathi V typedef struct PnvXferBuffer {
40b4cb930eSChalapathi V
41b4cb930eSChalapathi V uint32_t len;
42b4cb930eSChalapathi V uint8_t *data;
43b4cb930eSChalapathi V
44b4cb930eSChalapathi V } PnvXferBuffer;
45b4cb930eSChalapathi V
46b4cb930eSChalapathi V /* pnv_spi_xfer_buffer_methods */
pnv_spi_xfer_buffer_new(void)47b4cb930eSChalapathi V static PnvXferBuffer *pnv_spi_xfer_buffer_new(void)
48b4cb930eSChalapathi V {
49b4cb930eSChalapathi V PnvXferBuffer *payload = g_malloc0(sizeof(*payload));
50b4cb930eSChalapathi V
51b4cb930eSChalapathi V return payload;
52b4cb930eSChalapathi V }
53b4cb930eSChalapathi V
pnv_spi_xfer_buffer_free(PnvXferBuffer * payload)54b4cb930eSChalapathi V static void pnv_spi_xfer_buffer_free(PnvXferBuffer *payload)
55b4cb930eSChalapathi V {
565d305310SPhilippe Mathieu-Daudé g_free(payload->data);
575d305310SPhilippe Mathieu-Daudé g_free(payload);
58b4cb930eSChalapathi V }
59b4cb930eSChalapathi V
pnv_spi_xfer_buffer_write_ptr(PnvXferBuffer * payload,uint32_t offset,uint32_t length)60b4cb930eSChalapathi V static uint8_t *pnv_spi_xfer_buffer_write_ptr(PnvXferBuffer *payload,
61b4cb930eSChalapathi V uint32_t offset, uint32_t length)
62b4cb930eSChalapathi V {
63b4cb930eSChalapathi V if (payload->len < (offset + length)) {
64b4cb930eSChalapathi V payload->len = offset + length;
65b4cb930eSChalapathi V payload->data = g_realloc(payload->data, payload->len);
66b4cb930eSChalapathi V }
67b4cb930eSChalapathi V return &payload->data[offset];
68b4cb930eSChalapathi V }
69b4cb930eSChalapathi V
does_rdr_match(PnvSpi * s)70b4cb930eSChalapathi V static bool does_rdr_match(PnvSpi *s)
71b4cb930eSChalapathi V {
72b4cb930eSChalapathi V /*
73b4cb930eSChalapathi V * According to spec, the mask bits that are 0 are compared and the
74b4cb930eSChalapathi V * bits that are 1 are ignored.
75b4cb930eSChalapathi V */
76b4cb930eSChalapathi V uint16_t rdr_match_mask = GETFIELD(SPI_MM_RDR_MATCH_MASK,
77b4cb930eSChalapathi V s->regs[SPI_MM_REG]);
78b4cb930eSChalapathi V uint16_t rdr_match_val = GETFIELD(SPI_MM_RDR_MATCH_VAL,
79b4cb930eSChalapathi V s->regs[SPI_MM_REG]);
80b4cb930eSChalapathi V
81b4cb930eSChalapathi V if ((~rdr_match_mask & rdr_match_val) == ((~rdr_match_mask) &
82b4cb930eSChalapathi V GETFIELD(PPC_BITMASK(48, 63), s->regs[SPI_RCV_DATA_REG]))) {
83b4cb930eSChalapathi V return true;
84b4cb930eSChalapathi V }
85b4cb930eSChalapathi V return false;
86b4cb930eSChalapathi V }
87b4cb930eSChalapathi V
get_from_offset(PnvSpi * s,uint8_t offset)88b4cb930eSChalapathi V static uint8_t get_from_offset(PnvSpi *s, uint8_t offset)
89b4cb930eSChalapathi V {
90b4cb930eSChalapathi V uint8_t byte;
91b4cb930eSChalapathi V
92b4cb930eSChalapathi V /*
93b4cb930eSChalapathi V * Offset is an index between 0 and PNV_SPI_REG_SIZE - 1
94b4cb930eSChalapathi V * Check the offset before using it.
95b4cb930eSChalapathi V */
96b4cb930eSChalapathi V if (offset < PNV_SPI_REG_SIZE) {
97b4cb930eSChalapathi V byte = (s->regs[SPI_XMIT_DATA_REG] >> (56 - offset * 8)) & 0xFF;
98b4cb930eSChalapathi V } else {
99b4cb930eSChalapathi V /*
100b4cb930eSChalapathi V * Log an error and return a 0xFF since we have to assign something
101b4cb930eSChalapathi V * to byte before returning.
102b4cb930eSChalapathi V */
103b4cb930eSChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "Invalid offset = %d used to get byte "
104b4cb930eSChalapathi V "from TDR\n", offset);
105b4cb930eSChalapathi V byte = 0xff;
106b4cb930eSChalapathi V }
107b4cb930eSChalapathi V return byte;
108b4cb930eSChalapathi V }
109b4cb930eSChalapathi V
read_from_frame(PnvSpi * s,uint8_t * read_buf,uint8_t nr_bytes,uint8_t ecc_count,uint8_t shift_in_count)110b4cb930eSChalapathi V static uint8_t read_from_frame(PnvSpi *s, uint8_t *read_buf, uint8_t nr_bytes,
111b4cb930eSChalapathi V uint8_t ecc_count, uint8_t shift_in_count)
112b4cb930eSChalapathi V {
113b4cb930eSChalapathi V uint8_t byte;
114b4cb930eSChalapathi V int count = 0;
115b4cb930eSChalapathi V
116b4cb930eSChalapathi V while (count < nr_bytes) {
117b4cb930eSChalapathi V shift_in_count++;
118b4cb930eSChalapathi V if ((ecc_count != 0) &&
119b4cb930eSChalapathi V (shift_in_count == (PNV_SPI_REG_SIZE + ecc_count))) {
120b4cb930eSChalapathi V shift_in_count = 0;
121b4cb930eSChalapathi V } else {
122b4cb930eSChalapathi V byte = read_buf[count];
123b4cb930eSChalapathi V trace_pnv_spi_shift_rx(byte, count);
124b4cb930eSChalapathi V s->regs[SPI_RCV_DATA_REG] = (s->regs[SPI_RCV_DATA_REG] << 8) | byte;
125b4cb930eSChalapathi V }
126b4cb930eSChalapathi V count++;
127b4cb930eSChalapathi V } /* end of while */
128b4cb930eSChalapathi V return shift_in_count;
129b4cb930eSChalapathi V }
130b4cb930eSChalapathi V
spi_response(PnvSpi * s,int bits,PnvXferBuffer * rsp_payload)131b4cb930eSChalapathi V static void spi_response(PnvSpi *s, int bits, PnvXferBuffer *rsp_payload)
132b4cb930eSChalapathi V {
133b4cb930eSChalapathi V uint8_t ecc_count;
134b4cb930eSChalapathi V uint8_t shift_in_count;
135b4cb930eSChalapathi V
136b4cb930eSChalapathi V /*
137b4cb930eSChalapathi V * Processing here must handle:
138b4cb930eSChalapathi V * - Which bytes in the payload we should move to the RDR
139b4cb930eSChalapathi V * - Explicit mode counter configuration settings
140b4cb930eSChalapathi V * - RDR full and RDR overrun status
141b4cb930eSChalapathi V */
142b4cb930eSChalapathi V
143b4cb930eSChalapathi V /*
144b4cb930eSChalapathi V * First check that the response payload is the exact same
145b4cb930eSChalapathi V * number of bytes as the request payload was
146b4cb930eSChalapathi V */
147b4cb930eSChalapathi V if (rsp_payload->len != (s->N1_bytes + s->N2_bytes)) {
148b4cb930eSChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "Invalid response payload size in "
149b4cb930eSChalapathi V "bytes, expected %d, got %d\n",
150b4cb930eSChalapathi V (s->N1_bytes + s->N2_bytes), rsp_payload->len);
151b4cb930eSChalapathi V } else {
152b4cb930eSChalapathi V uint8_t ecc_control;
153b4cb930eSChalapathi V trace_pnv_spi_rx_received(rsp_payload->len);
154b4cb930eSChalapathi V trace_pnv_spi_log_Ncounts(s->N1_bits, s->N1_bytes, s->N1_tx,
155b4cb930eSChalapathi V s->N1_rx, s->N2_bits, s->N2_bytes, s->N2_tx, s->N2_rx);
156b4cb930eSChalapathi V /*
157b4cb930eSChalapathi V * Adding an ECC count let's us know when we have found a payload byte
158b4cb930eSChalapathi V * that was shifted in but cannot be loaded into RDR. Bits 29-30 of
159b4cb930eSChalapathi V * clock_config_reset_control register equal to either 0b00 or 0b10
160b4cb930eSChalapathi V * indicate that we are taking in data with ECC and either applying
161b4cb930eSChalapathi V * the ECC or discarding it.
162b4cb930eSChalapathi V */
163b4cb930eSChalapathi V ecc_count = 0;
164b4cb930eSChalapathi V ecc_control = GETFIELD(SPI_CLK_CFG_ECC_CTRL, s->regs[SPI_CLK_CFG_REG]);
165b4cb930eSChalapathi V if (ecc_control == 0 || ecc_control == 2) {
166b4cb930eSChalapathi V ecc_count = 1;
167b4cb930eSChalapathi V }
168b4cb930eSChalapathi V /*
169b4cb930eSChalapathi V * Use the N1_rx and N2_rx counts to control shifting data from the
170b4cb930eSChalapathi V * payload into the RDR. Keep an overall count of the number of bytes
171b4cb930eSChalapathi V * shifted into RDR so we can discard every 9th byte when ECC is
172b4cb930eSChalapathi V * enabled.
173b4cb930eSChalapathi V */
174b4cb930eSChalapathi V shift_in_count = 0;
175b4cb930eSChalapathi V /* Handle the N1 portion of the frame first */
176b4cb930eSChalapathi V if (s->N1_rx != 0) {
177b4cb930eSChalapathi V trace_pnv_spi_rx_read_N1frame();
178b4cb930eSChalapathi V shift_in_count = read_from_frame(s, &rsp_payload->data[0],
179b4cb930eSChalapathi V s->N1_bytes, ecc_count, shift_in_count);
180b4cb930eSChalapathi V }
181b4cb930eSChalapathi V /* Handle the N2 portion of the frame */
182b4cb930eSChalapathi V if (s->N2_rx != 0) {
183b4cb930eSChalapathi V trace_pnv_spi_rx_read_N2frame();
184b4cb930eSChalapathi V shift_in_count = read_from_frame(s,
185b4cb930eSChalapathi V &rsp_payload->data[s->N1_bytes], s->N2_bytes,
186b4cb930eSChalapathi V ecc_count, shift_in_count);
187b4cb930eSChalapathi V }
188b4cb930eSChalapathi V if ((s->N1_rx + s->N2_rx) > 0) {
189b4cb930eSChalapathi V /*
190b4cb930eSChalapathi V * Data was received so handle RDR status.
191b4cb930eSChalapathi V * It is easier to handle RDR_full and RDR_overrun status here
192b4cb930eSChalapathi V * since the RDR register's shift_byte_in method is called
193b4cb930eSChalapathi V * multiple times in a row. Controlling RDR status is done here
194b4cb930eSChalapathi V * instead of in the RDR scoped methods for that reason.
195b4cb930eSChalapathi V */
196b4cb930eSChalapathi V if (GETFIELD(SPI_STS_RDR_FULL, s->status) == 1) {
197b4cb930eSChalapathi V /*
198b4cb930eSChalapathi V * Data was shifted into the RDR before having been read
199b4cb930eSChalapathi V * causing previous data to have been overrun.
200b4cb930eSChalapathi V */
201b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_RDR_OVERRUN, s->status, 1);
202b4cb930eSChalapathi V } else {
203b4cb930eSChalapathi V /*
204b4cb930eSChalapathi V * Set status to indicate that the received data register is
205b4cb930eSChalapathi V * full. This flag is only cleared once the RDR is unloaded.
206b4cb930eSChalapathi V */
207b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_RDR_FULL, s->status, 1);
208b4cb930eSChalapathi V }
209b4cb930eSChalapathi V }
210b4cb930eSChalapathi V } /* end of else */
211b4cb930eSChalapathi V } /* end of spi_response() */
212b4cb930eSChalapathi V
transfer(PnvSpi * s,PnvXferBuffer * payload)213b4cb930eSChalapathi V static void transfer(PnvSpi *s, PnvXferBuffer *payload)
214b4cb930eSChalapathi V {
215b4cb930eSChalapathi V uint32_t tx;
216b4cb930eSChalapathi V uint32_t rx;
217b4cb930eSChalapathi V PnvXferBuffer *rsp_payload = NULL;
218b4cb930eSChalapathi V
219b4cb930eSChalapathi V rsp_payload = pnv_spi_xfer_buffer_new();
2202408ff81SPhilippe Mathieu-Daudé if (!rsp_payload) {
2212408ff81SPhilippe Mathieu-Daudé return;
2222408ff81SPhilippe Mathieu-Daudé }
223b4cb930eSChalapathi V for (int offset = 0; offset < payload->len; offset += s->transfer_len) {
224b4cb930eSChalapathi V tx = 0;
225b4cb930eSChalapathi V for (int i = 0; i < s->transfer_len; i++) {
226b4cb930eSChalapathi V if ((offset + i) >= payload->len) {
227b4cb930eSChalapathi V tx <<= 8;
228b4cb930eSChalapathi V } else {
229b4cb930eSChalapathi V tx = (tx << 8) | payload->data[offset + i];
230b4cb930eSChalapathi V }
231b4cb930eSChalapathi V }
232b4cb930eSChalapathi V rx = ssi_transfer(s->ssi_bus, tx);
233b4cb930eSChalapathi V for (int i = 0; i < s->transfer_len; i++) {
234b4cb930eSChalapathi V if ((offset + i) >= payload->len) {
235b4cb930eSChalapathi V break;
236b4cb930eSChalapathi V }
237b4cb930eSChalapathi V *(pnv_spi_xfer_buffer_write_ptr(rsp_payload, rsp_payload->len, 1)) =
238b4cb930eSChalapathi V (rx >> (8 * (s->transfer_len - 1) - i * 8)) & 0xFF;
239b4cb930eSChalapathi V }
240b4cb930eSChalapathi V }
241b4cb930eSChalapathi V spi_response(s, s->N1_bits, rsp_payload);
242*2a5eec6dSChalapathi V pnv_spi_xfer_buffer_free(rsp_payload);
243b4cb930eSChalapathi V }
244b4cb930eSChalapathi V
get_seq_index(PnvSpi * s)245b4cb930eSChalapathi V static inline uint8_t get_seq_index(PnvSpi *s)
246b4cb930eSChalapathi V {
247b4cb930eSChalapathi V return GETFIELD(SPI_STS_SEQ_INDEX, s->status);
248b4cb930eSChalapathi V }
249b4cb930eSChalapathi V
next_sequencer_fsm(PnvSpi * s)250b4cb930eSChalapathi V static inline void next_sequencer_fsm(PnvSpi *s)
251b4cb930eSChalapathi V {
252b4cb930eSChalapathi V uint8_t seq_index = get_seq_index(s);
253b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_INDEX, s->status, (seq_index + 1));
254b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_INDEX_INCREMENT);
255b4cb930eSChalapathi V }
256b4cb930eSChalapathi V
257b4cb930eSChalapathi V /*
258b4cb930eSChalapathi V * Calculate the N1 counters based on passed in opcode and
259b4cb930eSChalapathi V * internal register values.
260b4cb930eSChalapathi V * The method assumes that the opcode is a Shift_N1 opcode
261b4cb930eSChalapathi V * and doesn't test it.
262b4cb930eSChalapathi V * The counters returned are:
263b4cb930eSChalapathi V * N1 bits: Number of bits in the payload data that are significant
264b4cb930eSChalapathi V * to the responder.
265b4cb930eSChalapathi V * N1_bytes: Total count of payload bytes for the N1 (portion of the) frame.
266b4cb930eSChalapathi V * N1_tx: Total number of bytes taken from TDR for N1
267b4cb930eSChalapathi V * N1_rx: Total number of bytes taken from the payload for N1
268b4cb930eSChalapathi V */
calculate_N1(PnvSpi * s,uint8_t opcode)269b4cb930eSChalapathi V static void calculate_N1(PnvSpi *s, uint8_t opcode)
270b4cb930eSChalapathi V {
271b4cb930eSChalapathi V /*
272b4cb930eSChalapathi V * Shift_N1 opcode form: 0x3M
273b4cb930eSChalapathi V * Implicit mode:
274b4cb930eSChalapathi V * If M != 0 the shift count is M bytes and M is the number of tx bytes.
275b4cb930eSChalapathi V * Forced Implicit mode:
276b4cb930eSChalapathi V * M is the shift count but tx and rx is determined by the count control
277b4cb930eSChalapathi V * register fields. Note that we only check for forced Implicit mode when
278b4cb930eSChalapathi V * M != 0 since the mode doesn't make sense when M = 0.
279b4cb930eSChalapathi V * Explicit mode:
280b4cb930eSChalapathi V * If M == 0 then shift count is number of bits defined in the
281b4cb930eSChalapathi V * Counter Configuration Register's shift_count_N1 field.
282b4cb930eSChalapathi V */
283b4cb930eSChalapathi V if (PNV_SPI_OPCODE_LO_NIBBLE(opcode) == 0) {
284b4cb930eSChalapathi V /* Explicit mode */
285b4cb930eSChalapathi V s->N1_bits = GETFIELD(SPI_CTR_CFG_N1, s->regs[SPI_CTR_CFG_REG]);
286b4cb930eSChalapathi V s->N1_bytes = (s->N1_bits + 7) / 8;
287b4cb930eSChalapathi V s->N1_tx = 0;
288b4cb930eSChalapathi V s->N1_rx = 0;
289b4cb930eSChalapathi V /* If tx count control for N1 is set, load the tx value */
290b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N1_CTRL_B2, s->regs[SPI_CTR_CFG_REG]) == 1) {
291b4cb930eSChalapathi V s->N1_tx = s->N1_bytes;
292b4cb930eSChalapathi V }
293b4cb930eSChalapathi V /* If rx count control for N1 is set, load the rx value */
294b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N1_CTRL_B3, s->regs[SPI_CTR_CFG_REG]) == 1) {
295b4cb930eSChalapathi V s->N1_rx = s->N1_bytes;
296b4cb930eSChalapathi V }
297b4cb930eSChalapathi V } else {
298b4cb930eSChalapathi V /* Implicit mode/Forced Implicit mode, use M field from opcode */
299b4cb930eSChalapathi V s->N1_bytes = PNV_SPI_OPCODE_LO_NIBBLE(opcode);
300b4cb930eSChalapathi V s->N1_bits = s->N1_bytes * 8;
301b4cb930eSChalapathi V /*
302b4cb930eSChalapathi V * Assume that we are going to transmit the count
303b4cb930eSChalapathi V * (pure Implicit only)
304b4cb930eSChalapathi V */
305b4cb930eSChalapathi V s->N1_tx = s->N1_bytes;
306b4cb930eSChalapathi V s->N1_rx = 0;
307b4cb930eSChalapathi V /* Let Forced Implicit mode have an effect on the counts */
308b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N1_CTRL_B1, s->regs[SPI_CTR_CFG_REG]) == 1) {
309b4cb930eSChalapathi V /*
310b4cb930eSChalapathi V * If Forced Implicit mode and count control doesn't
311b4cb930eSChalapathi V * indicate transmit then reset the tx count to 0
312b4cb930eSChalapathi V */
313b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N1_CTRL_B2,
314b4cb930eSChalapathi V s->regs[SPI_CTR_CFG_REG]) == 0) {
315b4cb930eSChalapathi V s->N1_tx = 0;
316b4cb930eSChalapathi V }
317b4cb930eSChalapathi V /* If rx count control for N1 is set, load the rx value */
318b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N1_CTRL_B3,
319b4cb930eSChalapathi V s->regs[SPI_CTR_CFG_REG]) == 1) {
320b4cb930eSChalapathi V s->N1_rx = s->N1_bytes;
321b4cb930eSChalapathi V }
322b4cb930eSChalapathi V }
323b4cb930eSChalapathi V }
324b4cb930eSChalapathi V /*
325b4cb930eSChalapathi V * Enforce an upper limit on the size of N1 that is equal to the known size
326b4cb930eSChalapathi V * of the shift register, 64 bits or 72 bits if ECC is enabled.
327b4cb930eSChalapathi V * If the size exceeds 72 bits it is a user error so log an error,
328b4cb930eSChalapathi V * cap the size at a max of 64 bits or 72 bits and set the sequencer FSM
329b4cb930eSChalapathi V * error bit.
330b4cb930eSChalapathi V */
331b4cb930eSChalapathi V uint8_t ecc_control = GETFIELD(SPI_CLK_CFG_ECC_CTRL,
332b4cb930eSChalapathi V s->regs[SPI_CLK_CFG_REG]);
333b4cb930eSChalapathi V if (ecc_control == 0 || ecc_control == 2) {
334b4cb930eSChalapathi V if (s->N1_bytes > (PNV_SPI_REG_SIZE + 1)) {
335b4cb930eSChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "Unsupported N1 shift size when "
336b4cb930eSChalapathi V "ECC enabled, bytes = 0x%x, bits = 0x%x\n",
337b4cb930eSChalapathi V s->N1_bytes, s->N1_bits);
338b4cb930eSChalapathi V s->N1_bytes = PNV_SPI_REG_SIZE + 1;
339b4cb930eSChalapathi V s->N1_bits = s->N1_bytes * 8;
340b4cb930eSChalapathi V }
341b4cb930eSChalapathi V } else if (s->N1_bytes > PNV_SPI_REG_SIZE) {
342b4cb930eSChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "Unsupported N1 shift size, "
343b4cb930eSChalapathi V "bytes = 0x%x, bits = 0x%x\n",
344b4cb930eSChalapathi V s->N1_bytes, s->N1_bits);
345b4cb930eSChalapathi V s->N1_bytes = PNV_SPI_REG_SIZE;
346b4cb930eSChalapathi V s->N1_bits = s->N1_bytes * 8;
347b4cb930eSChalapathi V }
348b4cb930eSChalapathi V } /* end of calculate_N1 */
349b4cb930eSChalapathi V
350b4cb930eSChalapathi V /*
351b4cb930eSChalapathi V * Shift_N1 operation handler method
352b4cb930eSChalapathi V */
operation_shiftn1(PnvSpi * s,uint8_t opcode,PnvXferBuffer ** payload,bool send_n1_alone)353b4cb930eSChalapathi V static bool operation_shiftn1(PnvSpi *s, uint8_t opcode,
354b4cb930eSChalapathi V PnvXferBuffer **payload, bool send_n1_alone)
355b4cb930eSChalapathi V {
356b4cb930eSChalapathi V uint8_t n1_count;
357b4cb930eSChalapathi V bool stop = false;
358b4cb930eSChalapathi V
359b4cb930eSChalapathi V /*
360b4cb930eSChalapathi V * If there isn't a current payload left over from a stopped sequence
361b4cb930eSChalapathi V * create a new one.
362b4cb930eSChalapathi V */
363b4cb930eSChalapathi V if (*payload == NULL) {
364b4cb930eSChalapathi V *payload = pnv_spi_xfer_buffer_new();
365b4cb930eSChalapathi V }
366b4cb930eSChalapathi V /*
367b4cb930eSChalapathi V * Use a combination of N1 counters to build the N1 portion of the
368b4cb930eSChalapathi V * transmit payload.
369b4cb930eSChalapathi V * We only care about transmit at this time since the request payload
370b4cb930eSChalapathi V * only represents data going out on the controller output line.
371b4cb930eSChalapathi V * Leave mode specific considerations in the calculate function since
372b4cb930eSChalapathi V * all we really care about are counters that tell use exactly how
373b4cb930eSChalapathi V * many bytes are in the payload and how many of those bytes to
374b4cb930eSChalapathi V * include from the TDR into the payload.
375b4cb930eSChalapathi V */
376b4cb930eSChalapathi V calculate_N1(s, opcode);
377b4cb930eSChalapathi V trace_pnv_spi_log_Ncounts(s->N1_bits, s->N1_bytes, s->N1_tx,
378b4cb930eSChalapathi V s->N1_rx, s->N2_bits, s->N2_bytes, s->N2_tx, s->N2_rx);
379b4cb930eSChalapathi V /*
380b4cb930eSChalapathi V * Zero out the N2 counters here in case there is no N2 operation following
381b4cb930eSChalapathi V * the N1 operation in the sequencer. This keeps leftover N2 information
382b4cb930eSChalapathi V * from interfering with spi_response logic.
383b4cb930eSChalapathi V */
384b4cb930eSChalapathi V s->N2_bits = 0;
385b4cb930eSChalapathi V s->N2_bytes = 0;
386b4cb930eSChalapathi V s->N2_tx = 0;
387b4cb930eSChalapathi V s->N2_rx = 0;
388b4cb930eSChalapathi V /*
389b4cb930eSChalapathi V * N1_bytes is the overall size of the N1 portion of the frame regardless of
390b4cb930eSChalapathi V * whether N1 is used for tx, rx or both. Loop over the size to build a
391b4cb930eSChalapathi V * payload that is N1_bytes long.
392b4cb930eSChalapathi V * N1_tx is the count of bytes to take from the TDR and "shift" into the
393b4cb930eSChalapathi V * frame which means append those bytes to the payload for the N1 portion
394b4cb930eSChalapathi V * of the frame.
395b4cb930eSChalapathi V * If N1_tx is 0 or if the count exceeds the size of the TDR append 0xFF to
396b4cb930eSChalapathi V * the frame until the overall N1 count is reached.
397b4cb930eSChalapathi V */
398b4cb930eSChalapathi V n1_count = 0;
399b4cb930eSChalapathi V while (n1_count < s->N1_bytes) {
400b4cb930eSChalapathi V /*
401b4cb930eSChalapathi V * Assuming that if N1_tx is not equal to 0 then it is the same as
402b4cb930eSChalapathi V * N1_bytes.
403b4cb930eSChalapathi V */
404b4cb930eSChalapathi V if ((s->N1_tx != 0) && (n1_count < PNV_SPI_REG_SIZE)) {
405b4cb930eSChalapathi V
406b4cb930eSChalapathi V if (GETFIELD(SPI_STS_TDR_FULL, s->status) == 1) {
407b4cb930eSChalapathi V /*
408b4cb930eSChalapathi V * Note that we are only appending to the payload IF the TDR
409b4cb930eSChalapathi V * is full otherwise we don't touch the payload because we are
410b4cb930eSChalapathi V * going to NOT send the payload and instead tell the sequencer
411b4cb930eSChalapathi V * that called us to stop and wait for a TDR write so we have
412b4cb930eSChalapathi V * data to load into the payload.
413b4cb930eSChalapathi V */
414b4cb930eSChalapathi V uint8_t n1_byte = 0x00;
415b4cb930eSChalapathi V n1_byte = get_from_offset(s, n1_count);
416b4cb930eSChalapathi V trace_pnv_spi_tx_append("n1_byte", n1_byte, n1_count);
417b4cb930eSChalapathi V *(pnv_spi_xfer_buffer_write_ptr(*payload, (*payload)->len, 1)) =
418b4cb930eSChalapathi V n1_byte;
419b4cb930eSChalapathi V } else {
420b4cb930eSChalapathi V /*
421b4cb930eSChalapathi V * We hit a shift_n1 opcode TX but the TDR is empty, tell the
422b4cb930eSChalapathi V * sequencer to stop and break this loop.
423b4cb930eSChalapathi V */
424b4cb930eSChalapathi V trace_pnv_spi_sequencer_stop_requested("Shift N1"
425b4cb930eSChalapathi V "set for transmit but TDR is empty");
426b4cb930eSChalapathi V stop = true;
427b4cb930eSChalapathi V break;
428b4cb930eSChalapathi V }
429b4cb930eSChalapathi V } else {
430b4cb930eSChalapathi V /*
431b4cb930eSChalapathi V * Cases here:
432b4cb930eSChalapathi V * - we are receiving during the N1 frame segment and the RDR
433b4cb930eSChalapathi V * is full so we need to stop until the RDR is read
434b4cb930eSChalapathi V * - we are transmitting and we don't care about RDR status
435b4cb930eSChalapathi V * since we won't be loading RDR during the frame segment.
436b4cb930eSChalapathi V * - we are receiving and the RDR is empty so we allow the operation
437b4cb930eSChalapathi V * to proceed.
438b4cb930eSChalapathi V */
439b4cb930eSChalapathi V if ((s->N1_rx != 0) && (GETFIELD(SPI_STS_RDR_FULL,
440b4cb930eSChalapathi V s->status) == 1)) {
441b4cb930eSChalapathi V trace_pnv_spi_sequencer_stop_requested("shift N1"
442b4cb930eSChalapathi V "set for receive but RDR is full");
443b4cb930eSChalapathi V stop = true;
444b4cb930eSChalapathi V break;
445b4cb930eSChalapathi V } else {
446b4cb930eSChalapathi V trace_pnv_spi_tx_append_FF("n1_byte");
447b4cb930eSChalapathi V *(pnv_spi_xfer_buffer_write_ptr(*payload, (*payload)->len, 1))
448b4cb930eSChalapathi V = 0xff;
449b4cb930eSChalapathi V }
450b4cb930eSChalapathi V }
451b4cb930eSChalapathi V n1_count++;
452b4cb930eSChalapathi V } /* end of while */
453b4cb930eSChalapathi V /*
454b4cb930eSChalapathi V * If we are not stopping due to an empty TDR and we are doing an N1 TX
455b4cb930eSChalapathi V * and the TDR is full we need to clear the TDR_full status.
456b4cb930eSChalapathi V * Do this here instead of up in the loop above so we don't log the message
457b4cb930eSChalapathi V * in every loop iteration.
458b4cb930eSChalapathi V * Ignore the send_n1_alone flag, all that does is defer the TX until the N2
459b4cb930eSChalapathi V * operation, which was found immediately after the current opcode. The TDR
460b4cb930eSChalapathi V * was unloaded and will be shifted so we have to clear the TDR_full status.
461b4cb930eSChalapathi V */
462b4cb930eSChalapathi V if (!stop && (s->N1_tx != 0) &&
463b4cb930eSChalapathi V (GETFIELD(SPI_STS_TDR_FULL, s->status) == 1)) {
464b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_TDR_FULL, s->status, 0);
465b4cb930eSChalapathi V }
466b4cb930eSChalapathi V /*
467b4cb930eSChalapathi V * There are other reasons why the shifter would stop, such as a TDR empty
468b4cb930eSChalapathi V * or RDR full condition with N1 set to receive. If we haven't stopped due
469b4cb930eSChalapathi V * to either one of those conditions then check if the send_n1_alone flag is
470b4cb930eSChalapathi V * equal to False, indicating the next opcode is an N2 operation, AND if
471b4cb930eSChalapathi V * the N2 counter reload switch (bit 0 of the N2 count control field) is
472b4cb930eSChalapathi V * set. This condition requires a pacing write to "kick" off the N2
473b4cb930eSChalapathi V * shift which includes the N1 shift as well when send_n1_alone is False.
474b4cb930eSChalapathi V */
475b4cb930eSChalapathi V if (!stop && !send_n1_alone &&
476b4cb930eSChalapathi V (GETFIELD(SPI_CTR_CFG_N2_CTRL_B0, s->regs[SPI_CTR_CFG_REG]) == 1)) {
477b4cb930eSChalapathi V trace_pnv_spi_sequencer_stop_requested("N2 counter reload "
478b4cb930eSChalapathi V "active, stop N1 shift, TDR_underrun set to 1");
479b4cb930eSChalapathi V stop = true;
480b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_TDR_UNDERRUN, s->status, 1);
481b4cb930eSChalapathi V }
482b4cb930eSChalapathi V /*
483b4cb930eSChalapathi V * If send_n1_alone is set AND we have a full TDR then this is the first and
484b4cb930eSChalapathi V * last payload to send and we don't have an N2 frame segment to add to the
485b4cb930eSChalapathi V * payload.
486b4cb930eSChalapathi V */
487b4cb930eSChalapathi V if (send_n1_alone && !stop) {
488b4cb930eSChalapathi V /* We have a TX and a full TDR or an RX and an empty RDR */
489b4cb930eSChalapathi V trace_pnv_spi_tx_request("Shifting N1 frame", (*payload)->len);
490b4cb930eSChalapathi V transfer(s, *payload);
491b4cb930eSChalapathi V /* The N1 frame shift is complete so reset the N1 counters */
492b4cb930eSChalapathi V s->N2_bits = 0;
493b4cb930eSChalapathi V s->N2_bytes = 0;
494b4cb930eSChalapathi V s->N2_tx = 0;
495b4cb930eSChalapathi V s->N2_rx = 0;
496b4cb930eSChalapathi V pnv_spi_xfer_buffer_free(*payload);
497b4cb930eSChalapathi V *payload = NULL;
498b4cb930eSChalapathi V }
499b4cb930eSChalapathi V return stop;
500b4cb930eSChalapathi V } /* end of operation_shiftn1() */
501b4cb930eSChalapathi V
502b4cb930eSChalapathi V /*
503b4cb930eSChalapathi V * Calculate the N2 counters based on passed in opcode and
504b4cb930eSChalapathi V * internal register values.
505b4cb930eSChalapathi V * The method assumes that the opcode is a Shift_N2 opcode
506b4cb930eSChalapathi V * and doesn't test it.
507b4cb930eSChalapathi V * The counters returned are:
508b4cb930eSChalapathi V * N2 bits: Number of bits in the payload data that are significant
509b4cb930eSChalapathi V * to the responder.
510b4cb930eSChalapathi V * N2_bytes: Total count of payload bytes for the N2 frame.
511b4cb930eSChalapathi V * N2_tx: Total number of bytes taken from TDR for N2
512b4cb930eSChalapathi V * N2_rx: Total number of bytes taken from the payload for N2
513b4cb930eSChalapathi V */
calculate_N2(PnvSpi * s,uint8_t opcode)514b4cb930eSChalapathi V static void calculate_N2(PnvSpi *s, uint8_t opcode)
515b4cb930eSChalapathi V {
516b4cb930eSChalapathi V /*
517b4cb930eSChalapathi V * Shift_N2 opcode form: 0x4M
518b4cb930eSChalapathi V * Implicit mode:
519b4cb930eSChalapathi V * If M!=0 the shift count is M bytes and M is the number of rx bytes.
520b4cb930eSChalapathi V * Forced Implicit mode:
521b4cb930eSChalapathi V * M is the shift count but tx and rx is determined by the count control
522b4cb930eSChalapathi V * register fields. Note that we only check for Forced Implicit mode when
523b4cb930eSChalapathi V * M != 0 since the mode doesn't make sense when M = 0.
524b4cb930eSChalapathi V * Explicit mode:
525b4cb930eSChalapathi V * If M==0 then shift count is number of bits defined in the
526b4cb930eSChalapathi V * Counter Configuration Register's shift_count_N1 field.
527b4cb930eSChalapathi V */
528b4cb930eSChalapathi V if (PNV_SPI_OPCODE_LO_NIBBLE(opcode) == 0) {
529b4cb930eSChalapathi V /* Explicit mode */
530b4cb930eSChalapathi V s->N2_bits = GETFIELD(SPI_CTR_CFG_N2, s->regs[SPI_CTR_CFG_REG]);
531b4cb930eSChalapathi V s->N2_bytes = (s->N2_bits + 7) / 8;
532b4cb930eSChalapathi V s->N2_tx = 0;
533b4cb930eSChalapathi V s->N2_rx = 0;
534b4cb930eSChalapathi V /* If tx count control for N2 is set, load the tx value */
535b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N2_CTRL_B2, s->regs[SPI_CTR_CFG_REG]) == 1) {
536b4cb930eSChalapathi V s->N2_tx = s->N2_bytes;
537b4cb930eSChalapathi V }
538b4cb930eSChalapathi V /* If rx count control for N2 is set, load the rx value */
539b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N2_CTRL_B3, s->regs[SPI_CTR_CFG_REG]) == 1) {
540b4cb930eSChalapathi V s->N2_rx = s->N2_bytes;
541b4cb930eSChalapathi V }
542b4cb930eSChalapathi V } else {
543b4cb930eSChalapathi V /* Implicit mode/Forced Implicit mode, use M field from opcode */
544b4cb930eSChalapathi V s->N2_bytes = PNV_SPI_OPCODE_LO_NIBBLE(opcode);
545b4cb930eSChalapathi V s->N2_bits = s->N2_bytes * 8;
546b4cb930eSChalapathi V /* Assume that we are going to receive the count */
547b4cb930eSChalapathi V s->N2_rx = s->N2_bytes;
548b4cb930eSChalapathi V s->N2_tx = 0;
549b4cb930eSChalapathi V /* Let Forced Implicit mode have an effect on the counts */
550b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N2_CTRL_B1, s->regs[SPI_CTR_CFG_REG]) == 1) {
551b4cb930eSChalapathi V /*
552b4cb930eSChalapathi V * If Forced Implicit mode and count control doesn't
553b4cb930eSChalapathi V * indicate a receive then reset the rx count to 0
554b4cb930eSChalapathi V */
555b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N2_CTRL_B3,
556b4cb930eSChalapathi V s->regs[SPI_CTR_CFG_REG]) == 0) {
557b4cb930eSChalapathi V s->N2_rx = 0;
558b4cb930eSChalapathi V }
559b4cb930eSChalapathi V /* If tx count control for N2 is set, load the tx value */
560b4cb930eSChalapathi V if (GETFIELD(SPI_CTR_CFG_N2_CTRL_B2,
561b4cb930eSChalapathi V s->regs[SPI_CTR_CFG_REG]) == 1) {
562b4cb930eSChalapathi V s->N2_tx = s->N2_bytes;
563b4cb930eSChalapathi V }
564b4cb930eSChalapathi V }
565b4cb930eSChalapathi V }
566b4cb930eSChalapathi V /*
567b4cb930eSChalapathi V * Enforce an upper limit on the size of N1 that is equal to the
568b4cb930eSChalapathi V * known size of the shift register, 64 bits or 72 bits if ECC
569b4cb930eSChalapathi V * is enabled.
570b4cb930eSChalapathi V * If the size exceeds 72 bits it is a user error so log an error,
571b4cb930eSChalapathi V * cap the size at a max of 64 bits or 72 bits and set the sequencer FSM
572b4cb930eSChalapathi V * error bit.
573b4cb930eSChalapathi V */
574b4cb930eSChalapathi V uint8_t ecc_control = GETFIELD(SPI_CLK_CFG_ECC_CTRL,
575b4cb930eSChalapathi V s->regs[SPI_CLK_CFG_REG]);
576b4cb930eSChalapathi V if (ecc_control == 0 || ecc_control == 2) {
577b4cb930eSChalapathi V if (s->N2_bytes > (PNV_SPI_REG_SIZE + 1)) {
578b4cb930eSChalapathi V /* Unsupported N2 shift size when ECC enabled */
579b4cb930eSChalapathi V s->N2_bytes = PNV_SPI_REG_SIZE + 1;
580b4cb930eSChalapathi V s->N2_bits = s->N2_bytes * 8;
581b4cb930eSChalapathi V }
582b4cb930eSChalapathi V } else if (s->N2_bytes > PNV_SPI_REG_SIZE) {
583b4cb930eSChalapathi V /* Unsupported N2 shift size */
584b4cb930eSChalapathi V s->N2_bytes = PNV_SPI_REG_SIZE;
585b4cb930eSChalapathi V s->N2_bits = s->N2_bytes * 8;
586b4cb930eSChalapathi V }
587b4cb930eSChalapathi V } /* end of calculate_N2 */
588b4cb930eSChalapathi V
589b4cb930eSChalapathi V /*
590b4cb930eSChalapathi V * Shift_N2 operation handler method
591b4cb930eSChalapathi V */
592b4cb930eSChalapathi V
operation_shiftn2(PnvSpi * s,uint8_t opcode,PnvXferBuffer ** payload)593b4cb930eSChalapathi V static bool operation_shiftn2(PnvSpi *s, uint8_t opcode,
594b4cb930eSChalapathi V PnvXferBuffer **payload)
595b4cb930eSChalapathi V {
596b4cb930eSChalapathi V uint8_t n2_count;
597b4cb930eSChalapathi V bool stop = false;
598b4cb930eSChalapathi V
599b4cb930eSChalapathi V /*
600b4cb930eSChalapathi V * If there isn't a current payload left over from a stopped sequence
601b4cb930eSChalapathi V * create a new one.
602b4cb930eSChalapathi V */
603b4cb930eSChalapathi V if (*payload == NULL) {
604b4cb930eSChalapathi V *payload = pnv_spi_xfer_buffer_new();
605b4cb930eSChalapathi V }
606b4cb930eSChalapathi V /*
607b4cb930eSChalapathi V * Use a combination of N2 counters to build the N2 portion of the
608b4cb930eSChalapathi V * transmit payload.
609b4cb930eSChalapathi V */
610b4cb930eSChalapathi V calculate_N2(s, opcode);
611b4cb930eSChalapathi V trace_pnv_spi_log_Ncounts(s->N1_bits, s->N1_bytes, s->N1_tx,
612b4cb930eSChalapathi V s->N1_rx, s->N2_bits, s->N2_bytes, s->N2_tx, s->N2_rx);
613b4cb930eSChalapathi V /*
614b4cb930eSChalapathi V * The only difference between this code and the code for shift N1 is
615b4cb930eSChalapathi V * that this code has to account for the possible presence of N1 transmit
616b4cb930eSChalapathi V * bytes already taken from the TDR.
617b4cb930eSChalapathi V * If there are bytes to be transmitted for the N2 portion of the frame
618b4cb930eSChalapathi V * and there are still bytes in TDR that have not been copied into the
619b4cb930eSChalapathi V * TX data of the payload, this code will handle transmitting those
620b4cb930eSChalapathi V * remaining bytes.
621b4cb930eSChalapathi V * If for some reason the transmit count(s) add up to more than the size
622b4cb930eSChalapathi V * of the TDR we will just append 0xFF to the transmit payload data until
623b4cb930eSChalapathi V * the payload is N1 + N2 bytes long.
624b4cb930eSChalapathi V */
625b4cb930eSChalapathi V n2_count = 0;
626b4cb930eSChalapathi V while (n2_count < s->N2_bytes) {
627b4cb930eSChalapathi V /*
628b4cb930eSChalapathi V * If the RDR is full and we need to RX just bail out, letting the
629b4cb930eSChalapathi V * code continue will end up building the payload twice in the same
630b4cb930eSChalapathi V * buffer since RDR full causes a sequence stop and restart.
631b4cb930eSChalapathi V */
632b4cb930eSChalapathi V if ((s->N2_rx != 0) &&
633b4cb930eSChalapathi V (GETFIELD(SPI_STS_RDR_FULL, s->status) == 1)) {
634b4cb930eSChalapathi V trace_pnv_spi_sequencer_stop_requested("shift N2 set"
635b4cb930eSChalapathi V "for receive but RDR is full");
636b4cb930eSChalapathi V stop = true;
637b4cb930eSChalapathi V break;
638b4cb930eSChalapathi V }
639b4cb930eSChalapathi V if ((s->N2_tx != 0) && ((s->N1_tx + n2_count) <
640b4cb930eSChalapathi V PNV_SPI_REG_SIZE)) {
641b4cb930eSChalapathi V /* Always append data for the N2 segment if it is set for TX */
642b4cb930eSChalapathi V uint8_t n2_byte = 0x00;
643b4cb930eSChalapathi V n2_byte = get_from_offset(s, (s->N1_tx + n2_count));
644b4cb930eSChalapathi V trace_pnv_spi_tx_append("n2_byte", n2_byte, (s->N1_tx + n2_count));
645b4cb930eSChalapathi V *(pnv_spi_xfer_buffer_write_ptr(*payload, (*payload)->len, 1))
646b4cb930eSChalapathi V = n2_byte;
647b4cb930eSChalapathi V } else {
648b4cb930eSChalapathi V /*
649b4cb930eSChalapathi V * Regardless of whether or not N2 is set for TX or RX, we need
650b4cb930eSChalapathi V * the number of bytes in the payload to match the overall length
651b4cb930eSChalapathi V * of the operation.
652b4cb930eSChalapathi V */
653b4cb930eSChalapathi V trace_pnv_spi_tx_append_FF("n2_byte");
654b4cb930eSChalapathi V *(pnv_spi_xfer_buffer_write_ptr(*payload, (*payload)->len, 1))
655b4cb930eSChalapathi V = 0xff;
656b4cb930eSChalapathi V }
657b4cb930eSChalapathi V n2_count++;
658b4cb930eSChalapathi V } /* end of while */
659b4cb930eSChalapathi V if (!stop) {
660b4cb930eSChalapathi V /* We have a TX and a full TDR or an RX and an empty RDR */
661b4cb930eSChalapathi V trace_pnv_spi_tx_request("Shifting N2 frame", (*payload)->len);
662b4cb930eSChalapathi V transfer(s, *payload);
663b4cb930eSChalapathi V /*
664b4cb930eSChalapathi V * If we are doing an N2 TX and the TDR is full we need to clear the
665b4cb930eSChalapathi V * TDR_full status. Do this here instead of up in the loop above so we
666b4cb930eSChalapathi V * don't log the message in every loop iteration.
667b4cb930eSChalapathi V */
668b4cb930eSChalapathi V if ((s->N2_tx != 0) &&
669b4cb930eSChalapathi V (GETFIELD(SPI_STS_TDR_FULL, s->status) == 1)) {
670b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_TDR_FULL, s->status, 0);
671b4cb930eSChalapathi V }
672b4cb930eSChalapathi V /*
673b4cb930eSChalapathi V * The N2 frame shift is complete so reset the N2 counters.
674b4cb930eSChalapathi V * Reset the N1 counters also in case the frame was a combination of
675b4cb930eSChalapathi V * N1 and N2 segments.
676b4cb930eSChalapathi V */
677b4cb930eSChalapathi V s->N2_bits = 0;
678b4cb930eSChalapathi V s->N2_bytes = 0;
679b4cb930eSChalapathi V s->N2_tx = 0;
680b4cb930eSChalapathi V s->N2_rx = 0;
681b4cb930eSChalapathi V s->N1_bits = 0;
682b4cb930eSChalapathi V s->N1_bytes = 0;
683b4cb930eSChalapathi V s->N1_tx = 0;
684b4cb930eSChalapathi V s->N1_rx = 0;
685b4cb930eSChalapathi V pnv_spi_xfer_buffer_free(*payload);
686b4cb930eSChalapathi V *payload = NULL;
687b4cb930eSChalapathi V }
688b4cb930eSChalapathi V return stop;
689b4cb930eSChalapathi V } /* end of operation_shiftn2()*/
690b4cb930eSChalapathi V
operation_sequencer(PnvSpi * s)691b4cb930eSChalapathi V static void operation_sequencer(PnvSpi *s)
692b4cb930eSChalapathi V {
693b4cb930eSChalapathi V /*
694b4cb930eSChalapathi V * Loop through each sequencer operation ID and perform the requested
695b4cb930eSChalapathi V * operations.
696b4cb930eSChalapathi V * Flag for indicating if we should send the N1 frame or wait to combine
697b4cb930eSChalapathi V * it with a preceding N2 frame.
698b4cb930eSChalapathi V */
699b4cb930eSChalapathi V bool send_n1_alone = true;
700b4cb930eSChalapathi V bool stop = false; /* Flag to stop the sequencer */
701b4cb930eSChalapathi V uint8_t opcode = 0;
702b4cb930eSChalapathi V uint8_t masked_opcode = 0;
703b4cb930eSChalapathi V
704b4cb930eSChalapathi V /*
705b4cb930eSChalapathi V * PnvXferBuffer for containing the payload of the SPI frame.
706b4cb930eSChalapathi V * This is a static because there are cases where a sequence has to stop
707b4cb930eSChalapathi V * and wait for the target application to unload the RDR. If this occurs
708b4cb930eSChalapathi V * during a sequence where N1 is not sent alone and instead combined with
709b4cb930eSChalapathi V * N2 since the N1 tx length + the N2 tx length is less than the size of
710b4cb930eSChalapathi V * the TDR.
711b4cb930eSChalapathi V */
712b4cb930eSChalapathi V static PnvXferBuffer *payload;
713b4cb930eSChalapathi V
714b4cb930eSChalapathi V if (payload == NULL) {
715b4cb930eSChalapathi V payload = pnv_spi_xfer_buffer_new();
716b4cb930eSChalapathi V }
717b4cb930eSChalapathi V /*
718b4cb930eSChalapathi V * Clear the sequencer FSM error bit - general_SPI_status[3]
719b4cb930eSChalapathi V * before starting a sequence.
720b4cb930eSChalapathi V */
721b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_GEN_STATUS_B3, s->status, 0);
722b4cb930eSChalapathi V /*
723b4cb930eSChalapathi V * If the FSM is idle set the sequencer index to 0
724b4cb930eSChalapathi V * (new/restarted sequence)
725b4cb930eSChalapathi V */
726b4cb930eSChalapathi V if (GETFIELD(SPI_STS_SEQ_FSM, s->status) == SEQ_STATE_IDLE) {
727b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_INDEX, s->status, 0);
728b4cb930eSChalapathi V }
729b4cb930eSChalapathi V /*
730b4cb930eSChalapathi V * There are only 8 possible operation IDs to iterate through though
731b4cb930eSChalapathi V * some operations may cause more than one frame to be sequenced.
732b4cb930eSChalapathi V */
733b4cb930eSChalapathi V while (get_seq_index(s) < NUM_SEQ_OPS) {
734b4cb930eSChalapathi V opcode = s->seq_op[get_seq_index(s)];
735b4cb930eSChalapathi V /* Set sequencer state to decode */
736b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_DECODE);
737b4cb930eSChalapathi V /*
738b4cb930eSChalapathi V * Only the upper nibble of the operation ID is needed to know what
739b4cb930eSChalapathi V * kind of operation is requested.
740b4cb930eSChalapathi V */
741b4cb930eSChalapathi V masked_opcode = PNV_SPI_MASKED_OPCODE(opcode);
742b4cb930eSChalapathi V switch (masked_opcode) {
743b4cb930eSChalapathi V /*
744b4cb930eSChalapathi V * Increment the operation index in each case instead of just
745b4cb930eSChalapathi V * once at the end in case an operation like the branch
746b4cb930eSChalapathi V * operation needs to change the index.
747b4cb930eSChalapathi V */
748b4cb930eSChalapathi V case SEQ_OP_STOP:
749b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
750b4cb930eSChalapathi V /* A stop operation in any position stops the sequencer */
751b4cb930eSChalapathi V trace_pnv_spi_sequencer_op("STOP", get_seq_index(s));
752b4cb930eSChalapathi V
753b4cb930eSChalapathi V stop = true;
754b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status, FSM_IDLE);
755b4cb930eSChalapathi V s->loop_counter_1 = 0;
756b4cb930eSChalapathi V s->loop_counter_2 = 0;
757b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_IDLE);
758b4cb930eSChalapathi V break;
759b4cb930eSChalapathi V
760b4cb930eSChalapathi V case SEQ_OP_SELECT_SLAVE:
761b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
762b4cb930eSChalapathi V trace_pnv_spi_sequencer_op("SELECT_SLAVE", get_seq_index(s));
763b4cb930eSChalapathi V /*
764b4cb930eSChalapathi V * This device currently only supports a single responder
765b4cb930eSChalapathi V * connection at position 0. De-selecting a responder is fine
766b4cb930eSChalapathi V * and expected at the end of a sequence but selecting any
767b4cb930eSChalapathi V * responder other than 0 should cause an error.
768b4cb930eSChalapathi V */
769b4cb930eSChalapathi V s->responder_select = PNV_SPI_OPCODE_LO_NIBBLE(opcode);
770b4cb930eSChalapathi V if (s->responder_select == 0) {
771b4cb930eSChalapathi V trace_pnv_spi_shifter_done();
772b4cb930eSChalapathi V qemu_set_irq(s->cs_line[0], 1);
773b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_INDEX, s->status,
774b4cb930eSChalapathi V (get_seq_index(s) + 1));
775b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status, FSM_DONE);
776b4cb930eSChalapathi V } else if (s->responder_select != 1) {
777b4cb930eSChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "Slave selection other than 1 "
778b4cb930eSChalapathi V "not supported, select = 0x%x\n",
779b4cb930eSChalapathi V s->responder_select);
780b4cb930eSChalapathi V trace_pnv_spi_sequencer_stop_requested("invalid "
781b4cb930eSChalapathi V "responder select");
782b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status, FSM_IDLE);
783b4cb930eSChalapathi V stop = true;
784b4cb930eSChalapathi V } else {
785b4cb930eSChalapathi V /*
786b4cb930eSChalapathi V * Only allow an FSM_START state when a responder is
787b4cb930eSChalapathi V * selected
788b4cb930eSChalapathi V */
789b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status, FSM_START);
790b4cb930eSChalapathi V trace_pnv_spi_shifter_stating();
791b4cb930eSChalapathi V qemu_set_irq(s->cs_line[0], 0);
792b4cb930eSChalapathi V /*
793b4cb930eSChalapathi V * A Shift_N2 operation is only valid after a Shift_N1
794b4cb930eSChalapathi V * according to the spec. The spec doesn't say if that means
795b4cb930eSChalapathi V * immediately after or just after at any point. We will track
796b4cb930eSChalapathi V * the occurrence of a Shift_N1 to enforce this requirement in
797b4cb930eSChalapathi V * the most generic way possible by assuming that the rule
798b4cb930eSChalapathi V * applies once a valid responder select has occurred.
799b4cb930eSChalapathi V */
800b4cb930eSChalapathi V s->shift_n1_done = false;
801b4cb930eSChalapathi V next_sequencer_fsm(s);
802b4cb930eSChalapathi V }
803b4cb930eSChalapathi V break;
804b4cb930eSChalapathi V
805b4cb930eSChalapathi V case SEQ_OP_SHIFT_N1:
806b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
807b4cb930eSChalapathi V trace_pnv_spi_sequencer_op("SHIFT_N1", get_seq_index(s));
808b4cb930eSChalapathi V /*
809b4cb930eSChalapathi V * Only allow a shift_n1 when the state is not IDLE or DONE.
810b4cb930eSChalapathi V * In either of those two cases the sequencer is not in a proper
811b4cb930eSChalapathi V * state to perform shift operations because the sequencer has:
812b4cb930eSChalapathi V * - processed a responder deselect (DONE)
813b4cb930eSChalapathi V * - processed a stop opcode (IDLE)
814b4cb930eSChalapathi V * - encountered an error (IDLE)
815b4cb930eSChalapathi V */
816b4cb930eSChalapathi V if ((GETFIELD(SPI_STS_SHIFTER_FSM, s->status) == FSM_IDLE) ||
817b4cb930eSChalapathi V (GETFIELD(SPI_STS_SHIFTER_FSM, s->status) == FSM_DONE)) {
818b4cb930eSChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "Shift_N1 not allowed in "
819b4cb930eSChalapathi V "shifter state = 0x%llx", GETFIELD(
820b4cb930eSChalapathi V SPI_STS_SHIFTER_FSM, s->status));
821b4cb930eSChalapathi V /*
822b4cb930eSChalapathi V * Set sequencer FSM error bit 3 (general_SPI_status[3])
823b4cb930eSChalapathi V * in status reg.
824b4cb930eSChalapathi V */
825b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_GEN_STATUS_B3, s->status, 1);
826b4cb930eSChalapathi V trace_pnv_spi_sequencer_stop_requested("invalid shifter state");
827b4cb930eSChalapathi V stop = true;
828b4cb930eSChalapathi V } else {
829b4cb930eSChalapathi V /*
830b4cb930eSChalapathi V * Look for the special case where there is a shift_n1 set for
831b4cb930eSChalapathi V * transmit and it is followed by a shift_n2 set for transmit
832b4cb930eSChalapathi V * AND the combined transmit length of the two operations is
833b4cb930eSChalapathi V * less than or equal to the size of the TDR register. In this
834b4cb930eSChalapathi V * case we want to use both this current shift_n1 opcode and the
835b4cb930eSChalapathi V * following shift_n2 opcode to assemble the frame for
836b4cb930eSChalapathi V * transmission to the responder without requiring a refill of
837b4cb930eSChalapathi V * the TDR between the two operations.
838b4cb930eSChalapathi V */
839b4cb930eSChalapathi V if (PNV_SPI_MASKED_OPCODE(s->seq_op[get_seq_index(s) + 1])
840b4cb930eSChalapathi V == SEQ_OP_SHIFT_N2) {
841b4cb930eSChalapathi V send_n1_alone = false;
842b4cb930eSChalapathi V }
843b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status,
844b4cb930eSChalapathi V FSM_SHIFT_N1);
845b4cb930eSChalapathi V stop = operation_shiftn1(s, opcode, &payload, send_n1_alone);
846b4cb930eSChalapathi V if (stop) {
847b4cb930eSChalapathi V /*
848b4cb930eSChalapathi V * The operation code says to stop, this can occur if:
849b4cb930eSChalapathi V * (1) RDR is full and the N1 shift is set for receive
850b4cb930eSChalapathi V * (2) TDR was empty at the time of the N1 shift so we need
851b4cb930eSChalapathi V * to wait for data.
852b4cb930eSChalapathi V * (3) Neither 1 nor 2 are occurring and we aren't sending
853b4cb930eSChalapathi V * N1 alone and N2 counter reload is set (bit 0 of the N2
854b4cb930eSChalapathi V * counter reload field). In this case TDR_underrun will
855b4cb930eSChalapathi V * will be set and the Payload has been loaded so it is
856b4cb930eSChalapathi V * ok to advance the sequencer.
857b4cb930eSChalapathi V */
858b4cb930eSChalapathi V if (GETFIELD(SPI_STS_TDR_UNDERRUN, s->status)) {
859b4cb930eSChalapathi V s->shift_n1_done = true;
860b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status,
861b4cb930eSChalapathi V FSM_SHIFT_N2);
862b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_INDEX, s->status,
863b4cb930eSChalapathi V (get_seq_index(s) + 1));
864b4cb930eSChalapathi V } else {
865b4cb930eSChalapathi V /*
866b4cb930eSChalapathi V * This is case (1) or (2) so the sequencer needs to
867b4cb930eSChalapathi V * wait and NOT go to the next sequence yet.
868b4cb930eSChalapathi V */
869b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status,
870b4cb930eSChalapathi V FSM_WAIT);
871b4cb930eSChalapathi V }
872b4cb930eSChalapathi V } else {
873b4cb930eSChalapathi V /* Ok to move on to the next index */
874b4cb930eSChalapathi V s->shift_n1_done = true;
875b4cb930eSChalapathi V next_sequencer_fsm(s);
876b4cb930eSChalapathi V }
877b4cb930eSChalapathi V }
878b4cb930eSChalapathi V break;
879b4cb930eSChalapathi V
880b4cb930eSChalapathi V case SEQ_OP_SHIFT_N2:
881b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
882b4cb930eSChalapathi V trace_pnv_spi_sequencer_op("SHIFT_N2", get_seq_index(s));
883b4cb930eSChalapathi V if (!s->shift_n1_done) {
884b4cb930eSChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "Shift_N2 is not allowed if a "
885b4cb930eSChalapathi V "Shift_N1 is not done, shifter state = 0x%llx",
886b4cb930eSChalapathi V GETFIELD(SPI_STS_SHIFTER_FSM, s->status));
887b4cb930eSChalapathi V /*
888b4cb930eSChalapathi V * In case the sequencer actually stops if an N2 shift is
889b4cb930eSChalapathi V * requested before any N1 shift is done. Set sequencer FSM
890b4cb930eSChalapathi V * error bit 3 (general_SPI_status[3]) in status reg.
891b4cb930eSChalapathi V */
892b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_GEN_STATUS_B3, s->status, 1);
893b4cb930eSChalapathi V trace_pnv_spi_sequencer_stop_requested("shift_n2 "
894b4cb930eSChalapathi V "w/no shift_n1 done");
895b4cb930eSChalapathi V stop = true;
896b4cb930eSChalapathi V } else {
897b4cb930eSChalapathi V /* Ok to do a Shift_N2 */
898b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status,
899b4cb930eSChalapathi V FSM_SHIFT_N2);
900b4cb930eSChalapathi V stop = operation_shiftn2(s, opcode, &payload);
901b4cb930eSChalapathi V /*
902b4cb930eSChalapathi V * If the operation code says to stop set the shifter state to
903b4cb930eSChalapathi V * wait and stop
904b4cb930eSChalapathi V */
905b4cb930eSChalapathi V if (stop) {
906b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status,
907b4cb930eSChalapathi V FSM_WAIT);
908b4cb930eSChalapathi V } else {
909b4cb930eSChalapathi V /* Ok to move on to the next index */
910b4cb930eSChalapathi V next_sequencer_fsm(s);
911b4cb930eSChalapathi V }
912b4cb930eSChalapathi V }
913b4cb930eSChalapathi V break;
914b4cb930eSChalapathi V
915b4cb930eSChalapathi V case SEQ_OP_BRANCH_IFNEQ_RDR:
916b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
917b4cb930eSChalapathi V trace_pnv_spi_sequencer_op("BRANCH_IFNEQ_RDR", get_seq_index(s));
918b4cb930eSChalapathi V /*
919b4cb930eSChalapathi V * The memory mapping register RDR match value is compared against
920b4cb930eSChalapathi V * the 16 rightmost bytes of the RDR (potentially with masking).
921b4cb930eSChalapathi V * Since this comparison is performed against the contents of the
922b4cb930eSChalapathi V * RDR then a receive must have previously occurred otherwise
923b4cb930eSChalapathi V * there is no data to compare and the operation cannot be
924b4cb930eSChalapathi V * completed and will stop the sequencer until RDR full is set to
925b4cb930eSChalapathi V * 1.
926b4cb930eSChalapathi V */
927b4cb930eSChalapathi V if (GETFIELD(SPI_STS_RDR_FULL, s->status) == 1) {
928b4cb930eSChalapathi V bool rdr_matched = false;
929b4cb930eSChalapathi V rdr_matched = does_rdr_match(s);
930b4cb930eSChalapathi V if (rdr_matched) {
931b4cb930eSChalapathi V trace_pnv_spi_RDR_match("success");
932b4cb930eSChalapathi V /* A match occurred, increment the sequencer index. */
933b4cb930eSChalapathi V next_sequencer_fsm(s);
934b4cb930eSChalapathi V } else {
935b4cb930eSChalapathi V trace_pnv_spi_RDR_match("failed");
936b4cb930eSChalapathi V /*
937b4cb930eSChalapathi V * Branch the sequencer to the index coded into the op
938b4cb930eSChalapathi V * code.
939b4cb930eSChalapathi V */
940b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_INDEX, s->status,
941b4cb930eSChalapathi V PNV_SPI_OPCODE_LO_NIBBLE(opcode));
942b4cb930eSChalapathi V }
943b4cb930eSChalapathi V /*
944b4cb930eSChalapathi V * Regardless of where the branch ended up we want the
945b4cb930eSChalapathi V * sequencer to continue shifting so we have to clear
946b4cb930eSChalapathi V * RDR_full.
947b4cb930eSChalapathi V */
948b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_RDR_FULL, s->status, 0);
949b4cb930eSChalapathi V } else {
950b4cb930eSChalapathi V trace_pnv_spi_sequencer_stop_requested("RDR not"
951b4cb930eSChalapathi V "full for 0x6x opcode");
952b4cb930eSChalapathi V stop = true;
953b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status, FSM_WAIT);
954b4cb930eSChalapathi V }
955b4cb930eSChalapathi V break;
956b4cb930eSChalapathi V
957b4cb930eSChalapathi V case SEQ_OP_TRANSFER_TDR:
958b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
959b4cb930eSChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "Transfer TDR is not supported\n");
960b4cb930eSChalapathi V next_sequencer_fsm(s);
961b4cb930eSChalapathi V break;
962b4cb930eSChalapathi V
963b4cb930eSChalapathi V case SEQ_OP_BRANCH_IFNEQ_INC_1:
964b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
965b4cb930eSChalapathi V trace_pnv_spi_sequencer_op("BRANCH_IFNEQ_INC_1", get_seq_index(s));
966b4cb930eSChalapathi V /*
967b4cb930eSChalapathi V * The spec says the loop should execute count compare + 1 times.
968b4cb930eSChalapathi V * However we learned from engineering that we really only loop
969b4cb930eSChalapathi V * count_compare times, count compare = 0 makes this op code a
970b4cb930eSChalapathi V * no-op
971b4cb930eSChalapathi V */
972b4cb930eSChalapathi V if (s->loop_counter_1 !=
973b4cb930eSChalapathi V GETFIELD(SPI_CTR_CFG_CMP1, s->regs[SPI_CTR_CFG_REG])) {
974b4cb930eSChalapathi V /*
975b4cb930eSChalapathi V * Next index is the lower nibble of the branch operation ID,
976b4cb930eSChalapathi V * mask off all but the first three bits so we don't try to
977b4cb930eSChalapathi V * access beyond the sequencer_operation_reg boundary.
978b4cb930eSChalapathi V */
979b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_INDEX, s->status,
980b4cb930eSChalapathi V PNV_SPI_OPCODE_LO_NIBBLE(opcode));
981b4cb930eSChalapathi V s->loop_counter_1++;
982b4cb930eSChalapathi V } else {
983b4cb930eSChalapathi V /* Continue to next index if loop counter is reached */
984b4cb930eSChalapathi V next_sequencer_fsm(s);
985b4cb930eSChalapathi V }
986b4cb930eSChalapathi V break;
987b4cb930eSChalapathi V
988b4cb930eSChalapathi V case SEQ_OP_BRANCH_IFNEQ_INC_2:
989b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
990b4cb930eSChalapathi V trace_pnv_spi_sequencer_op("BRANCH_IFNEQ_INC_2", get_seq_index(s));
991b4cb930eSChalapathi V uint8_t condition2 = GETFIELD(SPI_CTR_CFG_CMP2,
992b4cb930eSChalapathi V s->regs[SPI_CTR_CFG_REG]);
993b4cb930eSChalapathi V /*
994b4cb930eSChalapathi V * The spec says the loop should execute count compare + 1 times.
995b4cb930eSChalapathi V * However we learned from engineering that we really only loop
996b4cb930eSChalapathi V * count_compare times, count compare = 0 makes this op code a
997b4cb930eSChalapathi V * no-op
998b4cb930eSChalapathi V */
999b4cb930eSChalapathi V if (s->loop_counter_2 != condition2) {
1000b4cb930eSChalapathi V /*
1001b4cb930eSChalapathi V * Next index is the lower nibble of the branch operation ID,
1002b4cb930eSChalapathi V * mask off all but the first three bits so we don't try to
1003b4cb930eSChalapathi V * access beyond the sequencer_operation_reg boundary.
1004b4cb930eSChalapathi V */
1005b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_INDEX,
1006b4cb930eSChalapathi V s->status, PNV_SPI_OPCODE_LO_NIBBLE(opcode));
1007b4cb930eSChalapathi V s->loop_counter_2++;
1008b4cb930eSChalapathi V } else {
1009b4cb930eSChalapathi V /* Continue to next index if loop counter is reached */
1010b4cb930eSChalapathi V next_sequencer_fsm(s);
1011b4cb930eSChalapathi V }
1012b4cb930eSChalapathi V break;
1013b4cb930eSChalapathi V
1014b4cb930eSChalapathi V default:
1015b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_EXECUTE);
1016b4cb930eSChalapathi V /* Ignore unsupported operations. */
1017b4cb930eSChalapathi V next_sequencer_fsm(s);
1018b4cb930eSChalapathi V break;
1019b4cb930eSChalapathi V } /* end of switch */
1020b4cb930eSChalapathi V /*
1021b4cb930eSChalapathi V * If we used all 8 opcodes without seeing a 00 - STOP in the sequence
1022b4cb930eSChalapathi V * we need to go ahead and end things as if there was a STOP at the
1023b4cb930eSChalapathi V * end.
1024b4cb930eSChalapathi V */
1025b4cb930eSChalapathi V if (get_seq_index(s) == NUM_SEQ_OPS) {
1026b4cb930eSChalapathi V /* All 8 opcodes completed, sequencer idling */
1027b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status, FSM_IDLE);
1028b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_INDEX, s->status, 0);
1029b4cb930eSChalapathi V s->loop_counter_1 = 0;
1030b4cb930eSChalapathi V s->loop_counter_2 = 0;
1031b4cb930eSChalapathi V s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_IDLE);
1032b4cb930eSChalapathi V break;
1033b4cb930eSChalapathi V }
1034b4cb930eSChalapathi V /* Break the loop if a stop was requested */
1035b4cb930eSChalapathi V if (stop) {
1036b4cb930eSChalapathi V break;
1037b4cb930eSChalapathi V }
1038b4cb930eSChalapathi V } /* end of while */
1039b4cb930eSChalapathi V return;
1040b4cb930eSChalapathi V } /* end of operation_sequencer() */
1041b4cb930eSChalapathi V
1042b4cb930eSChalapathi V /*
1043b4cb930eSChalapathi V * The SPIC engine and its internal sequencer can be interrupted and reset by
1044b4cb930eSChalapathi V * a hardware signal, the sbe_spicst_hard_reset bits from Pervasive
1045b4cb930eSChalapathi V * Miscellaneous Register of sbe_register_bo device.
1046b4cb930eSChalapathi V * Reset immediately aborts any SPI transaction in progress and returns the
1047b4cb930eSChalapathi V * sequencer and state machines to idle state.
1048b4cb930eSChalapathi V * The configuration register values are not changed. The status register is
1049b4cb930eSChalapathi V * not reset. The engine registers are not reset.
1050b4cb930eSChalapathi V * The SPIC engine reset does not have any affect on the attached devices.
1051b4cb930eSChalapathi V * Reset handling of any attached devices is beyond the scope of the engine.
1052b4cb930eSChalapathi V */
do_reset(DeviceState * dev)1053b4cb930eSChalapathi V static void do_reset(DeviceState *dev)
1054b4cb930eSChalapathi V {
1055b4cb930eSChalapathi V PnvSpi *s = PNV_SPI(dev);
1056bb44dc48SChalapathi V DeviceState *ssi_dev;
1057b4cb930eSChalapathi V
1058b4cb930eSChalapathi V trace_pnv_spi_reset();
1059b4cb930eSChalapathi V
1060bb44dc48SChalapathi V /* Connect cs irq */
1061bb44dc48SChalapathi V ssi_dev = ssi_get_cs(s->ssi_bus, 0);
1062bb44dc48SChalapathi V if (ssi_dev) {
1063bb44dc48SChalapathi V qemu_irq cs_line = qdev_get_gpio_in_named(ssi_dev, SSI_GPIO_CS, 0);
1064bb44dc48SChalapathi V qdev_connect_gpio_out_named(DEVICE(s), "cs", 0, cs_line);
1065bb44dc48SChalapathi V }
1066bb44dc48SChalapathi V
1067b4cb930eSChalapathi V /* Reset all N1 and N2 counters, and other constants */
1068b4cb930eSChalapathi V s->N2_bits = 0;
1069b4cb930eSChalapathi V s->N2_bytes = 0;
1070b4cb930eSChalapathi V s->N2_tx = 0;
1071b4cb930eSChalapathi V s->N2_rx = 0;
1072b4cb930eSChalapathi V s->N1_bits = 0;
1073b4cb930eSChalapathi V s->N1_bytes = 0;
1074b4cb930eSChalapathi V s->N1_tx = 0;
1075b4cb930eSChalapathi V s->N1_rx = 0;
1076b4cb930eSChalapathi V s->loop_counter_1 = 0;
1077b4cb930eSChalapathi V s->loop_counter_2 = 0;
1078b4cb930eSChalapathi V /* Disconnected from responder */
1079b4cb930eSChalapathi V qemu_set_irq(s->cs_line[0], 1);
1080b4cb930eSChalapathi V }
1081b4cb930eSChalapathi V
pnv_spi_xscom_read(void * opaque,hwaddr addr,unsigned size)108229318db1SChalapathi V static uint64_t pnv_spi_xscom_read(void *opaque, hwaddr addr, unsigned size)
108329318db1SChalapathi V {
108429318db1SChalapathi V PnvSpi *s = PNV_SPI(opaque);
108529318db1SChalapathi V uint32_t reg = addr >> 3;
108629318db1SChalapathi V uint64_t val = ~0ull;
108729318db1SChalapathi V
108829318db1SChalapathi V switch (reg) {
108929318db1SChalapathi V case ERROR_REG:
109029318db1SChalapathi V case SPI_CTR_CFG_REG:
109129318db1SChalapathi V case CONFIG_REG1:
109229318db1SChalapathi V case SPI_CLK_CFG_REG:
109329318db1SChalapathi V case SPI_MM_REG:
109429318db1SChalapathi V case SPI_XMIT_DATA_REG:
109529318db1SChalapathi V val = s->regs[reg];
109629318db1SChalapathi V break;
109729318db1SChalapathi V case SPI_RCV_DATA_REG:
109829318db1SChalapathi V val = s->regs[reg];
109929318db1SChalapathi V trace_pnv_spi_read_RDR(val);
110029318db1SChalapathi V s->status = SETFIELD(SPI_STS_RDR_FULL, s->status, 0);
1101b4cb930eSChalapathi V if (GETFIELD(SPI_STS_SHIFTER_FSM, s->status) == FSM_WAIT) {
1102b4cb930eSChalapathi V trace_pnv_spi_start_sequencer();
1103b4cb930eSChalapathi V operation_sequencer(s);
1104b4cb930eSChalapathi V }
110529318db1SChalapathi V break;
110629318db1SChalapathi V case SPI_SEQ_OP_REG:
110729318db1SChalapathi V val = 0;
110829318db1SChalapathi V for (int i = 0; i < PNV_SPI_REG_SIZE; i++) {
110929318db1SChalapathi V val = (val << 8) | s->seq_op[i];
111029318db1SChalapathi V }
111129318db1SChalapathi V break;
111229318db1SChalapathi V case SPI_STS_REG:
111329318db1SChalapathi V val = s->status;
111429318db1SChalapathi V break;
111529318db1SChalapathi V default:
111629318db1SChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "pnv_spi_regs: Invalid xscom "
111729318db1SChalapathi V "read at 0x%" PRIx32 "\n", reg);
111829318db1SChalapathi V }
111929318db1SChalapathi V
112029318db1SChalapathi V trace_pnv_spi_read(addr, val);
112129318db1SChalapathi V return val;
112229318db1SChalapathi V }
112329318db1SChalapathi V
pnv_spi_xscom_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)112429318db1SChalapathi V static void pnv_spi_xscom_write(void *opaque, hwaddr addr,
112529318db1SChalapathi V uint64_t val, unsigned size)
112629318db1SChalapathi V {
112729318db1SChalapathi V PnvSpi *s = PNV_SPI(opaque);
112829318db1SChalapathi V uint32_t reg = addr >> 3;
112929318db1SChalapathi V
113029318db1SChalapathi V trace_pnv_spi_write(addr, val);
113129318db1SChalapathi V
113229318db1SChalapathi V switch (reg) {
113329318db1SChalapathi V case ERROR_REG:
113429318db1SChalapathi V case SPI_CTR_CFG_REG:
113529318db1SChalapathi V case CONFIG_REG1:
113629318db1SChalapathi V case SPI_MM_REG:
113729318db1SChalapathi V case SPI_RCV_DATA_REG:
113829318db1SChalapathi V s->regs[reg] = val;
113929318db1SChalapathi V break;
114029318db1SChalapathi V case SPI_CLK_CFG_REG:
114129318db1SChalapathi V /*
114229318db1SChalapathi V * To reset the SPI controller write the sequence 0x5 0xA to
114329318db1SChalapathi V * reset_control field
114429318db1SChalapathi V */
114529318db1SChalapathi V if ((GETFIELD(SPI_CLK_CFG_RST_CTRL, s->regs[SPI_CLK_CFG_REG]) == 0x5)
114629318db1SChalapathi V && (GETFIELD(SPI_CLK_CFG_RST_CTRL, val) == 0xA)) {
114729318db1SChalapathi V /* SPI controller reset sequence completed, resetting */
114829318db1SChalapathi V s->regs[reg] = SPI_CLK_CFG_HARD_RST;
114929318db1SChalapathi V } else {
115029318db1SChalapathi V s->regs[reg] = val;
115129318db1SChalapathi V }
115229318db1SChalapathi V break;
115329318db1SChalapathi V case SPI_XMIT_DATA_REG:
115429318db1SChalapathi V /*
115529318db1SChalapathi V * Writing to the transmit data register causes the transmit data
115629318db1SChalapathi V * register full status bit in the status register to be set. Writing
115729318db1SChalapathi V * when the transmit data register full status bit is already set
115829318db1SChalapathi V * causes a "Resource Not Available" condition. This is not possible
115929318db1SChalapathi V * in the model since writes to this register are not asynchronous to
116029318db1SChalapathi V * the operation sequence like it would be in hardware.
116129318db1SChalapathi V */
116229318db1SChalapathi V s->regs[reg] = val;
116329318db1SChalapathi V trace_pnv_spi_write_TDR(val);
116429318db1SChalapathi V s->status = SETFIELD(SPI_STS_TDR_FULL, s->status, 1);
116529318db1SChalapathi V s->status = SETFIELD(SPI_STS_TDR_UNDERRUN, s->status, 0);
1166b4cb930eSChalapathi V trace_pnv_spi_start_sequencer();
1167b4cb930eSChalapathi V operation_sequencer(s);
116829318db1SChalapathi V break;
116929318db1SChalapathi V case SPI_SEQ_OP_REG:
117029318db1SChalapathi V for (int i = 0; i < PNV_SPI_REG_SIZE; i++) {
117129318db1SChalapathi V s->seq_op[i] = (val >> (56 - i * 8)) & 0xFF;
117229318db1SChalapathi V }
117329318db1SChalapathi V break;
117429318db1SChalapathi V case SPI_STS_REG:
117529318db1SChalapathi V /* other fields are ignore_write */
117629318db1SChalapathi V s->status = SETFIELD(SPI_STS_RDR_OVERRUN, s->status,
117729318db1SChalapathi V GETFIELD(SPI_STS_RDR, val));
117829318db1SChalapathi V s->status = SETFIELD(SPI_STS_TDR_OVERRUN, s->status,
117929318db1SChalapathi V GETFIELD(SPI_STS_TDR, val));
118029318db1SChalapathi V break;
118129318db1SChalapathi V default:
118229318db1SChalapathi V qemu_log_mask(LOG_GUEST_ERROR, "pnv_spi_regs: Invalid xscom "
118329318db1SChalapathi V "write at 0x%" PRIx32 "\n", reg);
118429318db1SChalapathi V }
118529318db1SChalapathi V return;
118629318db1SChalapathi V }
118729318db1SChalapathi V
118829318db1SChalapathi V static const MemoryRegionOps pnv_spi_xscom_ops = {
118929318db1SChalapathi V .read = pnv_spi_xscom_read,
119029318db1SChalapathi V .write = pnv_spi_xscom_write,
119129318db1SChalapathi V .valid.min_access_size = 8,
119229318db1SChalapathi V .valid.max_access_size = 8,
119329318db1SChalapathi V .impl.min_access_size = 8,
119429318db1SChalapathi V .impl.max_access_size = 8,
119529318db1SChalapathi V .endianness = DEVICE_BIG_ENDIAN,
119629318db1SChalapathi V };
119729318db1SChalapathi V
119829318db1SChalapathi V static Property pnv_spi_properties[] = {
119929318db1SChalapathi V DEFINE_PROP_UINT32("spic_num", PnvSpi, spic_num, 0),
1200b4cb930eSChalapathi V DEFINE_PROP_UINT8("transfer_len", PnvSpi, transfer_len, 4),
120129318db1SChalapathi V DEFINE_PROP_END_OF_LIST(),
120229318db1SChalapathi V };
120329318db1SChalapathi V
pnv_spi_realize(DeviceState * dev,Error ** errp)120429318db1SChalapathi V static void pnv_spi_realize(DeviceState *dev, Error **errp)
120529318db1SChalapathi V {
120629318db1SChalapathi V PnvSpi *s = PNV_SPI(dev);
120729318db1SChalapathi V g_autofree char *name = g_strdup_printf(TYPE_PNV_SPI_BUS ".%d",
120829318db1SChalapathi V s->spic_num);
120929318db1SChalapathi V s->ssi_bus = ssi_create_bus(dev, name);
121029318db1SChalapathi V s->cs_line = g_new0(qemu_irq, 1);
121129318db1SChalapathi V qdev_init_gpio_out_named(DEVICE(s), s->cs_line, "cs", 1);
121229318db1SChalapathi V
121329318db1SChalapathi V /* spi scoms */
121429318db1SChalapathi V pnv_xscom_region_init(&s->xscom_spic_regs, OBJECT(s), &pnv_spi_xscom_ops,
121529318db1SChalapathi V s, "xscom-spi", PNV10_XSCOM_PIB_SPIC_SIZE);
121629318db1SChalapathi V }
121729318db1SChalapathi V
pnv_spi_dt_xscom(PnvXScomInterface * dev,void * fdt,int offset)121829318db1SChalapathi V static int pnv_spi_dt_xscom(PnvXScomInterface *dev, void *fdt,
121929318db1SChalapathi V int offset)
122029318db1SChalapathi V {
122129318db1SChalapathi V PnvSpi *s = PNV_SPI(dev);
122229318db1SChalapathi V g_autofree char *name;
122329318db1SChalapathi V int s_offset;
122429318db1SChalapathi V const char compat[] = "ibm,power10-spi";
122529318db1SChalapathi V uint32_t spic_pcba = PNV10_XSCOM_PIB_SPIC_BASE +
122629318db1SChalapathi V s->spic_num * PNV10_XSCOM_PIB_SPIC_SIZE;
122729318db1SChalapathi V uint32_t reg[] = {
122829318db1SChalapathi V cpu_to_be32(spic_pcba),
122929318db1SChalapathi V cpu_to_be32(PNV10_XSCOM_PIB_SPIC_SIZE)
123029318db1SChalapathi V };
123129318db1SChalapathi V name = g_strdup_printf("pnv_spi@%x", spic_pcba);
123229318db1SChalapathi V s_offset = fdt_add_subnode(fdt, offset, name);
123329318db1SChalapathi V _FDT(s_offset);
123429318db1SChalapathi V
123529318db1SChalapathi V _FDT(fdt_setprop(fdt, s_offset, "reg", reg, sizeof(reg)));
123629318db1SChalapathi V _FDT(fdt_setprop(fdt, s_offset, "compatible", compat, sizeof(compat)));
123729318db1SChalapathi V _FDT((fdt_setprop_cell(fdt, s_offset, "spic_num#", s->spic_num)));
123829318db1SChalapathi V return 0;
123929318db1SChalapathi V }
124029318db1SChalapathi V
pnv_spi_class_init(ObjectClass * klass,void * data)124129318db1SChalapathi V static void pnv_spi_class_init(ObjectClass *klass, void *data)
124229318db1SChalapathi V {
124329318db1SChalapathi V DeviceClass *dc = DEVICE_CLASS(klass);
124429318db1SChalapathi V PnvXScomInterfaceClass *xscomc = PNV_XSCOM_INTERFACE_CLASS(klass);
124529318db1SChalapathi V
124629318db1SChalapathi V xscomc->dt_xscom = pnv_spi_dt_xscom;
124729318db1SChalapathi V
124829318db1SChalapathi V dc->desc = "PowerNV SPI";
124929318db1SChalapathi V dc->realize = pnv_spi_realize;
1250b4cb930eSChalapathi V device_class_set_legacy_reset(dc, do_reset);
125129318db1SChalapathi V device_class_set_props(dc, pnv_spi_properties);
125229318db1SChalapathi V }
125329318db1SChalapathi V
125429318db1SChalapathi V static const TypeInfo pnv_spi_info = {
125529318db1SChalapathi V .name = TYPE_PNV_SPI,
125629318db1SChalapathi V .parent = TYPE_SYS_BUS_DEVICE,
125729318db1SChalapathi V .instance_size = sizeof(PnvSpi),
125829318db1SChalapathi V .class_init = pnv_spi_class_init,
125929318db1SChalapathi V .interfaces = (InterfaceInfo[]) {
126029318db1SChalapathi V { TYPE_PNV_XSCOM_INTERFACE },
126129318db1SChalapathi V { }
126229318db1SChalapathi V }
126329318db1SChalapathi V };
126429318db1SChalapathi V
pnv_spi_register_types(void)126529318db1SChalapathi V static void pnv_spi_register_types(void)
126629318db1SChalapathi V {
126729318db1SChalapathi V type_register_static(&pnv_spi_info);
126829318db1SChalapathi V }
126929318db1SChalapathi V
127029318db1SChalapathi V type_init(pnv_spi_register_types);
1271