1
From f92321d5d80ca6920ca37f010a71e9ac3ad4cc01 Mon Sep 17 00:00:00 2001
2
From: Peter Maydell <peter.maydell@linaro.org>
3
Date: Mon, 18 Feb 2013 16:58:28 +0000
4
Subject: [PATCH 30/69] SPI devices: convert to qdev
6
Content-Type: text/plain; charset=UTF-8
7
Content-Transfer-Encoding: 8bit
9
Introduce a new SPI bus type, and use it to convert
10
all the OMAP SPI devices to qdev.
12
Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
14
hw/arm/nseries.c | 90 ++++++++++++++++++++------------
15
hw/arm/omap2.c | 34 +++++++-----
16
hw/input/tsc2005.c | 62 +++++++++++++++-------
17
hw/input/tsc210x.c | 113 +++++++++++++++++++++++++++-------------
18
hw/ssi/Makefile.objs | 1 +
19
hw/ssi/omap_spi.c | 140 +++++++++++++++++++++++++++++++++-----------------
20
hw/ssi/spi.c | 121 +++++++++++++++++++++++++++++++++++++++++++
21
include/hw/arm/omap.h | 14 ++---
22
include/hw/devices.h | 11 ++--
23
include/hw/spi.h | 62 ++++++++++++++++++++++
24
10 files changed, 482 insertions(+), 166 deletions(-)
25
create mode 100644 hw/ssi/spi.c
26
create mode 100644 include/hw/spi.h
28
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
29
index 6478501..f4218f0 100644
30
--- a/hw/arm/nseries.c
31
+++ b/hw/arm/nseries.c
33
#include "hw/i2c/i2c.h"
34
#include "hw/devices.h"
35
#include "hw/block/flash.h"
39
#include "hw/loader.h"
40
@@ -40,11 +41,8 @@ struct n800_s {
41
struct omap_mpu_state_s *mpu;
43
struct rfbi_chip_s blizzard;
46
- uint32_t (*txrx)(void *opaque, uint32_t value, int len);
54
@@ -244,7 +242,7 @@ static void n800_key_event(void *opaque, int keycode)
58
- tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
59
+ tsc2301_key_event(s->tsc, code, !(keycode & 0x80));
62
static const int n800_keys[16] = {
63
@@ -272,13 +270,12 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
65
/* XXX: are the three pins inverted inside the chip between the
66
* tsc and the cpu (N4111)? */
67
- qemu_irq penirq = NULL; /* NC */
68
- qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
69
- qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
71
- s->ts.chip = tsc2301_init(penirq, kbirq, dav);
72
- s->ts.opaque = s->ts.chip->opaque;
73
- s->ts.txrx = tsc210x_txrx;
74
+ s->tsc = spi_create_device(omap_mcspi_bus(s->mpu->mcspi, 0), "tsc2301", 0);
76
+ qdev_connect_gpio_out(s->tsc, 1, qdev_get_gpio_in(s->mpu->gpio,
77
+ N800_TSC_KP_IRQ_GPIO));
78
+ qdev_connect_gpio_out(s->tsc, 2, qdev_get_gpio_in(s->mpu->gpio,
81
for (i = 0; i < 0x80; i ++)
83
@@ -288,17 +285,15 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
85
qemu_add_kbd_event_handler(n800_key_event, s);
87
- tsc210x_set_transform(s->ts.chip, &n800_pointercal);
88
+ tsc2301_set_transform(s->tsc, &n800_pointercal);
91
static void n810_tsc_setup(struct n800_s *s)
93
- qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
95
- s->ts.opaque = tsc2005_init(pintdav);
96
- s->ts.txrx = tsc2005_txrx;
98
- tsc2005_set_transform(s->ts.opaque, &n810_pointercal, 400, 4000);
99
+ s->tsc = spi_create_device(omap_mcspi_bus(s->mpu->mcspi, 0), "tsc2005", 0);
100
+ qdev_connect_gpio_out(s->tsc, 0, qdev_get_gpio_in(s->mpu->gpio,
101
+ N810_TSC_TS_GPIO));
102
+ tsc2005_set_transform(s->tsc, &n810_pointercal, 400, 4000);
105
/* N810 Keyboard controller */
106
@@ -405,6 +400,7 @@ static void n810_kbd_setup(struct n800_s *s)
108
/* LCD MIPI DBI-C controller (URAL) */
114
@@ -424,8 +420,11 @@ struct mipid_s {
118
-static void mipid_reset(struct mipid_s *s)
119
+static void mipid_reset(DeviceState *qdev)
121
+ struct mipid_s *s = FROM_SPI_DEVICE(struct mipid_s,
122
+ SPI_DEVICE_FROM_QDEV(qdev));
127
@@ -444,9 +443,9 @@ static void mipid_reset(struct mipid_s *s)
131
-static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
132
+static uint32_t mipid_txrx(SPIDevice *spidev, uint32_t cmd, int len)
134
- struct mipid_s *s = (struct mipid_s *) opaque;
135
+ struct mipid_s *s = FROM_SPI_DEVICE(struct mipid_s, spidev);
139
@@ -466,7 +465,7 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
142
case 0x01: /* SWRESET */
144
+ mipid_reset(&s->spi.qdev);
147
case 0x02: /* BSTROFF */
148
@@ -670,23 +669,40 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
152
-static void *mipid_init(void)
153
+static int mipid_init(SPIDevice *spidev)
155
- struct mipid_s *s = (struct mipid_s *) g_malloc0(sizeof(*s));
159
+static Property mipid_properties[] = {
160
+ DEFINE_PROP_UINT32("id", struct mipid_s, id, 0),
161
+ DEFINE_PROP_END_OF_LIST()
166
+static void mipid_class_init(ObjectClass *klass, void *data)
168
+ DeviceClass *dc = DEVICE_CLASS(klass);
169
+ SPIDeviceClass *k = SPI_DEVICE_CLASS(klass);
172
+ k->init = mipid_init;
173
+ k->txrx = mipid_txrx;
174
+ dc->reset = mipid_reset;
175
+ dc->props = mipid_properties;
178
+static TypeInfo mipid_info = {
179
+ .name = "lcd_mipid",
180
+ .parent = TYPE_SPI_DEVICE,
181
+ .instance_size = sizeof(struct mipid_s),
182
+ .class_init = mipid_class_init,
185
static void n8x0_spi_setup(struct n800_s *s)
187
- void *tsc = s->ts.opaque;
188
- void *mipid = mipid_init();
190
- omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
191
- omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
192
+ s->mipid = spi_create_device_noinit(omap_mcspi_bus(s->mpu->mcspi, 0),
194
+ qdev_prop_set_uint32(s->mipid, "id", 0x838f03);
195
+ qdev_init_nofail(s->mipid);
198
/* This task is normally performed by the bootloader. If we're loading
199
@@ -1406,10 +1422,16 @@ static QEMUMachine n810_machine = {
200
DEFAULT_MACHINE_OPTIONS,
203
+static void nseries_register_types(void)
205
+ type_register_static(&mipid_info);
208
static void nseries_machine_init(void)
210
qemu_register_machine(&n800_machine);
211
qemu_register_machine(&n810_machine);
214
+type_init(nseries_register_types);
215
machine_init(nseries_machine_init);
216
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
217
index cd53ec6..6c21886 100644
220
@@ -2220,8 +2220,6 @@ static void omap2_mpu_reset(void *opaque)
221
omap_uart_reset(mpu->uart[1]);
222
omap_uart_reset(mpu->uart[2]);
223
omap_mmc_reset(mpu->mmc);
224
- omap_mcspi_reset(mpu->mcspi[0]);
225
- omap_mcspi_reset(mpu->mcspi[1]);
226
cpu_reset(CPU(mpu->cpu));
229
@@ -2464,16 +2462,28 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
230
&s->drq[OMAP24XX_DMA_MMC1_TX],
231
omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
233
- s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), s, 4,
234
- qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ),
235
- &s->drq[OMAP24XX_DMA_SPI1_TX0],
236
- omap_findclk(s, "spi1_fclk"),
237
- omap_findclk(s, "spi1_iclk"));
238
- s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), s, 2,
239
- qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ),
240
- &s->drq[OMAP24XX_DMA_SPI2_TX0],
241
- omap_findclk(s, "spi2_fclk"),
242
- omap_findclk(s, "spi2_iclk"));
243
+ s->mcspi = qdev_create(NULL, "omap_mcspi");
244
+ qdev_prop_set_int32(s->mcspi, "mpu_model", s->mpu_model);
245
+ qdev_init_nofail(s->mcspi);
246
+ busdev = SYS_BUS_DEVICE(s->mcspi);
247
+ sysbus_connect_irq(busdev, 0,
248
+ qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ));
249
+ sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_SPI1_TX0]);
250
+ sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_SPI1_RX0]);
251
+ sysbus_connect_irq(busdev, 3, s->drq[OMAP24XX_DMA_SPI1_TX1]);
252
+ sysbus_connect_irq(busdev, 4, s->drq[OMAP24XX_DMA_SPI1_RX1]);
253
+ sysbus_connect_irq(busdev, 5, s->drq[OMAP24XX_DMA_SPI1_TX2]);
254
+ sysbus_connect_irq(busdev, 6, s->drq[OMAP24XX_DMA_SPI1_RX2]);
255
+ sysbus_connect_irq(busdev, 7, s->drq[OMAP24XX_DMA_SPI1_TX3]);
256
+ sysbus_connect_irq(busdev, 8, s->drq[OMAP24XX_DMA_SPI1_RX3]);
257
+ sysbus_connect_irq(busdev, 9,
258
+ qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ));
259
+ sysbus_connect_irq(busdev, 10, s->drq[OMAP24XX_DMA_SPI2_TX0]);
260
+ sysbus_connect_irq(busdev, 11, s->drq[OMAP24XX_DMA_SPI2_RX0]);
261
+ sysbus_connect_irq(busdev, 12, s->drq[OMAP24XX_DMA_SPI2_TX1]);
262
+ sysbus_connect_irq(busdev, 13, s->drq[OMAP24XX_DMA_SPI2_RX1]);
263
+ sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4ta(s->l4, 35), 0));
264
+ sysbus_mmio_map(busdev, 1, omap_l4_region_base(omap_l4ta(s->l4, 36), 0));
266
s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
267
/* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
268
diff --git a/hw/input/tsc2005.c b/hw/input/tsc2005.c
269
index 89168a3..7e7fa59 100644
270
--- a/hw/input/tsc2005.c
271
+++ b/hw/input/tsc2005.c
273
#include "qemu/timer.h"
274
#include "ui/console.h"
275
#include "hw/devices.h"
278
//#define TSC2005_DEBUG
281
#define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - (p ? 12 : 10)))
285
qemu_irq pint; /* Combination of the nPENIRQ and DAV signals */
288
@@ -326,8 +328,10 @@ static void tsc2005_pin_update(TSC2005State *s)
292
-static void tsc2005_reset(TSC2005State *s)
293
+static void tsc2005_reset(DeviceState *qdev)
295
+ TSC2005State *s = FROM_SPI_DEVICE(TSC2005State,
296
+ SPI_DEVICE_FROM_QDEV(qdev));
300
@@ -350,18 +354,17 @@ static void tsc2005_reset(TSC2005State *s)
301
tsc2005_pin_update(s);
304
-static uint8_t tsc2005_txrx_word(void *opaque, uint8_t value)
305
+static uint8_t tsc2005_txrx_word(TSC2005State *s, uint8_t value)
307
- TSC2005State *s = opaque;
309
TRACE("value = 0x%08x, state=%d", value, s->state + 1);
310
switch (s->state ++) {
314
- if (value & (1 << 1))
317
+ if (value & (1 << 1)) {
318
+ tsc2005_reset(&s->spi.qdev);
320
s->nextfunction = (value >> 3) & 0xf;
321
s->nextprecision = (value >> 2) & 1;
322
if (s->enabled != !(value & 1)) {
323
@@ -415,14 +418,15 @@ static uint8_t tsc2005_txrx_word(void *opaque, uint8_t value)
327
-uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len)
328
+static uint32_t tsc2005_txrx(SPIDevice *spidev, uint32_t value, int len)
330
+ TSC2005State *s = FROM_SPI_DEVICE(TSC2005State, spidev);
332
TRACE("value=0x%08x, len=%d", value, len);
336
- ret |= tsc2005_txrx_word(opaque, (value >> len) & 0xff) << len;
337
+ ret |= tsc2005_txrx_word(s, (value >> len) & 0xff) << len;
341
@@ -578,18 +582,16 @@ static int tsc2005_load(QEMUFile *f, void *opaque, int version_id)
345
-void *tsc2005_init(qemu_irq pintdav)
346
+static int tsc2005_init(SPIDevice *spidev)
349
+ TSC2005State *s = FROM_SPI_DEVICE(TSC2005State, spidev);
351
- s = (TSC2005State *)
352
- g_malloc0(sizeof(TSC2005State));
356
s->precision = s->nextprecision = 0;
357
s->timer = qemu_new_timer_ns(vm_clock, tsc2005_timer_tick, s);
359
+ qdev_init_gpio_out(&spidev->qdev, &s->pint, 1);
363
@@ -604,15 +606,12 @@ void *tsc2005_init(qemu_irq pintdav)
369
qemu_add_mouse_event_handler(tsc2005_touchscreen_event, s, 1,
370
"QEMU TSC2005-driven Touchscreen");
372
- qemu_register_reset((void *) tsc2005_reset, s);
373
register_savevm(NULL, "tsc2005", -1, 0, tsc2005_save, tsc2005_load, s);
380
@@ -620,10 +619,11 @@ void *tsc2005_init(qemu_irq pintdav)
381
* from the touchscreen. Assuming 12-bit precision was used during
384
-void tsc2005_set_transform(void *opaque, MouseTransformInfo *info,
385
+void tsc2005_set_transform(DeviceState *qdev, MouseTransformInfo *info,
386
int z1_cons, int z2_cons)
388
- TSC2005State *s = (TSC2005State *) opaque;
389
+ TSC2005State *s = FROM_SPI_DEVICE(TSC2005State,
390
+ SPI_DEVICE_FROM_QDEV(qdev));
392
/* This version assumes touchscreen X & Y axis are parallel or
393
* perpendicular to LCD's X & Y axis in some way. */
394
@@ -657,3 +657,27 @@ void tsc2005_set_transform(void *opaque, MouseTransformInfo *info,
395
s->z1_cons = z1_cons;
396
s->z2_cons = z2_cons;
399
+static void tsc2005_class_init(ObjectClass *klass, void *data)
401
+ DeviceClass *dc = DEVICE_CLASS(klass);
402
+ SPIDeviceClass *k = SPI_DEVICE_CLASS(klass);
404
+ k->init = tsc2005_init;
405
+ k->txrx = tsc2005_txrx;
406
+ dc->reset = tsc2005_reset;
409
+static TypeInfo tsc2005_info = {
411
+ .parent = TYPE_SPI_DEVICE,
412
+ .instance_size = sizeof(TSC2005State),
413
+ .class_init = tsc2005_class_init,
416
+static void tsc2005_register_types(void)
418
+ type_register_static(&tsc2005_info);
421
+type_init(tsc2005_register_types)
422
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
423
index 9b854e7..a801fcf 100644
424
--- a/hw/input/tsc210x.c
425
+++ b/hw/input/tsc210x.c
427
#include "ui/console.h"
428
#include "hw/arm/omap.h" /* For I2SCodec and uWireSlave */
429
#include "hw/devices.h"
432
#define TSC_DATA_REGISTERS_PAGE 0x0
433
#define TSC_CONTROL_REGISTERS_PAGE 0x1
435
#define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - resolution[p]))
441
+ qemu_irq irq[3]; /* pint, kbint, davint */
445
@@ -49,7 +48,7 @@ typedef struct {
449
- int state, page, offset, irq;
450
+ int state, page, offset, pint;
451
uint16_t command, dav;
454
@@ -94,6 +93,11 @@ typedef struct {
460
+ TSC210xState tsc210x;
463
static const int resolution[4] = { 12, 8, 10, 12 };
465
#define TSC_MODE_NO_SCAN 0x0
466
@@ -160,7 +164,7 @@ static void tsc210x_reset(TSC210xState *s)
474
s->audio_ctrl1 = 0x0000;
475
@@ -204,9 +208,15 @@ static void tsc210x_reset(TSC210xState *s)
479
- qemu_set_irq(s->pint, !s->irq);
480
- qemu_set_irq(s->davint, !s->dav);
481
- qemu_irq_raise(s->kbint);
482
+ qemu_set_irq(s->irq[0], !s->pint);
483
+ qemu_set_irq(s->irq[2], !s->dav);
484
+ qemu_irq_raise(s->irq[1]);
487
+static void tsc2301_reset(DeviceState *qdev)
489
+ tsc210x_reset(&FROM_SPI_DEVICE(TSC2301State,
490
+ SPI_DEVICE_FROM_QDEV(qdev))->tsc210x);
494
@@ -383,7 +393,7 @@ static uint16_t tsc2102_data_register_read(TSC210xState *s, int reg)
495
if ((s->model & 0xff00) == 0x2300) {
496
if (s->kb.intr && (s->kb.mode & 2)) {
498
- qemu_irq_raise(s->kbint);
499
+ qemu_irq_raise(s->irq[1]);
503
@@ -609,7 +619,7 @@ static void tsc2102_control_register_write(
504
s->kb.debounce = (value >> 11) & 7;
505
if (s->kb.intr && s->kb.scan) {
507
- qemu_irq_raise(s->kbint);
508
+ qemu_irq_raise(s->irq[1]);
512
@@ -819,9 +829,9 @@ static void tsc210x_pin_update(TSC210xState *s)
516
- if (pin_state != s->irq) {
517
- s->irq = pin_state;
518
- qemu_set_irq(s->pint, !s->irq);
519
+ if (pin_state != s->pint) {
520
+ s->pint = pin_state;
521
+ qemu_set_irq(s->irq[0], !s->pint);
524
switch (s->nextfunction) {
525
@@ -879,7 +889,7 @@ static uint16_t tsc210x_read(TSC210xState *s)
526
case TSC_DATA_REGISTERS_PAGE:
527
ret = tsc2102_data_register_read(s, s->offset);
529
- qemu_irq_raise(s->davint);
530
+ qemu_irq_raise(s->irq[2]);
532
case TSC_CONTROL_REGISTERS_PAGE:
533
ret = tsc2102_control_register_read(s, s->offset);
534
@@ -933,9 +943,9 @@ static void tsc210x_write(TSC210xState *s, uint16_t value)
538
-uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len)
539
+static uint32_t tsc2301_txrx(SPIDevice *spidev, uint32_t value, int len)
541
- TSC210xState *s = opaque;
542
+ TSC210xState *s = &FROM_SPI_DEVICE(TSC2301State, spidev)->tsc210x;
546
@@ -964,7 +974,7 @@ static void tsc210x_timer_tick(void *opaque)
548
s->dav |= mode_regs[s->function];
549
tsc210x_pin_update(s);
550
- qemu_irq_lower(s->davint);
551
+ qemu_irq_lower(s->irq[2]);
554
static void tsc210x_touchscreen_event(void *opaque,
555
@@ -1017,7 +1027,7 @@ static void tsc210x_save(QEMUFile *f, void *opaque)
556
qemu_put_byte(f, s->offset);
557
qemu_put_byte(f, s->command);
559
- qemu_put_byte(f, s->irq);
560
+ qemu_put_byte(f, s->pint);
561
qemu_put_be16s(f, &s->dav);
563
qemu_put_timer(f, s->timer);
564
@@ -1063,7 +1073,7 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
565
s->offset = qemu_get_byte(f);
566
s->command = qemu_get_byte(f);
568
- s->irq = qemu_get_byte(f);
569
+ s->pint = qemu_get_byte(f);
570
qemu_get_be16s(f, &s->dav);
572
qemu_get_timer(f, s->timer);
573
@@ -1094,8 +1104,8 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
574
qemu_get_be16s(f, &s->filter_data[i]);
576
s->busy = qemu_timer_pending(s->timer);
577
- qemu_set_irq(s->pint, !s->irq);
578
- qemu_set_irq(s->davint, !s->dav);
579
+ qemu_set_irq(s->irq[0], !s->pint);
580
+ qemu_set_irq(s->irq[2], !s->dav);
584
@@ -1112,7 +1122,7 @@ uWireSlave *tsc2102_init(qemu_irq pint)
586
s->precision = s->nextprecision = 0;
587
s->timer = qemu_new_timer_ns(vm_clock, tsc210x_timer_tick, s);
593
@@ -1149,21 +1159,16 @@ uWireSlave *tsc2102_init(qemu_irq pint)
597
-uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
598
+static int tsc2301_init(SPIDevice *spidev)
601
+ TSC210xState *s = &FROM_SPI_DEVICE(TSC2301State, spidev)->tsc210x;
603
- s = (TSC210xState *)
604
- g_malloc0(sizeof(TSC210xState));
605
- memset(s, 0, sizeof(TSC210xState));
609
s->precision = s->nextprecision = 0;
610
s->timer = qemu_new_timer_ns(vm_clock, tsc210x_timer_tick, s);
614
+ qdev_init_gpio_out(&spidev->qdev, s->irq, 3);
618
@@ -1186,17 +1191,36 @@ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
619
s->codec.in.fifo = s->in_fifo;
620
s->codec.out.fifo = s->out_fifo;
624
qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
625
"QEMU TSC2301-driven Touchscreen");
627
AUD_register_card(s->name, &s->card);
629
- qemu_register_reset((void *) tsc210x_reset, s);
630
register_savevm(NULL, s->name, -1, 0, tsc210x_save, tsc210x_load, s);
636
+static void tsc2301_class_init(ObjectClass *klass, void *data)
638
+ DeviceClass *dc = DEVICE_CLASS(klass);
639
+ SPIDeviceClass *k = SPI_DEVICE_CLASS(klass);
641
+ k->init = tsc2301_init;
642
+ k->txrx = tsc2301_txrx;
643
+ dc->reset = tsc2301_reset;
646
+static TypeInfo tsc2301_info = {
648
+ .parent = TYPE_SPI_DEVICE,
649
+ .instance_size = sizeof(TSC2301State),
650
+ .class_init = tsc2301_class_init,
653
+static void tsc210x_register_types(void)
655
+ type_register_static(&tsc2301_info);
658
I2SCodec *tsc210x_codec(uWireSlave *chip)
659
@@ -1273,6 +1297,14 @@ void tsc210x_set_transform(uWireSlave *chip,
663
+void tsc2301_set_transform(DeviceState *qdev, MouseTransformInfo *info)
665
+ tsc210x_set_transform(
666
+ &FROM_SPI_DEVICE(TSC2301State,
667
+ SPI_DEVICE_FROM_QDEV(qdev))->tsc210x.chip,
671
void tsc210x_key_event(uWireSlave *chip, int key, int down)
673
TSC210xState *s = (TSC210xState *) chip->opaque;
674
@@ -1284,10 +1316,19 @@ void tsc210x_key_event(uWireSlave *chip, int key, int down)
676
if (down && (s->kb.down & ~s->kb.mask) && !s->kb.intr) {
678
- qemu_irq_lower(s->kbint);
679
+ qemu_irq_lower(s->irq[1]);
680
} else if (s->kb.intr && !(s->kb.down & ~s->kb.mask) &&
683
- qemu_irq_raise(s->kbint);
684
+ qemu_irq_raise(s->irq[1]);
688
+void tsc2301_key_event(DeviceState *qdev, int key, int down)
690
+ TSC2301State *s = FROM_SPI_DEVICE(TSC2301State,
691
+ SPI_DEVICE_FROM_QDEV(qdev));
692
+ tsc210x_key_event(&s->tsc210x.chip, key, down);
695
+type_init(tsc210x_register_types)
696
diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
697
index 9555825..c89c2a7 100644
698
--- a/hw/ssi/Makefile.objs
699
+++ b/hw/ssi/Makefile.objs
700
@@ -2,5 +2,6 @@ common-obj-$(CONFIG_PL022) += pl022.o
701
common-obj-$(CONFIG_SSI) += ssi.o
702
common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
703
common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
704
+common-obj-$(CONFIG_SSI) += spi.o
706
obj-$(CONFIG_OMAP) += omap_spi.o
707
diff --git a/hw/ssi/omap_spi.c b/hw/ssi/omap_spi.c
708
index 7a79df4..d9f2e0e 100644
709
--- a/hw/ssi/omap_spi.c
710
+++ b/hw/ssi/omap_spi.c
714
#include "hw/arm/omap.h"
715
+#include "hw/sysbus.h"
721
#define SPI_REV_OMAP3430 0x21
722
#define IS_OMAP3_SPI(s) ((s)->revision >= SPI_REV_OMAP3430)
724
-struct omap_mcspi_s {
725
+typedef struct omap_mcspi_bus_s {
730
@@ -62,8 +65,6 @@ struct omap_mcspi_s {
731
struct omap_mcspi_ch_s {
734
- uint32_t (*txrx)(void *opaque, uint32_t, int);
739
@@ -71,15 +72,22 @@ struct omap_mcspi_s {
748
+typedef struct omap_mcspi_s {
749
+ SysBusDevice busdev;
752
+ OMAPSPIBusState *bus;
755
-static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s)
756
+static inline void omap_mcspi_interrupt_update(OMAPSPIBusState *s)
758
qemu_set_irq(s->irq, s->irqst & s->irqen);
761
-static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_s *s,
762
+static inline void omap_mcspi_dmarequest_update(OMAPSPIBusState *s,
765
struct omap_mcspi_ch_s *ch = &s->ch[chnum];
766
@@ -107,7 +115,7 @@ static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_s *s,
770
-static void omap_mcspi_fifo_reset(struct omap_mcspi_s *s)
771
+static void omap_mcspi_fifo_reset(OMAPSPIBusState *s)
773
struct omap_mcspi_ch_s *ch;
775
@@ -156,7 +164,7 @@ static void omap_mcspi_fifo_put(struct omap_mcspi_fifo_s *s, int wl,
779
-static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
780
+static void omap_mcspi_transfer_run(OMAPSPIBusState *s, int chnum)
782
struct omap_mcspi_ch_s *ch = s->ch + chnum;
783
int trm = (ch->config >> 12) & 3;
784
@@ -172,21 +180,20 @@ static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
786
if (!(s->control & 1) || /* SINGLE */
787
(ch->config & (1 << 20))) { /* FORCE */
789
wl = 1 + (0x1f & (ch->config >> 7)); /* WL */
790
if (!IS_OMAP3_SPI(s) || s->fifo_ch != chnum ||
791
!((ch->config >> 27) & 3)) { /* FFER | FFEW */
792
- ch->rx = ch->txrx(ch->opaque, ch->tx, wl);
793
+ ch->rx = spi_txrx(s->bus, chnum, ch->tx, wl);
795
switch ((ch->config >> 27) & 3) {
796
case 1: /* !FFER, FFEW */
798
ch->tx = omap_mcspi_fifo_get(&s->tx_fifo, wl);
799
- ch->rx = ch->txrx(ch->opaque, ch->tx, wl);
800
+ ch->rx = spi_txrx(s->bus, chnum, ch->tx, wl);
803
case 2: /* FFER, !FFEW */
804
- ch->rx = ch->txrx(ch->opaque, ch->tx, wl);
805
+ ch->rx = spi_txrx(s->bus, chnum, ch->tx, wl);
807
omap_mcspi_fifo_put(&s->rx_fifo, wl, ch->rx);
809
@@ -196,7 +203,7 @@ static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
810
s->tx_fifo.len && s->fifo_wcnt) {
812
ch->tx = omap_mcspi_fifo_get(&s->tx_fifo, wl);
813
- ch->rx = ch->txrx(ch->opaque, ch->tx, wl);
814
+ ch->rx = spi_txrx(s->bus, chnum, ch->tx, wl);
816
omap_mcspi_fifo_put(&s->rx_fifo, wl, ch->rx);
818
@@ -217,7 +224,6 @@ static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
819
((s->xferlevel >> 16) & 0xffff)) /* WCNT */
820
s->irqst |= 1 << 17; /* EOW */
826
@@ -242,7 +248,7 @@ intr_update:
827
omap_mcspi_dmarequest_update(s, chnum);
830
-void omap_mcspi_reset(struct omap_mcspi_s *s)
831
+static void omap_mcspi_bus_reset(OMAPSPIBusState *s)
835
@@ -270,7 +276,7 @@ void omap_mcspi_reset(struct omap_mcspi_s *s)
836
static uint64_t omap_mcspi_read(void *opaque, hwaddr addr,
839
- struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
840
+ OMAPSPIBusState *s = (OMAPSPIBusState *) opaque;
844
@@ -415,7 +421,7 @@ static uint64_t omap_mcspi_read(void *opaque, hwaddr addr,
845
static void omap_mcspi_write(void *opaque, hwaddr addr,
846
uint64_t value, unsigned size)
848
- struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
849
+ OMAPSPIBusState *s = (OMAPSPIBusState *) opaque;
853
@@ -441,7 +447,7 @@ static void omap_mcspi_write(void *opaque, hwaddr addr,
854
case 0x10: /* MCSPI_SYSCONFIG */
855
TRACE("SYSCONFIG = 0x%08x", value);
856
if (value & (1 << 1)) /* SOFTRESET */
857
- omap_mcspi_reset(s);
858
+ omap_mcspi_bus_reset(s);
859
s->sysconfig = value & 0x31d;
862
@@ -598,41 +604,79 @@ static const MemoryRegionOps omap_mcspi_ops = {
863
.endianness = DEVICE_NATIVE_ENDIAN,
866
-struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta,
867
- struct omap_mpu_state_s *mpu,
868
- int chnum, qemu_irq irq, qemu_irq *drq,
869
- omap_clk fclk, omap_clk iclk)
870
+static void omap_mcspi_reset(DeviceState *qdev)
872
- struct omap_mcspi_s *s = g_malloc0(sizeof(*s) +
873
- chnum * sizeof(struct omap_mcspi_ch_s));
874
- struct omap_mcspi_ch_s *ch = s->ch;
878
- /* revision was hardcoded as 0x91 in original code -- odd */
879
- s->revision = cpu_class_omap3(mpu) ? SPI_REV_OMAP3430 : SPI_REV_OMAP2420;
881
- ch->txdrq = *drq ++;
882
- ch->rxdrq = *drq ++;
885
+ OMAPSPIState *s = FROM_SYSBUS(OMAPSPIState, SYS_BUS_DEVICE(qdev));
886
+ for (i = 0; i < s->buscount; i++) {
887
+ omap_mcspi_bus_reset(&s->bus[i]);
889
- omap_mcspi_reset(s);
892
- memory_region_init_io(&s->iomem, &omap_mcspi_ops, s, "omap.mcspi",
893
- omap_l4_region_size(ta, 0));
894
- omap_l4_attach(ta, 0, &s->iomem);
895
+static int omap_mcspi_init(SysBusDevice *busdev)
898
+ OMAPSPIBusState *bs;
899
+ OMAPSPIState *s = FROM_SYSBUS(OMAPSPIState, busdev);
901
+ s->buscount = (s->mpu_model < omap3430) ? 2 : 4;
902
+ s->bus = g_new0(OMAPSPIBusState, s->buscount);
903
+ for (i = 0; i < s->buscount; i++) {
905
+ if (s->mpu_model < omap3430) {
906
+ bs->revision = SPI_REV_OMAP2420;
907
+ bs->chnum = i ? 2 : 4;
909
+ bs->revision = SPI_REV_OMAP3430;
910
+ bs->chnum = (i > 2) ? 1 : (i ? 2 : 4);
912
+ sysbus_init_irq(busdev, &bs->irq);
913
+ bs->bus = spi_init_bus(&busdev->qdev, NULL, bs->chnum);
914
+ bs->ch = g_new0(struct omap_mcspi_ch_s, bs->chnum);
915
+ for (j = 0; j < bs->chnum; j++) {
916
+ sysbus_init_irq(busdev, &bs->ch[j].txdrq);
917
+ sysbus_init_irq(busdev, &bs->ch[j].rxdrq);
919
+ memory_region_init_io(&bs->iomem, &omap_mcspi_ops, bs, "omap.mcspi",
921
+ sysbus_init_mmio(busdev, &bs->iomem);
927
+SPIBus *omap_mcspi_bus(DeviceState *qdev, int bus_number)
929
+ OMAPSPIState *s = FROM_SYSBUS(OMAPSPIState, SYS_BUS_DEVICE(qdev));
930
+ if (bus_number < s->buscount) {
931
+ return s->bus[bus_number].bus;
933
+ hw_error("%s: invalid bus number %d\n", __FUNCTION__, bus_number);
936
-void omap_mcspi_attach(struct omap_mcspi_s *s,
937
- uint32_t (*txrx)(void *opaque, uint32_t, int),
940
+static Property omap_mcspi_properties[] = {
941
+ DEFINE_PROP_INT32("mpu_model", OMAPSPIState, mpu_model, 0),
942
+ DEFINE_PROP_END_OF_LIST()
945
+static void omap_mcspi_class_init(ObjectClass *klass, void *data)
947
- if (chipselect < 0 || chipselect >= s->chnum)
948
- hw_error("%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
949
+ DeviceClass *dc = DEVICE_CLASS(klass);
950
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
951
+ k->init = omap_mcspi_init;
952
+ dc->props = omap_mcspi_properties;
953
+ dc->reset = omap_mcspi_reset;
956
- s->ch[chipselect].txrx = txrx;
957
- s->ch[chipselect].opaque = opaque;
958
+static TypeInfo omap_mcspi_info = {
959
+ .name = "omap_mcspi",
960
+ .parent = TYPE_SYS_BUS_DEVICE,
961
+ .instance_size = sizeof(OMAPSPIState),
962
+ .class_init = omap_mcspi_class_init,
965
+static void omap_mcspi_register_types(void)
967
+ type_register_static(&omap_mcspi_info);
970
+type_init(omap_mcspi_register_types)
971
diff --git a/hw/ssi/spi.c b/hw/ssi/spi.c
973
index 0000000..d38050e
980
+ * Copyright (C) 2007-2010 Nokia Corporation
982
+ * This program is free software; you can redistribute it and/or
983
+ * modify it under the terms of the GNU General Public License as
984
+ * published by the Free Software Foundation; either version 2 or
985
+ * (at your option) any later version of the License.
987
+ * This program is distributed in the hope that it will be useful,
988
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
989
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
990
+ * GNU General Public License for more details.
992
+ * You should have received a copy of the GNU General Public License along
993
+ * with this program; if not, write to the Free Software Foundation, Inc.,
994
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1001
+ SPIDevice **device;
1004
+#define TYPE_SPI_BUS "spi-bus"
1005
+#define SPI_BUS(obj) OBJECT_CHECK(SPIBus, (obj), TYPE_SPI_BUS)
1007
+static Property spi_props[] = {
1008
+ DEFINE_PROP_UINT8("channel", SPIDevice, channel, 0),
1009
+ DEFINE_PROP_END_OF_LIST()
1012
+static const TypeInfo spi_bus_info = {
1013
+ .name = TYPE_SPI_BUS,
1014
+ .parent = TYPE_BUS,
1015
+ .instance_size = sizeof(SPIBus),
1018
+SPIBus *spi_init_bus(DeviceState *parent, const char *name, int num_channels)
1020
+ SPIBus *bus = FROM_QBUS(SPIBus, qbus_create(TYPE_SPI_BUS, parent, name));
1021
+ bus->channels = num_channels;
1022
+ bus->device = g_new0(SPIDevice*, bus->channels);
1026
+uint32_t spi_txrx(SPIBus *bus, int channel, uint32_t data, int len)
1029
+ SPIDeviceClass *sc;
1031
+ if (channel < bus->channels) {
1032
+ if ((dev = bus->device[channel])) {
1033
+ sc = SPI_DEVICE_GET_CLASS(dev);
1035
+ return sc->txrx(dev, data, len);
1039
+ hw_error("%s: invalid channel %d\n", __FUNCTION__, channel);
1044
+DeviceState *spi_create_device_noinit(SPIBus *bus, const char *name, int ch)
1046
+ if (ch >= bus->channels) {
1047
+ hw_error("%s: invalid channel %d\n", __FUNCTION__, ch);
1049
+ if (bus->device[ch]) {
1050
+ hw_error("%s: channel %d already has a device attached\n",
1051
+ __FUNCTION__, ch);
1053
+ DeviceState *qdev = qdev_create(&bus->qbus, name);
1054
+ qdev_prop_set_uint8(qdev, "channel", ch);
1055
+ SPIDevice *dev = SPI_DEVICE_FROM_QDEV(qdev);
1056
+ bus->device[ch] = dev;
1060
+DeviceState *spi_create_device(SPIBus *bus, const char *name, int ch)
1062
+ DeviceState *dev = spi_create_device_noinit(bus, name, ch);
1063
+ qdev_init_nofail(dev);
1067
+static int spi_device_qdev_init(DeviceState *dev)
1069
+ SPIDevice *s = SPI_DEVICE_FROM_QDEV(dev);
1070
+ SPIDeviceClass *sc = SPI_DEVICE_GET_CLASS(s);
1071
+ return sc->init(s);
1074
+static void spi_device_class_init(ObjectClass *klass, void *data)
1076
+ DeviceClass *k = DEVICE_CLASS(klass);
1077
+ k->init = spi_device_qdev_init;
1078
+ k->bus_type = TYPE_SPI_BUS;
1079
+ k->props = spi_props;
1082
+static TypeInfo spi_device_type_info = {
1083
+ .name = TYPE_SPI_DEVICE,
1084
+ .parent = TYPE_DEVICE,
1085
+ .instance_size = sizeof(SPIDevice),
1087
+ .class_size = sizeof(SPIDeviceClass),
1088
+ .class_init = spi_device_class_init,
1091
+static void spi_device_register_types(void)
1093
+ type_register_static(&spi_bus_info);
1094
+ type_register_static(&spi_device_type_info);
1097
+type_init(spi_device_register_types)
1098
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
1099
index 9f2612e..21d83a6 100644
1100
--- a/include/hw/arm/omap.h
1101
+++ b/include/hw/arm/omap.h
1103
# define hw_omap_h "omap.h"
1106
+#include "hw/spi.h"
1108
# define OMAP_EMIFS_BASE 0x00000000
1109
# define OMAP2_Q0_BASE 0x00000000
1110
# define OMAP_CS0_BASE 0x00000000
1111
@@ -897,15 +899,7 @@ void omap_uwire_attach(struct omap_uwire_s *s,
1112
uWireSlave *slave, int chipselect);
1115
-struct omap_mcspi_s;
1116
-struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta,
1117
- struct omap_mpu_state_s *mp,
1118
- int chnum, qemu_irq irq, qemu_irq *drq,
1119
- omap_clk fclk, omap_clk iclk);
1120
-void omap_mcspi_attach(struct omap_mcspi_s *s,
1121
- uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque,
1123
-void omap_mcspi_reset(struct omap_mcspi_s *s);
1124
+SPIBus *omap_mcspi_bus(DeviceState *omap_mcspi, int bus_number);
1128
@@ -1138,7 +1132,7 @@ struct omap_mpu_state_s {
1129
struct omap_gpmc_s *gpmc;
1130
struct omap_sysctl_s *sysc;
1132
- struct omap_mcspi_s *mcspi[2];
1133
+ DeviceState *mcspi;
1135
struct omap_dss_s *dss;
1137
diff --git a/include/hw/devices.h b/include/hw/devices.h
1138
index 545b53a..f10de3d 100644
1139
--- a/include/hw/devices.h
1140
+++ b/include/hw/devices.h
1141
@@ -16,17 +16,14 @@ void lan9118_init(NICInfo *, uint32_t, qemu_irq);
1144
uWireSlave *tsc2102_init(qemu_irq pint);
1145
-uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
1146
I2SCodec *tsc210x_codec(uWireSlave *chip);
1147
-uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
1148
-void tsc210x_set_transform(uWireSlave *chip,
1149
- MouseTransformInfo *info);
1150
+void tsc210x_set_transform(uWireSlave *chip, MouseTransformInfo *info);
1151
+void tsc2301_set_transform(DeviceState *qdev, MouseTransformInfo *info);
1152
void tsc210x_key_event(uWireSlave *chip, int key, int down);
1153
+void tsc2301_key_event(DeviceState *qdev, int key, int down);
1156
-void *tsc2005_init(qemu_irq pintdav);
1157
-uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
1158
-void tsc2005_set_transform(void *opaque, MouseTransformInfo *info,
1159
+void tsc2005_set_transform(DeviceState *qdev, MouseTransformInfo *info,
1160
int z1_cons, int z2_cons);
1162
/* stellaris_input.c */
1163
diff --git a/include/hw/spi.h b/include/hw/spi.h
1164
new file mode 100644
1165
index 0000000..fa59f40
1167
+++ b/include/hw/spi.h
1172
+ * Copyright (C) 2007-2010 Nokia Corporation
1174
+ * This program is free software; you can redistribute it and/or
1175
+ * modify it under the terms of the GNU General Public License as
1176
+ * published by the Free Software Foundation; either version 2 or
1177
+ * (at your option) any later version of the License.
1179
+ * This program is distributed in the hope that it will be useful,
1180
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1181
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1182
+ * GNU General Public License for more details.
1184
+ * You should have received a copy of the GNU General Public License along
1185
+ * with this program; if not, write to the Free Software Foundation, Inc.,
1186
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1193
+typedef struct SPIDevice SPIDevice;
1194
+typedef struct SPIBus SPIBus;
1196
+#define TYPE_SPI_DEVICE "spi-device"
1197
+#define SPI_DEVICE(obj) \
1198
+ OBJECT_CHECK(SPIDevice, (obj), TYPE_SPI_DEVICE)
1199
+#define SPI_DEVICE_CLASS(klass) \
1200
+ OBJECT_CLASS_CHECK(SPIDeviceClass, (klass), TYPE_SPI_DEVICE)
1201
+#define SPI_DEVICE_GET_CLASS(obj) \
1202
+ OBJECT_GET_CLASS(SPIDeviceClass, (obj), TYPE_SPI_DEVICE)
1204
+typedef int (*spi_device_initfn)(SPIDevice *dev);
1205
+typedef uint32_t (*spi_txrx_cb)(SPIDevice *dev, uint32_t, int);
1207
+typedef struct SPIDeviceClass {
1208
+ DeviceClass parent_class;
1210
+ spi_device_initfn init;
1217
+ /* internal fields used by SPI code */
1221
+SPIBus *spi_init_bus(DeviceState *parent, const char *name, int num_channels);
1222
+uint32_t spi_txrx(SPIBus *bus, int channel, uint32_t data, int len);
1224
+#define SPI_DEVICE_FROM_QDEV(dev) DO_UPCAST(SPIDevice, qdev, dev)
1225
+#define FROM_SPI_DEVICE(type, dev) DO_UPCAST(type, spi, dev)
1227
+DeviceState *spi_create_device(SPIBus *bus, const char *name, int ch);
1228
+DeviceState *spi_create_device_noinit(SPIBus *bus, const char *name, int ch);