Merge https://gitlab.denx.de/u-boot/custodians/u-boot-fsl-qoriq
[platform/kernel/u-boot.git] / drivers / spi / fsl_dspi.c
index 887edd8..b22c9b3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2000-2003
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
@@ -6,12 +7,14 @@
  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
  * Chao Fu (B44548@freescale.com)
  * Haikun Wang (B53464@freescale.com)
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
+
+#include <linux/math64.h>
+#include <common.h>
 #include <dm.h>
 #include <errno.h>
 #include <common.h>
+#include <log.h>
 #include <spi.h>
 #include <malloc.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #endif
 #include <fsl_dspi.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+
+/* linux/include/time.h */
+#define NSEC_PER_SEC   1000000000L
 
 DECLARE_GLOBAL_DATA_PTR;
 
 /* fsl_dspi_platdata flags */
-#define DSPI_FLAG_REGMAP_ENDIAN_BIG    (1 << 0)
+#define DSPI_FLAG_REGMAP_ENDIAN_BIG    BIT(0)
 
 /* idle data value */
 #define DSPI_IDLE_VAL                  0x0
@@ -96,13 +104,6 @@ struct fsl_dspi_priv {
        struct dspi *regs;
 };
 
-#ifndef CONFIG_DM_SPI
-struct fsl_dspi {
-       struct spi_slave slave;
-       struct fsl_dspi_priv priv;
-};
-#endif
-
 __weak void cpu_dspi_port_conf(void)
 {
 }
