root / hw / ssi.c @ 9a6ee9fd
History | View | Annotate | Download (4.1 kB)
1 | 90d37239 | Paul Brook | /*
|
---|---|---|---|
2 | 90d37239 | Paul Brook | * QEMU Synchronous Serial Interface support
|
3 | 90d37239 | Paul Brook | *
|
4 | 90d37239 | Paul Brook | * Copyright (c) 2009 CodeSourcery.
|
5 | b4a76e84 | Peter A. G. Crosthwaite | * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
|
6 | b4a76e84 | Peter A. G. Crosthwaite | * Copyright (c) 2012 PetaLogix Pty Ltd.
|
7 | 90d37239 | Paul Brook | * Written by Paul Brook
|
8 | 90d37239 | Paul Brook | *
|
9 | 8e31bf38 | Matthew Fernandez | * This code is licensed under the GNU GPL v2.
|
10 | 6b620ca3 | Paolo Bonzini | *
|
11 | 6b620ca3 | Paolo Bonzini | * Contributions after 2012-01-13 are licensed under the terms of the
|
12 | 6b620ca3 | Paolo Bonzini | * GNU GPL, version 2 or (at your option) any later version.
|
13 | 90d37239 | Paul Brook | */
|
14 | 90d37239 | Paul Brook | |
15 | 90d37239 | Paul Brook | #include "ssi.h" |
16 | 90d37239 | Paul Brook | |
17 | 90d37239 | Paul Brook | struct SSIBus {
|
18 | 02e2da45 | Paul Brook | BusState qbus; |
19 | 90d37239 | Paul Brook | }; |
20 | 90d37239 | Paul Brook | |
21 | 0d936928 | Anthony Liguori | #define TYPE_SSI_BUS "SSI" |
22 | 0d936928 | Anthony Liguori | #define SSI_BUS(obj) OBJECT_CHECK(SSIBus, (obj), TYPE_SSI_BUS)
|
23 | 0d936928 | Anthony Liguori | |
24 | 0d936928 | Anthony Liguori | static const TypeInfo ssi_bus_info = { |
25 | 0d936928 | Anthony Liguori | .name = TYPE_SSI_BUS, |
26 | 0d936928 | Anthony Liguori | .parent = TYPE_BUS, |
27 | 0d936928 | Anthony Liguori | .instance_size = sizeof(SSIBus),
|
28 | 10c4c98a | Gerd Hoffmann | }; |
29 | 10c4c98a | Gerd Hoffmann | |
30 | 66530953 | Peter A. G. Crosthwaite | static void ssi_cs_default(void *opaque, int n, int level) |
31 | 66530953 | Peter A. G. Crosthwaite | { |
32 | 66530953 | Peter A. G. Crosthwaite | SSISlave *s = SSI_SLAVE(opaque); |
33 | 66530953 | Peter A. G. Crosthwaite | bool cs = !!level;
|
34 | 66530953 | Peter A. G. Crosthwaite | assert(n == 0);
|
35 | 66530953 | Peter A. G. Crosthwaite | if (s->cs != cs) {
|
36 | 66530953 | Peter A. G. Crosthwaite | SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); |
37 | 66530953 | Peter A. G. Crosthwaite | if (ssc->set_cs) {
|
38 | 66530953 | Peter A. G. Crosthwaite | ssc->set_cs(s, cs); |
39 | 66530953 | Peter A. G. Crosthwaite | } |
40 | 66530953 | Peter A. G. Crosthwaite | } |
41 | 66530953 | Peter A. G. Crosthwaite | s->cs = cs; |
42 | 66530953 | Peter A. G. Crosthwaite | } |
43 | 66530953 | Peter A. G. Crosthwaite | |
44 | 66530953 | Peter A. G. Crosthwaite | static uint32_t ssi_transfer_raw_default(SSISlave *dev, uint32_t val)
|
45 | 66530953 | Peter A. G. Crosthwaite | { |
46 | 66530953 | Peter A. G. Crosthwaite | SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(dev); |
47 | 66530953 | Peter A. G. Crosthwaite | |
48 | 66530953 | Peter A. G. Crosthwaite | if ((dev->cs && ssc->cs_polarity == SSI_CS_HIGH) ||
|
49 | 66530953 | Peter A. G. Crosthwaite | (!dev->cs && ssc->cs_polarity == SSI_CS_LOW) || |
50 | 66530953 | Peter A. G. Crosthwaite | ssc->cs_polarity == SSI_CS_NONE) { |
51 | 66530953 | Peter A. G. Crosthwaite | return ssc->transfer(dev, val);
|
52 | 66530953 | Peter A. G. Crosthwaite | } |
53 | 66530953 | Peter A. G. Crosthwaite | return 0; |
54 | 66530953 | Peter A. G. Crosthwaite | } |
55 | 66530953 | Peter A. G. Crosthwaite | |
56 | d307af79 | Anthony Liguori | static int ssi_slave_init(DeviceState *dev) |
57 | 90d37239 | Paul Brook | { |
58 | cd6c4cf2 | Anthony Liguori | SSISlave *s = SSI_SLAVE(dev); |
59 | cd6c4cf2 | Anthony Liguori | SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); |
60 | 90d37239 | Paul Brook | |
61 | 66530953 | Peter A. G. Crosthwaite | if (ssc->transfer_raw == ssi_transfer_raw_default &&
|
62 | 66530953 | Peter A. G. Crosthwaite | ssc->cs_polarity != SSI_CS_NONE) { |
63 | 66530953 | Peter A. G. Crosthwaite | qdev_init_gpio_in(&s->qdev, ssi_cs_default, 1);
|
64 | 66530953 | Peter A. G. Crosthwaite | } |
65 | 66530953 | Peter A. G. Crosthwaite | |
66 | cd6c4cf2 | Anthony Liguori | return ssc->init(s);
|
67 | 90d37239 | Paul Brook | } |
68 | 90d37239 | Paul Brook | |
69 | 39bffca2 | Anthony Liguori | static void ssi_slave_class_init(ObjectClass *klass, void *data) |
70 | 90d37239 | Paul Brook | { |
71 | 66530953 | Peter A. G. Crosthwaite | SSISlaveClass *ssc = SSI_SLAVE_CLASS(klass); |
72 | 39bffca2 | Anthony Liguori | DeviceClass *dc = DEVICE_CLASS(klass); |
73 | 66530953 | Peter A. G. Crosthwaite | |
74 | 39bffca2 | Anthony Liguori | dc->init = ssi_slave_init; |
75 | 0d936928 | Anthony Liguori | dc->bus_type = TYPE_SSI_BUS; |
76 | 66530953 | Peter A. G. Crosthwaite | if (!ssc->transfer_raw) {
|
77 | 66530953 | Peter A. G. Crosthwaite | ssc->transfer_raw = ssi_transfer_raw_default; |
78 | 66530953 | Peter A. G. Crosthwaite | } |
79 | 90d37239 | Paul Brook | } |
80 | 90d37239 | Paul Brook | |
81 | 8c43a6f0 | Andreas Färber | static const TypeInfo ssi_slave_info = { |
82 | 39bffca2 | Anthony Liguori | .name = TYPE_SSI_SLAVE, |
83 | 39bffca2 | Anthony Liguori | .parent = TYPE_DEVICE, |
84 | 39bffca2 | Anthony Liguori | .class_init = ssi_slave_class_init, |
85 | 39bffca2 | Anthony Liguori | .class_size = sizeof(SSISlaveClass),
|
86 | 39bffca2 | Anthony Liguori | .abstract = true,
|
87 | 39bffca2 | Anthony Liguori | }; |
88 | 39bffca2 | Anthony Liguori | |
89 | 74687e40 | Peter A. G. Crosthwaite | DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name) |
90 | 74687e40 | Peter A. G. Crosthwaite | { |
91 | 74687e40 | Peter A. G. Crosthwaite | return qdev_create(&bus->qbus, name);
|
92 | 74687e40 | Peter A. G. Crosthwaite | } |
93 | 74687e40 | Peter A. G. Crosthwaite | |
94 | 90d37239 | Paul Brook | DeviceState *ssi_create_slave(SSIBus *bus, const char *name) |
95 | 90d37239 | Paul Brook | { |
96 | 74687e40 | Peter A. G. Crosthwaite | DeviceState *dev = ssi_create_slave_no_init(bus, name); |
97 | 74687e40 | Peter A. G. Crosthwaite | |
98 | e23a1b33 | Markus Armbruster | qdev_init_nofail(dev); |
99 | 90d37239 | Paul Brook | return dev;
|
100 | 90d37239 | Paul Brook | } |
101 | 90d37239 | Paul Brook | |
102 | 02e2da45 | Paul Brook | SSIBus *ssi_create_bus(DeviceState *parent, const char *name) |
103 | 90d37239 | Paul Brook | { |
104 | 02e2da45 | Paul Brook | BusState *bus; |
105 | 0d936928 | Anthony Liguori | bus = qbus_create(TYPE_SSI_BUS, parent, name); |
106 | 02e2da45 | Paul Brook | return FROM_QBUS(SSIBus, bus);
|
107 | 90d37239 | Paul Brook | } |
108 | 90d37239 | Paul Brook | |
109 | 90d37239 | Paul Brook | uint32_t ssi_transfer(SSIBus *bus, uint32_t val) |
110 | 90d37239 | Paul Brook | { |
111 | 0866aca1 | Anthony Liguori | BusChild *kid; |
112 | cd6c4cf2 | Anthony Liguori | SSISlaveClass *ssc; |
113 | b4a76e84 | Peter A. G. Crosthwaite | uint32_t r = 0;
|
114 | 0866aca1 | Anthony Liguori | |
115 | b4a76e84 | Peter A. G. Crosthwaite | QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { |
116 | b4a76e84 | Peter A. G. Crosthwaite | SSISlave *slave = SSI_SLAVE(kid->child); |
117 | b4a76e84 | Peter A. G. Crosthwaite | ssc = SSI_SLAVE_GET_CLASS(slave); |
118 | 66530953 | Peter A. G. Crosthwaite | r |= ssc->transfer_raw(slave, val); |
119 | 90d37239 | Paul Brook | } |
120 | b4a76e84 | Peter A. G. Crosthwaite | |
121 | b4a76e84 | Peter A. G. Crosthwaite | return r;
|
122 | 90d37239 | Paul Brook | } |
123 | 39bffca2 | Anthony Liguori | |
124 | 66530953 | Peter A. G. Crosthwaite | const VMStateDescription vmstate_ssi_slave = {
|
125 | 66530953 | Peter A. G. Crosthwaite | .name = "SSISlave",
|
126 | 66530953 | Peter A. G. Crosthwaite | .version_id = 1,
|
127 | 66530953 | Peter A. G. Crosthwaite | .minimum_version_id = 1,
|
128 | 66530953 | Peter A. G. Crosthwaite | .minimum_version_id_old = 1,
|
129 | 66530953 | Peter A. G. Crosthwaite | .fields = (VMStateField[]) { |
130 | 66530953 | Peter A. G. Crosthwaite | VMSTATE_BOOL(cs, SSISlave), |
131 | 66530953 | Peter A. G. Crosthwaite | VMSTATE_END_OF_LIST() |
132 | 66530953 | Peter A. G. Crosthwaite | } |
133 | 66530953 | Peter A. G. Crosthwaite | }; |
134 | 66530953 | Peter A. G. Crosthwaite | |
135 | 83f7d43a | Andreas Färber | static void ssi_slave_register_types(void) |
136 | 39bffca2 | Anthony Liguori | { |
137 | 0d936928 | Anthony Liguori | type_register_static(&ssi_bus_info); |
138 | 39bffca2 | Anthony Liguori | type_register_static(&ssi_slave_info); |
139 | 39bffca2 | Anthony Liguori | } |
140 | 39bffca2 | Anthony Liguori | |
141 | 83f7d43a | Andreas Färber | type_init(ssi_slave_register_types) |
142 | b4ae3cfa | Peter Crosthwaite | |
143 | b4ae3cfa | Peter Crosthwaite | typedef struct SSIAutoConnectArg { |
144 | b4ae3cfa | Peter Crosthwaite | qemu_irq **cs_linep; |
145 | b4ae3cfa | Peter Crosthwaite | SSIBus *bus; |
146 | b4ae3cfa | Peter Crosthwaite | } SSIAutoConnectArg; |
147 | b4ae3cfa | Peter Crosthwaite | |
148 | b4ae3cfa | Peter Crosthwaite | static int ssi_auto_connect_slave(Object *child, void *opaque) |
149 | b4ae3cfa | Peter Crosthwaite | { |
150 | b4ae3cfa | Peter Crosthwaite | SSIAutoConnectArg *arg = opaque; |
151 | b4ae3cfa | Peter Crosthwaite | SSISlave *dev = (SSISlave *)object_dynamic_cast(child, TYPE_SSI_SLAVE); |
152 | b4ae3cfa | Peter Crosthwaite | qemu_irq cs_line; |
153 | b4ae3cfa | Peter Crosthwaite | |
154 | b4ae3cfa | Peter Crosthwaite | if (!dev) {
|
155 | b4ae3cfa | Peter Crosthwaite | return 0; |
156 | b4ae3cfa | Peter Crosthwaite | } |
157 | b4ae3cfa | Peter Crosthwaite | |
158 | b4ae3cfa | Peter Crosthwaite | cs_line = qdev_get_gpio_in(DEVICE(dev), 0);
|
159 | b4ae3cfa | Peter Crosthwaite | qdev_set_parent_bus(DEVICE(dev), &arg->bus->qbus); |
160 | b4ae3cfa | Peter Crosthwaite | **arg->cs_linep = cs_line; |
161 | b4ae3cfa | Peter Crosthwaite | (*arg->cs_linep)++; |
162 | b4ae3cfa | Peter Crosthwaite | return 0; |
163 | b4ae3cfa | Peter Crosthwaite | } |
164 | b4ae3cfa | Peter Crosthwaite | |
165 | b4ae3cfa | Peter Crosthwaite | void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_line,
|
166 | b4ae3cfa | Peter Crosthwaite | SSIBus *bus) |
167 | b4ae3cfa | Peter Crosthwaite | { |
168 | b4ae3cfa | Peter Crosthwaite | SSIAutoConnectArg arg = { |
169 | b4ae3cfa | Peter Crosthwaite | .cs_linep = &cs_line, |
170 | b4ae3cfa | Peter Crosthwaite | .bus = bus |
171 | b4ae3cfa | Peter Crosthwaite | }; |
172 | b4ae3cfa | Peter Crosthwaite | |
173 | b4ae3cfa | Peter Crosthwaite | object_child_foreach(OBJECT(parent), ssi_auto_connect_slave, &arg); |
174 | b4ae3cfa | Peter Crosthwaite | } |