]>
Commit | Line | Data |
---|---|---|
90d37239 PB |
1 | /* |
2 | * QEMU Synchronous Serial Interface support | |
3 | * | |
4 | * Copyright (c) 2009 CodeSourcery. | |
5 | * Written by Paul Brook | |
6 | * | |
8e31bf38 | 7 | * This code is licensed under the GNU GPL v2. |
6b620ca3 PB |
8 | * |
9 | * Contributions after 2012-01-13 are licensed under the terms of the | |
10 | * GNU GPL, version 2 or (at your option) any later version. | |
90d37239 PB |
11 | */ |
12 | ||
13 | #include "ssi.h" | |
14 | ||
15 | struct SSIBus { | |
02e2da45 | 16 | BusState qbus; |
90d37239 PB |
17 | }; |
18 | ||
10c4c98a GH |
19 | static struct BusInfo ssi_bus_info = { |
20 | .name = "SSI", | |
21 | .size = sizeof(SSIBus), | |
22 | }; | |
23 | ||
81a322d4 | 24 | static int ssi_slave_init(DeviceState *dev, DeviceInfo *base_info) |
90d37239 | 25 | { |
cd6c4cf2 AL |
26 | SSISlave *s = SSI_SLAVE(dev); |
27 | SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); | |
02e2da45 PB |
28 | SSIBus *bus; |
29 | ||
30 | bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev)); | |
d8bb00d6 PB |
31 | if (QTAILQ_FIRST(&bus->qbus.children) != dev |
32 | || QTAILQ_NEXT(dev, sibling) != NULL) { | |
02e2da45 PB |
33 | hw_error("Too many devices on SSI bus"); |
34 | } | |
90d37239 | 35 | |
cd6c4cf2 | 36 | return ssc->init(s); |
90d37239 PB |
37 | } |
38 | ||
39bffca2 | 39 | static void ssi_slave_class_init(ObjectClass *klass, void *data) |
90d37239 | 40 | { |
39bffca2 AL |
41 | DeviceClass *dc = DEVICE_CLASS(klass); |
42 | dc->init = ssi_slave_init; | |
43 | dc->bus_info = &ssi_bus_info; | |
90d37239 PB |
44 | } |
45 | ||
39bffca2 AL |
46 | static TypeInfo ssi_slave_info = { |
47 | .name = TYPE_SSI_SLAVE, | |
48 | .parent = TYPE_DEVICE, | |
49 | .class_init = ssi_slave_class_init, | |
50 | .class_size = sizeof(SSISlaveClass), | |
51 | .abstract = true, | |
52 | }; | |
53 | ||
90d37239 PB |
54 | DeviceState *ssi_create_slave(SSIBus *bus, const char *name) |
55 | { | |
56 | DeviceState *dev; | |
02e2da45 | 57 | dev = qdev_create(&bus->qbus, name); |
e23a1b33 | 58 | qdev_init_nofail(dev); |
90d37239 PB |
59 | return dev; |
60 | } | |
61 | ||
02e2da45 | 62 | SSIBus *ssi_create_bus(DeviceState *parent, const char *name) |
90d37239 | 63 | { |
02e2da45 | 64 | BusState *bus; |
10c4c98a | 65 | bus = qbus_create(&ssi_bus_info, parent, name); |
02e2da45 | 66 | return FROM_QBUS(SSIBus, bus); |
90d37239 PB |
67 | } |
68 | ||
69 | uint32_t ssi_transfer(SSIBus *bus, uint32_t val) | |
70 | { | |
02e2da45 PB |
71 | DeviceState *dev; |
72 | SSISlave *slave; | |
cd6c4cf2 | 73 | SSISlaveClass *ssc; |
d8bb00d6 | 74 | dev = QTAILQ_FIRST(&bus->qbus.children); |
02e2da45 | 75 | if (!dev) { |
90d37239 PB |
76 | return 0; |
77 | } | |
cd6c4cf2 AL |
78 | slave = SSI_SLAVE(dev); |
79 | ssc = SSI_SLAVE_GET_CLASS(slave); | |
80 | return ssc->transfer(slave, val); | |
90d37239 | 81 | } |
39bffca2 AL |
82 | |
83 | static void register_ssi_slave(void) | |
84 | { | |
85 | type_register_static(&ssi_slave_info); | |
86 | } | |
87 | ||
88 | device_init(register_ssi_slave); |