2 * QEMU Synchronous Serial Interface support
4 * Copyright (c) 2009 CodeSourcery.
5 * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
6 * Copyright (c) 2012 PetaLogix Pty Ltd.
7 * Written by Paul Brook
9 * This code is licensed under the GNU GPL v2.
11 * Contributions after 2012-01-13 are licensed under the terms of the
12 * GNU GPL, version 2 or (at your option) any later version.
15 #include "qemu/osdep.h"
16 #include "hw/qdev-properties.h"
17 #include "hw/ssi/ssi.h"
18 #include "migration/vmstate.h"
19 #include "qemu/module.h"
20 #include "qapi/error.h"
21 #include "qom/object.h"
27 #define TYPE_SSI_BUS "SSI"
28 OBJECT_DECLARE_SIMPLE_TYPE(SSIBus
, SSI_BUS
)
30 DeviceState
*ssi_get_cs(SSIBus
*bus
, uint8_t cs_index
)
32 BusState
*b
= BUS(bus
);
35 QTAILQ_FOREACH(kid
, &b
->children
, sibling
) {
36 SSIPeripheral
*kid_ssi
= SSI_PERIPHERAL(kid
->child
);
37 if (kid_ssi
->cs_index
== cs_index
) {
45 static const TypeInfo ssi_bus_info
= {
48 .instance_size
= sizeof(SSIBus
),
51 static void ssi_cs_default(void *opaque
, int n
, int level
)
53 SSIPeripheral
*s
= SSI_PERIPHERAL(opaque
);
58 s
->spc
->set_cs(s
, cs
);
64 static uint32_t ssi_transfer_raw_default(SSIPeripheral
*dev
, uint32_t val
)
66 SSIPeripheralClass
*ssc
= dev
->spc
;
68 if ((dev
->cs
&& ssc
->cs_polarity
== SSI_CS_HIGH
) ||
69 (!dev
->cs
&& ssc
->cs_polarity
== SSI_CS_LOW
) ||
70 ssc
->cs_polarity
== SSI_CS_NONE
) {
71 return ssc
->transfer(dev
, val
);
76 static void ssi_peripheral_realize(DeviceState
*dev
, Error
**errp
)
78 SSIPeripheral
*s
= SSI_PERIPHERAL(dev
);
79 SSIPeripheralClass
*ssc
= SSI_PERIPHERAL_GET_CLASS(s
);
81 if (ssc
->transfer_raw
== ssi_transfer_raw_default
&&
82 ssc
->cs_polarity
!= SSI_CS_NONE
) {
83 qdev_init_gpio_in_named(dev
, ssi_cs_default
, SSI_GPIO_CS
, 1);
87 ssc
->realize(s
, errp
);
90 static Property ssi_peripheral_properties
[] = {
91 DEFINE_PROP_UINT8("cs", SSIPeripheral
, cs_index
, 0),
92 DEFINE_PROP_END_OF_LIST(),
95 static void ssi_peripheral_class_init(ObjectClass
*klass
, void *data
)
97 SSIPeripheralClass
*ssc
= SSI_PERIPHERAL_CLASS(klass
);
98 DeviceClass
*dc
= DEVICE_CLASS(klass
);
100 dc
->realize
= ssi_peripheral_realize
;
101 dc
->bus_type
= TYPE_SSI_BUS
;
102 if (!ssc
->transfer_raw
) {
103 ssc
->transfer_raw
= ssi_transfer_raw_default
;
105 device_class_set_props(dc
, ssi_peripheral_properties
);
108 static const TypeInfo ssi_peripheral_info
= {
109 .name
= TYPE_SSI_PERIPHERAL
,
110 .parent
= TYPE_DEVICE
,
111 .class_init
= ssi_peripheral_class_init
,
112 .class_size
= sizeof(SSIPeripheralClass
),
116 bool ssi_realize_and_unref(DeviceState
*dev
, SSIBus
*bus
, Error
**errp
)
118 return qdev_realize_and_unref(dev
, &bus
->parent_obj
, errp
);
121 DeviceState
*ssi_create_peripheral(SSIBus
*bus
, const char *name
)
123 DeviceState
*dev
= qdev_new(name
);
125 ssi_realize_and_unref(dev
, bus
, &error_fatal
);
129 SSIBus
*ssi_create_bus(DeviceState
*parent
, const char *name
)
132 bus
= qbus_new(TYPE_SSI_BUS
, parent
, name
);
136 uint32_t ssi_transfer(SSIBus
*bus
, uint32_t val
)
138 BusState
*b
= BUS(bus
);
142 QTAILQ_FOREACH(kid
, &b
->children
, sibling
) {
143 SSIPeripheral
*p
= SSI_PERIPHERAL(kid
->child
);
144 r
|= p
->spc
->transfer_raw(p
, val
);
150 const VMStateDescription vmstate_ssi_peripheral
= {
153 .minimum_version_id
= 1,
154 .fields
= (VMStateField
[]) {
155 VMSTATE_BOOL(cs
, SSIPeripheral
),
156 VMSTATE_END_OF_LIST()
160 static void ssi_peripheral_register_types(void)
162 type_register_static(&ssi_bus_info
);
163 type_register_static(&ssi_peripheral_info
);
166 type_init(ssi_peripheral_register_types
)