@@ -109,3 +109,4 @@ CONFIG_IOH3420=y
CONFIG_I82801B11=y
CONFIG_ACPI=y
CONFIG_SMBIOS=y
+CONFIG_SDM=y
@@ -21,6 +21,10 @@ common-obj-$(CONFIG_MACIO) += macio/
obj-$(CONFIG_IVSHMEM) += ivshmem.o
+obj-$(CONFIG_SDM) += sdm-device.o
+obj-$(CONFIG_SDM) += sdm-communication.o
+obj-$(CONFIG_SDM) += sdm-signal.o
+
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
obj-$(CONFIG_NSERIES) += cbus.o
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
new file mode 100644
@@ -0,0 +1,68 @@
+/*
+ * SDM Communication
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ * Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "hw/misc/sdm-communication.h"
+#include "qom/object_interfaces.h"
+
+int sdm_communication_signal(SDMCommunication *sdmc, SDMDevice *sdm,
+ SDMSignalData *signal)
+{
+ SDMCommunicationClass *sdmck = SDM_COMMUNICATION_GET_CLASS(sdmc);
+
+ if (sdmck->signal) {
+ return sdmck->signal(sdmc, sdm, signal);
+ } else {
+ return -1;
+ }
+}
+
+int sdm_communication_connect(SDMCommunication *sdmc, SDMDevice *sdm)
+{
+ SDMCommunicationClass *sdmck = SDM_COMMUNICATION_GET_CLASS(sdmc);
+
+ if (sdmck->connect) {
+ return sdmck->connect(sdmc, sdm);
+ } else {
+ return -1;
+ }
+}
+
+int sdm_communication_update_num_slaves(SDMCommunication *sdmc, SDMDevice *sdm,
+ uint16_t num_slaves)
+{
+ SDMCommunicationClass *sdmck = SDM_COMMUNICATION_GET_CLASS(sdmc);
+
+ if (sdmck->update_num_slaves) {
+ return sdmck->update_num_slaves(sdmc, sdm, num_slaves);
+ } else {
+ return -1;
+ }
+}
+
+static const TypeInfo sdm_communication_info = {
+ .name = TYPE_SDM_COMMUNICATION,
+ .parent = TYPE_OBJECT,
+ .abstract = true,
+ .class_size = sizeof(SDMCommunicationClass),
+ .instance_size = sizeof(SDMCommunication),
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+static void register_types(void)
+{
+ type_register_static(&sdm_communication_info);
+}
+
+type_init(register_types);
new file mode 100644
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ * Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include "hw/misc/sdm-device.h"
+
+int sdm_device_notify(SDMDevice *sdm, SDMSignalData *signal)
+{
+ SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+ if (sdmc->notify) {
+ return sdmc->notify(sdm, signal);
+ } else {
+ return -1;
+ }
+}
+
+int sdm_device_accept(SDMDevice *sdm)
+{
+ SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+ if (sdmc->accept) {
+ return sdmc->accept(sdm);
+ } else {
+ return -1;
+ }
+}
+
+int sdm_device_get_num_slaves(SDMDevice *sdm)
+{
+ SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+ if (sdmc->get_num_slaves) {
+ return sdmc->get_num_slaves(sdm);
+ } else {
+ return 0;
+ }
+}
+
+int sdm_device_set_num_slaves(SDMDevice *sdm, uint16_t num_slaves)
+{
+ SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+ if (sdmc->set_num_slaves) {
+ return sdmc->set_num_slaves(sdm, num_slaves);
+ } else {
+ return 0;
+ }
+}
+
+bool sdm_device_is_master(SDMDevice *sdm)
+{
+ SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+ if (sdmc->is_master) {
+ return sdmc->is_master(sdm);
+ } else {
+ return false;
+ }
+}
+
+static void register_types(void)
+{
+ static const TypeInfo sdm_device_info = {
+ .name = TYPE_SDM_DEVICE,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(SDMDeviceClass),
+ };
+
+ type_register_static(&sdm_device_info);
+}
+
+type_init(register_types)
new file mode 100644
@@ -0,0 +1,51 @@
+/*
+ * SDM Signal
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include "hw/misc/sdm-signal.h"
+#include "qom/object_interfaces.h"
+
+int sdm_signal_hw_ops(SDMSignal *signal, SDMSignalData *data) {
+ SDMSignalClass *signalc = SDM_SIGNAL_GET_CLASS(signal);
+
+ if (signalc->hw_ops) {
+ return signalc->hw_ops(signal, data);
+ } else {
+ return 0;
+ }
+}
+
+bool sdm_signal_hw_only(SDMSignal *signal)
+{
+ SDMSignalClass *signalc = SDM_SIGNAL_GET_CLASS(signal);
+
+ if (signalc->hw_only) {
+ return signalc->hw_only(signal);
+ } else {
+ return false;
+ }
+}
+
+static const TypeInfo sdm_signal_info = {
+ .name = TYPE_SDM_SIGNAL,
+ .parent = TYPE_OBJECT,
+ .class_size = sizeof(SDMSignalClass),
+ .instance_size = sizeof(SDMSignal),
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+static void register_types(void)
+{
+ type_register_static(&sdm_signal_info);
+}
+
+type_init(register_types);
new file mode 100644
@@ -0,0 +1,60 @@
+/*
+ * SDM Communication
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ * Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef HW_SDM_COMM_H
+#define HW_SDM_COMM_H
+
+#include "hw/misc/sdm-device.h"
+
+#define TYPE_SDM_COMMUNICATION "sdm-communication"
+#define SDM_COMMUNICATION(obj) \
+ OBJECT_CHECK(SDMCommunication, (obj), TYPE_SDM_COMMUNICATION)
+#define SDM_COMMUNICATION_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SDMCommunicationClass, (obj), TYPE_SDM_COMMUNICATION)
+#define SDM_COMMUNICATION_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SDMCommunicationClass, (klass), \
+ TYPE_SDM_COMMUNICATION);
+
+typedef struct SDMCommunication SDMCommunication;
+typedef struct SDMCommunicationClass SDMCommunicationClass;
+
+/**
+ * @SDMCommunicationClass
+ *
+ * @parent_class: opaque parent class container
+ */
+struct SDMCommunicationClass {
+ ObjectClass parent_class;
+
+ int (*signal)(SDMCommunication *sdmc, SDMDevice *sdm,
+ SDMSignalData *signal);
+ int (*connect)(SDMCommunication *sdmc, SDMDevice *sdm);
+ int (*update_num_slaves)(SDMCommunication *sdmc, SDMDevice *sdm,
+ uint16_t num_slaves);
+};
+
+/**
+ * @SDMCommunication
+ *
+ * @parent: opaque parent object container
+ */
+struct SDMCommunication {
+ /* private */
+ Object parent;
+};
+
+int sdm_communication_signal(SDMCommunication *sdmc, SDMDevice *sdm,
+ SDMSignalData *signal);
+int sdm_communication_connect(SDMCommunication *sdmc, SDMDevice *sdm);
+int sdm_communication_update_num_slaves(SDMCommunication *sdmc,
+ SDMDevice *sdm, uint16_t num_slaves);
+
+#endif
new file mode 100644
@@ -0,0 +1,61 @@
+/*
+ * SDM Device
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ * Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef HW_SDM_H
+#define HW_SDM_H
+
+#include "qemu-common.h"
+#include "qom/object.h"
+#include "hw/misc/sdm-signal.h"
+
+#define TYPE_SDM_DEVICE "sdm-device"
+#define SDM_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SDMDeviceClass, (klass), TYPE_SDM_DEVICE);
+#define SDM_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SDMDeviceClass, (obj), TYPE_SDM_DEVICE)
+#define SDM_DEVICE(obj) \
+ INTERFACE_CHECK(SDMDevice, (obj), TYPE_SDM_DEVICE)
+
+typedef struct SDMDevice SDMDevice;
+typedef struct SDMDeviceClass SDMDeviceClass;
+
+/**
+ * SDMDeviceClass
+ *
+ * @parent_class: opaque parent class container
+ */
+struct SDMDeviceClass {
+ InterfaceClass parent_class;
+
+ int (**signal_hw_ops)(SDMDevice *sdm, SDMSignalData *signal);
+
+ /* Notify the device about a new signal. If the signal cannot
+ * be handled by device (busy), returns -1. The communication
+ * channel should then try to deliver the signal again later.
+ */
+ int (*notify)(SDMDevice *sdm, SDMSignalData *signal);
+ int (*accept)(SDMDevice *sdm);
+ int (*get_num_slaves)(SDMDevice *sdm);
+ int (*set_num_slaves)(SDMDevice *sdm, uint16_t num_slaves);
+ bool (*is_master)(SDMDevice *sdm);
+};
+
+struct SDMDevice {
+ /* private */
+ Object parent;
+};
+
+int sdm_device_notify(SDMDevice *sdm, SDMSignalData *signal);
+int sdm_device_accept(SDMDevice *sdm);
+int sdm_device_get_num_slaves(SDMDevice *sdm);
+int sdm_device_set_num_slaves(SDMDevice *sdm, uint16_t num_slaves);
+bool sdm_device_is_master(SDMDevice *sdm);
+#endif
new file mode 100644
@@ -0,0 +1,60 @@
+/*
+ * SDM Signal
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef HW_SDM_SIGNAL_H
+#define HW_SDM_SIGNAL_H
+
+#include "qemu-common.h"
+#include "qom/object.h"
+
+#define TYPE_SDM_SIGNAL "sdm-signal"
+#define SDM_SIGNAL(obj) \
+ OBJECT_CHECK(SDMSignal, (obj), TYPE_SDM_SIGNAL)
+#define SDM_SIGNAL_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SDMSignalClass, (obj), TYPE_SDM_SIGNAL)
+#define SDM_SIGNAL_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SDMSignalClass, (klass), \
+ TYPE_SDM_SIGNAL)
+
+typedef struct SDMSignalData SDMSignalData;
+typedef struct SDMSignal SDMSignal;
+typedef struct SDMSignalClass SDMSignalClass;
+
+struct SDMSignalData {
+ uint32_t type;
+ uint32_t slave;
+ uint32_t payload[2];
+};
+
+/**
+ * @SDMSignalClass
+ *
+ * @parent_class: opaque parent class container
+ */
+struct SDMSignalClass {
+ ObjectClass parent_class;
+
+ int (*hw_ops)(SDMSignal *signal, SDMSignalData *data);
+ bool (*hw_only)(SDMSignal *signal);
+};
+
+/**
+ * @SDMSignal
+ *
+ * @parent: opaque parent object container
+ */
+struct SDMSignal {
+ /* private */
+ Object parent;
+};
+
+int sdm_signal_hw_ops(SDMSignal *signal, SDMSignalData *data);
+bool sdm_signal_hw_only(SDMSignal *signal);
+#endif