Statistics
| Branch: | Revision:

root / hw / xilinx_spi.c @ a1bc20df

History | View | Annotate | Download (9.5 kB)

1 929d1b52 Peter A. G. Crosthwaite
/*
2 929d1b52 Peter A. G. Crosthwaite
 * QEMU model of the Xilinx SPI Controller
3 929d1b52 Peter A. G. Crosthwaite
 *
4 929d1b52 Peter A. G. Crosthwaite
 * Copyright (C) 2010 Edgar E. Iglesias.
5 929d1b52 Peter A. G. Crosthwaite
 * Copyright (C) 2012 Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
6 929d1b52 Peter A. G. Crosthwaite
 * Copyright (C) 2012 PetaLogix
7 929d1b52 Peter A. G. Crosthwaite
 *
8 929d1b52 Peter A. G. Crosthwaite
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 929d1b52 Peter A. G. Crosthwaite
 * of this software and associated documentation files (the "Software"), to deal
10 929d1b52 Peter A. G. Crosthwaite
 * in the Software without restriction, including without limitation the rights
11 929d1b52 Peter A. G. Crosthwaite
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 929d1b52 Peter A. G. Crosthwaite
 * copies of the Software, and to permit persons to whom the Software is
13 929d1b52 Peter A. G. Crosthwaite
 * furnished to do so, subject to the following conditions:
14 929d1b52 Peter A. G. Crosthwaite
 *
15 929d1b52 Peter A. G. Crosthwaite
 * The above copyright notice and this permission notice shall be included in
16 929d1b52 Peter A. G. Crosthwaite
 * all copies or substantial portions of the Software.
17 929d1b52 Peter A. G. Crosthwaite
 *
18 929d1b52 Peter A. G. Crosthwaite
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 929d1b52 Peter A. G. Crosthwaite
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 929d1b52 Peter A. G. Crosthwaite
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 929d1b52 Peter A. G. Crosthwaite
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 929d1b52 Peter A. G. Crosthwaite
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 929d1b52 Peter A. G. Crosthwaite
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 929d1b52 Peter A. G. Crosthwaite
 * THE SOFTWARE.
25 929d1b52 Peter A. G. Crosthwaite
 */
26 929d1b52 Peter A. G. Crosthwaite
27 929d1b52 Peter A. G. Crosthwaite
#include "sysbus.h"
28 929d1b52 Peter A. G. Crosthwaite
#include "sysemu.h"
29 929d1b52 Peter A. G. Crosthwaite
#include "qemu-log.h"
30 929d1b52 Peter A. G. Crosthwaite
#include "fifo.h"
31 929d1b52 Peter A. G. Crosthwaite
32 929d1b52 Peter A. G. Crosthwaite
#include "ssi.h"
33 929d1b52 Peter A. G. Crosthwaite
34 929d1b52 Peter A. G. Crosthwaite
#ifdef XILINX_SPI_ERR_DEBUG
35 929d1b52 Peter A. G. Crosthwaite
#define DB_PRINT(...) do { \
36 929d1b52 Peter A. G. Crosthwaite
    fprintf(stderr,  ": %s: ", __func__); \
37 929d1b52 Peter A. G. Crosthwaite
    fprintf(stderr, ## __VA_ARGS__); \
38 929d1b52 Peter A. G. Crosthwaite
    } while (0);
39 929d1b52 Peter A. G. Crosthwaite
#else
40 929d1b52 Peter A. G. Crosthwaite
    #define DB_PRINT(...)
