common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / spi / zynq_spi.c
index 6ed2165355785e8be5240bb89b0a2d019fff12c1..e3bad5532a540162099fc04a2b13a4d6fa6f3e12 100644 (file)
@@ -1,17 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2013 Xilinx, Inc.
  * (C) Copyright 2015 Jagan Teki <jteki@openedev.com>
  *
  * Xilinx Zynq PS SPI controller driver (master mode only)
- *
- * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <common.h>
 #include <dm.h>
+#include <log.h>
 #include <malloc.h>
 #include <spi.h>
+#include <time.h>
 #include <asm/io.h>
+#include <linux/delay.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -56,6 +58,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 +67,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 */
 };
@@ -71,13 +76,17 @@ static int zynq_spi_ofdata_to_platdata(struct udevice *bus)
 {
        struct zynq_spi_platdata *plat = bus->platdata;
        const void *blob = gd->fdt_blob;
-       int node = bus->of_offset;
+       int node = dev_of_offset(bus);
 
-       plat->regs = (struct zynq_spi_regs *)dev_get_addr(bus);
+       plat->regs = (struct zynq_spi_regs *)devfdt_get_addr(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__,
@@ -92,7 +101,8 @@ static void zynq_spi_init_hw(struct zynq_spi_priv *priv)
        u32 confr;
 
        /* Disable SPI */
-       writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
+       confr = ZYNQ_SPI_ENR_SPI_EN_MASK;
+       writel(~confr, &regs->enr);
 
        /* Disable Interrupts */
        writel(ZYNQ_SPI_IXR_ALL_MASK, &regs->idr);
@@ -132,10 +142,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);
        /*
@@ -146,15 +165,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)
@@ -173,8 +200,10 @@ static int zynq_spi_release_bus(struct udevice *dev)
        struct udevice *bus = dev->parent;
        struct zynq_spi_priv *priv = dev_get_priv(bus);
        struct zynq_spi_regs *regs = priv->regs;
+       u32 confr;
 
-       writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
+       confr = ZYNQ_SPI_ENR_SPI_EN_MASK;
+       writel(~confr, &regs->enr);
 
        return 0;
 }
@@ -230,7 +259,7 @@ static int zynq_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
                /* Read the data from RX FIFO */
                status = readl(&regs->isr);
-               while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) {
+               while ((status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) && rx_len) {
                        buf = readl(&regs->rxdr);
                        if (rx_buf)
                                *rx_buf++ = buf;
@@ -313,6 +342,7 @@ static const struct dm_spi_ops zynq_spi_ops = {
 
 static const struct udevice_id zynq_spi_ids[] = {
        { .compatible = "xlnx,zynq-spi-r1p6" },
+       { .compatible = "cdns,spi-r1p6" },
        { }
 };