]> git.sur5r.net Git - u-boot/blobdiff - drivers/spi/designware_spi.c
Merge git://git.denx.de/u-boot-dm
[u-boot] / drivers / spi / designware_spi.c
index 1bc0d04cca6f28b9b3bd1a5ec29536b3a3d890db..9d5e29c6c3f690eeff560042a946ac27d4030fd1 100644 (file)
@@ -3,7 +3,8 @@
  *
  * Copyright (C) 2014 Stefan Roese <sr@denx.de>
  *
- * Very loosly based on the Linux driver version which is:
+ * Very loosely based on the Linux driver:
+ * drivers/spi/spi-dw.c, which is:
  * Copyright (c) 2009, Intel Corporation.
  *
  * SPDX-License-Identifier:    GPL-2.0
@@ -17,6 +18,7 @@
 #include <fdtdec.h>
 #include <linux/compat.h>
 #include <asm/io.h>
+#include <asm/arch/clock_manager.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -72,16 +74,16 @@ DECLARE_GLOBAL_DATA_PTR;
 #define SPI_CFS_OFFSET                 12
 
 /* Bit fields in SR, 7 bits */
-#define SR_MASK                                0x7f            /* cover 7 bits */
-#define SR_BUSY                                (1 << 0)
-#define SR_TF_NOT_FULL                 (1 << 1)
-#define SR_TF_EMPT                     (1 << 2)
-#define SR_RF_NOT_EMPT                 (1 << 3)
-#define SR_RF_FULL                     (1 << 4)
-#define SR_TX_ERR                      (1 << 5)
-#define SR_DCOL                                (1 << 6)
+#define SR_MASK                                GENMASK(6, 0)   /* cover 7 bits */
+#define SR_BUSY                                BIT(0)
+#define SR_TF_NOT_FULL                 BIT(1)
+#define SR_TF_EMPT                     BIT(2)
+#define SR_RF_NOT_EMPT                 BIT(3)
+#define SR_RF_FULL                     BIT(4)
+#define SR_TX_ERR                      BIT(5)
+#define SR_DCOL                                BIT(6)
 
