1*31e17060SPaolo Bonzini /* 2*31e17060SPaolo Bonzini * QEMU model of the Xilinx Zynq SPI controller 3*31e17060SPaolo Bonzini * 4*31e17060SPaolo Bonzini * Copyright (c) 2012 Peter A. G. Crosthwaite 5*31e17060SPaolo Bonzini * 6*31e17060SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 7*31e17060SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 8*31e17060SPaolo Bonzini * in the Software without restriction, including without limitation the rights 9*31e17060SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10*31e17060SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 11*31e17060SPaolo Bonzini * furnished to do so, subject to the following conditions: 12*31e17060SPaolo Bonzini * 13*31e17060SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 14*31e17060SPaolo Bonzini * all copies or substantial portions of the Software. 15*31e17060SPaolo Bonzini * 16*31e17060SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17*31e17060SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18*31e17060SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19*31e17060SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20*31e17060SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21*31e17060SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22*31e17060SPaolo Bonzini * THE SOFTWARE. 23*31e17060SPaolo Bonzini */ 24*31e17060SPaolo Bonzini 25*31e17060SPaolo Bonzini #include "hw/sysbus.h" 26*31e17060SPaolo Bonzini #include "sysemu/sysemu.h" 27*31e17060SPaolo Bonzini #include "hw/ptimer.h" 28*31e17060SPaolo Bonzini #include "qemu/log.h" 29*31e17060SPaolo Bonzini #include "qemu/fifo8.h" 30*31e17060SPaolo Bonzini #include "hw/ssi.h" 31*31e17060SPaolo Bonzini #include "qemu/bitops.h" 32*31e17060SPaolo Bonzini 33*31e17060SPaolo Bonzini #ifdef XILINX_SPIPS_ERR_DEBUG 34*31e17060SPaolo Bonzini #define DB_PRINT(...) do { \ 35*31e17060SPaolo Bonzini fprintf(stderr, ": %s: ", __func__); \ 36*31e17060SPaolo Bonzini fprintf(stderr, ## __VA_ARGS__); \ 37*31e17060SPaolo Bonzini } while (0); 38*31e17060SPaolo Bonzini #else 39*31e17060SPaolo Bonzini #define DB_PRINT(...) 40*31e17060SPaolo Bonzini #endif 41*31e17060SPaolo Bonzini 42*31e17060SPaolo Bonzini /* config register */ 43*31e17060SPaolo Bonzini #define R_CONFIG (0x00 / 4) 44*31e17060SPaolo Bonzini #define IFMODE (1 << 31) 45*31e17060SPaolo Bonzini #define ENDIAN (1 << 26) 46*31e17060SPaolo Bonzini #define MODEFAIL_GEN_EN (1 << 17) 47*31e17060SPaolo Bonzini #define MAN_START_COM (1 << 16) 48*31e17060SPaolo Bonzini #define MAN_START_EN (1 << 15) 49*31e17060SPaolo Bonzini #define MANUAL_CS (1 << 14) 50*31e17060SPaolo Bonzini #define CS (0xF << 10) 51*31e17060SPaolo Bonzini #define CS_SHIFT (10) 52*31e17060SPaolo Bonzini #define PERI_SEL (1 << 9) 53*31e17060SPaolo Bonzini #define REF_CLK (1 << 8) 54*31e17060SPaolo Bonzini #define FIFO_WIDTH (3 << 6) 55*31e17060SPaolo Bonzini #define BAUD_RATE_DIV (7 << 3) 56*31e17060SPaolo Bonzini #define CLK_PH (1 << 2) 57*31e17060SPaolo Bonzini #define CLK_POL (1 << 1) 58*31e17060SPaolo Bonzini #define MODE_SEL (1 << 0) 59*31e17060SPaolo Bonzini 60*31e17060SPaolo Bonzini /* interrupt mechanism */ 61*31e17060SPaolo Bonzini #define R_INTR_STATUS (0x04 / 4) 62*31e17060SPaolo Bonzini #define R_INTR_EN (0x08 / 4) 63*31e17060SPaolo Bonzini #define R_INTR_DIS (0x0C / 4) 64*31e17060SPaolo Bonzini #define R_INTR_MASK (0x10 / 4) 65*31e17060SPaolo Bonzini #define IXR_TX_FIFO_UNDERFLOW (1 << 6) 66*31e17060SPaolo Bonzini #define IXR_RX_FIFO_FULL (1 << 5) 67*31e17060SPaolo Bonzini #define IXR_RX_FIFO_NOT_EMPTY (1 << 4) 68*31e17060SPaolo Bonzini #define IXR_TX_FIFO_FULL (1 << 3) 69*31e17060SPaolo Bonzini #define IXR_TX_FIFO_NOT_FULL (1 << 2) 70*31e17060SPaolo Bonzini #define IXR_TX_FIFO_MODE_FAIL (1 << 1) 71*31e17060SPaolo Bonzini #define IXR_RX_FIFO_OVERFLOW (1 << 0) 72*31e17060SPaolo Bonzini #define IXR_ALL ((IXR_TX_FIFO_UNDERFLOW<<1)-1) 73*31e17060SPaolo Bonzini 74*31e17060SPaolo Bonzini #define R_EN (0x14 / 4) 75*31e17060SPaolo Bonzini #define R_DELAY (0x18 / 4) 76*31e17060SPaolo Bonzini #define R_TX_DATA (0x1C / 4) 77*31e17060SPaolo Bonzini #define R_RX_DATA (0x20 / 4) 78*31e17060SPaolo Bonzini #define R_SLAVE_IDLE_COUNT (0x24 / 4) 79*31e17060SPaolo Bonzini #define R_TX_THRES (0x28 / 4) 80*31e17060SPaolo Bonzini #define R_RX_THRES (0x2C / 4) 81*31e17060SPaolo Bonzini #define R_TXD1 (0x80 / 4) 82*31e17060SPaolo Bonzini #define R_TXD2 (0x84 / 4) 83*31e17060SPaolo Bonzini #define R_TXD3 (0x88 / 4) 84*31e17060SPaolo Bonzini 85*31e17060SPaolo Bonzini #define R_LQSPI_CFG (0xa0 / 4) 86*31e17060SPaolo Bonzini #define R_LQSPI_CFG_RESET 0x03A002EB 87*31e17060SPaolo Bonzini #define LQSPI_CFG_LQ_MODE (1 << 31) 88*31e17060SPaolo Bonzini #define LQSPI_CFG_TWO_MEM (1 << 30) 89*31e17060SPaolo Bonzini #define LQSPI_CFG_SEP_BUS (1 << 30) 90*31e17060SPaolo Bonzini #define LQSPI_CFG_U_PAGE (1 << 28) 91*31e17060SPaolo Bonzini #define LQSPI_CFG_MODE_EN (1 << 25) 92*31e17060SPaolo Bonzini #define LQSPI_CFG_MODE_WIDTH 8 93*31e17060SPaolo Bonzini #define LQSPI_CFG_MODE_SHIFT 16 94*31e17060SPaolo Bonzini #define LQSPI_CFG_DUMMY_WIDTH 3 95*31e17060SPaolo Bonzini #define LQSPI_CFG_DUMMY_SHIFT 8 96*31e17060SPaolo Bonzini #define LQSPI_CFG_INST_CODE 0xFF 97*31e17060SPaolo Bonzini 98*31e17060SPaolo Bonzini #define R_LQSPI_STS (0xA4 / 4) 99*31e17060SPaolo Bonzini #define LQSPI_STS_WR_RECVD (1 << 1) 100*31e17060SPaolo Bonzini 101*31e17060SPaolo Bonzini #define R_MOD_ID (0xFC / 4) 102*31e17060SPaolo Bonzini 103*31e17060SPaolo Bonzini #define R_MAX (R_MOD_ID+1) 104*31e17060SPaolo Bonzini 105*31e17060SPaolo Bonzini /* size of TXRX FIFOs */ 106*31e17060SPaolo Bonzini #define RXFF_A 32 107*31e17060SPaolo Bonzini #define TXFF_A 32 108*31e17060SPaolo Bonzini 109*31e17060SPaolo Bonzini /* 16MB per linear region */ 110*31e17060SPaolo Bonzini #define LQSPI_ADDRESS_BITS 24 111*31e17060SPaolo Bonzini /* Bite off 4k chunks at a time */ 112*31e17060SPaolo Bonzini #define LQSPI_CACHE_SIZE 1024 113*31e17060SPaolo Bonzini 114*31e17060SPaolo Bonzini #define SNOOP_CHECKING 0xFF 115*31e17060SPaolo Bonzini #define SNOOP_NONE 0xFE 116*31e17060SPaolo Bonzini #define SNOOP_STRIPING 0 117*31e17060SPaolo Bonzini 118*31e17060SPaolo Bonzini typedef enum { 119*31e17060SPaolo Bonzini READ = 0x3, 120*31e17060SPaolo Bonzini FAST_READ = 0xb, 121*31e17060SPaolo Bonzini DOR = 0x3b, 122*31e17060SPaolo Bonzini QOR = 0x6b, 123*31e17060SPaolo Bonzini DIOR = 0xbb, 124*31e17060SPaolo Bonzini QIOR = 0xeb, 125*31e17060SPaolo Bonzini 126*31e17060SPaolo Bonzini PP = 0x2, 127*31e17060SPaolo Bonzini DPP = 0xa2, 128*31e17060SPaolo Bonzini QPP = 0x32, 129*31e17060SPaolo Bonzini } FlashCMD; 130*31e17060SPaolo Bonzini 131*31e17060SPaolo Bonzini typedef struct { 132*31e17060SPaolo Bonzini SysBusDevice busdev; 133*31e17060SPaolo Bonzini MemoryRegion iomem; 134*31e17060SPaolo Bonzini MemoryRegion mmlqspi; 135*31e17060SPaolo Bonzini 136*31e17060SPaolo Bonzini qemu_irq irq; 137*31e17060SPaolo Bonzini int irqline; 138*31e17060SPaolo Bonzini 139*31e17060SPaolo Bonzini uint8_t num_cs; 140*31e17060SPaolo Bonzini uint8_t num_busses; 141*31e17060SPaolo Bonzini 142*31e17060SPaolo Bonzini uint8_t snoop_state; 143*31e17060SPaolo Bonzini qemu_irq *cs_lines; 144*31e17060SPaolo Bonzini SSIBus **spi; 145*31e17060SPaolo Bonzini 146*31e17060SPaolo Bonzini Fifo8 rx_fifo; 147*31e17060SPaolo Bonzini Fifo8 tx_fifo; 148*31e17060SPaolo Bonzini 149*31e17060SPaolo Bonzini uint8_t num_txrx_bytes; 150*31e17060SPaolo Bonzini 151*31e17060SPaolo Bonzini uint32_t regs[R_MAX]; 152*31e17060SPaolo Bonzini 153*31e17060SPaolo Bonzini uint32_t lqspi_buf[LQSPI_CACHE_SIZE]; 154*31e17060SPaolo Bonzini hwaddr lqspi_cached_addr; 155*31e17060SPaolo Bonzini } XilinxSPIPS; 156*31e17060SPaolo Bonzini 157*31e17060SPaolo Bonzini #define TYPE_XILINX_SPIPS "xilinx,spips" 158*31e17060SPaolo Bonzini 159*31e17060SPaolo Bonzini #define XILINX_SPIPS(obj) \ 160*31e17060SPaolo Bonzini OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS) 161*31e17060SPaolo Bonzini 162*31e17060SPaolo Bonzini static inline int num_effective_busses(XilinxSPIPS *s) 163*31e17060SPaolo Bonzini { 164*31e17060SPaolo Bonzini return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS && 165*31e17060SPaolo Bonzini s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1; 166*31e17060SPaolo Bonzini } 167*31e17060SPaolo Bonzini 168*31e17060SPaolo Bonzini static void xilinx_spips_update_cs_lines(XilinxSPIPS *s) 169*31e17060SPaolo Bonzini { 170*31e17060SPaolo Bonzini int i, j; 171*31e17060SPaolo Bonzini bool found = false; 172*31e17060SPaolo Bonzini int field = s->regs[R_CONFIG] >> CS_SHIFT; 173*31e17060SPaolo Bonzini 174*31e17060SPaolo Bonzini for (i = 0; i < s->num_cs; i++) { 175*31e17060SPaolo Bonzini for (j = 0; j < num_effective_busses(s); j++) { 176*31e17060SPaolo Bonzini int upage = !!(s->regs[R_LQSPI_STS] & LQSPI_CFG_U_PAGE); 177*31e17060SPaolo Bonzini int cs_to_set = (j * s->num_cs + i + upage) % 178*31e17060SPaolo Bonzini (s->num_cs * s->num_busses); 179*31e17060SPaolo Bonzini 180*31e17060SPaolo Bonzini if (~field & (1 << i) && !found) { 181*31e17060SPaolo Bonzini DB_PRINT("selecting slave %d\n", i); 182*31e17060SPaolo Bonzini qemu_set_irq(s->cs_lines[cs_to_set], 0); 183*31e17060SPaolo Bonzini } else { 184*31e17060SPaolo Bonzini qemu_set_irq(s->cs_lines[cs_to_set], 1); 185*31e17060SPaolo Bonzini } 186*31e17060SPaolo Bonzini } 187*31e17060SPaolo Bonzini if (~field & (1 << i)) { 188*31e17060SPaolo Bonzini found = true; 189*31e17060SPaolo Bonzini } 190*31e17060SPaolo Bonzini } 191*31e17060SPaolo Bonzini if (!found) { 192*31e17060SPaolo Bonzini s->snoop_state = SNOOP_CHECKING; 193*31e17060SPaolo Bonzini } 194*31e17060SPaolo Bonzini } 195*31e17060SPaolo Bonzini 196*31e17060SPaolo Bonzini static void xilinx_spips_update_ixr(XilinxSPIPS *s) 197*31e17060SPaolo Bonzini { 198*31e17060SPaolo Bonzini /* These are set/cleared as they occur */ 199*31e17060SPaolo Bonzini s->regs[R_INTR_STATUS] &= (IXR_TX_FIFO_UNDERFLOW | IXR_RX_FIFO_OVERFLOW | 200*31e17060SPaolo Bonzini IXR_TX_FIFO_MODE_FAIL); 201*31e17060SPaolo Bonzini /* these are pure functions of fifo state, set them here */ 202*31e17060SPaolo Bonzini s->regs[R_INTR_STATUS] |= 203*31e17060SPaolo Bonzini (fifo8_is_full(&s->rx_fifo) ? IXR_RX_FIFO_FULL : 0) | 204*31e17060SPaolo Bonzini (s->rx_fifo.num >= s->regs[R_RX_THRES] ? IXR_RX_FIFO_NOT_EMPTY : 0) | 205*31e17060SPaolo Bonzini (fifo8_is_full(&s->tx_fifo) ? IXR_TX_FIFO_FULL : 0) | 206*31e17060SPaolo Bonzini (s->tx_fifo.num < s->regs[R_TX_THRES] ? IXR_TX_FIFO_NOT_FULL : 0); 207*31e17060SPaolo Bonzini /* drive external interrupt pin */ 208*31e17060SPaolo Bonzini int new_irqline = !!(s->regs[R_INTR_MASK] & s->regs[R_INTR_STATUS] & 209*31e17060SPaolo Bonzini IXR_ALL); 210*31e17060SPaolo Bonzini if (new_irqline != s->irqline) { 211*31e17060SPaolo Bonzini s->irqline = new_irqline; 212*31e17060SPaolo Bonzini qemu_set_irq(s->irq, s->irqline); 213*31e17060SPaolo Bonzini } 214*31e17060SPaolo Bonzini } 215*31e17060SPaolo Bonzini 216*31e17060SPaolo Bonzini static void xilinx_spips_reset(DeviceState *d) 217*31e17060SPaolo Bonzini { 218*31e17060SPaolo Bonzini XilinxSPIPS *s = XILINX_SPIPS(d); 219*31e17060SPaolo Bonzini 220*31e17060SPaolo Bonzini int i; 221*31e17060SPaolo Bonzini for (i = 0; i < R_MAX; i++) { 222*31e17060SPaolo Bonzini s->regs[i] = 0; 223*31e17060SPaolo Bonzini } 224*31e17060SPaolo Bonzini 225*31e17060SPaolo Bonzini fifo8_reset(&s->rx_fifo); 226*31e17060SPaolo Bonzini fifo8_reset(&s->rx_fifo); 227*31e17060SPaolo Bonzini /* non zero resets */ 228*31e17060SPaolo Bonzini s->regs[R_CONFIG] |= MODEFAIL_GEN_EN; 229*31e17060SPaolo Bonzini s->regs[R_SLAVE_IDLE_COUNT] = 0xFF; 230*31e17060SPaolo Bonzini s->regs[R_TX_THRES] = 1; 231*31e17060SPaolo Bonzini s->regs[R_RX_THRES] = 1; 232*31e17060SPaolo Bonzini /* FIXME: move magic number definition somewhere sensible */ 233*31e17060SPaolo Bonzini s->regs[R_MOD_ID] = 0x01090106; 234*31e17060SPaolo Bonzini s->regs[R_LQSPI_CFG] = R_LQSPI_CFG_RESET; 235*31e17060SPaolo Bonzini s->snoop_state = SNOOP_CHECKING; 236*31e17060SPaolo Bonzini xilinx_spips_update_ixr(s); 237*31e17060SPaolo Bonzini xilinx_spips_update_cs_lines(s); 238*31e17060SPaolo Bonzini } 239*31e17060SPaolo Bonzini 240*31e17060SPaolo Bonzini static void xilinx_spips_flush_txfifo(XilinxSPIPS *s) 241*31e17060SPaolo Bonzini { 242*31e17060SPaolo Bonzini for (;;) { 243*31e17060SPaolo Bonzini int i; 244*31e17060SPaolo Bonzini uint8_t rx; 245*31e17060SPaolo Bonzini uint8_t tx = 0; 246*31e17060SPaolo Bonzini 247*31e17060SPaolo Bonzini for (i = 0; i < num_effective_busses(s); ++i) { 248*31e17060SPaolo Bonzini if (!i || s->snoop_state == SNOOP_STRIPING) { 249*31e17060SPaolo Bonzini if (fifo8_is_empty(&s->tx_fifo)) { 250*31e17060SPaolo Bonzini s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW; 251*31e17060SPaolo Bonzini xilinx_spips_update_ixr(s); 252*31e17060SPaolo Bonzini return; 253*31e17060SPaolo Bonzini } else { 254*31e17060SPaolo Bonzini tx = fifo8_pop(&s->tx_fifo); 255*31e17060SPaolo Bonzini } 256*31e17060SPaolo Bonzini } 257*31e17060SPaolo Bonzini rx = ssi_transfer(s->spi[i], (uint32_t)tx); 258*31e17060SPaolo Bonzini DB_PRINT("tx = %02x rx = %02x\n", tx, rx); 259*31e17060SPaolo Bonzini if (!i || s->snoop_state == SNOOP_STRIPING) { 260*31e17060SPaolo Bonzini if (fifo8_is_full(&s->rx_fifo)) { 261*31e17060SPaolo Bonzini s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW; 262*31e17060SPaolo Bonzini DB_PRINT("rx FIFO overflow"); 263*31e17060SPaolo Bonzini } else { 264*31e17060SPaolo Bonzini fifo8_push(&s->rx_fifo, (uint8_t)rx); 265*31e17060SPaolo Bonzini } 266*31e17060SPaolo Bonzini } 267*31e17060SPaolo Bonzini } 268*31e17060SPaolo Bonzini 269*31e17060SPaolo Bonzini switch (s->snoop_state) { 270*31e17060SPaolo Bonzini case (SNOOP_CHECKING): 271*31e17060SPaolo Bonzini switch (tx) { /* new instruction code */ 272*31e17060SPaolo Bonzini case READ: /* 3 address bytes, no dummy bytes/cycles */ 273*31e17060SPaolo Bonzini case PP: 274*31e17060SPaolo Bonzini case DPP: 275*31e17060SPaolo Bonzini case QPP: 276*31e17060SPaolo Bonzini s->snoop_state = 3; 277*31e17060SPaolo Bonzini break; 278*31e17060SPaolo Bonzini case FAST_READ: /* 3 address bytes, 1 dummy byte */ 279*31e17060SPaolo Bonzini case DOR: 280*31e17060SPaolo Bonzini case QOR: 281*31e17060SPaolo Bonzini case DIOR: /* FIXME: these vary between vendor - set to spansion */ 282*31e17060SPaolo Bonzini s->snoop_state = 4; 283*31e17060SPaolo Bonzini break; 284*31e17060SPaolo Bonzini case QIOR: /* 3 address bytes, 2 dummy bytes */ 285*31e17060SPaolo Bonzini s->snoop_state = 6; 286*31e17060SPaolo Bonzini break; 287*31e17060SPaolo Bonzini default: 288*31e17060SPaolo Bonzini s->snoop_state = SNOOP_NONE; 289*31e17060SPaolo Bonzini } 290*31e17060SPaolo Bonzini break; 291*31e17060SPaolo Bonzini case (SNOOP_STRIPING): 292*31e17060SPaolo Bonzini case (SNOOP_NONE): 293*31e17060SPaolo Bonzini break; 294*31e17060SPaolo Bonzini default: 295*31e17060SPaolo Bonzini s->snoop_state--; 296*31e17060SPaolo Bonzini } 297*31e17060SPaolo Bonzini } 298*31e17060SPaolo Bonzini } 299*31e17060SPaolo Bonzini 300*31e17060SPaolo Bonzini static inline void rx_data_bytes(XilinxSPIPS *s, uint32_t *value, int max) 301*31e17060SPaolo Bonzini { 302*31e17060SPaolo Bonzini int i; 303*31e17060SPaolo Bonzini 304*31e17060SPaolo Bonzini *value = 0; 305*31e17060SPaolo Bonzini for (i = 0; i < max && !fifo8_is_empty(&s->rx_fifo); ++i) { 306*31e17060SPaolo Bonzini uint32_t next = fifo8_pop(&s->rx_fifo) & 0xFF; 307*31e17060SPaolo Bonzini *value |= next << 8 * (s->regs[R_CONFIG] & ENDIAN ? 3-i : i); 308*31e17060SPaolo Bonzini } 309*31e17060SPaolo Bonzini } 310*31e17060SPaolo Bonzini 311*31e17060SPaolo Bonzini static uint64_t xilinx_spips_read(void *opaque, hwaddr addr, 312*31e17060SPaolo Bonzini unsigned size) 313*31e17060SPaolo Bonzini { 314*31e17060SPaolo Bonzini XilinxSPIPS *s = opaque; 315*31e17060SPaolo Bonzini uint32_t mask = ~0; 316*31e17060SPaolo Bonzini uint32_t ret; 317*31e17060SPaolo Bonzini 318*31e17060SPaolo Bonzini addr >>= 2; 319*31e17060SPaolo Bonzini switch (addr) { 320*31e17060SPaolo Bonzini case R_CONFIG: 321*31e17060SPaolo Bonzini mask = 0x0002FFFF; 322*31e17060SPaolo Bonzini break; 323*31e17060SPaolo Bonzini case R_INTR_STATUS: 324*31e17060SPaolo Bonzini case R_INTR_MASK: 325*31e17060SPaolo Bonzini mask = IXR_ALL; 326*31e17060SPaolo Bonzini break; 327*31e17060SPaolo Bonzini case R_EN: 328*31e17060SPaolo Bonzini mask = 0x1; 329*31e17060SPaolo Bonzini break; 330*31e17060SPaolo Bonzini case R_SLAVE_IDLE_COUNT: 331*31e17060SPaolo Bonzini mask = 0xFF; 332*31e17060SPaolo Bonzini break; 333*31e17060SPaolo Bonzini case R_MOD_ID: 334*31e17060SPaolo Bonzini mask = 0x01FFFFFF; 335*31e17060SPaolo Bonzini break; 336*31e17060SPaolo Bonzini case R_INTR_EN: 337*31e17060SPaolo Bonzini case R_INTR_DIS: 338*31e17060SPaolo Bonzini case R_TX_DATA: 339*31e17060SPaolo Bonzini mask = 0; 340*31e17060SPaolo Bonzini break; 341*31e17060SPaolo Bonzini case R_RX_DATA: 342*31e17060SPaolo Bonzini rx_data_bytes(s, &ret, s->num_txrx_bytes); 343*31e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret); 344*31e17060SPaolo Bonzini xilinx_spips_update_ixr(s); 345*31e17060SPaolo Bonzini return ret; 346*31e17060SPaolo Bonzini } 347*31e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, s->regs[addr] & mask); 348*31e17060SPaolo Bonzini return s->regs[addr] & mask; 349*31e17060SPaolo Bonzini 350*31e17060SPaolo Bonzini } 351*31e17060SPaolo Bonzini 352*31e17060SPaolo Bonzini static inline void tx_data_bytes(XilinxSPIPS *s, uint32_t value, int num) 353*31e17060SPaolo Bonzini { 354*31e17060SPaolo Bonzini int i; 355*31e17060SPaolo Bonzini for (i = 0; i < num && !fifo8_is_full(&s->tx_fifo); ++i) { 356*31e17060SPaolo Bonzini if (s->regs[R_CONFIG] & ENDIAN) { 357*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, (uint8_t)(value >> 24)); 358*31e17060SPaolo Bonzini value <<= 8; 359*31e17060SPaolo Bonzini } else { 360*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, (uint8_t)value); 361*31e17060SPaolo Bonzini value >>= 8; 362*31e17060SPaolo Bonzini } 363*31e17060SPaolo Bonzini } 364*31e17060SPaolo Bonzini } 365*31e17060SPaolo Bonzini 366*31e17060SPaolo Bonzini static void xilinx_spips_write(void *opaque, hwaddr addr, 367*31e17060SPaolo Bonzini uint64_t value, unsigned size) 368*31e17060SPaolo Bonzini { 369*31e17060SPaolo Bonzini int mask = ~0; 370*31e17060SPaolo Bonzini int man_start_com = 0; 371*31e17060SPaolo Bonzini XilinxSPIPS *s = opaque; 372*31e17060SPaolo Bonzini 373*31e17060SPaolo Bonzini DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value); 374*31e17060SPaolo Bonzini addr >>= 2; 375*31e17060SPaolo Bonzini switch (addr) { 376*31e17060SPaolo Bonzini case R_CONFIG: 377*31e17060SPaolo Bonzini mask = 0x0002FFFF; 378*31e17060SPaolo Bonzini if (value & MAN_START_COM) { 379*31e17060SPaolo Bonzini man_start_com = 1; 380*31e17060SPaolo Bonzini } 381*31e17060SPaolo Bonzini break; 382*31e17060SPaolo Bonzini case R_INTR_STATUS: 383*31e17060SPaolo Bonzini mask = IXR_ALL; 384*31e17060SPaolo Bonzini s->regs[R_INTR_STATUS] &= ~(mask & value); 385*31e17060SPaolo Bonzini goto no_reg_update; 386*31e17060SPaolo Bonzini case R_INTR_DIS: 387*31e17060SPaolo Bonzini mask = IXR_ALL; 388*31e17060SPaolo Bonzini s->regs[R_INTR_MASK] &= ~(mask & value); 389*31e17060SPaolo Bonzini goto no_reg_update; 390*31e17060SPaolo Bonzini case R_INTR_EN: 391*31e17060SPaolo Bonzini mask = IXR_ALL; 392*31e17060SPaolo Bonzini s->regs[R_INTR_MASK] |= mask & value; 393*31e17060SPaolo Bonzini goto no_reg_update; 394*31e17060SPaolo Bonzini case R_EN: 395*31e17060SPaolo Bonzini mask = 0x1; 396*31e17060SPaolo Bonzini break; 397*31e17060SPaolo Bonzini case R_SLAVE_IDLE_COUNT: 398*31e17060SPaolo Bonzini mask = 0xFF; 399*31e17060SPaolo Bonzini break; 400*31e17060SPaolo Bonzini case R_RX_DATA: 401*31e17060SPaolo Bonzini case R_INTR_MASK: 402*31e17060SPaolo Bonzini case R_MOD_ID: 403*31e17060SPaolo Bonzini mask = 0; 404*31e17060SPaolo Bonzini break; 405*31e17060SPaolo Bonzini case R_TX_DATA: 406*31e17060SPaolo Bonzini tx_data_bytes(s, (uint32_t)value, s->num_txrx_bytes); 407*31e17060SPaolo Bonzini goto no_reg_update; 408*31e17060SPaolo Bonzini case R_TXD1: 409*31e17060SPaolo Bonzini tx_data_bytes(s, (uint32_t)value, 1); 410*31e17060SPaolo Bonzini goto no_reg_update; 411*31e17060SPaolo Bonzini case R_TXD2: 412*31e17060SPaolo Bonzini tx_data_bytes(s, (uint32_t)value, 2); 413*31e17060SPaolo Bonzini goto no_reg_update; 414*31e17060SPaolo Bonzini case R_TXD3: 415*31e17060SPaolo Bonzini tx_data_bytes(s, (uint32_t)value, 3); 416*31e17060SPaolo Bonzini goto no_reg_update; 417*31e17060SPaolo Bonzini } 418*31e17060SPaolo Bonzini s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask); 419*31e17060SPaolo Bonzini no_reg_update: 420*31e17060SPaolo Bonzini if (man_start_com) { 421*31e17060SPaolo Bonzini xilinx_spips_flush_txfifo(s); 422*31e17060SPaolo Bonzini } 423*31e17060SPaolo Bonzini xilinx_spips_update_ixr(s); 424*31e17060SPaolo Bonzini xilinx_spips_update_cs_lines(s); 425*31e17060SPaolo Bonzini } 426*31e17060SPaolo Bonzini 427*31e17060SPaolo Bonzini static const MemoryRegionOps spips_ops = { 428*31e17060SPaolo Bonzini .read = xilinx_spips_read, 429*31e17060SPaolo Bonzini .write = xilinx_spips_write, 430*31e17060SPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN, 431*31e17060SPaolo Bonzini }; 432*31e17060SPaolo Bonzini 433*31e17060SPaolo Bonzini #define LQSPI_CACHE_SIZE 1024 434*31e17060SPaolo Bonzini 435*31e17060SPaolo Bonzini static uint64_t 436*31e17060SPaolo Bonzini lqspi_read(void *opaque, hwaddr addr, unsigned int size) 437*31e17060SPaolo Bonzini { 438*31e17060SPaolo Bonzini int i; 439*31e17060SPaolo Bonzini XilinxSPIPS *s = opaque; 440*31e17060SPaolo Bonzini 441*31e17060SPaolo Bonzini if (addr >= s->lqspi_cached_addr && 442*31e17060SPaolo Bonzini addr <= s->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) { 443*31e17060SPaolo Bonzini return s->lqspi_buf[(addr - s->lqspi_cached_addr) >> 2]; 444*31e17060SPaolo Bonzini } else { 445*31e17060SPaolo Bonzini int flash_addr = (addr / num_effective_busses(s)); 446*31e17060SPaolo Bonzini int slave = flash_addr >> LQSPI_ADDRESS_BITS; 447*31e17060SPaolo Bonzini int cache_entry = 0; 448*31e17060SPaolo Bonzini 449*31e17060SPaolo Bonzini DB_PRINT("config reg status: %08x\n", s->regs[R_LQSPI_CFG]); 450*31e17060SPaolo Bonzini 451*31e17060SPaolo Bonzini fifo8_reset(&s->tx_fifo); 452*31e17060SPaolo Bonzini fifo8_reset(&s->rx_fifo); 453*31e17060SPaolo Bonzini 454*31e17060SPaolo Bonzini s->regs[R_CONFIG] &= ~CS; 455*31e17060SPaolo Bonzini s->regs[R_CONFIG] |= (~(1 << slave) << CS_SHIFT) & CS; 456*31e17060SPaolo Bonzini xilinx_spips_update_cs_lines(s); 457*31e17060SPaolo Bonzini 458*31e17060SPaolo Bonzini /* instruction */ 459*31e17060SPaolo Bonzini DB_PRINT("pushing read instruction: %02x\n", 460*31e17060SPaolo Bonzini (uint8_t)(s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE)); 461*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE); 462*31e17060SPaolo Bonzini /* read address */ 463*31e17060SPaolo Bonzini DB_PRINT("pushing read address %06x\n", flash_addr); 464*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 16)); 465*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 8)); 466*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, (uint8_t)flash_addr); 467*31e17060SPaolo Bonzini /* mode bits */ 468*31e17060SPaolo Bonzini if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_MODE_EN) { 469*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, extract32(s->regs[R_LQSPI_CFG], 470*31e17060SPaolo Bonzini LQSPI_CFG_MODE_SHIFT, 471*31e17060SPaolo Bonzini LQSPI_CFG_MODE_WIDTH)); 472*31e17060SPaolo Bonzini } 473*31e17060SPaolo Bonzini /* dummy bytes */ 474*31e17060SPaolo Bonzini for (i = 0; i < (extract32(s->regs[R_LQSPI_CFG], LQSPI_CFG_DUMMY_SHIFT, 475*31e17060SPaolo Bonzini LQSPI_CFG_DUMMY_WIDTH)); ++i) { 476*31e17060SPaolo Bonzini DB_PRINT("pushing dummy byte\n"); 477*31e17060SPaolo Bonzini fifo8_push(&s->tx_fifo, 0); 478*31e17060SPaolo Bonzini } 479*31e17060SPaolo Bonzini xilinx_spips_flush_txfifo(s); 480*31e17060SPaolo Bonzini fifo8_reset(&s->rx_fifo); 481*31e17060SPaolo Bonzini 482*31e17060SPaolo Bonzini DB_PRINT("starting QSPI data read\n"); 483*31e17060SPaolo Bonzini 484*31e17060SPaolo Bonzini for (i = 0; i < LQSPI_CACHE_SIZE / 4; ++i) { 485*31e17060SPaolo Bonzini tx_data_bytes(s, 0, 4); 486*31e17060SPaolo Bonzini xilinx_spips_flush_txfifo(s); 487*31e17060SPaolo Bonzini rx_data_bytes(s, &s->lqspi_buf[cache_entry], 4); 488*31e17060SPaolo Bonzini cache_entry++; 489*31e17060SPaolo Bonzini } 490*31e17060SPaolo Bonzini 491*31e17060SPaolo Bonzini s->regs[R_CONFIG] |= CS; 492*31e17060SPaolo Bonzini xilinx_spips_update_cs_lines(s); 493*31e17060SPaolo Bonzini 494*31e17060SPaolo Bonzini s->lqspi_cached_addr = addr; 495*31e17060SPaolo Bonzini return lqspi_read(opaque, addr, size); 496*31e17060SPaolo Bonzini } 497*31e17060SPaolo Bonzini } 498*31e17060SPaolo Bonzini 499*31e17060SPaolo Bonzini static const MemoryRegionOps lqspi_ops = { 500*31e17060SPaolo Bonzini .read = lqspi_read, 501*31e17060SPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN, 502*31e17060SPaolo Bonzini .valid = { 503*31e17060SPaolo Bonzini .min_access_size = 4, 504*31e17060SPaolo Bonzini .max_access_size = 4 505*31e17060SPaolo Bonzini } 506*31e17060SPaolo Bonzini }; 507*31e17060SPaolo Bonzini 508*31e17060SPaolo Bonzini static void xilinx_spips_realize(DeviceState *dev, Error **errp) 509*31e17060SPaolo Bonzini { 510*31e17060SPaolo Bonzini XilinxSPIPS *s = XILINX_SPIPS(dev); 511*31e17060SPaolo Bonzini SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 512*31e17060SPaolo Bonzini int i; 513*31e17060SPaolo Bonzini 514*31e17060SPaolo Bonzini DB_PRINT("inited device model\n"); 515*31e17060SPaolo Bonzini 516*31e17060SPaolo Bonzini s->spi = g_new(SSIBus *, s->num_busses); 517*31e17060SPaolo Bonzini for (i = 0; i < s->num_busses; ++i) { 518*31e17060SPaolo Bonzini char bus_name[16]; 519*31e17060SPaolo Bonzini snprintf(bus_name, 16, "spi%d", i); 520*31e17060SPaolo Bonzini s->spi[i] = ssi_create_bus(dev, bus_name); 521*31e17060SPaolo Bonzini } 522*31e17060SPaolo Bonzini 523*31e17060SPaolo Bonzini s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses); 524*31e17060SPaolo Bonzini ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]); 525*31e17060SPaolo Bonzini ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]); 526*31e17060SPaolo Bonzini sysbus_init_irq(sbd, &s->irq); 527*31e17060SPaolo Bonzini for (i = 0; i < s->num_cs * s->num_busses; ++i) { 528*31e17060SPaolo Bonzini sysbus_init_irq(sbd, &s->cs_lines[i]); 529*31e17060SPaolo Bonzini } 530*31e17060SPaolo Bonzini 531*31e17060SPaolo Bonzini memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4); 532*31e17060SPaolo Bonzini sysbus_init_mmio(sbd, &s->iomem); 533*31e17060SPaolo Bonzini 534*31e17060SPaolo Bonzini memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi", 535*31e17060SPaolo Bonzini (1 << LQSPI_ADDRESS_BITS) * 2); 536*31e17060SPaolo Bonzini sysbus_init_mmio(sbd, &s->mmlqspi); 537*31e17060SPaolo Bonzini 538*31e17060SPaolo Bonzini s->irqline = -1; 539*31e17060SPaolo Bonzini s->lqspi_cached_addr = ~0ULL; 540*31e17060SPaolo Bonzini 541*31e17060SPaolo Bonzini fifo8_create(&s->rx_fifo, RXFF_A); 542*31e17060SPaolo Bonzini fifo8_create(&s->tx_fifo, TXFF_A); 543*31e17060SPaolo Bonzini } 544*31e17060SPaolo Bonzini 545*31e17060SPaolo Bonzini static int xilinx_spips_post_load(void *opaque, int version_id) 546*31e17060SPaolo Bonzini { 547*31e17060SPaolo Bonzini xilinx_spips_update_ixr((XilinxSPIPS *)opaque); 548*31e17060SPaolo Bonzini xilinx_spips_update_cs_lines((XilinxSPIPS *)opaque); 549*31e17060SPaolo Bonzini return 0; 550*31e17060SPaolo Bonzini } 551*31e17060SPaolo Bonzini 552*31e17060SPaolo Bonzini static const VMStateDescription vmstate_xilinx_spips = { 553*31e17060SPaolo Bonzini .name = "xilinx_spips", 554*31e17060SPaolo Bonzini .version_id = 2, 555*31e17060SPaolo Bonzini .minimum_version_id = 2, 556*31e17060SPaolo Bonzini .minimum_version_id_old = 2, 557*31e17060SPaolo Bonzini .post_load = xilinx_spips_post_load, 558*31e17060SPaolo Bonzini .fields = (VMStateField[]) { 559*31e17060SPaolo Bonzini VMSTATE_FIFO8(tx_fifo, XilinxSPIPS), 560*31e17060SPaolo Bonzini VMSTATE_FIFO8(rx_fifo, XilinxSPIPS), 561*31e17060SPaolo Bonzini VMSTATE_UINT32_ARRAY(regs, XilinxSPIPS, R_MAX), 562*31e17060SPaolo Bonzini VMSTATE_UINT8(snoop_state, XilinxSPIPS), 563*31e17060SPaolo Bonzini VMSTATE_END_OF_LIST() 564*31e17060SPaolo Bonzini } 565*31e17060SPaolo Bonzini }; 566*31e17060SPaolo Bonzini 567*31e17060SPaolo Bonzini static Property xilinx_spips_properties[] = { 568*31e17060SPaolo Bonzini DEFINE_PROP_UINT8("num-busses", XilinxSPIPS, num_busses, 1), 569*31e17060SPaolo Bonzini DEFINE_PROP_UINT8("num-ss-bits", XilinxSPIPS, num_cs, 4), 570*31e17060SPaolo Bonzini DEFINE_PROP_UINT8("num-txrx-bytes", XilinxSPIPS, num_txrx_bytes, 1), 571*31e17060SPaolo Bonzini DEFINE_PROP_END_OF_LIST(), 572*31e17060SPaolo Bonzini }; 573*31e17060SPaolo Bonzini static void xilinx_spips_class_init(ObjectClass *klass, void *data) 574*31e17060SPaolo Bonzini { 575*31e17060SPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 576*31e17060SPaolo Bonzini 577*31e17060SPaolo Bonzini dc->realize = xilinx_spips_realize; 578*31e17060SPaolo Bonzini dc->reset = xilinx_spips_reset; 579*31e17060SPaolo Bonzini dc->props = xilinx_spips_properties; 580*31e17060SPaolo Bonzini dc->vmsd = &vmstate_xilinx_spips; 581*31e17060SPaolo Bonzini } 582*31e17060SPaolo Bonzini 583*31e17060SPaolo Bonzini static const TypeInfo xilinx_spips_info = { 584*31e17060SPaolo Bonzini .name = TYPE_XILINX_SPIPS, 585*31e17060SPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE, 586*31e17060SPaolo Bonzini .instance_size = sizeof(XilinxSPIPS), 587*31e17060SPaolo Bonzini .class_init = xilinx_spips_class_init, 588*31e17060SPaolo Bonzini }; 589*31e17060SPaolo Bonzini 590*31e17060SPaolo Bonzini static void xilinx_spips_register_types(void) 591*31e17060SPaolo Bonzini { 592*31e17060SPaolo Bonzini type_register_static(&xilinx_spips_info); 593*31e17060SPaolo Bonzini } 594*31e17060SPaolo Bonzini 595*31e17060SPaolo Bonzini type_init(xilinx_spips_register_types) 596