@@ -272,7 +273,18 @@ static int dspi_xfer(struct fsl_dspi_priv *priv, uint cs, unsigned int bitlen,
        if (len > 1) {
                int tmp_len = len - 1;
                while (tmp_len--) {
-                       if (dout != NULL) {
+                       if ((dout != NULL) && (din != NULL)) {
+                               if (priv->charbit == 16) {
+                                       dspi_tx(priv, ctrl, *spi_wr16++);
+                                       *spi_rd16++ = dspi_rx(priv);
+                               }
+                               else {
+                                       dspi_tx(priv, ctrl, *spi_wr++);
+                                       *spi_rd++ = dspi_rx(priv);
+                               }
+                       }
+
+                       else if (dout != NULL) {
                                if (priv->charbit == 16)
                                        dspi_tx(priv, ctrl, *spi_wr16++);
                                else
@@ -280,7 +292,7 @@ static int dspi_xfer(struct fsl_dspi_priv *priv, uint cs, unsigned int bitlen,
                                dspi_rx(priv);
                        }
 
-                       if (din != NULL) {
+                       else if (din != NULL) {
                                dspi_tx(priv, ctrl, DSPI_IDLE_VAL);
                                if (priv->charbit == 16)
                                        *spi_rd16++ = dspi_rx(priv);
@@ -296,7 +308,18 @@ static int dspi_xfer(struct fsl_dspi_priv *priv, uint cs, unsigned int bitlen,
                ctrl &= ~DSPI_TFR_CONT;
 
        if (len) {
-               if (dout != NULL) {
+               if ((dout != NULL) && (din != NULL)) {
+                       if (priv->charbit == 16) {
+                               dspi_tx(priv, ctrl, *spi_wr16++);
+                               *spi_rd16++ = dspi_rx(priv);
+                       }
+                       else {
+                               dspi_tx(priv, ctrl, *spi_wr++);
+                               *spi_rd++ = dspi_rx(priv);
+                       }
+               }
+
+               else if (dout != NULL) {
                        if (priv->charbit == 16)
                                dspi_tx(priv, ctrl, *spi_wr16);
                        else
@@ -304,7 +327,7 @@ static int dspi_xfer(struct fsl_dspi_priv *priv, uint cs, unsigned int bitlen,
                        dspi_rx(priv);
                }
 
-               if (din != NULL) {
+               else if (din != NULL) {
                        dspi_tx(priv, ctrl, DSPI_IDLE_VAL);
                        if (priv->charbit == 16)
                                *spi_rd16 = dspi_rx(priv);
@@ -360,6 +383,40 @@ static int fsl_dspi_hz_to_spi_baud(int *pbr, int *br,
        return -EINVAL;
 }
 
+static void ns_delay_scale(unsigned char *psc, unsigned char *sc, int delay_ns,
+                          unsigned long clkrate)
+{
+       int scale_needed, scale, minscale = INT_MAX;
+       int pscale_tbl[4] = {1, 3, 5, 7};
+       u32 remainder;
+       int i, j;
+
+       scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
+                                  &remainder);
+       if (remainder)
+               scale_needed++;
+
+       for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
+               for (j = 0; j <= DSPI_CTAR_SCALE_BITS; j++) {
+                       scale = pscale_tbl[i] * (2 << j);
+                       if (scale >= scale_needed) {
+                               if (scale < minscale) {
+                                       minscale = scale;
+                                       *psc = i;
+                                       *sc = j;
+                               }
+                               break;
+                       }
+               }
+
+       if (minscale == INT_MAX) {
+               pr_warn("Cannot find correct scale values for %dns delay at clkrate %ld, using max prescaler value",
+                       delay_ns, clkrate);
+               *psc = ARRAY_SIZE(pscale_tbl) - 1;
+               *sc = DSPI_CTAR_SCALE_BITS;
+       }
+}
+
 static int fsl_dspi_cfg_speed(struct fsl_dspi_priv *priv, uint speed)
 {
        int ret;
@@ -388,150 +445,14 @@ static int fsl_dspi_cfg_speed(struct fsl_dspi_priv *priv, uint speed)
 
        return 0;
 }
-#ifndef CONFIG_DM_SPI
-void spi_init(void)
-{
-       /* Nothing to do */
-}
 
-void spi_init_f(void)
-{
-       /* Nothing to do */
-}
-
-void spi_init_r(void)
-{
-       /* Nothing to do */
-}
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-       if (((cs >= 0) && (cs < 8)) && ((bus >= 0) && (bus < 8)))
-               return 1;
-       else
-               return 0;
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-                                 unsigned int max_hz, unsigned int mode)
-{
-       struct fsl_dspi *dspi;
-       uint mcr_cfg_val;
-
-       dspi = spi_alloc_slave(struct fsl_dspi, bus, cs);
-       if (!dspi)
-               return NULL;
-
-       cpu_dspi_port_conf();
-
-#ifdef CONFIG_SYS_FSL_DSPI_BE
-       dspi->priv.flags |= DSPI_FLAG_REGMAP_ENDIAN_BIG;
-#endif
-
-       dspi->priv.regs = (struct dspi *)MMAP_DSPI;
-
-#ifdef CONFIG_M68K
-       dspi->priv.bus_clk = gd->bus_clk;
-#else
-       dspi->priv.bus_clk = mxc_get_clock(MXC_DSPI_CLK);
-#endif
-       dspi->priv.speed_hz = FSL_DSPI_DEFAULT_SCK_FREQ;
-
-       /* default: all CS signals inactive state is high */
-       mcr_cfg_val = DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK |
-               DSPI_MCR_CRXF | DSPI_MCR_CTXF;
-       fsl_dspi_init_mcr(&dspi->priv, mcr_cfg_val);
-
-       for (i = 0; i < FSL_DSPI_MAX_CHIPSELECT; i++)
-               dspi->priv.ctar_val[i] = DSPI_CTAR_DEFAULT_VALUE;
-
-#ifdef CONFIG_SYS_DSPI_CTAR0
-       if (FSL_DSPI_MAX_CHIPSELECT > 0)
-               dspi->priv.ctar_val[0] = CONFIG_SYS_DSPI_CTAR0;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR1
-       if (FSL_DSPI_MAX_CHIPSELECT > 1)
-               dspi->priv.ctar_val[1] = CONFIG_SYS_DSPI_CTAR1;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR2
-       if (FSL_DSPI_MAX_CHIPSELECT > 2)
-               dspi->priv.ctar_val[2] = CONFIG_SYS_DSPI_CTAR2;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR3
-       if (FSL_DSPI_MAX_CHIPSELECT > 3)
-               dspi->priv.ctar_val[3] = CONFIG_SYS_DSPI_CTAR3;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR4
-       if (FSL_DSPI_MAX_CHIPSELECT > 4)
-               dspi->priv.ctar_val[4] = CONFIG_SYS_DSPI_CTAR4;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR5
-       if (FSL_DSPI_MAX_CHIPSELECT > 5)
-               dspi->priv.ctar_val[5] = CONFIG_SYS_DSPI_CTAR5;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR6
-       if (FSL_DSPI_MAX_CHIPSELECT > 6)
-               dspi->priv.ctar_val[6] = CONFIG_SYS_DSPI_CTAR6;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR7
-       if (FSL_DSPI_MAX_CHIPSELECT > 7)
-               dspi->priv.ctar_val[7] = CONFIG_SYS_DSPI_CTAR7;
-#endif
-
-       fsl_dspi_cfg_speed(&dspi->priv, max_hz);
-
-       /* configure transfer mode */
-       fsl_dspi_cfg_ctar_mode(&dspi->priv, cs, mode);
-
-       /* configure active state of CSX */
-       fsl_dspi_cfg_cs_active_state(&dspi->priv, cs, mode);
-
-       return &dspi->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
-       free(slave);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
-       uint sr_val;
-       struct fsl_dspi *dspi = (struct fsl_dspi *)slave;
-
-       cpu_dspi_claim_bus(slave->bus, slave->cs);
-
-       fsl_dspi_clr_fifo(&dspi->priv);
-
-       /* check module TX and RX status */
-       sr_val = dspi_read32(dspi->priv.flags, &dspi->priv.regs->sr);
-       if ((sr_val & DSPI_SR_TXRXS) != DSPI_SR_TXRXS) {
-               debug("DSPI RX/TX not ready!\n");
-               return -EIO;
-       }
-
-       return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-       struct fsl_dspi *dspi = (struct fsl_dspi *)slave;
-
-       dspi_halt(&dspi->priv, 1);
-       cpu_dspi_release_bus(slave->bus.slave->cs);
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-            void *din, unsigned long flags)
-{
-       struct fsl_dspi *dspi = (struct fsl_dspi *)slave;
-       return dspi_xfer(&dspi->priv, slave->cs, bitlen, dout, din, flags);
-}
-#else
 static int fsl_dspi_child_pre_probe(struct udevice *dev)
 {
        struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
        struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+       u32 cs_sck_delay = 0, sck_cs_delay = 0;
+       unsigned char pcssck = 0, cssck = 0;
+       unsigned char pasc = 0, asc = 0;
 
        if (slave_plat->cs >= priv->num_chipselect) {
                debug("DSPI invalid chipselect number %d(max %d)!\n",
@@ -539,7 +460,18 @@ static int fsl_dspi_child_pre_probe(struct udevice *dev)
                return -EINVAL;
        }
 
-       priv->ctar_val[slave_plat->cs] = DSPI_CTAR_DEFAULT_VALUE;
+       ofnode_read_u32(dev->node, "fsl,spi-cs-sck-delay", &cs_sck_delay);
+       ofnode_read_u32(dev->node, "fsl,spi-sck-cs-delay", &sck_cs_delay);
+
+       /* Set PCS to SCK delay scale values */
+       ns_delay_scale(&pcssck, &cssck, cs_sck_delay, priv->bus_clk);
+
+       /* Set After SCK delay scale values */
+       ns_delay_scale(&pasc, &asc, sck_cs_delay, priv->bus_clk);
+
+       priv->ctar_val[slave_plat->cs] = DSPI_CTAR_DEFAULT_VALUE |
+                                        DSPI_CTAR_PCSSCK(pcssck) |
+                                        DSPI_CTAR_PASC(pasc);
 
        debug("DSPI pre_probe slave device on CS %u, max_hz %u, mode 0x%x.\n",
              slave_plat->cs, slave_plat->max_hz, slave_plat->mode);
@@ -594,7 +526,7 @@ static int fsl_dspi_claim_bus(struct udevice *dev)
 
        priv = dev_get_priv(bus);
 
-       /* processor special prepartion work */
+       /* processor special preparation work */
        cpu_dspi_claim_bus(bus->seq, slave_plat->cs);
 
        /* configure transfer mode */
@@ -646,7 +578,7 @@ static int fsl_dspi_ofdata_to_platdata(struct udevice *bus)
        fdt_addr_t addr;
        struct fsl_dspi_platdata *plat = bus->platdata;
        const void *blob = gd->fdt_blob;
-       int node = bus->of_offset;
+       int node = dev_of_offset(bus);
 
        if (fdtdec_get_bool(blob, node, "big-endian"))
                plat->flags |= DSPI_FLAG_REGMAP_ENDIAN_BIG;
@@ -654,7 +586,7 @@ static int fsl_dspi_ofdata_to_platdata(struct udevice *bus)
        plat->num_chipselect =
                fdtdec_get_int(blob, node, "num-cs", FSL_DSPI_MAX_CHIPSELECT);
 
-       addr = dev_get_addr(bus);
+       addr = dev_read_addr(bus);
        if (addr == FDT_ADDR_T_NONE) {
                debug("DSPI: Can't get base address or size\n");
                return -ENOMEM;
@@ -734,4 +666,3 @@ U_BOOT_DRIVER(fsl_dspi) = {
        .child_pre_probe = fsl_dspi_child_pre_probe,
        .bind = fsl_dspi_bind,
 };
-#endif