[U-Boot] [PATCH] zynq: spi: Honour the activation / deactivation delay

Moritz Fischer moritz.fischer at ettus.com
Thu Dec 8 21:11:09 CET 2016


This is not currently implemented. Add support for this so that the
Chrome OS EC can be used reliably.

Signed-off-by: Moritz Fischer <moritz.fischer at ettus.com>
Cc: Jagan Teki <jagan at openedev.com>
Cc: Simon Glass <sjg at chromium.org>
Cc: u-boot at lists.denx.de
---
 drivers/spi/zynq_spi.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index 15ca271..5e7954c 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -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)
-- 
2.7.4



More information about the U-Boot mailing list