41 929d1b52 Peter A. G. Crosthwaite
#endif
42 929d1b52 Peter A. G. Crosthwaite
43 929d1b52 Peter A. G. Crosthwaite
#define R_DGIER     (0x1c / 4)
44 929d1b52 Peter A. G. Crosthwaite
#define R_DGIER_IE  (1 << 31)
45 929d1b52 Peter A. G. Crosthwaite
46 929d1b52 Peter A. G. Crosthwaite
#define R_IPISR     (0x20 / 4)
47 929d1b52 Peter A. G. Crosthwaite
#define IRQ_DRR_NOT_EMPTY    (1 << (31 - 23))
48 929d1b52 Peter A. G. Crosthwaite
#define IRQ_DRR_OVERRUN      (1 << (31 - 26))
49 929d1b52 Peter A. G. Crosthwaite
#define IRQ_DRR_FULL         (1 << (31 - 27))
50 929d1b52 Peter A. G. Crosthwaite
#define IRQ_TX_FF_HALF_EMPTY (1 << 6)
51 929d1b52 Peter A. G. Crosthwaite
#define IRQ_DTR_UNDERRUN     (1 << 3)
52 929d1b52 Peter A. G. Crosthwaite
#define IRQ_DTR_EMPTY        (1 << (31 - 29))
53 929d1b52 Peter A. G. Crosthwaite
54 929d1b52 Peter A. G. Crosthwaite
#define R_IPIER     (0x28 / 4)
55 929d1b52 Peter A. G. Crosthwaite
#define R_SRR       (0x40 / 4)
56 929d1b52 Peter A. G. Crosthwaite
#define R_SPICR     (0x60 / 4)
57 929d1b52 Peter A. G. Crosthwaite
#define R_SPICR_TXFF_RST     (1 << 5)
58 929d1b52 Peter A. G. Crosthwaite
#define R_SPICR_RXFF_RST     (1 << 6)
59 929d1b52 Peter A. G. Crosthwaite
#define R_SPICR_MTI          (1 << 8)
60 929d1b52 Peter A. G. Crosthwaite
61 929d1b52 Peter A. G. Crosthwaite
#define R_SPISR     (0x64 / 4)
62 929d1b52 Peter A. G. Crosthwaite
#define SR_TX_FULL    (1 << 3)
63 929d1b52 Peter A. G. Crosthwaite
#define SR_TX_EMPTY   (1 << 2)
64 929d1b52 Peter A. G. Crosthwaite
#define SR_RX_FULL    (1 << 1)
65 929d1b52 Peter A. G. Crosthwaite
#define SR_RX_EMPTY   (1 << 0)
66 929d1b52 Peter A. G. Crosthwaite
67 929d1b52 Peter A. G. Crosthwaite
#define R_SPIDTR    (0x68 / 4)
68 929d1b52 Peter A. G. Crosthwaite
#define R_SPIDRR    (0x6C / 4)
69 929d1b52 Peter A. G. Crosthwaite
#define R_SPISSR    (0x70 / 4)
70 929d1b52 Peter A. G. Crosthwaite
#define R_TX_FF_OCY (0x74 / 4)
71 929d1b52 Peter A. G. Crosthwaite
#define R_RX_FF_OCY (0x78 / 4)
72 929d1b52 Peter A. G. Crosthwaite
#define R_MAX       (0x7C / 4)
73 929d1b52 Peter A. G. Crosthwaite
74 929d1b52 Peter A. G. Crosthwaite
#define FIFO_CAPACITY 256
75 929d1b52 Peter A. G. Crosthwaite
76 929d1b52 Peter A. G. Crosthwaite
typedef struct XilinxSPI {
77 929d1b52 Peter A. G. Crosthwaite
    SysBusDevice busdev;
78 929d1b52 Peter A. G. Crosthwaite
    MemoryRegion mmio;
79 929d1b52 Peter A. G. Crosthwaite
80 929d1b52 Peter A. G. Crosthwaite
    qemu_irq irq;
81 929d1b52 Peter A. G. Crosthwaite
    int irqline;
82 929d1b52 Peter A. G. Crosthwaite
83 929d1b52 Peter A. G. Crosthwaite
    uint8_t num_cs;
84 929d1b52 Peter A. G. Crosthwaite
    qemu_irq *cs_lines;
85 929d1b52 Peter A. G. Crosthwaite
86 929d1b52 Peter A. G. Crosthwaite
    SSIBus *spi;
87 929d1b52 Peter A. G. Crosthwaite
88 929d1b52 Peter A. G. Crosthwaite
    Fifo8 rx_fifo;
89 929d1b52 Peter A. G. Crosthwaite
    Fifo8 tx_fifo;
90 929d1b52 Peter A. G. Crosthwaite
91 929d1b52 Peter A. G. Crosthwaite
    uint32_t regs[R_MAX];
92 929d1b52 Peter A. G. Crosthwaite
} XilinxSPI;
93 929d1b52 Peter A. G. Crosthwaite
94 929d1b52 Peter A. G. Crosthwaite
static void txfifo_reset(XilinxSPI *s)
95 929d1b52 Peter A. G. Crosthwaite
{
96 929d1b52 Peter A. G. Crosthwaite
    fifo8_reset(&s->tx_fifo);
97 929d1b52 Peter A. G. Crosthwaite
98 929d1b52 Peter A. G. Crosthwaite
    s->regs[R_SPISR] &= ~SR_TX_FULL;
99 929d1b52 Peter A. G. Crosthwaite
    s->regs[R_SPISR] |= SR_TX_EMPTY;
100 929d1b52 Peter A. G. Crosthwaite
}
101 929d1b52 Peter A. G. Crosthwaite
102 929d1b52 Peter A. G. Crosthwaite
static void rxfifo_reset(XilinxSPI *s)
103 929d1b52 Peter A. G. Crosthwaite
{
104 929d1b52 Peter A. G. Crosthwaite
    fifo8_reset(&s->rx_fifo);
105 929d1b52 Peter A. G. Crosthwaite
106 929d1b52 Peter A. G. Crosthwaite
    s->regs[R_SPISR] |= SR_RX_EMPTY;
107 929d1b52 Peter A. G. Crosthwaite
    s->regs[R_SPISR] &= ~SR_RX_FULL;
108 929d1b52 Peter A. G. Crosthwaite
}
109 929d1b52 Peter A. G. Crosthwaite
110 929d1b52 Peter A. G. Crosthwaite
static void xlx_spi_update_cs(XilinxSPI *s)
111 929d1b52 Peter A. G. Crosthwaite
{
112 929d1b52 Peter A. G. Crosthwaite
   int i;
113 929d1b52 Peter A. G. Crosthwaite
114 929d1b52 Peter A. G. Crosthwaite
    for (i = 0; i < s->num_cs; ++i) {
115 929d1b52 Peter A. G. Crosthwaite
        qemu_set_irq(s->cs_lines[i], !(~s->regs[R_SPISSR] & 1 << i));
116 929d1b52 Peter A. G. Crosthwaite
    }
117 929d1b52 Peter A. G. Crosthwaite
}
118 929d1b52 Peter A. G. Crosthwaite
119 929d1b52 Peter A. G. Crosthwaite
static void xlx_spi_update_irq(XilinxSPI *s)
120 929d1b52 Peter A. G. Crosthwaite
{
121 929d1b52 Peter A. G. Crosthwaite
    uint32_t pending;
122 929d1b52 Peter A. G. Crosthwaite
123 929d1b52 Peter A. G. Crosthwaite
    s->regs[R_IPISR] |=
124 929d1b52 Peter A. G. Crosthwaite
            (!fifo8_is_empty(&s->rx_fifo) ? IRQ_DRR_NOT_EMPTY : 0) |
125 929d1b52 Peter A. G. Crosthwaite
            (fifo8_is_full(&s->rx_fifo) ? IRQ_DRR_FULL : 0);
126 929d1b52 Peter A. G. Crosthwaite
127 929d1b52 Peter A. G. Crosthwaite
    pending = s->regs[R_IPISR] & s->regs[R_IPIER];
128 929d1b52 Peter A. G. Crosthwaite
129 929d1b52 Peter A. G. Crosthwaite
    pending = pending && (s->regs[R_DGIER] & R_DGIER_IE);
130 929d1b52 Peter A. G. Crosthwaite
    pending = !!pending;
131 929d1b52 Peter A. G. Crosthwaite
132 929d1b52 Peter A. G. Crosthwaite
    /* This call lies right in the data paths so don't call the
133 929d1b52 Peter A. G. Crosthwaite
       irq chain unless things really changed.  */
134 929d1b52 Peter A. G. Crosthwaite
    if (pending != s->irqline) {
135 929d1b52 Peter A. G. Crosthwaite
        s->irqline = pending;
136 929d1b52 Peter A. G. Crosthwaite
        DB_PRINT("irq_change of state %d ISR:%x IER:%X\n",
137 929d1b52 Peter A. G. Crosthwaite
                    pending, s->regs[R_IPISR], s->regs[R_IPIER]);
138 929d1b52 Peter A. G. Crosthwaite
        qemu_set_irq(s->irq, pending);
139 929d1b52 Peter A. G. Crosthwaite
    }
140 929d1b52 Peter A. G. Crosthwaite
141 929d1b52 Peter A. G. Crosthwaite
}
142 929d1b52 Peter A. G. Crosthwaite
143 929d1b52 Peter A. G. Crosthwaite
static void xlx_spi_do_reset(XilinxSPI *s)
144 929d1b52 Peter A. G. Crosthwaite
{
145 929d1b52 Peter A. G. Crosthwaite
    memset(s->regs, 0, sizeof s->regs);
146 929d1b52 Peter A. G. Crosthwaite
147 929d1b52 Peter A. G. Crosthwaite
    rxfifo_reset(s);
148 929d1b52 Peter A. G. Crosthwaite
    txfifo_reset(s);
149 929d1b52 Peter A. G. Crosthwaite
150 929d1b52 Peter A. G. Crosthwaite
    s->regs[R_SPISSR] = ~0;
151 929d1b52 Peter A. G. Crosthwaite
    xlx_spi_update_irq(s);
152 929d1b52 Peter A. G. Crosthwaite
    xlx_spi_update_cs(s);
153 929d1b52 Peter A. G. Crosthwaite
}
154 929d1b52 Peter A. G. Crosthwaite
155 929d1b52 Peter A. G. Crosthwaite
static void xlx_spi_reset(DeviceState *d)
156 929d1b52 Peter A. G. Crosthwaite
{
157 929d1b52 Peter A. G. Crosthwaite
    xlx_spi_do_reset(DO_UPCAST(XilinxSPI, busdev.qdev, d));
158 929d1b52 Peter A. G. Crosthwaite
}
159 929d1b52 Peter A. G. Crosthwaite
160 929d1b52 Peter A. G. Crosthwaite
static inline int spi_master_enabled(XilinxSPI *s)
161 929d1b52 Peter A. G. Crosthwaite
{
162 929d1b52 Peter A. G. Crosthwaite
    return !(s->regs[R_SPICR] & R_SPICR_MTI);
163 929d1b52 Peter A. G. Crosthwaite
}
164 929d1b52 Peter A. G. Crosthwaite
165 929d1b52 Peter A. G. Crosthwaite
static void spi_flush_txfifo(XilinxSPI *s)
166 929d1b52 Peter A. G. Crosthwaite
{
167 929d1b52 Peter A. G. Crosthwaite
    uint32_t tx;
168 929d1b52 Peter A. G. Crosthwaite
    uint32_t rx;
169 929d1b52 Peter A. G. Crosthwaite
170 929d1b52 Peter A. G. Crosthwaite
    while (!fifo8_is_empty(&s->tx_fifo)) {
171 929d1b52 Peter A. G. Crosthwaite
        tx = (uint32_t)fifo8_pop(&s->tx_fifo);
172 929d1b52 Peter A. G. Crosthwaite
        DB_PRINT("data tx:%x\n", tx);
173 929d1b52 Peter A. G. Crosthwaite
        rx = ssi_transfer(s->spi, tx);
174 929d1b52 Peter A. G. Crosthwaite
        DB_PRINT("data rx:%x\n", rx);
175 929d1b52 Peter A. G. Crosthwaite
        if (fifo8_is_full(&s->rx_fifo)) {
176 929d1b52 Peter A. G. Crosthwaite
            s->regs[R_IPISR] |= IRQ_DRR_OVERRUN;
177 929d1b52 Peter A. G. Crosthwaite
        } else {
178 929d1b52 Peter A. G. Crosthwaite
            fifo8_push(&s->rx_fifo, (uint8_t)rx);
179 929d1b52 Peter A. G. Crosthwaite
            if (fifo8_is_full(&s->rx_fifo)) {
180 929d1b52 Peter A. G. Crosthwaite
                s->regs[R_SPISR] |= SR_RX_FULL;
181 929d1b52 Peter A. G. Crosthwaite
                s->regs[R_IPISR] |= IRQ_DRR_FULL;
182 929d1b52 Peter A. G. Crosthwaite
            }
183 929d1b52 Peter A. G. Crosthwaite
        }
184 929d1b52 Peter A. G. Crosthwaite
185 929d1b52 Peter A. G. Crosthwaite
        s->regs[R_SPISR] &= ~SR_RX_EMPTY;
186 929d1b52 Peter A. G. Crosthwaite
        s->regs[R_SPISR] &= ~SR_TX_FULL;
187 929d1b52 Peter A. G. Crosthwaite
        s->regs[R_SPISR] |= SR_TX_EMPTY;
188 929d1b52 Peter A. G. Crosthwaite
189 929d1b52 Peter A. G. Crosthwaite
        s->regs[R_IPISR] |= IRQ_DTR_EMPTY;
190 929d1b52 Peter A. G. Crosthwaite
        s->regs[R_IPISR] |= IRQ_DRR_NOT_EMPTY;
191 929d1b52 Peter A. G. Crosthwaite
    }
192 929d1b52 Peter A. G. Crosthwaite
193 929d1b52 Peter A. G. Crosthwaite
}
194 929d1b52 Peter A. G. Crosthwaite
195 929d1b52 Peter A. G. Crosthwaite
static uint64_t
196 a8170e5e Avi Kivity
spi_read(void *opaque, hwaddr addr, unsigned int size)
197 929d1b52 Peter A. G. Crosthwaite
{
198 929d1b52 Peter A. G. Crosthwaite
    XilinxSPI *s = opaque;
199 929d1b52 Peter A. G. Crosthwaite
    uint32_t r = 0;
200 929d1b52 Peter A. G. Crosthwaite
201 929d1b52 Peter A. G. Crosthwaite
    addr >>= 2;
202 929d1b52 Peter A. G. Crosthwaite
    switch (addr) {
203 929d1b52 Peter A. G. Crosthwaite
    case R_SPIDRR:
204 929d1b52 Peter A. G. Crosthwaite
        if (fifo8_is_empty(&s->rx_fifo)) {
205 929d1b52 Peter A. G. Crosthwaite
            DB_PRINT("Read from empty FIFO!\n");
206 929d1b52 Peter A. G. Crosthwaite
            return 0xdeadbeef;
207 929d1b52 Peter A. G. Crosthwaite
        }
208 929d1b52 Peter A. G. Crosthwaite
209 929d1b52 Peter A. G. Crosthwaite
        s->regs[R_SPISR] &= ~SR_RX_FULL;
210 929d1b52 Peter A. G. Crosthwaite
        r = fifo8_pop(&s->rx_fifo);
211 929d1b52 Peter A. G. Crosthwaite
        if (fifo8_is_empty(&s->rx_fifo)) {
212 929d1b52 Peter A. G. Crosthwaite
            s->regs[R_SPISR] |= SR_RX_EMPTY;
213 929d1b52 Peter A. G. Crosthwaite
        }
214 929d1b52 Peter A. G. Crosthwaite
        break;
215 929d1b52 Peter A. G. Crosthwaite
216 929d1b52 Peter A. G. Crosthwaite
    case R_SPISR:
217 929d1b52 Peter A. G. Crosthwaite
        r = s->regs[addr];
218 929d1b52 Peter A. G. Crosthwaite
        break;
219 929d1b52 Peter A. G. Crosthwaite
220 929d1b52 Peter A. G. Crosthwaite
    default:
221 929d1b52 Peter A. G. Crosthwaite
        if (addr < ARRAY_SIZE(s->regs)) {
222 929d1b52 Peter A. G. Crosthwaite
            r = s->regs[addr];
223 929d1b52 Peter A. G. Crosthwaite
        }
224 929d1b52 Peter A. G. Crosthwaite
        break;
225 929d1b52 Peter A. G. Crosthwaite
226 929d1b52 Peter A. G. Crosthwaite
    }
227 929d1b52 Peter A. G. Crosthwaite
    DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, r);
