ssi: Add slave autoconnect helper
authorPeter Crosthwaite <peter.crosthwaite@xilinx.com>
Mon, 1 Oct 2012 02:34:37 +0000 (12:34 +1000)
committerPeter Crosthwaite <peter.crosthwaite@xilinx.com>
Wed, 10 Oct 2012 01:13:32 +0000 (11:13 +1000)
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.crosthwaite@xilinx.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
hw/ssi.c
hw/ssi.h
hw/xilinx_spi.c
hw/xilinx_spips.c

index c47419d57fdb29d573dfcdb392c6ba46350ac191..2b56357153628cd8e96ce1d89ae7bb0e0c6eee8d 100644 (file)
--- 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);
+}
index 2bde9f5b44bcae5011fdbcbd3fd0892bf7503603..a05d60beb4ad6e5a394ff864fd2230bb93da6620 100644 (file)
--- 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);
 
index 7db47877e24fdcd43f2f1a51b455a8c769bd2ddb..5cdf967c20be0f1444379d4844df1ee64d500918 100644 (file)
@@ -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);
 
index a886c5d311ccb2a2850c3c04809d3def84d756cf..f64a7828fee84448fcac819fd83e334b15be2d89 100644 (file)
@@ -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);