[PATCH] spi: imx: Respect delay_us

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Make the driver respect the set delay between transfers. It will
pre-calculate the maximum delay for the set of requested transfers
and use that between each transfer. The reference manual is
unclear on what happens if you change the period registry
mid stream.

Signed-off-by: Joakim Plate <joakim.plate@xxxxxxxxxxx>
---
 drivers/spi/spi-imx.c | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index b2dd0a4d2446..03a2986c7246 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
+#include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
@@ -97,6 +98,7 @@ struct spi_imx_data {
 	struct clk *clk_ipg;
 	unsigned long spi_clk;
 	unsigned int spi_bus_clk;
+	unsigned int delay_usecs;
 
 	unsigned int bits_per_word;
 	unsigned int spi_drctl;
@@ -283,6 +285,11 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 #define MX51_ECSPI_STAT		0x18
 #define MX51_ECSPI_STAT_RR		(1 <<  3)
 
+#define MX51_ECSPI_PERIODREG	0x1C
+#define MX51_ECSPI_PERIODREG_SAMPLEPERIOD(period)	((period) & 0x7FFF)
+#define MX51_ECSPI_PERIODREG_CSRC			BIT(15)
+#define MX51_ECSPI_PERIODREG_CSD(csd)			(((csd) & 0x3f) << 16)
+
 #define MX51_ECSPI_TESTREG	0x20
 #define MX51_ECSPI_TESTREG_LBC	BIT(31)
 
@@ -513,7 +520,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
 	struct spi_transfer *xfer;
 	u32 ctrl = MX51_ECSPI_CTRL_ENABLE;
 	u32 min_speed_hz = ~0U;
-	u32 testreg, delay;
+	u32 testreg, delay, delay_usecs = 0;
 	u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
 
 	/* set Master or Slave mode */
@@ -574,6 +581,15 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
 
 	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
+
+	/*
+	 * Store maximum transfers delay to avoid changing in burst
+	 */
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		if (xfer->delay_usecs > delay_usecs)
+			delay_usecs = xfer->delay_usecs;
+	}
+
 	/*
 	 * Wait until the changes in the configuration register CONFIGREG
 	 * propagate into the hardware. It takes exactly one tick of the
@@ -611,6 +627,9 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
 {
 	u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
 	u32 clk;
+	u32 period = 0;
+	u64 ticks;
+
 
 	/* Clear BL field and set the right value */
 	ctrl &= ~MX51_ECSPI_CTRL_BL_MASK;
@@ -627,6 +646,17 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
 	ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->spi_bus_clk, &clk);
 	spi_imx->spi_bus_clk = clk;
 
+	/* set sample rate */
+	ticks = mul_u64_u32_div(spi_imx->delay_usecs, clk, 1000000);
+	if (ticks <= 0x7FFF) {
+		period |= MX51_ECSPI_PERIODREG_SAMPLEPERIOD(ticks);
+	} else {
+		ticks = mul_u64_u32_div(spi_imx->delay_usecs, 32768, 1000000);
+		period |= MX51_ECSPI_PERIODREG_SAMPLEPERIOD(ticks);
+		period |= MX51_ECSPI_PERIODREG_CSRC;
+	}
+	writel(period, spi_imx->base + MX51_ECSPI_PERIODREG);
+
 	/*
 	 * ERR009165: work in XHC mode instead of SMC as PIO on the chips
 	 * before i.mx6ul.
-- 
2.25.1




[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux