Added helper function to automatically connect SPI slaves based on the QOM child
nodes of a device. A SSI master device can call this routine to automatically
hook-up all child nodes to its SPI bus.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
Acked-by: Peter Maydell <peter.mayd...@linaro.org>
---

 hw/ssi.c          |   33 +++++++++++++++++++++++++++++++++
 hw/ssi.h          |    4 ++++
 hw/xilinx_spi.c   |    6 ++++--
 hw/xilinx_spips.c |    4 +++-
 4 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/hw/ssi.c b/hw/ssi.c
index c47419d..2b56357 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -139,3 +139,36 @@ static void ssi_slave_register_types(void)
 }
 
 type_init(ssi_slave_register_types)
+
+typedef struct SSIAutoConnectArg {
+    qemu_irq **cs_linep;
+    SSIBus *bus;
+} SSIAutoConnectArg;
+
+static int ssi_auto_connect_slave(Object *child, void *opaque)
+{
+    SSIAutoConnectArg *arg = opaque;
+    SSISlave *dev = (SSISlave *)object_dynamic_cast(child, TYPE_SSI_SLAVE);
+    qemu_irq cs_line;
+
+    if (!dev) {
+        return 0;
+    }
+
+    cs_line = qdev_get_gpio_in(DEVICE(dev), 0);
+    qdev_set_parent_bus(DEVICE(dev), &arg->bus->qbus);
+    **arg->cs_linep = cs_line;
+    (*arg->cs_linep)++;
+    return 0;
+}
+
+void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_line,
+                             SSIBus *bus)
+{
+    SSIAutoConnectArg arg = {
+        .cs_linep = &cs_line,
+        .bus = bus
+    };
+
+    object_child_foreach(OBJECT(parent), ssi_auto_connect_slave, &arg);
+}
diff --git a/hw/ssi.h b/hw/ssi.h
index 2bde9f5..a05d60b 100644
--- a/hw/ssi.h
+++ b/hw/ssi.h
@@ -83,6 +83,10 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char 
*name);
 
 uint32_t ssi_transfer(SSIBus *bus, uint32_t val);
 
+/* Automatically connect all children nodes a spi controller as slaves */
+void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_lines,
+                             SSIBus *bus);
+
 /* max111x.c */
 void max111x_set_input(DeviceState *dev, int line, uint8_t value);
 
diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c
index 7db4787..5cdf967 100644
--- a/hw/xilinx_spi.c
+++ b/hw/xilinx_spi.c
@@ -320,8 +320,12 @@ static int xilinx_spi_init(SysBusDevice *dev)
     XilinxSPI *s = FROM_SYSBUS(typeof(*s), dev);
 
     DB_PRINT("\n");
+
+    s->spi = ssi_create_bus(&dev->qdev, "spi");
+
     sysbus_init_irq(dev, &s->irq);
     s->cs_lines = g_new(qemu_irq, s->num_cs);
+    ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi);
     for (i = 0; i < s->num_cs; ++i) {
         sysbus_init_irq(dev, &s->cs_lines[i]);
     }
@@ -331,8 +335,6 @@ static int xilinx_spi_init(SysBusDevice *dev)
 
     s->irqline = -1;
 
-    s->spi = ssi_create_bus(&dev->qdev, "spi");
-
     fifo8_create(&s->tx_fifo, FIFO_CAPACITY);
     fifo8_create(&s->rx_fifo, FIFO_CAPACITY);
 
diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index a886c5d..f64a782 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -289,6 +289,9 @@ static int xilinx_spips_init(SysBusDevice *dev)
 
     DB_PRINT("inited device model\n");
 
+    s->spi = ssi_create_bus(&dev->qdev, "spi");
+
+    ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi);
     sysbus_init_irq(dev, &s->irq);
     for (i = 0; i < NUM_CS_LINES; ++i) {
         sysbus_init_irq(dev, &s->cs_lines[i]);
@@ -298,7 +301,6 @@ static int xilinx_spips_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->iomem);
 
     s->irqline = -1;
-    s->spi = ssi_create_bus(&dev->qdev, "spi");
 
     fifo8_create(&s->rx_fifo, RXFF_A);
     fifo8_create(&s->tx_fifo, TXFF_A);
-- 
1.7.0.4


Reply via email to