]> git.sur5r.net Git - u-boot/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-spi
authorTom Rini <trini@konsulko.com>
Fri, 5 May 2017 20:45:30 +0000 (16:45 -0400)
committerTom Rini <trini@konsulko.com>
Fri, 5 May 2017 20:45:30 +0000 (16:45 -0400)
drivers/spi/atmel_spi.c
drivers/spi/omap3_spi.c
drivers/spi/zynq_spi.c

index 76491142318342da1c7cf222fac7fe531230c5a4..4701b79f161f46b38c1cd39c4580e91248e08740 100644 (file)
@@ -296,6 +296,9 @@ static void atmel_spi_cs_activate(struct udevice *dev)
        struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
        u32 cs = slave_plat->cs;
 
+       if (!dm_gpio_is_valid(&priv->cs_gpios[cs]))
+               return;
+
        dm_gpio_set_value(&priv->cs_gpios[cs], 0);
 }
 
@@ -306,6 +309,9 @@ static void atmel_spi_cs_deactivate(struct udevice *dev)
        struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
        u32 cs = slave_plat->cs;
 
+       if (!dm_gpio_is_valid(&priv->cs_gpios[cs]))
+               return;
+
        dm_gpio_set_value(&priv->cs_gpios[cs], 1);
 }
 
@@ -473,6 +479,9 @@ static int atmel_spi_probe(struct udevice *bus)
        }
 
        for(i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) {
+               if (!dm_gpio_is_valid(&priv->cs_gpios[i]))
+                       continue;
+
                dm_gpio_set_dir_flags(&priv->cs_gpios[i],
                                      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
        }
index 8a8945010973c54c09f5eac4532354315ee6f3bc..76d376ac44500eebc7b201f463ba0ee55259fb61 100644 (file)
@@ -692,6 +692,5 @@ U_BOOT_DRIVER(omap3_spi) = {
        .probe = omap3_spi_probe,
        .ops    = &omap3_spi_ops,
        .priv_auto_alloc_size = sizeof(struct omap3_spi_priv),
-       .probe = omap3_spi_probe,
 };
 #endif
index 5a9b1f0f2ee4cc369c1da3b1b655ae7e5d7f540d..2b77f1ccdcf6f16e10b9ee16061cd5400b4acbce 100644 (file)
@@ -56,6 +56,8 @@ struct zynq_spi_platdata {
        struct zynq_spi_regs *regs;
        u32 frequency;          /* input frequency */
        u32 speed_hz;
+       uint deactivate_delay_us;       /* Delay to wait after deactivate */
+       uint activate_delay_us;         /* Delay to wait after activate */
 };
 
 /* zynq spi priv */
@@ -63,6 +65,7 @@ struct zynq_spi_priv {
        struct zynq_spi_regs *regs;
        u8 cs;
        u8 mode;
+       ulong last_transaction_us;      /* Time of last transaction end */
        u8 fifo_depth;
        u32 freq;               /* required frequency */
 };
@@ -78,6 +81,10 @@ static int zynq_spi_ofdata_to_platdata(struct udevice *bus)
        /* FIXME: Use 250MHz as a suitable default */
        plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
                                        250000000);
+       plat->deactivate_delay_us = fdtdec_get_int(blob, node,
+                                       "spi-deactivate-delay", 0);
+       plat->activate_delay_us = fdtdec_get_int(blob, node,
+                                                "spi-activate-delay", 0);
        plat->speed_hz = plat->frequency / 2;
 
        debug("%s: regs=%p max-frequency=%d\n", __func__,
@@ -133,10 +140,19 @@ static int zynq_spi_probe(struct udevice *bus)
 static void spi_cs_activate(struct udevice *dev)
 {
        struct udevice *bus = dev->parent;
+       struct zynq_spi_platdata *plat = bus->platdata;
        struct zynq_spi_priv *priv = dev_get_priv(bus);
        struct zynq_spi_regs *regs = priv->regs;
        u32 cr;
 
+       /* If it's too soon to do another transaction, wait */
+       if (plat->deactivate_delay_us && priv->last_transaction_us) {
+               ulong delay_us;         /* The delay completed so far */
+               delay_us = timer_get_us() - priv->last_transaction_us;
+               if (delay_us < plat->deactivate_delay_us)
+                       udelay(plat->deactivate_delay_us - delay_us);
+       }
+
        clrbits_le32(&regs->cr, ZYNQ_SPI_CR_CS_MASK);
        cr = readl(&regs->cr);
        /*
@@ -147,15 +163,23 @@ static void spi_cs_activate(struct udevice *dev)
         */
        cr |= (~(1 << priv->cs) << ZYNQ_SPI_CR_SS_SHIFT) & ZYNQ_SPI_CR_CS_MASK;
        writel(cr, &regs->cr);
+
+       if (plat->activate_delay_us)
+               udelay(plat->activate_delay_us);
 }
 
 static void spi_cs_deactivate(struct udevice *dev)
 {
        struct udevice *bus = dev->parent;
+       struct zynq_spi_platdata *plat = bus->platdata;
        struct zynq_spi_priv *priv = dev_get_priv(bus);
        struct zynq_spi_regs *regs = priv->regs;
 
        setbits_le32(&regs->cr, ZYNQ_SPI_CR_CS_MASK);
+
+       /* Remember time of this transaction so we can honour the bus delay */
+       if (plat->deactivate_delay_us)
+               priv->last_transaction_us = timer_get_us();
 }
 
 static int zynq_spi_claim_bus(struct udevice *dev)