@@ -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.
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@rt-labs.com> --- drivers/spi/spi-imx.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-)