228 929d1b52 Peter A. G. Crosthwaite
    xlx_spi_update_irq(s);
229 929d1b52 Peter A. G. Crosthwaite
    return r;
230 929d1b52 Peter A. G. Crosthwaite
}
231 929d1b52 Peter A. G. Crosthwaite
232 929d1b52 Peter A. G. Crosthwaite
static void
233 a8170e5e Avi Kivity
spi_write(void *opaque, hwaddr addr,
234 929d1b52 Peter A. G. Crosthwaite
            uint64_t val64, unsigned int size)
235 929d1b52 Peter A. G. Crosthwaite
{
236 929d1b52 Peter A. G. Crosthwaite
    XilinxSPI *s = opaque;
237 929d1b52 Peter A. G. Crosthwaite
    uint32_t value = val64;
238 929d1b52 Peter A. G. Crosthwaite
239 929d1b52 Peter A. G. Crosthwaite
    DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, value);
240 929d1b52 Peter A. G. Crosthwaite
    addr >>= 2;
241 929d1b52 Peter A. G. Crosthwaite
    switch (addr) {
242 929d1b52 Peter A. G. Crosthwaite
    case R_SRR:
243 929d1b52 Peter A. G. Crosthwaite
        if (value != 0xa) {
244 929d1b52 Peter A. G. Crosthwaite
            DB_PRINT("Invalid write to SRR %x\n", value);
245 929d1b52 Peter A. G. Crosthwaite
        } else {
246 929d1b52 Peter A. G. Crosthwaite
            xlx_spi_do_reset(s);
247 929d1b52 Peter A. G. Crosthwaite
        }
248 929d1b52 Peter A. G. Crosthwaite
        break;
249 929d1b52 Peter A. G. Crosthwaite
250 929d1b52 Peter A. G. Crosthwaite
    case R_SPIDTR:
251 929d1b52 Peter A. G. Crosthwaite
        s->regs[R_SPISR] &= ~SR_TX_EMPTY;
252 929d1b52 Peter A. G. Crosthwaite
        fifo8_push(&s->tx_fifo, (uint8_t)value);
253 929d1b52 Peter A. G. Crosthwaite
        if (fifo8_is_full(&s->tx_fifo)) {
254 929d1b52 Peter A. G. Crosthwaite
            s->regs[R_SPISR] |= SR_TX_FULL;
255 929d1b52 Peter A. G. Crosthwaite
        }
256 929d1b52 Peter A. G. Crosthwaite
        if (!spi_master_enabled(s)) {
257 929d1b52 Peter A. G. Crosthwaite
            goto done;
258 929d1b52 Peter A. G. Crosthwaite
        } else {
259 929d1b52 Peter A. G. Crosthwaite
            DB_PRINT("DTR and master enabled\n");
260 929d1b52 Peter A. G. Crosthwaite
        }
261 929d1b52 Peter A. G. Crosthwaite
        spi_flush_txfifo(s);
262 929d1b52 Peter A. G. Crosthwaite
        break;
263 929d1b52 Peter A. G. Crosthwaite
264 929d1b52 Peter A. G. Crosthwaite
    case R_SPISR:
265 929d1b52 Peter A. G. Crosthwaite
        DB_PRINT("Invalid write to SPISR %x\n", value);
266 929d1b52 Peter A. G. Crosthwaite
        break;
267 929d1b52 Peter A. G. Crosthwaite
268 929d1b52 Peter A. G. Crosthwaite
    case R_IPISR:
269 929d1b52 Peter A. G. Crosthwaite
        /* Toggle the bits.  */
270 929d1b52 Peter A. G. Crosthwaite
        s->regs[addr] ^= value;
271 929d1b52 Peter A. G. Crosthwaite
        break;
272 929d1b52 Peter A. G. Crosthwaite
273 929d1b52 Peter A. G. Crosthwaite
    /* Slave Select Register.  */
274 929d1b52 Peter A. G. Crosthwaite
    case R_SPISSR:
275 929d1b52 Peter A. G. Crosthwaite
        s->regs[addr] = value;
276 929d1b52 Peter A. G. Crosthwaite
        xlx_spi_update_cs(s);
277 929d1b52 Peter A. G. Crosthwaite
        break;
278 929d1b52 Peter A. G. Crosthwaite
279 929d1b52 Peter A. G. Crosthwaite
    case R_SPICR:
280 929d1b52 Peter A. G. Crosthwaite
        /* FIXME: reset irq and sr state to empty queues.  */
281 929d1b52 Peter A. G. Crosthwaite
        if (value & R_SPICR_RXFF_RST) {
282 929d1b52 Peter A. G. Crosthwaite
            rxfifo_reset(s);
283 929d1b52 Peter A. G. Crosthwaite
        }
284 929d1b52 Peter A. G. Crosthwaite
285 929d1b52 Peter A. G. Crosthwaite
        if (value & R_SPICR_TXFF_RST) {
286 929d1b52 Peter A. G. Crosthwaite
            txfifo_reset(s);
287 929d1b52 Peter A. G. Crosthwaite
        }
288 929d1b52 Peter A. G. Crosthwaite
        value &= ~(R_SPICR_RXFF_RST | R_SPICR_TXFF_RST);
289 929d1b52 Peter A. G. Crosthwaite
        s->regs[addr] = value;
290 929d1b52 Peter A. G. Crosthwaite
291 929d1b52 Peter A. G. Crosthwaite
        if (!(value & R_SPICR_MTI)) {
292 929d1b52 Peter A. G. Crosthwaite
            spi_flush_txfifo(s);
293 929d1b52 Peter A. G. Crosthwaite
        }
294 929d1b52 Peter A. G. Crosthwaite
        break;
295 929d1b52 Peter A. G. Crosthwaite
296 929d1b52 Peter A. G. Crosthwaite
    default:
297 929d1b52 Peter A. G. Crosthwaite
        if (addr < ARRAY_SIZE(s->regs)) {
298 929d1b52 Peter A. G. Crosthwaite
            s->regs[addr] = value;
299 929d1b52 Peter A. G. Crosthwaite
        }
300 929d1b52 Peter A. G. Crosthwaite
        break;
301 929d1b52 Peter A. G. Crosthwaite
    }
302 929d1b52 Peter A. G. Crosthwaite
303 929d1b52 Peter A. G. Crosthwaite
done:
304 929d1b52 Peter A. G. Crosthwaite
    xlx_spi_update_irq(s);
305 929d1b52 Peter A. G. Crosthwaite
}
306 929d1b52 Peter A. G. Crosthwaite
307 929d1b52 Peter A. G. Crosthwaite
static const MemoryRegionOps spi_ops = {
308 929d1b52 Peter A. G. Crosthwaite
    .read = spi_read,
309 929d1b52 Peter A. G. Crosthwaite
    .write = spi_write,
310 929d1b52 Peter A. G. Crosthwaite
    .endianness = DEVICE_NATIVE_ENDIAN,
311 929d1b52 Peter A. G. Crosthwaite
    .valid = {
312 929d1b52 Peter A. G. Crosthwaite
        .min_access_size = 4,
313 929d1b52 Peter A. G. Crosthwaite
        .max_access_size = 4
314 929d1b52 Peter A. G. Crosthwaite
    }
315 929d1b52 Peter A. G. Crosthwaite
};
316 929d1b52 Peter A. G. Crosthwaite
317 929d1b52 Peter A. G. Crosthwaite
static int xilinx_spi_init(SysBusDevice *dev)
318 929d1b52 Peter A. G. Crosthwaite
{
319 929d1b52 Peter A. G. Crosthwaite
    int i;
320 929d1b52 Peter A. G. Crosthwaite
    XilinxSPI *s = FROM_SYSBUS(typeof(*s), dev);
321 929d1b52 Peter A. G. Crosthwaite
322 929d1b52 Peter A. G. Crosthwaite
    DB_PRINT("\n");
323 b4ae3cfa Peter Crosthwaite
324 b4ae3cfa Peter Crosthwaite
    s->spi = ssi_create_bus(&dev->qdev, "spi");
325 b4ae3cfa Peter Crosthwaite
326 929d1b52 Peter A. G. Crosthwaite
    sysbus_init_irq(dev, &s->irq);
327 929d1b52 Peter A. G. Crosthwaite
    s->cs_lines = g_new(qemu_irq, s->num_cs);
328 b4ae3cfa Peter Crosthwaite
    ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi);
