]> Git Repo - qemu.git/blame - hw/ssi/xilinx_spips.c
xilinx_spips: Add support for RX discard and RX drain
[qemu.git] / hw / ssi / xilinx_spips.c
CommitLineData
94befa45
PC
1/*
2 * QEMU model of the Xilinx Zynq SPI controller
3 *
4 * Copyright (c) 2012 Peter A. G. Crosthwaite
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
8ef94f0b 25#include "qemu/osdep.h"
83c9f4ca 26#include "hw/sysbus.h"
9c17d615 27#include "sysemu/sysemu.h"
83c9f4ca 28#include "hw/ptimer.h"
1de7afc9 29#include "qemu/log.h"
1de7afc9 30#include "qemu/bitops.h"
6363235b 31#include "hw/ssi/xilinx_spips.h"
83c3a1f6 32#include "qapi/error.h"
ef06ca39 33#include "hw/register.h"
83c3a1f6 34#include "migration/blocker.h"
94befa45 35
4a5b6fa8
PC
36#ifndef XILINX_SPIPS_ERR_DEBUG
37#define XILINX_SPIPS_ERR_DEBUG 0
94befa45
PC
38#endif
39
4a5b6fa8
PC
40#define DB_PRINT_L(level, ...) do { \
41 if (XILINX_SPIPS_ERR_DEBUG > (level)) { \
42 fprintf(stderr, ": %s: ", __func__); \
43 fprintf(stderr, ## __VA_ARGS__); \
44 } \
45} while (0);
46
94befa45
PC
47/* config register */
48#define R_CONFIG (0x00 / 4)
c8f8f9fb 49#define IFMODE (1U << 31)
f1241144 50#define ENDIAN (1 << 26)
94befa45
PC
51#define MODEFAIL_GEN_EN (1 << 17)
52#define MAN_START_COM (1 << 16)
53#define MAN_START_EN (1 << 15)
54#define MANUAL_CS (1 << 14)
55#define CS (0xF << 10)
56#define CS_SHIFT (10)
57#define PERI_SEL (1 << 9)
58#define REF_CLK (1 << 8)
59#define FIFO_WIDTH (3 << 6)
60#define BAUD_RATE_DIV (7 << 3)
61#define CLK_PH (1 << 2)
62#define CLK_POL (1 << 1)
63#define MODE_SEL (1 << 0)
2133a5f6 64#define R_CONFIG_RSVD (0x7bf40000)
94befa45
PC
65
66/* interrupt mechanism */
67#define R_INTR_STATUS (0x04 / 4)
68#define R_INTR_EN (0x08 / 4)
69#define R_INTR_DIS (0x0C / 4)
70#define R_INTR_MASK (0x10 / 4)
71#define IXR_TX_FIFO_UNDERFLOW (1 << 6)
72#define IXR_RX_FIFO_FULL (1 << 5)
73#define IXR_RX_FIFO_NOT_EMPTY (1 << 4)
74#define IXR_TX_FIFO_FULL (1 << 3)
75#define IXR_TX_FIFO_NOT_FULL (1 << 2)
76#define IXR_TX_FIFO_MODE_FAIL (1 << 1)
77#define IXR_RX_FIFO_OVERFLOW (1 << 0)
78#define IXR_ALL ((IXR_TX_FIFO_UNDERFLOW<<1)-1)
79
80#define R_EN (0x14 / 4)
81#define R_DELAY (0x18 / 4)
82#define R_TX_DATA (0x1C / 4)
83#define R_RX_DATA (0x20 / 4)
84#define R_SLAVE_IDLE_COUNT (0x24 / 4)
85#define R_TX_THRES (0x28 / 4)
86#define R_RX_THRES (0x2C / 4)
f1241144
PC
87#define R_TXD1 (0x80 / 4)
88#define R_TXD2 (0x84 / 4)
89#define R_TXD3 (0x88 / 4)
90
91#define R_LQSPI_CFG (0xa0 / 4)
92#define R_LQSPI_CFG_RESET 0x03A002EB
c8f8f9fb 93#define LQSPI_CFG_LQ_MODE (1U << 31)
f1241144
PC
94#define LQSPI_CFG_TWO_MEM (1 << 30)
95#define LQSPI_CFG_SEP_BUS (1 << 30)
96#define LQSPI_CFG_U_PAGE (1 << 28)
97#define LQSPI_CFG_MODE_EN (1 << 25)
98#define LQSPI_CFG_MODE_WIDTH 8
99#define LQSPI_CFG_MODE_SHIFT 16
100#define LQSPI_CFG_DUMMY_WIDTH 3
101#define LQSPI_CFG_DUMMY_SHIFT 8
102#define LQSPI_CFG_INST_CODE 0xFF
103
ef06ca39
FI
104#define R_CMND (0xc0 / 4)
105 #define R_CMND_RXFIFO_DRAIN (1 << 19)
106 FIELD(CMND, PARTIAL_BYTE_LEN, 16, 3)
107#define R_CMND_EXT_ADD (1 << 15)
108 FIELD(CMND, RX_DISCARD, 8, 7)
109 FIELD(CMND, DUMMY_CYCLES, 2, 6)
110#define R_CMND_DMA_EN (1 << 1)
111#define R_CMND_PUSH_WAIT (1 << 0)
f1241144
PC
112#define R_LQSPI_STS (0xA4 / 4)
113#define LQSPI_STS_WR_RECVD (1 << 1)
114
94befa45
PC
115#define R_MOD_ID (0xFC / 4)
116
94befa45 117/* size of TXRX FIFOs */
94befa45
PC
118#define RXFF_A 32
119#define TXFF_A 32
120
10e60b35
PC
121#define RXFF_A_Q (64 * 4)
122#define TXFF_A_Q (64 * 4)
123
f1241144
PC
124/* 16MB per linear region */
125#define LQSPI_ADDRESS_BITS 24
f1241144
PC
126
127#define SNOOP_CHECKING 0xFF
ef06ca39
FI
128#define SNOOP_ADDR 0xF0
129#define SNOOP_NONE 0xEE
f1241144
PC
130#define SNOOP_STRIPING 0
131
f1241144
PC
132static inline int num_effective_busses(XilinxSPIPS *s)
133{
e0891bd8
NR
134 return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
135 s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1;
f1241144
PC
136}
137
c4f08ffe
PC
138static inline bool xilinx_spips_cs_is_set(XilinxSPIPS *s, int i, int field)
139{
140 return ~field & (1 << i) && (s->regs[R_CONFIG] & MANUAL_CS
141 || !fifo8_is_empty(&s->tx_fifo));
142}
143
94befa45
PC
144static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
145{
f1241144 146 int i, j;
94befa45
PC
147 bool found = false;
148 int field = s->regs[R_CONFIG] >> CS_SHIFT;
149
f1241144
PC
150 for (i = 0; i < s->num_cs; i++) {
151 for (j = 0; j < num_effective_busses(s); j++) {
152 int upage = !!(s->regs[R_LQSPI_STS] & LQSPI_CFG_U_PAGE);
153 int cs_to_set = (j * s->num_cs + i + upage) %
154 (s->num_cs * s->num_busses);
155
c4f08ffe 156 if (xilinx_spips_cs_is_set(s, i, field) && !found) {
4a5b6fa8 157 DB_PRINT_L(0, "selecting slave %d\n", i);
f1241144 158 qemu_set_irq(s->cs_lines[cs_to_set], 0);
ef06ca39
FI
159 if (s->cs_lines_state[cs_to_set]) {
160 s->cs_lines_state[cs_to_set] = false;
161 s->rx_discard = ARRAY_FIELD_EX32(s->regs, CMND, RX_DISCARD);
162 }
f1241144 163 } else {
4a5b6fa8 164 DB_PRINT_L(0, "deselecting slave %d\n", i);
f1241144 165 qemu_set_irq(s->cs_lines[cs_to_set], 1);
ef06ca39 166 s->cs_lines_state[cs_to_set] = true;
f1241144
PC
167 }
168 }
c4f08ffe 169 if (xilinx_spips_cs_is_set(s, i, field)) {
94befa45 170 found = true;
94befa45 171 }
f1241144
PC
172 }
173 if (!found) {
174 s->snoop_state = SNOOP_CHECKING;
ef06ca39
FI
175 s->cmd_dummies = 0;
176 s->link_state = 1;
177 s->link_state_next = 1;
178 s->link_state_next_when = 0;
4a5b6fa8 179 DB_PRINT_L(1, "moving to snoop check state\n");
f1241144 180 }
94befa45
PC
181}
182
183static void xilinx_spips_update_ixr(XilinxSPIPS *s)
184{
3ea728d0
PC
185 if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_LQ_MODE) {
186 return;
187 }
94befa45
PC
188 /* These are set/cleared as they occur */
189 s->regs[R_INTR_STATUS] &= (IXR_TX_FIFO_UNDERFLOW | IXR_RX_FIFO_OVERFLOW |
190 IXR_TX_FIFO_MODE_FAIL);
191 /* these are pure functions of fifo state, set them here */
192 s->regs[R_INTR_STATUS] |=
193 (fifo8_is_full(&s->rx_fifo) ? IXR_RX_FIFO_FULL : 0) |
194 (s->rx_fifo.num >= s->regs[R_RX_THRES] ? IXR_RX_FIFO_NOT_EMPTY : 0) |
195 (fifo8_is_full(&s->tx_fifo) ? IXR_TX_FIFO_FULL : 0) |
196 (s->tx_fifo.num < s->regs[R_TX_THRES] ? IXR_TX_FIFO_NOT_FULL : 0);
197 /* drive external interrupt pin */
198 int new_irqline = !!(s->regs[R_INTR_MASK] & s->regs[R_INTR_STATUS] &
199 IXR_ALL);
200 if (new_irqline != s->irqline) {
201 s->irqline = new_irqline;
202 qemu_set_irq(s->irq, s->irqline);
203 }
204}
205
206static void xilinx_spips_reset(DeviceState *d)
207{
f8b9fe24 208 XilinxSPIPS *s = XILINX_SPIPS(d);
94befa45
PC
209
210 int i;
6363235b 211 for (i = 0; i < XLNX_SPIPS_R_MAX; i++) {
94befa45
PC
212 s->regs[i] = 0;
213 }
214
215 fifo8_reset(&s->rx_fifo);
216 fifo8_reset(&s->rx_fifo);
217 /* non zero resets */
218 s->regs[R_CONFIG] |= MODEFAIL_GEN_EN;
219 s->regs[R_SLAVE_IDLE_COUNT] = 0xFF;
220 s->regs[R_TX_THRES] = 1;
221 s->regs[R_RX_THRES] = 1;
222 /* FIXME: move magic number definition somewhere sensible */
223 s->regs[R_MOD_ID] = 0x01090106;
f1241144 224 s->regs[R_LQSPI_CFG] = R_LQSPI_CFG_RESET;
ef06ca39
FI
225 s->link_state = 1;
226 s->link_state_next = 1;
227 s->link_state_next_when = 0;
f1241144 228 s->snoop_state = SNOOP_CHECKING;
ef06ca39 229 s->cmd_dummies = 0;
94befa45
PC
230 xilinx_spips_update_ixr(s);
231 xilinx_spips_update_cs_lines(s);
232}
233
c3725b85 234/* N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
9151da25
PC
235 * column wise (from element 0 to N-1). num is the length of x, and dir
236 * reverses the direction of the transform. Best illustrated by example:
237 * Each digit in the below array is a single bit (num == 3):
238 *
c3725b85
FI
239 * {{ 76543210, } ----- stripe (dir == false) -----> {{ 741gdaFC, }
240 * { hgfedcba, } { 630fcHEB, }
241 * { HGFEDCBA, }} <---- upstripe (dir == true) ----- { 52hebGDA, }}
9151da25
PC
242 */
243
244static inline void stripe8(uint8_t *x, int num, bool dir)
245{
246 uint8_t r[num];
247 memset(r, 0, sizeof(uint8_t) * num);
248 int idx[2] = {0, 0};
c3725b85 249 int bit[2] = {0, 7};
9151da25
PC
250 int d = dir;
251
252 for (idx[0] = 0; idx[0] < num; ++idx[0]) {
c3725b85
FI
253 for (bit[0] = 7; bit[0] >= 0; bit[0]--) {
254 r[idx[!d]] |= x[idx[d]] & 1 << bit[d] ? 1 << bit[!d] : 0;
9151da25
PC
255 idx[1] = (idx[1] + 1) % num;
256 if (!idx[1]) {
c3725b85 257 bit[1]--;
9151da25
PC
258 }
259 }
260 }
261 memcpy(x, r, sizeof(uint8_t) * num);
262}
263
ef06ca39
FI
264static int xilinx_spips_num_dummies(XilinxQSPIPS *qs, uint8_t command)
265{
266 if (!qs) {
267 /* The SPI device is not a QSPI device */
268 return -1;
269 }
270
271 switch (command) { /* check for dummies */
272 case READ: /* no dummy bytes/cycles */
273 case PP:
274 case DPP:
275 case QPP:
276 case READ_4:
277 case PP_4:
278 case QPP_4:
279 return 0;
280 case FAST_READ:
281 case DOR:
282 case QOR:
283 case DOR_4:
284 case QOR_4:
285 return 1;
286 case DIOR:
287 case FAST_READ_4:
288 case DIOR_4:
289 return 2;
290 case QIOR:
291 case QIOR_4:
292 return 5;
293 default:
294 return -1;
295 }
296}
297
298static inline uint8_t get_addr_length(XilinxSPIPS *s, uint8_t cmd)
299{
300 switch (cmd) {
301 case PP_4:
302 case QPP_4:
303 case READ_4:
304 case QIOR_4:
305 case FAST_READ_4:
306 case DOR_4:
307 case QOR_4:
308 case DIOR_4:
309 return 4;
310 default:
311 return (s->regs[R_CMND] & R_CMND_EXT_ADD) ? 4 : 3;
312 }
313}
314
94befa45
PC
315static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
316{
4a5b6fa8 317 int debug_level = 0;
ef06ca39
FI
318 XilinxQSPIPS *q = (XilinxQSPIPS *) object_dynamic_cast(OBJECT(s),
319 TYPE_XILINX_QSPIPS);
4a5b6fa8 320
94befa45 321 for (;;) {
f1241144 322 int i;
f1241144 323 uint8_t tx = 0;
9151da25 324 uint8_t tx_rx[num_effective_busses(s)];
ef06ca39
FI
325 uint8_t dummy_cycles = 0;
326 uint8_t addr_length;
f1241144 327
9151da25
PC
328 if (fifo8_is_empty(&s->tx_fifo)) {
329 if (!(s->regs[R_LQSPI_CFG] & LQSPI_CFG_LQ_MODE)) {
330 s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW;
331 }
332 xilinx_spips_update_ixr(s);
333 return;
334 } else if (s->snoop_state == SNOOP_STRIPING) {
335 for (i = 0; i < num_effective_busses(s); ++i) {
336 tx_rx[i] = fifo8_pop(&s->tx_fifo);
f1241144 337 }
9151da25 338 stripe8(tx_rx, num_effective_busses(s), false);
ef06ca39 339 } else if (s->snoop_state >= SNOOP_ADDR) {
9151da25
PC
340 tx = fifo8_pop(&s->tx_fifo);
341 for (i = 0; i < num_effective_busses(s); ++i) {
342 tx_rx[i] = tx;
343 }
ef06ca39
FI
344 } else {
345 /* Extract a dummy byte and generate dummy cycles according to the
346 * link state */
347 tx = fifo8_pop(&s->tx_fifo);
348 dummy_cycles = 8 / s->link_state;
9151da25
PC
349 }
350
351 for (i = 0; i < num_effective_busses(s); ++i) {
c3725b85 352 int bus = num_effective_busses(s) - 1 - i;
ef06ca39
FI
353 if (dummy_cycles) {
354 int d;
355 for (d = 0; d < dummy_cycles; ++d) {
356 tx_rx[0] = ssi_transfer(s->spi[bus], (uint32_t)tx_rx[0]);
357 }
358 } else {
359 DB_PRINT_L(debug_level, "tx = %02x\n", tx_rx[i]);
360 tx_rx[i] = ssi_transfer(s->spi[bus], (uint32_t)tx_rx[i]);
361 DB_PRINT_L(debug_level, "rx = %02x\n", tx_rx[i]);
362 }
9151da25
PC
363 }
364
ef06ca39
FI
365 if (s->regs[R_CMND] & R_CMND_RXFIFO_DRAIN) {
366 DB_PRINT_L(debug_level, "dircarding drained rx byte\n");
367 /* Do nothing */
368 } else if (s->rx_discard) {
369 DB_PRINT_L(debug_level, "dircarding discarded rx byte\n");
370 s->rx_discard -= 8 / s->link_state;
371 } else if (fifo8_is_full(&s->rx_fifo)) {
9151da25 372 s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW;
4a5b6fa8 373 DB_PRINT_L(0, "rx FIFO overflow");
9151da25
PC
374 } else if (s->snoop_state == SNOOP_STRIPING) {
375 stripe8(tx_rx, num_effective_busses(s), true);
376 for (i = 0; i < num_effective_busses(s); ++i) {
377 fifo8_push(&s->rx_fifo, (uint8_t)tx_rx[i]);
ef06ca39 378 DB_PRINT_L(debug_level, "pushing striped rx byte\n");
f1241144 379 }
9151da25 380 } else {
ef06ca39 381 DB_PRINT_L(debug_level, "pushing unstriped rx byte\n");
9151da25 382 fifo8_push(&s->rx_fifo, (uint8_t)tx_rx[0]);
f1241144 383 }
94befa45 384
ef06ca39
FI
385 if (s->link_state_next_when) {
386 s->link_state_next_when--;
387 if (!s->link_state_next_when) {
388 s->link_state = s->link_state_next;
389 }
390 }
391
4a5b6fa8
PC
392 DB_PRINT_L(debug_level, "initial snoop state: %x\n",
393 (unsigned)s->snoop_state);
f1241144
PC
394 switch (s->snoop_state) {
395 case (SNOOP_CHECKING):
ef06ca39
FI
396 /* Store the count of dummy bytes in the txfifo */
397 s->cmd_dummies = xilinx_spips_num_dummies(q, tx);
398 addr_length = get_addr_length(s, tx);
399 if (s->cmd_dummies < 0) {
400 s->snoop_state = SNOOP_NONE;
401 } else {
402 s->snoop_state = SNOOP_ADDR + addr_length - 1;
403 }
404 switch (tx) {
08a9635b 405 case DPP:
08a9635b 406 case DOR:
ef06ca39
FI
407 case DOR_4:
408 s->link_state_next = 2;
409 s->link_state_next_when = addr_length + s->cmd_dummies;
410 break;
411 case QPP:
412 case QPP_4:
08a9635b 413 case QOR:
ef06ca39
FI
414 case QOR_4:
415 s->link_state_next = 4;
416 s->link_state_next_when = addr_length + s->cmd_dummies;
417 break;
418 case DIOR:
419 case DIOR_4:
420 s->link_state = 2;
f1241144 421 break;
ef06ca39
FI
422 case QIOR:
423 case QIOR_4:
424 s->link_state = 4;
f1241144 425 break;
ef06ca39
FI
426 }
427 break;
428 case (SNOOP_ADDR):
429 /* Address has been transmitted, transmit dummy cycles now if
430 * needed */
431 if (s->cmd_dummies < 0) {
f1241144 432 s->snoop_state = SNOOP_NONE;
ef06ca39
FI
433 } else {
434 s->snoop_state = s->cmd_dummies;
f1241144 435 }
94befa45 436 break;
f1241144
PC
437 case (SNOOP_STRIPING):
438 case (SNOOP_NONE):
4a5b6fa8
PC
439 /* Once we hit the boring stuff - squelch debug noise */
440 if (!debug_level) {
441 DB_PRINT_L(0, "squelching debug info ....\n");
442 debug_level = 1;
443 }
f1241144
PC
444 break;
445 default:
446 s->snoop_state--;
94befa45 447 }
4a5b6fa8
PC
448 DB_PRINT_L(debug_level, "final snoop state: %x\n",
449 (unsigned)s->snoop_state);
f1241144
PC
450 }
451}
94befa45 452
b0b7ae62 453static inline void rx_data_bytes(XilinxSPIPS *s, uint8_t *value, int max)
f1241144
PC
454{
455 int i;
456
f1241144 457 for (i = 0; i < max && !fifo8_is_empty(&s->rx_fifo); ++i) {
b0b7ae62 458 value[i] = fifo8_pop(&s->rx_fifo);
94befa45 459 }
94befa45
PC
460}
461
a8170e5e 462static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
94befa45
PC
463 unsigned size)
464{
465 XilinxSPIPS *s = opaque;
466 uint32_t mask = ~0;
467 uint32_t ret;
b0b7ae62 468 uint8_t rx_buf[4];
94befa45
PC
469
470 addr >>= 2;
471 switch (addr) {
472 case R_CONFIG:
2133a5f6 473 mask = ~(R_CONFIG_RSVD | MAN_START_COM);
94befa45
PC
474 break;
475 case R_INTR_STATUS:
87920b44
PC
476 ret = s->regs[addr] & IXR_ALL;
477 s->regs[addr] = 0;
4a5b6fa8 478 DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
87920b44 479 return ret;
94befa45
PC
480 case R_INTR_MASK:
481 mask = IXR_ALL;
482 break;
483 case R_EN:
484 mask = 0x1;
485 break;
486 case R_SLAVE_IDLE_COUNT:
487 mask = 0xFF;
488 break;
489 case R_MOD_ID:
490 mask = 0x01FFFFFF;
491 break;
492 case R_INTR_EN:
493 case R_INTR_DIS:
494 case R_TX_DATA:
495 mask = 0;
496 break;
497 case R_RX_DATA:
b0b7ae62
PC
498 memset(rx_buf, 0, sizeof(rx_buf));
499 rx_data_bytes(s, rx_buf, s->num_txrx_bytes);
500 ret = s->regs[R_CONFIG] & ENDIAN ? cpu_to_be32(*(uint32_t *)rx_buf)
501 : cpu_to_le32(*(uint32_t *)rx_buf);
4a5b6fa8 502 DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
94befa45
PC
503 xilinx_spips_update_ixr(s);
504 return ret;
505 }
4a5b6fa8
PC
506 DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4,
507 s->regs[addr] & mask);
94befa45
PC
508 return s->regs[addr] & mask;
509
510}
511
f1241144
PC
512static inline void tx_data_bytes(XilinxSPIPS *s, uint32_t value, int num)
513{
514 int i;
515 for (i = 0; i < num && !fifo8_is_full(&s->tx_fifo); ++i) {
516 if (s->regs[R_CONFIG] & ENDIAN) {
517 fifo8_push(&s->tx_fifo, (uint8_t)(value >> 24));
518 value <<= 8;
519 } else {
520 fifo8_push(&s->tx_fifo, (uint8_t)value);
521 value >>= 8;
522 }
523 }
524}
525
a8170e5e 526static void xilinx_spips_write(void *opaque, hwaddr addr,
94befa45
PC
527 uint64_t value, unsigned size)
528{
529 int mask = ~0;
530 int man_start_com = 0;
531 XilinxSPIPS *s = opaque;
532
4a5b6fa8 533 DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value);
94befa45
PC
534 addr >>= 2;
535 switch (addr) {
536 case R_CONFIG:
2133a5f6 537 mask = ~(R_CONFIG_RSVD | MAN_START_COM);
94befa45
PC
538 if (value & MAN_START_COM) {
539 man_start_com = 1;
540 }
541 break;
542 case R_INTR_STATUS:
543 mask = IXR_ALL;
544 s->regs[R_INTR_STATUS] &= ~(mask & value);
545 goto no_reg_update;
546 case R_INTR_DIS:
547 mask = IXR_ALL;
548 s->regs[R_INTR_MASK] &= ~(mask & value);
549 goto no_reg_update;
550 case R_INTR_EN:
551 mask = IXR_ALL;
552 s->regs[R_INTR_MASK] |= mask & value;
553 goto no_reg_update;
554 case R_EN:
555 mask = 0x1;
556 break;
557 case R_SLAVE_IDLE_COUNT:
558 mask = 0xFF;
559 break;
560 case R_RX_DATA:
561 case R_INTR_MASK:
562 case R_MOD_ID:
563 mask = 0;
564 break;
565 case R_TX_DATA:
f1241144
PC
566 tx_data_bytes(s, (uint32_t)value, s->num_txrx_bytes);
567 goto no_reg_update;
568 case R_TXD1:
569 tx_data_bytes(s, (uint32_t)value, 1);
570 goto no_reg_update;
571 case R_TXD2:
572 tx_data_bytes(s, (uint32_t)value, 2);
573 goto no_reg_update;
574 case R_TXD3:
575 tx_data_bytes(s, (uint32_t)value, 3);
94befa45
PC
576 goto no_reg_update;
577 }
578 s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
579no_reg_update:
c4f08ffe 580 xilinx_spips_update_cs_lines(s);
e100f3be
PC
581 if ((man_start_com && s->regs[R_CONFIG] & MAN_START_EN) ||
582 (fifo8_is_empty(&s->tx_fifo) && s->regs[R_CONFIG] & MAN_START_EN)) {
94befa45
PC
583 xilinx_spips_flush_txfifo(s);
584 }
94befa45 585 xilinx_spips_update_cs_lines(s);
c4f08ffe 586 xilinx_spips_update_ixr(s);
94befa45
PC
587}
588
589static const MemoryRegionOps spips_ops = {
590 .read = xilinx_spips_read,
591 .write = xilinx_spips_write,
592 .endianness = DEVICE_LITTLE_ENDIAN,
593};
594
252b99ba
FK
595static void xilinx_qspips_invalidate_mmio_ptr(XilinxQSPIPS *q)
596{
597 XilinxSPIPS *s = &q->parent_obj;
598
83c3a1f6 599 if ((q->mmio_execution_enabled) && (q->lqspi_cached_addr != ~0ULL)) {
252b99ba
FK
600 /* Invalidate the current mapped mmio */
601 memory_region_invalidate_mmio_ptr(&s->mmlqspi, q->lqspi_cached_addr,
602 LQSPI_CACHE_SIZE);
252b99ba 603 }
83c3a1f6
KF
604
605 q->lqspi_cached_addr = ~0ULL;
252b99ba
FK
606}
607
b5cd9143
PC
608static void xilinx_qspips_write(void *opaque, hwaddr addr,
609 uint64_t value, unsigned size)
610{
611 XilinxQSPIPS *q = XILINX_QSPIPS(opaque);
ef06ca39 612 XilinxSPIPS *s = XILINX_SPIPS(opaque);
b5cd9143
PC
613
614 xilinx_spips_write(opaque, addr, value, size);
615 addr >>= 2;
616
617 if (addr == R_LQSPI_CFG) {
252b99ba 618 xilinx_qspips_invalidate_mmio_ptr(q);
b5cd9143 619 }
ef06ca39
FI
620 if (s->regs[R_CMND] & R_CMND_RXFIFO_DRAIN) {
621 fifo8_reset(&s->rx_fifo);
622 }
b5cd9143
PC
623}
624
625static const MemoryRegionOps qspips_ops = {
626 .read = xilinx_spips_read,
627 .write = xilinx_qspips_write,
628 .endianness = DEVICE_LITTLE_ENDIAN,
629};
630
f1241144
PC
631#define LQSPI_CACHE_SIZE 1024
632
252b99ba 633static void lqspi_load_cache(void *opaque, hwaddr addr)
f1241144 634{
6b91f015 635 XilinxQSPIPS *q = opaque;
f1241144 636 XilinxSPIPS *s = opaque;
252b99ba
FK
637 int i;
638 int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1))
639 / num_effective_busses(s));
640 int slave = flash_addr >> LQSPI_ADDRESS_BITS;
641 int cache_entry = 0;
642 uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
643
644 if (addr < q->lqspi_cached_addr ||
645 addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
646 xilinx_qspips_invalidate_mmio_ptr(q);
15408b42
PC
647 s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
648 s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0;
f1241144 649
4a5b6fa8 650 DB_PRINT_L(0, "config reg status: %08x\n", s->regs[R_LQSPI_CFG]);
f1241144
PC
651
652 fifo8_reset(&s->tx_fifo);
653 fifo8_reset(&s->rx_fifo);
654
f1241144 655 /* instruction */
4a5b6fa8
PC
656 DB_PRINT_L(0, "pushing read instruction: %02x\n",
657 (unsigned)(uint8_t)(s->regs[R_LQSPI_CFG] &
658 LQSPI_CFG_INST_CODE));
f1241144
PC
659 fifo8_push(&s->tx_fifo, s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE);
660 /* read address */
4a5b6fa8 661 DB_PRINT_L(0, "pushing read address %06x\n", flash_addr);
f1241144
PC
662 fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 16));
663 fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 8));
664 fifo8_push(&s->tx_fifo, (uint8_t)flash_addr);
665 /* mode bits */
666 if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_MODE_EN) {
667 fifo8_push(&s->tx_fifo, extract32(s->regs[R_LQSPI_CFG],
668 LQSPI_CFG_MODE_SHIFT,
669 LQSPI_CFG_MODE_WIDTH));
670 }
671 /* dummy bytes */
672 for (i = 0; i < (extract32(s->regs[R_LQSPI_CFG], LQSPI_CFG_DUMMY_SHIFT,
673 LQSPI_CFG_DUMMY_WIDTH)); ++i) {
4a5b6fa8 674 DB_PRINT_L(0, "pushing dummy byte\n");
f1241144
PC
675 fifo8_push(&s->tx_fifo, 0);
676 }
c4f08ffe 677 xilinx_spips_update_cs_lines(s);
f1241144
PC
678 xilinx_spips_flush_txfifo(s);
679 fifo8_reset(&s->rx_fifo);
680
4a5b6fa8 681 DB_PRINT_L(0, "starting QSPI data read\n");
f1241144 682
b0b7ae62
PC
683 while (cache_entry < LQSPI_CACHE_SIZE) {
684 for (i = 0; i < 64; ++i) {
685 tx_data_bytes(s, 0, 1);
a66418f6 686 }
f1241144 687 xilinx_spips_flush_txfifo(s);
b0b7ae62
PC
688 for (i = 0; i < 64; ++i) {
689 rx_data_bytes(s, &q->lqspi_buf[cache_entry++], 1);
a66418f6 690 }
f1241144
PC
691 }
692
15408b42
PC
693 s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
694 s->regs[R_LQSPI_STS] |= u_page_save;
f1241144
PC
695 xilinx_spips_update_cs_lines(s);
696
b0b7ae62 697 q->lqspi_cached_addr = flash_addr * num_effective_busses(s);
252b99ba
FK
698 }
699}
700
701static void *lqspi_request_mmio_ptr(void *opaque, hwaddr addr, unsigned *size,
702 unsigned *offset)
703{
704 XilinxQSPIPS *q = opaque;
83c3a1f6 705 hwaddr offset_within_the_region;
252b99ba 706
83c3a1f6
KF
707 if (!q->mmio_execution_enabled) {
708 return NULL;
709 }
710
711 offset_within_the_region = addr & ~(LQSPI_CACHE_SIZE - 1);
252b99ba
FK
712 lqspi_load_cache(opaque, offset_within_the_region);
713 *size = LQSPI_CACHE_SIZE;
714 *offset = offset_within_the_region;
715 return q->lqspi_buf;
716}
717
718static uint64_t
719lqspi_read(void *opaque, hwaddr addr, unsigned int size)
720{
721 XilinxQSPIPS *q = opaque;
722 uint32_t ret;
723
724 if (addr >= q->lqspi_cached_addr &&
725 addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
726 uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
727 ret = cpu_to_le32(*(uint32_t *)retp);
728 DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
729 (unsigned)ret);
730 return ret;
731 } else {
732 lqspi_load_cache(opaque, addr);
f1241144
PC
733 return lqspi_read(opaque, addr, size);
734 }
735}
736
737static const MemoryRegionOps lqspi_ops = {
738 .read = lqspi_read,
252b99ba 739 .request_ptr = lqspi_request_mmio_ptr,
f1241144
PC
740 .endianness = DEVICE_NATIVE_ENDIAN,
741 .valid = {
b0b7ae62 742 .min_access_size = 1,
f1241144
PC
743 .max_access_size = 4
744 }
745};
746
f8b9fe24 747static void xilinx_spips_realize(DeviceState *dev, Error **errp)
94befa45 748{
f8b9fe24
PC
749 XilinxSPIPS *s = XILINX_SPIPS(dev);
750 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
10e60b35 751 XilinxSPIPSClass *xsc = XILINX_SPIPS_GET_CLASS(s);
c8cccba3 752 qemu_irq *cs;
94befa45
PC
753 int i;
754
4a5b6fa8 755 DB_PRINT_L(0, "realized spips\n");
94befa45 756
f1241144
PC
757 s->spi = g_new(SSIBus *, s->num_busses);
758 for (i = 0; i < s->num_busses; ++i) {
759 char bus_name[16];
760 snprintf(bus_name, 16, "spi%d", i);
f8b9fe24 761 s->spi[i] = ssi_create_bus(dev, bus_name);
f1241144 762 }
b4ae3cfa 763
2790cd91 764 s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses);
ef06ca39 765 s->cs_lines_state = g_new0(bool, s->num_cs * s->num_busses);
c8cccba3
PB
766 for (i = 0, cs = s->cs_lines; i < s->num_busses; ++i, cs += s->num_cs) {
767 ssi_auto_connect_slaves(DEVICE(s), cs, s->spi[i]);
768 }
769
f8b9fe24 770 sysbus_init_irq(sbd, &s->irq);
f1241144 771 for (i = 0; i < s->num_cs * s->num_busses; ++i) {
f8b9fe24 772 sysbus_init_irq(sbd, &s->cs_lines[i]);
94befa45
PC
773 }
774
29776739 775 memory_region_init_io(&s->iomem, OBJECT(s), xsc->reg_ops, s,
6363235b 776 "spi", XLNX_SPIPS_R_MAX * 4);
f8b9fe24 777 sysbus_init_mmio(sbd, &s->iomem);
94befa45
PC
778
779 s->irqline = -1;
94befa45 780
10e60b35
PC
781 fifo8_create(&s->rx_fifo, xsc->rx_fifo_size);
782 fifo8_create(&s->tx_fifo, xsc->tx_fifo_size);
94befa45
PC
783}
784
6b91f015
PC
785static void xilinx_qspips_realize(DeviceState *dev, Error **errp)
786{
787 XilinxSPIPS *s = XILINX_SPIPS(dev);
788 XilinxQSPIPS *q = XILINX_QSPIPS(dev);
789 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
790
4a5b6fa8 791 DB_PRINT_L(0, "realized qspips\n");
6b91f015
PC
792
793 s->num_busses = 2;
794 s->num_cs = 2;
795 s->num_txrx_bytes = 4;
796
797 xilinx_spips_realize(dev, errp);
29776739 798 memory_region_init_io(&s->mmlqspi, OBJECT(s), &lqspi_ops, s, "lqspi",
6b91f015
PC
799 (1 << LQSPI_ADDRESS_BITS) * 2);
800 sysbus_init_mmio(sbd, &s->mmlqspi);
801
802 q->lqspi_cached_addr = ~0ULL;
83c3a1f6
KF
803
804 /* mmio_execution breaks migration better aborting than having strange
805 * bugs.
806 */
807 if (q->mmio_execution_enabled) {
808 error_setg(&q->migration_blocker,
809 "enabling mmio_execution breaks migration");
810 migrate_add_blocker(q->migration_blocker, &error_fatal);
811 }
6b91f015
PC
812}
813
94befa45
PC
814static int xilinx_spips_post_load(void *opaque, int version_id)
815{
816 xilinx_spips_update_ixr((XilinxSPIPS *)opaque);
817 xilinx_spips_update_cs_lines((XilinxSPIPS *)opaque);
818 return 0;
819}
820
821static const VMStateDescription vmstate_xilinx_spips = {
822 .name = "xilinx_spips",
f1241144
PC
823 .version_id = 2,
824 .minimum_version_id = 2,
94befa45
PC
825 .post_load = xilinx_spips_post_load,
826 .fields = (VMStateField[]) {
827 VMSTATE_FIFO8(tx_fifo, XilinxSPIPS),
828 VMSTATE_FIFO8(rx_fifo, XilinxSPIPS),
6363235b 829 VMSTATE_UINT32_ARRAY(regs, XilinxSPIPS, XLNX_SPIPS_R_MAX),
f1241144 830 VMSTATE_UINT8(snoop_state, XilinxSPIPS),
94befa45
PC
831 VMSTATE_END_OF_LIST()
832 }
833};
834
83c3a1f6
KF
835static Property xilinx_qspips_properties[] = {
836 /* We had to turn this off for 2.10 as it is not compatible with migration.
837 * It can be enabled but will prevent the device to be migrated.
838 * This will go aways when a fix will be released.
839 */
840 DEFINE_PROP_BOOL("x-mmio-exec", XilinxQSPIPS, mmio_execution_enabled,
841 false),
842 DEFINE_PROP_END_OF_LIST(),
843};
844
f1241144
PC
845static Property xilinx_spips_properties[] = {
846 DEFINE_PROP_UINT8("num-busses", XilinxSPIPS, num_busses, 1),
847 DEFINE_PROP_UINT8("num-ss-bits", XilinxSPIPS, num_cs, 4),
848 DEFINE_PROP_UINT8("num-txrx-bytes", XilinxSPIPS, num_txrx_bytes, 1),
849 DEFINE_PROP_END_OF_LIST(),
850};
6b91f015
PC
851
852static void xilinx_qspips_class_init(ObjectClass *klass, void * data)
853{
854 DeviceClass *dc = DEVICE_CLASS(klass);
10e60b35 855 XilinxSPIPSClass *xsc = XILINX_SPIPS_CLASS(klass);
6b91f015
PC
856
857 dc->realize = xilinx_qspips_realize;
83c3a1f6 858 dc->props = xilinx_qspips_properties;
b5cd9143 859 xsc->reg_ops = &qspips_ops;
10e60b35
PC
860 xsc->rx_fifo_size = RXFF_A_Q;
861 xsc->tx_fifo_size = TXFF_A_Q;
6b91f015
PC
862}
863
94befa45
PC
864static void xilinx_spips_class_init(ObjectClass *klass, void *data)
865{
866 DeviceClass *dc = DEVICE_CLASS(klass);
10e60b35 867 XilinxSPIPSClass *xsc = XILINX_SPIPS_CLASS(klass);
94befa45 868
f8b9fe24 869 dc->realize = xilinx_spips_realize;
94befa45 870 dc->reset = xilinx_spips_reset;
f1241144 871 dc->props = xilinx_spips_properties;
94befa45 872 dc->vmsd = &vmstate_xilinx_spips;
10e60b35 873
b5cd9143 874 xsc->reg_ops = &spips_ops;
10e60b35
PC
875 xsc->rx_fifo_size = RXFF_A;
876 xsc->tx_fifo_size = TXFF_A;
94befa45
PC
877}
878
879static const TypeInfo xilinx_spips_info = {
f8b9fe24 880 .name = TYPE_XILINX_SPIPS,
94befa45
PC
881 .parent = TYPE_SYS_BUS_DEVICE,
882 .instance_size = sizeof(XilinxSPIPS),
883 .class_init = xilinx_spips_class_init,
10e60b35 884 .class_size = sizeof(XilinxSPIPSClass),
94befa45
PC
885};
886
6b91f015
PC
887static const TypeInfo xilinx_qspips_info = {
888 .name = TYPE_XILINX_QSPIPS,
889 .parent = TYPE_XILINX_SPIPS,
890 .instance_size = sizeof(XilinxQSPIPS),
891 .class_init = xilinx_qspips_class_init,
892};
893
94befa45
PC
894static void xilinx_spips_register_types(void)
895{
896 type_register_static(&xilinx_spips_info);
6b91f015 897 type_register_static(&xilinx_qspips_info);
94befa45
PC
898}
899
900type_init(xilinx_spips_register_types)
This page took 0.449075 seconds and 4 git commands to generate.