-#define RX_TIMEOUT                     1000
+#define RX_TIMEOUT                     1000            /* timeout in ms */
 
 struct dw_spi_platdata {
        s32 frequency;          /* Default clock frequency, -1 for none */
@@ -95,7 +97,6 @@ struct dw_spi_priv {
 
        int bits_per_word;
        u8 cs;                  /* chip select pin */
-       u8 n_bytes;             /* current is a 1/2/4 byte op */
        u8 tmode;               /* TR/TO/RO/EEPROM */
        u8 type;                /* SPI/SSP/MicroWire */
        int len;
@@ -131,9 +132,9 @@ static int dw_spi_ofdata_to_platdata(struct udevice *bus)
 {
        struct dw_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 dw_spi *)fdtdec_get_addr(blob, node, "reg");
+       plat->regs = (struct dw_spi *)dev_get_addr(bus);
 
        /* Use 500KHz as a suitable default */
        plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
@@ -163,13 +164,13 @@ static void spi_hw_init(struct dw_spi_priv *priv)
        if (!priv->fifo_len) {
                u32 fifo;
 
-               for (fifo = 2; fifo <= 257; fifo++) {
+               for (fifo = 1; fifo < 256; fifo++) {
                        dw_writew(priv, DW_SPI_TXFLTR, fifo);
                        if (fifo != dw_readw(priv, DW_SPI_TXFLTR))
                                break;
                }
 
-               priv->fifo_len = (fifo == 257) ? 0 : fifo;
+               priv->fifo_len = (fifo == 1) ? 0 : fifo;
                dw_writew(priv, DW_SPI_TXFLTR, 0);
        }
        debug("%s: fifo_len=%d\n", __func__, priv->fifo_len);
@@ -185,7 +186,6 @@ static int dw_spi_probe(struct udevice *bus)
 
        /* Currently only bits_per_word == 8 supported */
        priv->bits_per_word = 8;
-       priv->n_bytes = 1;
 
        priv->tmode = 0; /* Tx & Rx */
 
@@ -200,19 +200,19 @@ static inline u32 tx_max(struct dw_spi_priv *priv)
 {
        u32 tx_left, tx_room, rxtx_gap;
 
-       tx_left = (priv->tx_end - priv->tx) / priv->n_bytes;
+       tx_left = (priv->tx_end - priv->tx) / (priv->bits_per_word >> 3);
        tx_room = priv->fifo_len - dw_readw(priv, DW_SPI_TXFLR);
 
        /*
         * Another concern is about the tx/rx mismatch, we
-        * though to use (priv->fifo_len - rxflr - txflr) as
+        * thought about using (priv->fifo_len - rxflr - txflr) as
         * one maximum value for tx, but it doesn't cover the
         * data which is out of tx/rx fifo and inside the
         * shift registers. So a control from sw point of
         * view is taken.
         */
        rxtx_gap = ((priv->rx_end - priv->rx) - (priv->tx_end - priv->tx)) /
-               priv->n_bytes;
+               (priv->bits_per_word >> 3);
 
        return min3(tx_left, tx_room, (u32)(priv->fifo_len - rxtx_gap));
 }
@@ -220,7 +220,7 @@ static inline u32 tx_max(struct dw_spi_priv *priv)
 /* Return the max entries we should read out of rx fifo */
 static inline u32 rx_max(struct dw_spi_priv *priv)
 {
-       u32 rx_left = (priv->rx_end - priv->rx) / priv->n_bytes;
+       u32 rx_left = (priv->rx_end - priv->rx) / (priv->bits_per_word >> 3);
 
        return min_t(u32, rx_left, dw_readw(priv, DW_SPI_RXFLR));
 }
@@ -233,14 +233,14 @@ static void dw_writer(struct dw_spi_priv *priv)
        while (max--) {
                /* Set the tx word if the transfer's original "tx" is not null */
                if (priv->tx_end - priv->len) {
-                       if (priv->n_bytes == 1)
+                       if (priv->bits_per_word == 8)
                                txw = *(u8 *)(priv->tx);
                        else
                                txw = *(u16 *)(priv->tx);
                }
                dw_writew(priv, DW_SPI_DR, txw);
                debug("%s: tx=0x%02x\n", __func__, txw);
-               priv->tx += priv->n_bytes;
+               priv->tx += priv->bits_per_word >> 3;
        }
 }
 
@@ -261,14 +261,18 @@ static int dw_reader(struct dw_spi_priv *priv)
        while (max--) {
                rxw = dw_readw(priv, DW_SPI_DR);
                debug("%s: rx=0x%02x\n", __func__, rxw);
-               /* Care rx only if the transfer's original "rx" is not null */
+
+               /*
+                * Care about rx only if the transfer's original "rx" is
+                * not null
+                */
                if (priv->rx_end - priv->len) {
-                       if (priv->n_bytes == 1)
+                       if (priv->bits_per_word == 8)
                                *(u8 *)(priv->rx) = rxw;
                        else
                                *(u16 *)(priv->rx) = rxw;
                }
-               priv->rx += priv->n_bytes;
+               priv->rx += priv->bits_per_word >> 3;
        }
 
        return 0;
@@ -297,7 +301,6 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
        u8 *rx = din;
        int ret = 0;
        u32 cr0 = 0;
-       u8 bits = 0;
        u32 cs;
 
        /* spi core configured to do 8 bit transfers */
@@ -306,9 +309,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
                return -1;
        }
 
-       bits = priv->bits_per_word;
-       priv->n_bytes = bits >> 3;
-       cr0 = (bits - 1) | (priv->type << SPI_FRF_OFFSET) |
+       cr0 = (priv->bits_per_word - 1) | (priv->type << SPI_FRF_OFFSET) |
                (priv->mode << SPI_MODE_OFFSET) |
                (priv->tmode << SPI_TMOD_OFFSET);
 
@@ -322,7 +323,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
        cr0 &= ~SPI_TMOD_MASK;
        cr0 |= (priv->tmode << SPI_TMOD_OFFSET);
 
-       priv->len = bitlen / 8;
+       priv->len = bitlen >> 3;
        debug("%s: rx=%p tx=%p len=%d [bytes]\n", __func__, rx, tx, priv->len);
 
        priv->tx = (void *)tx;
@@ -368,7 +369,7 @@ static int dw_spi_set_speed(struct udevice *bus, uint speed)
        spi_enable_chip(priv, 0);
 
        /* clk_div doesn't support odd number */
-       clk_div = CONFIG_DW_SPI_REF_CLK / speed;
+       clk_div = cm_get_spi_controller_clk_hz() / speed;
        clk_div = (clk_div + 1) & 0xfffe;
        dw_writel(priv, DW_SPI_BAUDR, clk_div);
 
@@ -408,7 +409,7 @@ static const struct dm_spi_ops dw_spi_ops = {
 };
 
 static const struct udevice_id dw_spi_ids[] = {
-       { .compatible = "snps,dw-spi-mmio" },
+       { .compatible = "snps,dw-apb-ssi" },
        { }
 };
 
@@ -420,6 +421,5 @@ U_BOOT_DRIVER(dw_spi) = {
        .ofdata_to_platdata = dw_spi_ofdata_to_platdata,
        .platdata_auto_alloc_size = sizeof(struct dw_spi_platdata),
        .priv_auto_alloc_size = sizeof(struct dw_spi_priv),
-       .per_child_auto_alloc_size = sizeof(struct spi_slave),
        .probe = dw_spi_probe,
 };