329 929d1b52 Peter A. G. Crosthwaite
    for (i = 0; i < s->num_cs; ++i) {
330 929d1b52 Peter A. G. Crosthwaite
        sysbus_init_irq(dev, &s->cs_lines[i]);
331 929d1b52 Peter A. G. Crosthwaite
    }
332 929d1b52 Peter A. G. Crosthwaite
333 929d1b52 Peter A. G. Crosthwaite
    memory_region_init_io(&s->mmio, &spi_ops, s, "xilinx-spi", R_MAX * 4);
334 929d1b52 Peter A. G. Crosthwaite
    sysbus_init_mmio(dev, &s->mmio);
335 929d1b52 Peter A. G. Crosthwaite
336 929d1b52 Peter A. G. Crosthwaite
    s->irqline = -1;
337 929d1b52 Peter A. G. Crosthwaite
338 929d1b52 Peter A. G. Crosthwaite
    fifo8_create(&s->tx_fifo, FIFO_CAPACITY);
339 929d1b52 Peter A. G. Crosthwaite
    fifo8_create(&s->rx_fifo, FIFO_CAPACITY);
340 929d1b52 Peter A. G. Crosthwaite
341 929d1b52 Peter A. G. Crosthwaite
    return 0;
342 929d1b52 Peter A. G. Crosthwaite
}
343 929d1b52 Peter A. G. Crosthwaite
344 929d1b52 Peter A. G. Crosthwaite
static const VMStateDescription vmstate_xilinx_spi = {
345 929d1b52 Peter A. G. Crosthwaite
    .name = "xilinx_spi",
346 929d1b52 Peter A. G. Crosthwaite
    .version_id = 1,
347 929d1b52 Peter A. G. Crosthwaite
    .minimum_version_id = 1,
348 929d1b52 Peter A. G. Crosthwaite
    .minimum_version_id_old = 1,
349 929d1b52 Peter A. G. Crosthwaite
    .fields = (VMStateField[]) {
350 929d1b52 Peter A. G. Crosthwaite
        VMSTATE_FIFO8(tx_fifo, XilinxSPI),
351 929d1b52 Peter A. G. Crosthwaite
        VMSTATE_FIFO8(rx_fifo, XilinxSPI),
352 929d1b52 Peter A. G. Crosthwaite
        VMSTATE_UINT32_ARRAY(regs, XilinxSPI, R_MAX),
353 929d1b52 Peter A. G. Crosthwaite
        VMSTATE_END_OF_LIST()
354 929d1b52 Peter A. G. Crosthwaite
    }
355 929d1b52 Peter A. G. Crosthwaite
};
356 929d1b52 Peter A. G. Crosthwaite
357 929d1b52 Peter A. G. Crosthwaite
static Property xilinx_spi_properties[] = {
358 929d1b52 Peter A. G. Crosthwaite
    DEFINE_PROP_UINT8("num-ss-bits", XilinxSPI, num_cs, 1),
359 929d1b52 Peter A. G. Crosthwaite
    DEFINE_PROP_END_OF_LIST(),
360 929d1b52 Peter A. G. Crosthwaite
};
361 929d1b52 Peter A. G. Crosthwaite
362 929d1b52 Peter A. G. Crosthwaite
static void xilinx_spi_class_init(ObjectClass *klass, void *data)
363 929d1b52 Peter A. G. Crosthwaite
{
364 929d1b52 Peter A. G. Crosthwaite
    DeviceClass *dc = DEVICE_CLASS(klass);
365 929d1b52 Peter A. G. Crosthwaite
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
366 929d1b52 Peter A. G. Crosthwaite
367 929d1b52 Peter A. G. Crosthwaite
    k->init = xilinx_spi_init;
368 929d1b52 Peter A. G. Crosthwaite
    dc->reset = xlx_spi_reset;
369 929d1b52 Peter A. G. Crosthwaite
    dc->props = xilinx_spi_properties;
370 929d1b52 Peter A. G. Crosthwaite
    dc->vmsd = &vmstate_xilinx_spi;
371 929d1b52 Peter A. G. Crosthwaite
}
372 929d1b52 Peter A. G. Crosthwaite
373 929d1b52 Peter A. G. Crosthwaite
static TypeInfo xilinx_spi_info = {
374 929d1b52 Peter A. G. Crosthwaite
    .name           = "xlnx.xps-spi",
375 929d1b52 Peter A. G. Crosthwaite
    .parent         = TYPE_SYS_BUS_DEVICE,
376 929d1b52 Peter A. G. Crosthwaite
    .instance_size  = sizeof(XilinxSPI),
377 929d1b52 Peter A. G. Crosthwaite
    .class_init     = xilinx_spi_class_init,
378 929d1b52 Peter A. G. Crosthwaite
};
379 929d1b52 Peter A. G. Crosthwaite
380 929d1b52 Peter A. G. Crosthwaite
static void xilinx_spi_register_types(void)
381 929d1b52 Peter A. G. Crosthwaite
{
382 929d1b52 Peter A. G. Crosthwaite
    type_register_static(&xilinx_spi_info);
383 929d1b52 Peter A. G. Crosthwaite
}
384 929d1b52 Peter A. G. Crosthwaite
385 929d1b52 Peter A. G. Crosthwaite
type_init(xilinx_spi_register_types)