Skip to contentSkip to conversation

dm : spi: Convert Freescale DSPI to driver model

PATCH New Haikun.Wang at freescale.com 3 participants 6 messages Feb 28, 2015 – Mar 5, 2015 1 message not in the archive SPI

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 dm : spi: Convert Freescale DSPI to driver model

Move the Freescale DSPI driver over to driver model.

Signed-off-by Haikun Wang <B53464 at freescale.com<mailto:[email protected]>>

---

This patch adds two new files drivers/spi/fsl_dspi.c and include/fsl_dspi.h. They will replace files drivers/spi/cf_spi.c and arch/m68k/include/asm/coldfire/dspi.h. I need submit patch to remove them later.
Board dts files are also needed to make this change work.

Changes in v1: None

 drivers/spi/Makefile   |   1 +
 drivers/spi/fsl_dspi.c | 461 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fsl_dspi.h     | 156 +++++++++++++++++
 3 files changed, 618 insertions(+)
 create mode 100644 drivers/spi/fsl_dspi.c
 create mode 100644 include/fsl_dspi.h
drivers/spi/Makefile +1 -0
index edbd520..9c2b8de 100644
@@ -49,3 +49,4 @@ obj-$(CONFIG_TI_QSPI) += ti_qspi.o
 obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
 obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
+obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
drivers/spi/fsl_dspi.c new file +461 -0

461 lines not on this page · raw message

include/fsl_dspi.h new file +156 -0

156 lines not on this page · raw message

--
2.1.0.27.g96db324

#1 lore raw

PATCH 1/1 dm : spi: Convert Freescale DSPI to driver model

Hi,

Quoted 10 lines · Haikun.Wang at freescale.com

Move the Freescale DSPI driver over to driver model.

---

This patch adds two new files drivers/spi/fsl_dspi.c and include/fsl_dspi.h. They will replace files drivers/spi/cf_spi.c and arch/m68k/include/asm/coldfire/dspi.h.
I need submit patch to remove them later.
Board dts files are also needed to make this change work.

Apart from one thing (the chip selects) this all looks correct to me. Some style comments below. Also the patch seems to be in Courier font!

I'm interested in your thoughts on what is missing from the SPI uclass too.

Quoted 38 lines

Changes in v1: None

drivers/spi/Makefile | 1 +
drivers/spi/fsl_dspi.c | 461
+++++++++++++++++++++++++++++++++++++++++++++++++
include/fsl_dspi.h | 156 +++++++++++++++++

3 files changed, 618 insertions(+)

create mode 100644 drivers/spi/fsl_dspi.c
create mode 100644 include/fsl_dspi.h

drivers/spi/Makefile +0 -0
index edbd520..9c2b8de 100644
@@ -49,3 +49,4 @@ obj-$(CONFIG_TI_QSPI) += ti_qspi.o

obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o

drivers/spi/Makefile +1 -0
+obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
drivers/spi/fsl_dspi.c new file +12 -0
new file mode 100644
index 0000000..69c037b
@@ -0,0 +1,461 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com)
+ * Chao Fu (B44548 at freescale.com)
+ * Haikun Wang (B53464 at freescale.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#include <dm.h>

drivers/spi/fsl_dspi.c line 22

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+#include <errno.h>
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <fdtdec.h>
+#include <asm/arch/clock.h>
+#include <fsl_dspi.h>
+
+

Remove extract blank line

drivers/spi/fsl_dspi.c line 29

Quoted 7 lines
drivers/spi/fsl_dspi.c new file +7 -0
+DECLARE_GLOBAL_DATA_PTR;
+
+/* fsl_dspi_platdata flag */
+#define DSPI_FLAG_REGMAP_ENDIAN_BIG    (1 << 0)
+
+/* idle data value */
+#define DSPI_IDLE_VAL                 (0x0)

Please no brackets around simple constants (I understand if they are -ve, but this serves no purpose).

Quoted 12 lines
drivers/spi/fsl_dspi.c new file +12 -0
+
+/* max chipselect signals number */
+#define FSL_DSPI_MAX_CHIPSELECT        (6)
+
+/* CTAR register pre-configure value */
+#define DSPI_CTAR_DEFAULT_VALUE        (DSPI_CTAR_TRSZ(7) | \
+                                       DSPI_CTAR_PCSSCK_1CLK | \
+                                       DSPI_CTAR_PASC(0) | \
+                                       DSPI_CTAR_PDT(0) | \
+                                       DSPI_CTAR_CSSCK(0) | \
+                                       DSPI_CTAR_ASC(0) | \
+                                       DSPI_CTAR_DT(0))

drivers/spi/fsl_dspi.c line 51

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+
+/* CTAR register pre-configure mask */
+#define DSPI_CTAR_SET_MODE_MASK        (DSPI_CTAR_TRSZ(15) | \
+                                       DSPI_CTAR_PCSSCK(3) | \
+                                       DSPI_CTAR_PASC(3) | \
+                                       DSPI_CTAR_PDT(3) | \
+                                       DSPI_CTAR_CSSCK(15) | \
+                                       DSPI_CTAR_ASC(15) | \
+                                       DSPI_CTAR_DT(15))
+

Please comment these things below:

/**
* struct fsl_dspi_platdata - platform data for ... *
* @flag: some sort of flag and you can find the enum here...
...

Quoted 7 lines
drivers/spi/fsl_dspi.c new file +7 -0
+struct fsl_dspi_platdata {
+       uint flag;
+       uint baudrate;
+       uint num_chipselect;
+       uint regs;
+};
+

drivers/spi/fsl_dspi.c line 68

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+struct fsl_dspi_priv {
+       uint mode;
+       uint mcr_val;
+       uint bus_clk;
+       uint baudrate;
+       uint charbit;
+       uint num_chipselect;
+       uint ctar_val[FSL_DSPI_MAX_CHIPSELECT];
+       uint regs;
+       struct dm_spi_slave_platdata *cur_slave_plat;

What is that for?

drivers/spi/fsl_dspi.c line 73

Quoted 5 lines
drivers/spi/fsl_dspi.c new file +5 -0
+};
+
+static uint dspi_read32(struct udevice *bus, uint offset)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);

blank line between declarations and code (throughout)

drivers/spi/fsl_dspi.c line 75

Quoted 2 lines
drivers/spi/fsl_dspi.c new file +2 -0
+       return plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               in_be32(plat->regs + offset) : in_le32(plat->regs + offset);

I think it is better to put regs in your private data rather than platform data. Platform data should be used in your probe function mostly. It's OK to use it sparing for uncommon things, but this feels like something that should be in private data.

I have tended to put an fdt_addr_t in platform data and a struct reg_definition * in private data.

Also where is your C structure for the registers? We normally use that sort of thing in U-Boot.

Quoted 31 lines
drivers/spi/fsl_dspi.c new file +30 -0
+}
+
+static void dspi_write32(struct udevice *bus, uint offset, uint val)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               out_be32(plat->regs + offset, val) :
+               out_le32(plat->regs + offset, val);
+       return;
+}
+
+static void dspi_halt(struct udevice *bus, u8 halt)
+{
+       uint mcr_val;
+
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+
+       if (halt)
+               mcr_val |= DSPI_MCR_HALT;
+       else
+               mcr_val &= ~DSPI_MCR_HALT;
+
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       return;
+}
+
+static int fsl_dspi_child_pre_probe(struct udevice *dev)
+{
+       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

drivers/spi/fsl_dspi.c line 110

Quoted 5 lines
drivers/spi/fsl_dspi.c new file +5 -0
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+
+       if (slave_plat->cs >= priv->num_chipselect) {
+               printf("DSPI invalid chipselect number %d(max %d)!\n",
+                      slave_plat->cs, priv->num_chipselect - 1);

Maybe you want debug() here, up to you.

drivers/spi/fsl_dspi.c line 116

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+               return -EINVAL;
+       }
+
+       priv->ctar_val[slave_plat->cs] = DSPI_CTAR_DEFAULT_VALUE;
+
+       priv->cur_slave_plat = slave_plat;

Not sure what you are doing here?

drivers/spi/fsl_dspi.c line 127

Quoted 12 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       debug("DSPI pre_probe slave device on CS %u, max_hz %u, mode

0x%x.\n",

drivers/spi/fsl_dspi.c new file +9 -0
+             slave_plat->cs, slave_plat->max_hz, slave_plat->mode);
+
+       return 0;
+}
+
+static int fsl_dspi_child_post_remove(struct udevice *dev)
+{
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+       priv->cur_slave_plat = NULL;

or here?

Quoted 56 lines
drivers/spi/fsl_dspi.c new file +56 -0
+       return 0;
+}
+
+static int fsl_dspi_probe(struct udevice *bus)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_bus *dm_spi_bus;
+       uint mcr_val = 0;
+
+       dm_spi_bus = bus->uclass_priv;
+
+       /* get input clk frequency */
+       priv->bus_clk = mxc_get_clock(MXC_DSPI_CLK);
+       priv->regs = plat->regs;
+       priv->num_chipselect = plat->num_chipselect;
+       priv->baudrate = plat->baudrate;
+       /* frame data length in bits, default 8bits */
+       priv->charbit = 8;
+
+       dm_spi_bus->max_hz = plat->baudrate;
+
+       /* halt DSPI module */
+       dspi_halt(bus, 1);
+
+       /* default: all CS inactive state is high */
+       mcr_val |= DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK |
+               DSPI_MCR_CRXF | DSPI_MCR_CTXF;
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       /* resume module */
+       dspi_halt(bus, 0);
+
+       priv->mcr_val = mcr_val;
+
+       debug("%s probe done, bus-num %d.\n", bus->name, bus->seq);
+
+       return 0;
+}
+
+static int fsl_dspi_claim_bus(struct udevice *bus)
+{
+       uint mcr_val;
+
+       dspi_halt(bus, 1);
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+       /* flush RX and TX FIFO */
+       mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF);
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       dspi_halt(bus, 0);
+
+       return 0;
+}
+
+static int fsl_dspi_release_bus(struct udevice *bus)

drivers/spi/fsl_dspi.c line 193

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+{
+       /* halt module */
+       dspi_halt(bus, 1);
+       return 0;
+}
+
+static void dspi_tx(struct udevice *bus, u32 ctrl, u16 data)
+{
+       while (((dspi_read32(bus, DSPI_SR) & 0x0000F000) >> 12) >= 4)
+               ;

Can this ever timeout/hang? Also why are you using u16 for the data? It doesn't seem necessary here or in the next function. You could use u32 I think?

drivers/spi/fsl_dspi.c line 203

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+
+       dspi_write32(bus, DSPI_TFR, (ctrl | data));
+
+       return;
+}
+
+static u16 dspi_rx(struct udevice *bus)
+{
+       while ((dspi_read32(bus, DSPI_SR) & 0x000000F0) == 0)
+               ;

or this?

Quoted 11 lines
drivers/spi/fsl_dspi.c new file +9 -0
+
+       return (u16)(dspi_read32(bus, DSPI_RFR) & 0xFFFF);
+}
+
+static int fsl_dspi_xfer(struct udevice *dev, unsigned int bitlen,
+               const void *dout, void *din, unsigned long flags)
+{
+       struct fsl_dspi_priv *priv;
+       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

drivers/spi/fsl_dspi.c new file +1 -0
+       struct udevice *bus;

drivers/spi/fsl_dspi.c line 223

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       u16 *spi_rd16 = NULL, *spi_wr16 = NULL;
+       u8 *spi_rd = NULL, *spi_wr = NULL;
+       static u32 ctrl;
+       uint len = bitlen >> 3;
+
+       bus = dev->parent;
+       if (bus)
+               priv = dev_get_priv(bus);
+       else
+               return -ENODEV;

This must have a parent. There is no need for this check. If someone calls this with the root device they deserve trouble! If you like you could have

assert(bus);

Quoted 59 lines
drivers/spi/fsl_dspi.c new file +59 -0
+
+       if (priv->charbit == 16) {
+               bitlen >>= 1;
+               spi_wr16 = (u16 *)dout;
+               spi_rd16 = (u16 *)din;
+       } else {
+               spi_wr = (u8 *)dout;
+               spi_rd = (u8 *)din;
+       }
+
+       if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN)
+               ctrl |= DSPI_TFR_CONT;
+
+       ctrl = ctrl & DSPI_TFR_CONT;
+       ctrl = ctrl | DSPI_TFR_CTAS(0) | DSPI_TFR_PCS(slave_plat->cs);
+
+       if (len > 1) {
+               int tmp_len = len - 1;
+               while (tmp_len--) {
+                       if (dout != NULL) {
+                               if (priv->charbit == 16)
+                                       dspi_tx(bus, ctrl, *spi_wr16++);
+                               else
+                                       dspi_tx(bus, ctrl, *spi_wr++);
+                               dspi_rx(bus);
+                       }
+
+                       if (din != NULL) {
+                               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                               if (priv->charbit == 16)
+                                       *spi_rd16++ = dspi_rx(bus);
+                               else
+                                       *spi_rd++ = dspi_rx(bus);
+                       }
+               }
+
+               len = 1;        /* remaining byte */
+       }
+
+       if ((flags & SPI_XFER_END) == SPI_XFER_END)
+               ctrl &= ~DSPI_TFR_CONT;
+
+       if (len) {
+               if (dout != NULL) {
+                       if (priv->charbit == 16)
+                               dspi_tx(bus, ctrl, *spi_wr16);
+                       else
+                               dspi_tx(bus, ctrl, *spi_wr);
+                       dspi_rx(bus);
+               }
+
+               if (din != NULL) {
+                       dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                       if (priv->charbit == 16)
+                               *spi_rd16 = dspi_rx(bus);
+                       else
+                               *spi_rd = dspi_rx(bus);
+               }
+       } else {

drivers/spi/fsl_dspi.c line 292

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+               /* dummy read */
+               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+               dspi_rx(bus);
+       }
+
+       return 0;
+}
+
+static int fsl_dspi_hz_to_spi_baud(int *pbr, int *br,
+               int speed_hz, uint clkrate)

Should document args here.

Quoted 28 lines
drivers/spi/fsl_dspi.c new file +28 -0
+{
+       /* Valid baud rate pre-scaler values */
+       int pbr_tbl[4] = {2, 3, 5, 7};
+       int brs[16] = {2, 4, 6, 8,
+               16, 32, 64, 128,
+               256, 512, 1024, 2048,
+               4096, 8192, 16384, 32768};
+       int temp, i = 0, j = 0;
+
+       temp = clkrate / speed_hz;
+
+       for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
+               for (j = 0; j < ARRAY_SIZE(brs); j++) {
+                       if (pbr_tbl[i] * brs[j] >= temp) {
+                               *pbr = i;
+                               *br = j;
+                               return 0;
+                       }
+               }
+
+       printf("Can not find valid baud rate,speed_hz is %d, ", speed_hz);
+       printf("clkrate is %d, we use the max prescaler value.\n", clkrate);
+
+       *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+       *br =  ARRAY_SIZE(brs) - 1;
+       return -EINVAL;
+}
+

drivers/spi/fsl_dspi.c line 330

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+static int fsl_dspi_set_speed(struct udevice *bus, uint speed)
+{
+       u8 cs;
+       int ret;
+       uint bus_setup;
+       int best_i, best_j, bus_clk;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;
+
+       cs = slave_plat->cs;

You can't do this. Is the problem that you have a different speed setting for each chip select? If so then we should either fix the uclass interface to support this, or you could store the speed and adjust it just before the transfer. But in this function you don't know the chip select and should not try to guess it.

Quoted 27 lines
drivers/spi/fsl_dspi.c new file +8 -0
+
+       bus_clk = priv->bus_clk;
+
+       debug("DSPI set_speed: expected SCK speed %u, bus_clk %u.\n",
+             speed, bus_clk);
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~(DSPI_CTAR_DBR | DSPI_CTAR_PBR(0x3) |

DSPI_CTAR_BR(0xf));

drivers/spi/fsl_dspi.c new file +18 -0
+       bus_setup |= priv->ctar_val[cs];
+
+       ret = fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
+       if (ret) {
+               speed = priv->baudrate;
+               debug("DSPI set_speed use default SCK rate %u.\n", speed);
+               fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
+       }
+
+       bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       priv->baudrate = speed;
+
+       return 0;
+}
+
+static int fsl_dspi_set_mode(struct udevice *bus, uint mode)

drivers/spi/fsl_dspi.c line 366

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+{
+       u8 cs;
+       uint bus_setup;
+       uint mcr_val;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;
+
+       debug("DSPI set_mode: mode 0x%x.\n", mode);
+
+       cs = slave_plat->cs;

Similar point here.

Quoted 25 lines
drivers/spi/fsl_dspi.c new file +25 -0
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~DSPI_CTAR_SET_MODE_MASK;
+       bus_setup |= priv->ctar_val[cs];
+       bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA | DSPI_CTAR_LSBFE);
+
+       if (mode & SPI_CPOL)
+               bus_setup |= DSPI_CTAR_CPOL;
+       if (mode & SPI_CPHA)
+               bus_setup |= DSPI_CTAR_CPHA;
+       if (mode & SPI_LSB_FIRST)
+               bus_setup |= DSPI_CTAR_LSBFE;
+
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       if (mode & SPI_CS_HIGH) {
+               dspi_halt(bus, 1);
+               mcr_val = dspi_read32(bus, DSPI_MCR);
+               /* CSx inactive state is low */
+               mcr_val &= ~DSPI_MCR_PCSIS(cs);
+               dspi_write32(bus, DSPI_MCR, mcr_val);
+               dspi_halt(bus, 0);
+       }
+
+       priv->mode = mode;

drivers/spi/fsl_dspi.c line 401

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       priv->charbit = ((dspi_read32(bus, DSPI_CTAR(0)) & 0x78000000)
+                == 0x78000000) ? 16 : 8;
+
+       return 0;
+}
+
+static int fsl_dspi_bind(struct udevice *bus)
+{
+       debug("%s assigned req_seq %d.\n", bus->name, bus->req_seq);
+       return 0;

You can drop this unless you want it for debugging. If the latter, please add a comment like /* This doesn't do anything except help with debugging */

drivers/spi/fsl_dspi.c line 411

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+}
+
+static int fsl_dspi_ofdata_to_platdata(struct udevice *bus)
+{
+       uint addr;
+       struct fsl_dspi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
+
+       plat->flag = 0;

It will already be zero. All data allocated by driver model is zeroed.

drivers/spi/fsl_dspi.c line 414

Quoted 3 lines
drivers/spi/fsl_dspi.c new file +3 -0
+       if (fdtdec_get_bool(blob, node, "big-endian"))
+               plat->flag |= DSPI_FLAG_REGMAP_ENDIAN_BIG;
+

Extra black line here

drivers/spi/fsl_dspi.c line 419

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +3 -0
+
+       plat->num_chipselect =
+               fdtdec_get_int(blob, node, "num-cs",

FSL_DSPI_MAX_CHIPSELECT);

drivers/spi/fsl_dspi.c new file +2 -0
+
+       addr = fdtdec_get_addr(blob, node, "reg");

You can use dev_get_addr(dev) if you like.

drivers/spi/fsl_dspi.c line 427

Quoted 8 lines
drivers/spi/fsl_dspi.c new file +8 -0
+       if (addr == FDT_ADDR_T_NONE) {
+               printf("DSPI: Can't get base address or size\n");
+               return -ENOMEM;
+       }
+       plat->regs = addr;
+
+       plat->baudrate =
+               fdtdec_get_int(blob, node, "spi-max-frequency", 10000000);

The name 'baudrate' bothers me, but that if that is what you normally call it on your hardware, then that is fine.

Quoted 63 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       debug("DSPI: regs=0x%x, max-frequency=%d, endianess=%s,

num-cs=%d\n",

drivers/spi/fsl_dspi.c new file +32 -0
+             plat->regs, plat->baudrate,
+             plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le",
+             plat->num_chipselect);
+
+       return 0;
+}
+static const struct dm_spi_ops fsl_dspi_ops = {
+       .claim_bus      = fsl_dspi_claim_bus,
+       .release_bus    = fsl_dspi_release_bus,
+       .xfer           = fsl_dspi_xfer,
+       .set_speed      = fsl_dspi_set_speed,
+       .set_mode       = fsl_dspi_set_mode,
+};
+
+static const struct udevice_id fsl_dspi_ids[] = {
+       { .compatible = "fsl,vf610-dspi" },
+       { }
+};
+
+U_BOOT_DRIVER(fsl_dspi) = {
+       .name   = "fsl_dspi",
+       .id     = UCLASS_SPI,
+       .of_match = fsl_dspi_ids,
+       .ops    = &fsl_dspi_ops,
+       .ofdata_to_platdata = fsl_dspi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct fsl_dspi_platdata),
+       .priv_auto_alloc_size = sizeof(struct fsl_dspi_priv),
+       .probe  = fsl_dspi_probe,
+       .child_pre_probe = fsl_dspi_child_pre_probe,
+       .child_post_remove = fsl_dspi_child_post_remove,
+       .bind = fsl_dspi_bind,
+};
include/fsl_dspi.h new file +22 -0
new file mode 100644
index 0000000..8cf02d3
@@ -0,0 +1,156 @@
+/*
+ * Freescale DSPI Module Defines
+ *
+ * Copyright (C) 2004-2007, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com)
+ * Chao Fu (B44548 at freesacle.com)
+ * Haikun Wang (B53464 at freescale.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _FSL_DSPI_H_
+#define _FSL_DSPI_H_
+
+/* DMA Serial Peripheral Interface (DSPI) */
+struct dspi {
+       u32 mcr;        /* 0x00 */
+       u32 resv0;      /* 0x04 */
+       u32 tcr;        /* 0x08 */
+       u32 ctar[8];    /* 0x0C - 0x28 */
+       u32 sr;         /* 0x2C */
+       u32 irsr;       /* 0x30 */

include/fsl_dspi.h line 32

Quoted 10 lines
include/fsl_dspi.h new file +10 -0
+       u32 tfr;        /* 0x34 - PUSHR */
+       u32 rfr;        /* 0x38 - POPR */
+#ifdef CONFIG_MCF547x_8x
+       u32 tfdr[4];    /* 0x3C */
+       u8 resv2[0x30]; /* 0x40 */
+       u32 rfdr[4];    /* 0x7C */
+#else
+       u32 tfdr[16];   /* 0x3C */
+       u32 rfdr[16];   /* 0x7C */
+#endif

Since you have this structure, can you not use it in your code for register access?

Quoted 8 lines
include/fsl_dspi.h new file +8 -0
+};
+
+/* Module configuration */
+#define DSPI_MCR                        (0x0)
+#define DSPI_MCR_MSTR                  (0x80000000)
+#define DSPI_MCR_CSCK                  (0x40000000)
+#define DSPI_MCR_DCONF(x)              (((x)&0x03)<<28)
+#define DSPI_MCR_FRZ                   (0x08000000)

include/fsl_dspi.h line 50

Quoted 10 lines
include/fsl_dspi.h new file +10 -0
+#define DSPI_MCR_MTFE                  (0x04000000)
+#define DSPI_MCR_PCSSE                 (0x02000000)
+#define DSPI_MCR_ROOE                  (0x01000000)
+#define DSPI_MCR_PCSIS(x)               (1<<(16+(x)))
+#define DSPI_MCR_PCSIS_MASK             (0xff<<16)
+#define DSPI_MCR_CSIS7                 (0x00800000)
+#define DSPI_MCR_CSIS6                 (0x00400000)
+#define DSPI_MCR_CSIS5                 (0x00200000)
+#define DSPI_MCR_CSIS4                 (0x00100000)
+#define DSPI_MCR_CSIS3                 (0x00080000)

Please remove brackets where not needed

include/fsl_dspi.h line 60

Quoted 10 lines
include/fsl_dspi.h new file +10 -0
+#define DSPI_MCR_CSIS2                 (0x00040000)
+#define DSPI_MCR_CSIS1                 (0x00020000)
+#define DSPI_MCR_CSIS0                 (0x00010000)
+#define DSPI_MCR_DOZE                  (0x00008000)
+#define DSPI_MCR_MDIS                  (0x00004000)
+#define DSPI_MCR_DTXF                  (0x00002000)
+#define DSPI_MCR_DRXF                  (0x00001000)
+#define DSPI_MCR_CTXF                  (0x00000800)
+#define DSPI_MCR_CRXF                  (0x00000400)
+#define DSPI_MCR_SMPL_PT(x)            (((x)&0x03)<<8)

Spaces around operators

Also can you please use tabs instead of spaces to indent things? It looks like these are spaces.

Quoted 97 lines
include/fsl_dspi.h new file +96 -1
+#define DSPI_MCR_FCPCS                 (0x00000001)
+#define DSPI_MCR_PES                   (0x00000001)
+#define DSPI_MCR_HALT                  (0x00000001)
+
+/* Transfer count */
+#define DSPI_TCR                        (0x8)
+#define DSPI_TCR_SPI_TCNT(x)           (((x)&0x0000FFFF)<<16)
+
+/* Clock and transfer attributes */
+#define DSPI_CTAR(x)                    (0x0c + (x * 4))
+#define DSPI_CTAR_DBR                  (0x80000000)
+#define DSPI_CTAR_TRSZ(x)              (((x)&0x0F)<<27)
+#define DSPI_CTAR_CPOL                 (0x04000000)
+#define DSPI_CTAR_CPHA                 (0x02000000)
+#define DSPI_CTAR_LSBFE                        (0x01000000)
+#define DSPI_CTAR_PCSSCK(x)            (((x)&0x03)<<22)
+#define DSPI_CTAR_PCSSCK_7CLK          (0x00A00000)
+#define DSPI_CTAR_PCSSCK_5CLK          (0x00800000)
+#define DSPI_CTAR_PCSSCK_3CLK          (0x00400000)
+#define DSPI_CTAR_PCSSCK_1CLK          (0x00000000)
+#define DSPI_CTAR_PASC(x)              (((x)&0x03)<<20)
+#define DSPI_CTAR_PASC_7CLK            (0x00300000)
+#define DSPI_CTAR_PASC_5CLK            (0x00200000)
+#define DSPI_CTAR_PASC_3CLK            (0x00100000)
+#define DSPI_CTAR_PASC_1CLK            (0x00000000)
+#define DSPI_CTAR_PDT(x)               (((x)&0x03)<<18)
+#define DSPI_CTAR_PDT_7CLK             (0x000A0000)
+#define DSPI_CTAR_PDT_5CLK             (0x00080000)
+#define DSPI_CTAR_PDT_3CLK             (0x00040000)
+#define DSPI_CTAR_PDT_1CLK             (0x00000000)
+#define DSPI_CTAR_PBR(x)               (((x)&0x03)<<16)
+#define DSPI_CTAR_PBR_7CLK             (0x00030000)
+#define DSPI_CTAR_PBR_5CLK             (0x00020000)
+#define DSPI_CTAR_PBR_3CLK             (0x00010000)
+#define DSPI_CTAR_PBR_1CLK             (0x00000000)
+#define DSPI_CTAR_CSSCK(x)             (((x)&0x0F)<<12)
+#define DSPI_CTAR_ASC(x)               (((x)&0x0F)<<8)
+#define DSPI_CTAR_DT(x)                        (((x)&0x0F)<<4)
+#define DSPI_CTAR_BR(x)                        (((x)&0x0F))
+
+/* Status */
+#define DSPI_SR                         (0x2c)
+#define DSPI_SR_TCF                    (0x80000000)
+#define DSPI_SR_TXRXS                  (0x40000000)
+#define DSPI_SR_EOQF                   (0x10000000)
+#define DSPI_SR_TFUF                   (0x08000000)
+#define DSPI_SR_TFFF                   (0x02000000)
+#define DSPI_SR_RFOF                   (0x00080000)
+#define DSPI_SR_RFDF                   (0x00020000)
+#define DSPI_SR_TXCTR(x)               (((x)&0x0F)<<12)
+#define DSPI_SR_TXPTR(x)               (((x)&0x0F)<<8)
+#define DSPI_SR_RXCTR(x)               (((x)&0x0F)<<4)
+#define DSPI_SR_RXPTR(x)               (((x)&0x0F))
+
+/* DMA/interrupt request selct and enable */
+#define DSPI_IRSR                       (0x30)
+#define DSPI_IRSR_TCFE                 (0x80000000)
+#define DSPI_IRSR_EOQFE                        (0x10000000)
+#define DSPI_IRSR_TFUFE                        (0x08000000)
+#define DSPI_IRSR_TFFFE                        (0x02000000)
+#define DSPI_IRSR_TFFFS                        (0x01000000)
+#define DSPI_IRSR_RFOFE                        (0x00080000)
+#define DSPI_IRSR_RFDFE                        (0x00020000)
+#define DSPI_IRSR_RFDFS                        (0x00010000)
+
+/* Transfer control - 32-bit access */
+#define DSPI_TFR                        (0x34)
+#define DSPI_TFR_PCS(x)                 (((1 << x) & 0x0000003f) << 16)
+#define DSPI_TFR_CONT                  (0x80000000)
+#define DSPI_TFR_CTAS(x)               (((x)&0x07)<<28)
+#define DSPI_TFR_EOQ                   (0x08000000)
+#define DSPI_TFR_CTCNT                 (0x04000000)
+#define DSPI_TFR_CS7                   (0x00800000)
+#define DSPI_TFR_CS6                   (0x00400000)
+#define DSPI_TFR_CS5                   (0x00200000)
+#define DSPI_TFR_CS4                   (0x00100000)
+#define DSPI_TFR_CS3                   (0x00080000)
+#define DSPI_TFR_CS2                   (0x00040000)
+#define DSPI_TFR_CS1                   (0x00020000)
+#define DSPI_TFR_CS0                   (0x00010000)
+
+/* Transfer Fifo */
+#define DSPI_TFR_TXDATA(x)             (((x)&0xFFFF))
+
+/* Bit definitions and macros for DRFR */
+#define DSPI_RFR                        (0x38)
+#define DSPI_RFR_RXDATA(x)             (((x)&0xFFFF))
+
+/* Bit definitions and macros for DTFDR group */
+#define DSPI_TFDR_TXDATA(x)            (((x)&0x0000FFFF))
+#define DSPI_TFDR_TXCMD(x)             (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for DRFDR group */
+#define DSPI_RFDR_RXDATA(x)            (((x)&0x0000FFFF))
+
+#endif                         /* _FSL_DSPI_H_ */
--
Quoted 2 lines

2.1.0.27.g96db324

Regards,
Simon

#2 lore raw

PATCH 1/1 dm : spi: Convert Freescale DSPI to driver model

Quoted 71 lines · Simon Glass

Hi,

Quoted 10 lines · Haikun.Wang at freescale.com

Move the Freescale DSPI driver over to driver model.

---

This patch adds two new files drivers/spi/fsl_dspi.c and include/fsl_dspi.h. They will replace files drivers/spi/cf_spi.c and arch/m68k/include/asm/coldfire/dspi.h.
I need submit patch to remove them later.
Board dts files are also needed to make this change work.

Apart from one thing (the chip selects) this all looks correct to me. Some style comments below. Also the patch seems to be in Courier font!

I'm interested in your thoughts on what is missing from the SPI uclass too.

Quoted 38 lines

Changes in v1: None

drivers/spi/Makefile | 1 +
drivers/spi/fsl_dspi.c | 461
+++++++++++++++++++++++++++++++++++++++++++++++++
include/fsl_dspi.h | 156 +++++++++++++++++

3 files changed, 618 insertions(+)

create mode 100644 drivers/spi/fsl_dspi.c
create mode 100644 include/fsl_dspi.h

drivers/spi/Makefile +0 -0
index edbd520..9c2b8de 100644
@@ -49,3 +49,4 @@ obj-$(CONFIG_TI_QSPI) += ti_qspi.o

obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o

drivers/spi/Makefile +1 -0
+obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
drivers/spi/fsl_dspi.c new file +12 -0
new file mode 100644
index 0000000..69c037b
@@ -0,0 +1,461 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com)
+ * Chao Fu (B44548 at freescale.com)
+ * Haikun Wang (B53464 at freescale.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#include <dm.h>

drivers/spi/fsl_dspi.c line 22

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+#include <errno.h>
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <fdtdec.h>
+#include <asm/arch/clock.h>
+#include <fsl_dspi.h>
+
+

Remove extract blank line

Quoted 10 lines

drivers/spi/fsl_dspi.c line 29

Quoted 7 lines
drivers/spi/fsl_dspi.c new file +7 -0
+DECLARE_GLOBAL_DATA_PTR;
+
+/* fsl_dspi_platdata flag */
+#define DSPI_FLAG_REGMAP_ENDIAN_BIG    (1 << 0)
+
+/* idle data value */
+#define DSPI_IDLE_VAL                 (0x0)

Please no brackets around simple constants (I understand if they are -ve, but this serves no purpose).

fine.

Quoted 17 lines
Quoted 17 lines
drivers/spi/fsl_dspi.c new file +16 -0
+
+/* max chipselect signals number */
+#define FSL_DSPI_MAX_CHIPSELECT        (6)
+
+/* CTAR register pre-configure value */
+#define DSPI_CTAR_DEFAULT_VALUE        (DSPI_CTAR_TRSZ(7) | \
+                                       DSPI_CTAR_PCSSCK_1CLK | \
+                                       DSPI_CTAR_PASC(0) | \
+                                       DSPI_CTAR_PDT(0) | \
+                                       DSPI_CTAR_CSSCK(0) | \
+                                       DSPI_CTAR_ASC(0) | \
+                                       DSPI_CTAR_DT(0))
+
+/* CTAR register pre-configure mask */
+#define DSPI_CTAR_SET_MODE_MASK        (DSPI_CTAR_TRSZ(15) | \
+                                       DSPI_CTAR_PCSSCK(3) | \
Quoted 8 lines

drivers/spi/fsl_dspi.c line 51

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+                                       DSPI_CTAR_PASC(3) | \
+                                       DSPI_CTAR_PDT(3) | \
+                                       DSPI_CTAR_CSSCK(15) | \
+                                       DSPI_CTAR_ASC(15) | \
+                                       DSPI_CTAR_DT(15))
+

Please comment these things below:

fine.

Quoted 35 lines

/**
* struct fsl_dspi_platdata - platform data for ... *
* @flag: some sort of flag and you can find the enum here...
...

Quoted 7 lines
drivers/spi/fsl_dspi.c new file +7 -0
+struct fsl_dspi_platdata {
+       uint flag;
+       uint baudrate;
+       uint num_chipselect;
+       uint regs;
+};
+

drivers/spi/fsl_dspi.c line 68

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+struct fsl_dspi_priv {
+       uint mode;
+       uint mcr_val;
+       uint bus_clk;
+       uint baudrate;
+       uint charbit;
+       uint num_chipselect;
+       uint ctar_val[FSL_DSPI_MAX_CHIPSELECT];
+       uint regs;
+       struct dm_spi_slave_platdata *cur_slave_plat;

What is that for?

drivers/spi/fsl_dspi.c line 73

Quoted 5 lines
drivers/spi/fsl_dspi.c new file +5 -0
+};
+
+static uint dspi_read32(struct udevice *bus, uint offset)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);

blank line between declarations and code (throughout)

Quoted 7 lines

drivers/spi/fsl_dspi.c line 75

Quoted 2 lines
drivers/spi/fsl_dspi.c new file +2 -0
+       return plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               in_be32(plat->regs + offset) : in_le32(plat->regs + offset);

I think it is better to put regs in your private data rather than platform data. Platform data should be used in your probe function mostly. It's OK to use it sparing for uncommon things, but this feels like something that should be in private data.

OK, I will move it.

Quoted 6 lines

I have tended to put an fdt_addr_t in platform data and a struct reg_definition * in private data.

Also where is your C structure for the registers? We normally use that sort of thing in U-Boot.

There is no obvious difference between the two methods. And I think the code seems more clean in current way.

Quoted 31 lines
Quoted 31 lines
drivers/spi/fsl_dspi.c new file +30 -0
+}
+
+static void dspi_write32(struct udevice *bus, uint offset, uint val)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               out_be32(plat->regs + offset, val) :
+               out_le32(plat->regs + offset, val);
+       return;
+}
+
+static void dspi_halt(struct udevice *bus, u8 halt)
+{
+       uint mcr_val;
+
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+
+       if (halt)
+               mcr_val |= DSPI_MCR_HALT;
+       else
+               mcr_val &= ~DSPI_MCR_HALT;
+
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       return;
+}
+
+static int fsl_dspi_child_pre_probe(struct udevice *dev)
+{
+       struct dm_spi_slave_platdata *slave_plat =
Quoted 8 lines

drivers/spi/fsl_dspi.c line 110

Quoted 6 lines

dev_get_parent_platdata(dev);

drivers/spi/fsl_dspi.c new file +5 -0
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+
+       if (slave_plat->cs >= priv->num_chipselect) {
+               printf("DSPI invalid chipselect number %d(max %d)!\n",
+                      slave_plat->cs, priv->num_chipselect - 1);

Maybe you want debug() here, up to you.

OK.

Quoted 87 lines

drivers/spi/fsl_dspi.c line 116

Quoted 7 lines
drivers/spi/fsl_dspi.c new file +6 -0
+               return -EINVAL;
+       }
+
+       priv->ctar_val[slave_plat->cs] = DSPI_CTAR_DEFAULT_VALUE;
+
+       priv->cur_slave_plat = slave_plat;

Not sure what you are doing here?

drivers/spi/fsl_dspi.c line 127

Quoted 12 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       debug("DSPI pre_probe slave device on CS %u, max_hz %u, mode

0x%x.\n",

drivers/spi/fsl_dspi.c new file +9 -0
+             slave_plat->cs, slave_plat->max_hz, slave_plat->mode);
+
+       return 0;
+}
+
+static int fsl_dspi_child_post_remove(struct udevice *dev)
+{
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+       priv->cur_slave_plat = NULL;

or here?

Quoted 62 lines
drivers/spi/fsl_dspi.c new file +62 -0
+       return 0;
+}
+
+static int fsl_dspi_probe(struct udevice *bus)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_bus *dm_spi_bus;
+       uint mcr_val = 0;
+
+       dm_spi_bus = bus->uclass_priv;
+
+       /* get input clk frequency */
+       priv->bus_clk = mxc_get_clock(MXC_DSPI_CLK);
+       priv->regs = plat->regs;
+       priv->num_chipselect = plat->num_chipselect;
+       priv->baudrate = plat->baudrate;
+       /* frame data length in bits, default 8bits */
+       priv->charbit = 8;
+
+       dm_spi_bus->max_hz = plat->baudrate;
+
+       /* halt DSPI module */
+       dspi_halt(bus, 1);
+
+       /* default: all CS inactive state is high */
+       mcr_val |= DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK |
+               DSPI_MCR_CRXF | DSPI_MCR_CTXF;
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       /* resume module */
+       dspi_halt(bus, 0);
+
+       priv->mcr_val = mcr_val;
+
+       debug("%s probe done, bus-num %d.\n", bus->name, bus->seq);
+
+       return 0;
+}
+
+static int fsl_dspi_claim_bus(struct udevice *bus)
+{
+       uint mcr_val;
+
+       dspi_halt(bus, 1);
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+       /* flush RX and TX FIFO */
+       mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF);
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       dspi_halt(bus, 0);
+
+       return 0;
+}
+
+static int fsl_dspi_release_bus(struct udevice *bus)
+{
+       /* halt module */
+       dspi_halt(bus, 1);
+       return 0;
+}
+
Quoted 8 lines

drivers/spi/fsl_dspi.c line 193

Quoted 4 lines
drivers/spi/fsl_dspi.c new file +4 -0
+static void dspi_tx(struct udevice *bus, u32 ctrl, u16 data)
+{
+       while (((dspi_read32(bus, DSPI_SR) & 0x0000F000) >> 12) >= 4)
+               ;

Can this ever timeout/hang? Also why are you using u16 for the data? It doesn't seem necessary here or in the next function. You could use u32 I think?

fine, I will handle the timeout case. Max data size of every transfer is 16bits, so I use u16.

Quoted 40 lines

drivers/spi/fsl_dspi.c line 203

Quoted 11 lines
drivers/spi/fsl_dspi.c new file +10 -0
+
+       dspi_write32(bus, DSPI_TFR, (ctrl | data));
+
+       return;
+}
+
+static u16 dspi_rx(struct udevice *bus)
+{
+       while ((dspi_read32(bus, DSPI_SR) & 0x000000F0) == 0)
+               ;

or this?

Quoted 11 lines
drivers/spi/fsl_dspi.c new file +9 -0
+
+       return (u16)(dspi_read32(bus, DSPI_RFR) & 0xFFFF);
+}
+
+static int fsl_dspi_xfer(struct udevice *dev, unsigned int bitlen,
+               const void *dout, void *din, unsigned long flags)
+{
+       struct fsl_dspi_priv *priv;
+       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

drivers/spi/fsl_dspi.c new file +1 -0
+       struct udevice *bus;

drivers/spi/fsl_dspi.c line 223

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       u16 *spi_rd16 = NULL, *spi_wr16 = NULL;
+       u8 *spi_rd = NULL, *spi_wr = NULL;
+       static u32 ctrl;
+       uint len = bitlen >> 3;
+
+       bus = dev->parent;
+       if (bus)
+               priv = dev_get_priv(bus);
+       else
+               return -ENODEV;

This must have a parent. There is no need for this check. If someone calls this with the root device they deserve trouble! If you like you could have

Quoted 1 line

assert(bus);

I will remove.

Quoted 64 lines
Quoted 64 lines
drivers/spi/fsl_dspi.c new file +63 -0
+
+       if (priv->charbit == 16) {
+               bitlen >>= 1;
+               spi_wr16 = (u16 *)dout;
+               spi_rd16 = (u16 *)din;
+       } else {
+               spi_wr = (u8 *)dout;
+               spi_rd = (u8 *)din;
+       }
+
+       if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN)
+               ctrl |= DSPI_TFR_CONT;
+
+       ctrl = ctrl & DSPI_TFR_CONT;
+       ctrl = ctrl | DSPI_TFR_CTAS(0) | DSPI_TFR_PCS(slave_plat->cs);
+
+       if (len > 1) {
+               int tmp_len = len - 1;
+               while (tmp_len--) {
+                       if (dout != NULL) {
+                               if (priv->charbit == 16)
+                                       dspi_tx(bus, ctrl, *spi_wr16++);
+                               else
+                                       dspi_tx(bus, ctrl, *spi_wr++);
+                               dspi_rx(bus);
+                       }
+
+                       if (din != NULL) {
+                               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                               if (priv->charbit == 16)
+                                       *spi_rd16++ = dspi_rx(bus);
+                               else
+                                       *spi_rd++ = dspi_rx(bus);
+                       }
+               }
+
+               len = 1;        /* remaining byte */
+       }
+
+       if ((flags & SPI_XFER_END) == SPI_XFER_END)
+               ctrl &= ~DSPI_TFR_CONT;
+
+       if (len) {
+               if (dout != NULL) {
+                       if (priv->charbit == 16)
+                               dspi_tx(bus, ctrl, *spi_wr16);
+                       else
+                               dspi_tx(bus, ctrl, *spi_wr);
+                       dspi_rx(bus);
+               }
+
+               if (din != NULL) {
+                       dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                       if (priv->charbit == 16)
+                               *spi_rd16 = dspi_rx(bus);
+                       else
+                               *spi_rd = dspi_rx(bus);
+               }
+       } else {
+               /* dummy read */
+               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+               dspi_rx(bus);
+       }
Quoted 8 lines

drivers/spi/fsl_dspi.c line 292

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+
+       return 0;
+}
+
+static int fsl_dspi_hz_to_spi_baud(int *pbr, int *br,
+               int speed_hz, uint clkrate)

Should document args here.

Will add.

Quoted 37 lines
Quoted 37 lines
drivers/spi/fsl_dspi.c new file +36 -0
+{
+       /* Valid baud rate pre-scaler values */
+       int pbr_tbl[4] = {2, 3, 5, 7};
+       int brs[16] = {2, 4, 6, 8,
+               16, 32, 64, 128,
+               256, 512, 1024, 2048,
+               4096, 8192, 16384, 32768};
+       int temp, i = 0, j = 0;
+
+       temp = clkrate / speed_hz;
+
+       for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
+               for (j = 0; j < ARRAY_SIZE(brs); j++) {
+                       if (pbr_tbl[i] * brs[j] >= temp) {
+                               *pbr = i;
+                               *br = j;
+                               return 0;
+                       }
+               }
+
+       printf("Can not find valid baud rate,speed_hz is %d, ", speed_hz);
+       printf("clkrate is %d, we use the max prescaler value.\n", clkrate);
+
+       *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+       *br =  ARRAY_SIZE(brs) - 1;
+       return -EINVAL;
+}
+
+static int fsl_dspi_set_speed(struct udevice *bus, uint speed)
+{
+       u8 cs;
+       int ret;
+       uint bus_setup;
+       int best_i, best_j, bus_clk;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;
Quoted 8 lines

drivers/spi/fsl_dspi.c

Quoted 2 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       cs = slave_plat->cs;

You can't do this. Is the problem that you have a different speed setting for each chip select? If so then we should either fix the uclass interface to support this, or you could store the speed and adjust it just before the transfer. But in this function you don't know the chip select and should not try to guess it.

fine, CS is really not needed in this function, I will improve.

Quoted 32 lines
Quoted 32 lines
drivers/spi/fsl_dspi.c new file +8 -0
+
+       bus_clk = priv->bus_clk;
+
+       debug("DSPI set_speed: expected SCK speed %u, bus_clk %u.\n",
+             speed, bus_clk);
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~(DSPI_CTAR_DBR | DSPI_CTAR_PBR(0x3) |

DSPI_CTAR_BR(0xf));

drivers/spi/fsl_dspi.c new file +22 -0
+       bus_setup |= priv->ctar_val[cs];
+
+       ret = fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
+       if (ret) {
+               speed = priv->baudrate;
+               debug("DSPI set_speed use default SCK rate %u.\n", speed);
+               fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
+       }
+
+       bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       priv->baudrate = speed;
+
+       return 0;
+}
+
+static int fsl_dspi_set_mode(struct udevice *bus, uint mode)
+{
+       u8 cs;
+       uint bus_setup;
+       uint mcr_val;
Quoted 8 lines

drivers/spi/fsl_dspi.c line 366

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;
+
+       debug("DSPI set_mode: mode 0x%x.\n", mode);
+
+       cs = slave_plat->cs;

Similar point here.

[] Here is different from the above function, I need know the cs here, or I remove some configuration to other function?
There are two reasons about this.
A. We need configure transfer mode and clock attributes in CTAR register before transfer.
There are some other attributes except CPOL, CPHA, LSBFE in CTAR register. And those attributes value may be different between every chipselect device.
I get CPOL, CPHA, LSBFE from SPI uclass.
I can get the rest attributes' value by two methods, defining macros or reading from device tree.
I adopt the first method in this version.
Later I plan to add a attribute in flash device dts node.
My current process flow:
1. define macro for CTAR pre-configure value, CTAR pre-configure values may be different between every chipselect device and I only define one in this version, need improve.
2. Save CTAR pre-configure value in function 'child_pre_probe' identify with chipselect number.
3. And then write the CTAR pre-register value to register in function 'set_mode' according corresponding chipselect number.

B. when configure the state of PCSx active, I also need know the chipselect number because DSPI have more than one chipselect signal and they need be configured independently.

Quoted 32 lines
Quoted 32 lines
drivers/spi/fsl_dspi.c new file +31 -0
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~DSPI_CTAR_SET_MODE_MASK;
+       bus_setup |= priv->ctar_val[cs];
+       bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA | DSPI_CTAR_LSBFE);
+
+       if (mode & SPI_CPOL)
+               bus_setup |= DSPI_CTAR_CPOL;
+       if (mode & SPI_CPHA)
+               bus_setup |= DSPI_CTAR_CPHA;
+       if (mode & SPI_LSB_FIRST)
+               bus_setup |= DSPI_CTAR_LSBFE;
+
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       if (mode & SPI_CS_HIGH) {
+               dspi_halt(bus, 1);
+               mcr_val = dspi_read32(bus, DSPI_MCR);
+               /* CSx inactive state is low */
+               mcr_val &= ~DSPI_MCR_PCSIS(cs);
+               dspi_write32(bus, DSPI_MCR, mcr_val);
+               dspi_halt(bus, 0);
+       }
+
+       priv->mode = mode;
+       priv->charbit = ((dspi_read32(bus, DSPI_CTAR(0)) & 0x78000000)
+                == 0x78000000) ? 16 : 8;
+
+       return 0;
+}
+
Quoted 8 lines

drivers/spi/fsl_dspi.c line 401

Quoted 4 lines
drivers/spi/fsl_dspi.c new file +4 -0
+static int fsl_dspi_bind(struct udevice *bus)
+{
+       debug("%s assigned req_seq %d.\n", bus->name, bus->req_seq);
+       return 0;

You can drop this unless you want it for debugging. If the latter, please add a comment like /* This doesn't do anything except help with debugging */

I will add the comment.

Quoted 11 lines

drivers/spi/fsl_dspi.c line 411

Quoted 11 lines
drivers/spi/fsl_dspi.c new file +10 -0
+}
+
+static int fsl_dspi_ofdata_to_platdata(struct udevice *bus)
+{
+       uint addr;
+       struct fsl_dspi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
+
+       plat->flag = 0;

I will remove.

Quoted 8 lines

It will already be zero. All data allocated by driver model is zeroed.

drivers/spi/fsl_dspi.c line 414

Quoted 3 lines
drivers/spi/fsl_dspi.c new file +3 -0
+       if (fdtdec_get_bool(blob, node, "big-endian"))
+               plat->flag |= DSPI_FLAG_REGMAP_ENDIAN_BIG;
+

Extra black line here

Quoted 8 lines

drivers/spi/fsl_dspi.c line 419

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +3 -0
+
+       plat->num_chipselect =
+               fdtdec_get_int(blob, node, "num-cs",

FSL_DSPI_MAX_CHIPSELECT);

drivers/spi/fsl_dspi.c new file +2 -0
+
+       addr = fdtdec_get_addr(blob, node, "reg");

You can use dev_get_addr(dev) if you like.

any difference?

Quoted 10 lines

drivers/spi/fsl_dspi.c line 427

Quoted 9 lines
drivers/spi/fsl_dspi.c new file +8 -0
+       if (addr == FDT_ADDR_T_NONE) {
+               printf("DSPI: Can't get base address or size\n");
+               return -ENOMEM;
+       }
+       plat->regs = addr;
+
+       plat->baudrate =
+               fdtdec_get_int(blob, node, "spi-max-frequency", 10000000);
Quoted 2 lines

The name 'baudrate' bothers me, but that if that is what you normally call it on your hardware, then that is fine.

I will rename with "speed_hz", how about?

Quoted 69 lines
Quoted 69 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       debug("DSPI: regs=0x%x, max-frequency=%d, endianess=%s,

num-cs=%d\n",

drivers/spi/fsl_dspi.c new file +32 -0
+             plat->regs, plat->baudrate,
+             plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le",
+             plat->num_chipselect);
+
+       return 0;
+}
+static const struct dm_spi_ops fsl_dspi_ops = {
+       .claim_bus      = fsl_dspi_claim_bus,
+       .release_bus    = fsl_dspi_release_bus,
+       .xfer           = fsl_dspi_xfer,
+       .set_speed      = fsl_dspi_set_speed,
+       .set_mode       = fsl_dspi_set_mode,
+};
+
+static const struct udevice_id fsl_dspi_ids[] = {
+       { .compatible = "fsl,vf610-dspi" },
+       { }
+};
+
+U_BOOT_DRIVER(fsl_dspi) = {
+       .name   = "fsl_dspi",
+       .id     = UCLASS_SPI,
+       .of_match = fsl_dspi_ids,
+       .ops    = &fsl_dspi_ops,
+       .ofdata_to_platdata = fsl_dspi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct fsl_dspi_platdata),
+       .priv_auto_alloc_size = sizeof(struct fsl_dspi_priv),
+       .probe  = fsl_dspi_probe,
+       .child_pre_probe = fsl_dspi_child_pre_probe,
+       .child_post_remove = fsl_dspi_child_post_remove,
+       .bind = fsl_dspi_bind,
+};
include/fsl_dspi.h new file +27 -0
new file mode 100644
index 0000000..8cf02d3
@@ -0,0 +1,156 @@
+/*
+ * Freescale DSPI Module Defines
+ *
+ * Copyright (C) 2004-2007, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com)
+ * Chao Fu (B44548 at freesacle.com)
+ * Haikun Wang (B53464 at freescale.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _FSL_DSPI_H_
+#define _FSL_DSPI_H_
+
+/* DMA Serial Peripheral Interface (DSPI) */
+struct dspi {
+       u32 mcr;        /* 0x00 */
+       u32 resv0;      /* 0x04 */
+       u32 tcr;        /* 0x08 */
+       u32 ctar[8];    /* 0x0C - 0x28 */
+       u32 sr;         /* 0x2C */
+       u32 irsr;       /* 0x30 */
+       u32 tfr;        /* 0x34 - PUSHR */
+       u32 rfr;        /* 0x38 - POPR */
+#ifdef CONFIG_MCF547x_8x
+       u32 tfdr[4];    /* 0x3C */
+       u8 resv2[0x30]; /* 0x40 */
Quoted 8 lines

include/fsl_dspi.h line 32

Quoted 5 lines
include/fsl_dspi.h new file +5 -0
+       u32 rfdr[4];    /* 0x7C */
+#else
+       u32 tfdr[16];   /* 0x3C */
+       u32 rfdr[16];   /* 0x7C */
+#endif

Since you have this structure, can you not use it in your code for register access?

I copy it from the old driver. I will remove it if we keep the current registers access method.

Quoted 22 lines
Quoted 9 lines
include/fsl_dspi.h new file +8 -0
+};
+
+/* Module configuration */
+#define DSPI_MCR                        (0x0)
+#define DSPI_MCR_MSTR                  (0x80000000)
+#define DSPI_MCR_CSCK                  (0x40000000)
+#define DSPI_MCR_DCONF(x)              (((x)&0x03)<<28)
+#define DSPI_MCR_FRZ                   (0x08000000)

include/fsl_dspi.h line 50

Quoted 10 lines
include/fsl_dspi.h new file +10 -0
+#define DSPI_MCR_MTFE                  (0x04000000)
+#define DSPI_MCR_PCSSE                 (0x02000000)
+#define DSPI_MCR_ROOE                  (0x01000000)
+#define DSPI_MCR_PCSIS(x)               (1<<(16+(x)))
+#define DSPI_MCR_PCSIS_MASK             (0xff<<16)
+#define DSPI_MCR_CSIS7                 (0x00800000)
+#define DSPI_MCR_CSIS6                 (0x00400000)
+#define DSPI_MCR_CSIS5                 (0x00200000)
+#define DSPI_MCR_CSIS4                 (0x00100000)
+#define DSPI_MCR_CSIS3                 (0x00080000)

Please remove brackets where not needed

Quoted 12 lines

include/fsl_dspi.h line 60

Quoted 10 lines
include/fsl_dspi.h new file +10 -0
+#define DSPI_MCR_CSIS2                 (0x00040000)
+#define DSPI_MCR_CSIS1                 (0x00020000)
+#define DSPI_MCR_CSIS0                 (0x00010000)
+#define DSPI_MCR_DOZE                  (0x00008000)
+#define DSPI_MCR_MDIS                  (0x00004000)
+#define DSPI_MCR_DTXF                  (0x00002000)
+#define DSPI_MCR_DRXF                  (0x00001000)
+#define DSPI_MCR_CTXF                  (0x00000800)
+#define DSPI_MCR_CRXF                  (0x00000400)
+#define DSPI_MCR_SMPL_PT(x)            (((x)&0x03)<<8)

Spaces around operators

OK.

Quoted 3 lines

Also can you please use tabs instead of spaces to indent things? It looks like these are spaces.

My mistake.

--

Best regards,
Wang Haikun

Quoted 104 lines
Quoted 98 lines
include/fsl_dspi.h new file +96 -1
+#define DSPI_MCR_FCPCS                 (0x00000001)
+#define DSPI_MCR_PES                   (0x00000001)
+#define DSPI_MCR_HALT                  (0x00000001)
+
+/* Transfer count */
+#define DSPI_TCR                        (0x8)
+#define DSPI_TCR_SPI_TCNT(x)           (((x)&0x0000FFFF)<<16)
+
+/* Clock and transfer attributes */
+#define DSPI_CTAR(x)                    (0x0c + (x * 4))
+#define DSPI_CTAR_DBR                  (0x80000000)
+#define DSPI_CTAR_TRSZ(x)              (((x)&0x0F)<<27)
+#define DSPI_CTAR_CPOL                 (0x04000000)
+#define DSPI_CTAR_CPHA                 (0x02000000)
+#define DSPI_CTAR_LSBFE                        (0x01000000)
+#define DSPI_CTAR_PCSSCK(x)            (((x)&0x03)<<22)
+#define DSPI_CTAR_PCSSCK_7CLK          (0x00A00000)
+#define DSPI_CTAR_PCSSCK_5CLK          (0x00800000)
+#define DSPI_CTAR_PCSSCK_3CLK          (0x00400000)
+#define DSPI_CTAR_PCSSCK_1CLK          (0x00000000)
+#define DSPI_CTAR_PASC(x)              (((x)&0x03)<<20)
+#define DSPI_CTAR_PASC_7CLK            (0x00300000)
+#define DSPI_CTAR_PASC_5CLK            (0x00200000)
+#define DSPI_CTAR_PASC_3CLK            (0x00100000)
+#define DSPI_CTAR_PASC_1CLK            (0x00000000)
+#define DSPI_CTAR_PDT(x)               (((x)&0x03)<<18)
+#define DSPI_CTAR_PDT_7CLK             (0x000A0000)
+#define DSPI_CTAR_PDT_5CLK             (0x00080000)
+#define DSPI_CTAR_PDT_3CLK             (0x00040000)
+#define DSPI_CTAR_PDT_1CLK             (0x00000000)
+#define DSPI_CTAR_PBR(x)               (((x)&0x03)<<16)
+#define DSPI_CTAR_PBR_7CLK             (0x00030000)
+#define DSPI_CTAR_PBR_5CLK             (0x00020000)
+#define DSPI_CTAR_PBR_3CLK             (0x00010000)
+#define DSPI_CTAR_PBR_1CLK             (0x00000000)
+#define DSPI_CTAR_CSSCK(x)             (((x)&0x0F)<<12)
+#define DSPI_CTAR_ASC(x)               (((x)&0x0F)<<8)
+#define DSPI_CTAR_DT(x)                        (((x)&0x0F)<<4)
+#define DSPI_CTAR_BR(x)                        (((x)&0x0F))
+
+/* Status */
+#define DSPI_SR                         (0x2c)
+#define DSPI_SR_TCF                    (0x80000000)
+#define DSPI_SR_TXRXS                  (0x40000000)
+#define DSPI_SR_EOQF                   (0x10000000)
+#define DSPI_SR_TFUF                   (0x08000000)
+#define DSPI_SR_TFFF                   (0x02000000)
+#define DSPI_SR_RFOF                   (0x00080000)
+#define DSPI_SR_RFDF                   (0x00020000)
+#define DSPI_SR_TXCTR(x)               (((x)&0x0F)<<12)
+#define DSPI_SR_TXPTR(x)               (((x)&0x0F)<<8)
+#define DSPI_SR_RXCTR(x)               (((x)&0x0F)<<4)
+#define DSPI_SR_RXPTR(x)               (((x)&0x0F))
+
+/* DMA/interrupt request selct and enable */
+#define DSPI_IRSR                       (0x30)
+#define DSPI_IRSR_TCFE                 (0x80000000)
+#define DSPI_IRSR_EOQFE                        (0x10000000)
+#define DSPI_IRSR_TFUFE                        (0x08000000)
+#define DSPI_IRSR_TFFFE                        (0x02000000)
+#define DSPI_IRSR_TFFFS                        (0x01000000)
+#define DSPI_IRSR_RFOFE                        (0x00080000)
+#define DSPI_IRSR_RFDFE                        (0x00020000)
+#define DSPI_IRSR_RFDFS                        (0x00010000)
+
+/* Transfer control - 32-bit access */
+#define DSPI_TFR                        (0x34)
+#define DSPI_TFR_PCS(x)                 (((1 << x) & 0x0000003f) << 16)
+#define DSPI_TFR_CONT                  (0x80000000)
+#define DSPI_TFR_CTAS(x)               (((x)&0x07)<<28)
+#define DSPI_TFR_EOQ                   (0x08000000)
+#define DSPI_TFR_CTCNT                 (0x04000000)
+#define DSPI_TFR_CS7                   (0x00800000)
+#define DSPI_TFR_CS6                   (0x00400000)
+#define DSPI_TFR_CS5                   (0x00200000)
+#define DSPI_TFR_CS4                   (0x00100000)
+#define DSPI_TFR_CS3                   (0x00080000)
+#define DSPI_TFR_CS2                   (0x00040000)
+#define DSPI_TFR_CS1                   (0x00020000)
+#define DSPI_TFR_CS0                   (0x00010000)
+
+/* Transfer Fifo */
+#define DSPI_TFR_TXDATA(x)             (((x)&0xFFFF))
+
+/* Bit definitions and macros for DRFR */
+#define DSPI_RFR                        (0x38)
+#define DSPI_RFR_RXDATA(x)             (((x)&0xFFFF))
+
+/* Bit definitions and macros for DTFDR group */
+#define DSPI_TFDR_TXDATA(x)            (((x)&0x0000FFFF))
+#define DSPI_TFDR_TXCMD(x)             (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for DRFDR group */
+#define DSPI_RFDR_RXDATA(x)            (((x)&0x0000FFFF))
+
+#endif                         /* _FSL_DSPI_H_ */
--
Quoted 2 lines

2.1.0.27.g96db324

Regards,
Simon

A message that is not in the archive (sent off-list or not yet received): BN1PR0301MB0612FD5918F16525B9EF615EF81E0@BN1PR0301MB0612.namprd03.prod.outlook.com

#4 lore raw

PATCH 1/1 dm : spi: Convert Freescale DSPI to driver model

+Tom for the coding style question

Hi,

Quoted 160 lines · Haikun.Wang at freescale.com
Quoted 81 lines

-----Original Message-----
From: sjg at google.com [mailto:sjg at google.com] On Behalf Of Simon Glass
Sent: Tuesday, March 03, 2015 2:56 AM
To: Wang Haikun-B53464
Cc: u-boot at lists.denx.de; Jagan Teki
Subject: Re: [U-Boot] [PATCH v1]dm : spi: Convert Freescale DSPI to driver model

Hi,

Quoted 6 lines · Haikun.Wang at freescale.com

Move the Freescale DSPI driver over to driver model.

---

This patch adds two new files drivers/spi/fsl_dspi.c and

include/fsl_dspi.h.

Quoted 4 lines

They will replace files drivers/spi/cf_spi.c and arch/m68k/include/asm/coldfire/dspi.h.
I need submit patch to remove them later.
Board dts files are also needed to make this change work.

Apart from one thing (the chip selects) this all looks correct to me. Some style comments below. Also the patch seems to be in Courier font!

I'm interested in your thoughts on what is missing from the SPI uclass too.

Quoted 37 lines

Changes in v1: None

drivers/spi/Makefile | 1 +
drivers/spi/fsl_dspi.c | 461
+++++++++++++++++++++++++++++++++++++++++++++++++
include/fsl_dspi.h | 156 +++++++++++++++++

3 files changed, 618 insertions(+)

create mode 100644 drivers/spi/fsl_dspi.c create mode 100644 include/fsl_dspi.h

drivers/spi/Makefile index renamed from drivers/spi/Makefile +0 -0

edbd520..9c2b8de 100644

drivers/spi/Makefile +0 -0
@@ -49,3 +49,4 @@ obj-$(CONFIG_TI_QSPI) += ti_qspi.o

obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o

drivers/spi/Makefile +1 -0
+obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
drivers/spi/fsl_dspi.c new file renamed from drivers/spi/fsl_dspi.c +0 -0

mode 100644 index 0000000..69c037b

drivers/spi/fsl_dspi.c new file +12 -0
@@ -0,0 +1,461 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com)
+ * Chao Fu (B44548 at freescale.com)
+ * Haikun Wang (B53464 at freescale.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#include <dm.h>

drivers/spi/fsl_dspi.c line 22

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+#include <errno.h>
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <fdtdec.h>
+#include <asm/arch/clock.h>
+#include <fsl_dspi.h>
+
+

Remove extract blank line

Quoted 10 lines

drivers/spi/fsl_dspi.c line 29

Quoted 7 lines
drivers/spi/fsl_dspi.c new file +7 -0
+DECLARE_GLOBAL_DATA_PTR;
+
+/* fsl_dspi_platdata flag */
+#define DSPI_FLAG_REGMAP_ENDIAN_BIG    (1 << 0)
+
+/* idle data value */
+#define DSPI_IDLE_VAL                 (0x0)

Please no brackets around simple constants (I understand if they are -ve, but this serves no purpose).

[] fine.

Quoted 17 lines
Quoted 17 lines
drivers/spi/fsl_dspi.c new file +16 -0
+
+/* max chipselect signals number */
+#define FSL_DSPI_MAX_CHIPSELECT        (6)
+
+/* CTAR register pre-configure value */
+#define DSPI_CTAR_DEFAULT_VALUE        (DSPI_CTAR_TRSZ(7) | \
+                                       DSPI_CTAR_PCSSCK_1CLK | \
+                                       DSPI_CTAR_PASC(0) | \
+                                       DSPI_CTAR_PDT(0) | \
+                                       DSPI_CTAR_CSSCK(0) | \
+                                       DSPI_CTAR_ASC(0) | \
+                                       DSPI_CTAR_DT(0))
+
+/* CTAR register pre-configure mask */
+#define DSPI_CTAR_SET_MODE_MASK        (DSPI_CTAR_TRSZ(15) | \
+                                       DSPI_CTAR_PCSSCK(3) | \
Quoted 8 lines

drivers/spi/fsl_dspi.c line 51

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+                                       DSPI_CTAR_PASC(3) | \
+                                       DSPI_CTAR_PDT(3) | \
+                                       DSPI_CTAR_CSSCK(15) | \
+                                       DSPI_CTAR_ASC(15) | \
+                                       DSPI_CTAR_DT(15))
+

Please comment these things below:

[] fine.

Quoted 34 lines

/**
* struct fsl_dspi_platdata - platform data for ... *
* @flag: some sort of flag and you can find the enum here...
...

Quoted 7 lines
drivers/spi/fsl_dspi.c new file +7 -0
+struct fsl_dspi_platdata {
+       uint flag;
+       uint baudrate;
+       uint num_chipselect;
+       uint regs;
+};
+

drivers/spi/fsl_dspi.c line 68

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+struct fsl_dspi_priv {
+       uint mode;
+       uint mcr_val;
+       uint bus_clk;
+       uint baudrate;
+       uint charbit;
+       uint num_chipselect;
+       uint ctar_val[FSL_DSPI_MAX_CHIPSELECT];
+       uint regs;
+       struct dm_spi_slave_platdata *cur_slave_plat;

What is that for?

drivers/spi/fsl_dspi.c line 73

Quoted 4 lines
drivers/spi/fsl_dspi.c new file +4 -0
+};
+
+static uint dspi_read32(struct udevice *bus, uint offset) {
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);

blank line between declarations and code (throughout)

Quoted 8 lines

drivers/spi/fsl_dspi.c line 75

Quoted 3 lines
drivers/spi/fsl_dspi.c new file +3 -0
+       return plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               in_be32(plat->regs + offset) : in_le32(plat->regs +
+ offset);

I think it is better to put regs in your private data rather than platform data. Platform data should be used in your probe function mostly. It's OK to use it sparing for uncommon things, but this feels like something that should be in private data.

Quoted 8 lines

[] Ok, I will move it.

Quoted 6 lines

I have tended to put an fdt_addr_t in platform data and a struct reg_definition * in private data.

Also where is your C structure for the registers? We normally use that sort of thing in U-Boot.

[] There is no obvious difference between the two methods. And I think the code seems more clean in current way.

See the bottom of this page.

http://www.denx.de/wiki/U-Boot/CodingStyle

Quoted 346 lines
Quoted 29 lines
Quoted 29 lines
drivers/spi/fsl_dspi.c new file +28 -0
+}
+
+static void dspi_write32(struct udevice *bus, uint offset, uint val)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               out_be32(plat->regs + offset, val) :
+               out_le32(plat->regs + offset, val);
+       return;
+}
+
+static void dspi_halt(struct udevice *bus, u8 halt) {
+       uint mcr_val;
+
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+
+       if (halt)
+               mcr_val |= DSPI_MCR_HALT;
+       else
+               mcr_val &= ~DSPI_MCR_HALT;
+
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       return;
+}
+
+static int fsl_dspi_child_pre_probe(struct udevice *dev) {
+       struct dm_spi_slave_platdata *slave_plat =
Quoted 8 lines

drivers/spi/fsl_dspi.c line 110

Quoted 6 lines

dev_get_parent_platdata(dev);

drivers/spi/fsl_dspi.c new file +5 -0
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+
+       if (slave_plat->cs >= priv->num_chipselect) {
+               printf("DSPI invalid chipselect number %d(max %d)!\n",
+                      slave_plat->cs, priv->num_chipselect - 1);

Maybe you want debug() here, up to you.

[] ok.

Quoted 82 lines

drivers/spi/fsl_dspi.c line 116

Quoted 7 lines
drivers/spi/fsl_dspi.c new file +6 -0
+               return -EINVAL;
+       }
+
+       priv->ctar_val[slave_plat->cs] = DSPI_CTAR_DEFAULT_VALUE;
+
+       priv->cur_slave_plat = slave_plat;

Not sure what you are doing here?

drivers/spi/fsl_dspi.c line 127

Quoted 11 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       debug("DSPI pre_probe slave device on CS %u, max_hz %u, mode

0x%x.\n",

drivers/spi/fsl_dspi.c new file +8 -0
+             slave_plat->cs, slave_plat->max_hz, slave_plat->mode);
+
+       return 0;
+}
+
+static int fsl_dspi_child_post_remove(struct udevice *dev) {
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+       priv->cur_slave_plat = NULL;

or here?

Quoted 58 lines
drivers/spi/fsl_dspi.c new file +58 -0
+       return 0;
+}
+
+static int fsl_dspi_probe(struct udevice *bus) {
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_bus *dm_spi_bus;
+       uint mcr_val = 0;
+
+       dm_spi_bus = bus->uclass_priv;
+
+       /* get input clk frequency */
+       priv->bus_clk = mxc_get_clock(MXC_DSPI_CLK);
+       priv->regs = plat->regs;
+       priv->num_chipselect = plat->num_chipselect;
+       priv->baudrate = plat->baudrate;
+       /* frame data length in bits, default 8bits */
+       priv->charbit = 8;
+
+       dm_spi_bus->max_hz = plat->baudrate;
+
+       /* halt DSPI module */
+       dspi_halt(bus, 1);
+
+       /* default: all CS inactive state is high */
+       mcr_val |= DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK |
+               DSPI_MCR_CRXF | DSPI_MCR_CTXF;
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       /* resume module */
+       dspi_halt(bus, 0);
+
+       priv->mcr_val = mcr_val;
+
+       debug("%s probe done, bus-num %d.\n", bus->name, bus->seq);
+
+       return 0;
+}
+
+static int fsl_dspi_claim_bus(struct udevice *bus) {
+       uint mcr_val;
+
+       dspi_halt(bus, 1);
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+       /* flush RX and TX FIFO */
+       mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF);
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       dspi_halt(bus, 0);
+
+       return 0;
+}
+
+static int fsl_dspi_release_bus(struct udevice *bus) {
+       /* halt module */
+       dspi_halt(bus, 1);
+       return 0;
+}
Quoted 8 lines

drivers/spi/fsl_dspi.c line 193

Quoted 4 lines
drivers/spi/fsl_dspi.c new file +4 -0
+
+static void dspi_tx(struct udevice *bus, u32 ctrl, u16 data) {
+       while (((dspi_read32(bus, DSPI_SR) & 0x0000F000) >> 12) >= 4)
+               ;

Can this ever timeout/hang? Also why are you using u16 for the data? It doesn't seem necessary here or in the next function. You could use u32 I think?

[] fine, I will handle the timeout case. Max data size of every transfer is 16bits, so I use u16.

Quoted 37 lines

drivers/spi/fsl_dspi.c line 203

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +9 -0
+
+       dspi_write32(bus, DSPI_TFR, (ctrl | data));
+
+       return;
+}
+
+static u16 dspi_rx(struct udevice *bus) {
+       while ((dspi_read32(bus, DSPI_SR) & 0x000000F0) == 0)
+               ;

or this?

Quoted 9 lines
drivers/spi/fsl_dspi.c new file +7 -0
+
+       return (u16)(dspi_read32(bus, DSPI_RFR) & 0xFFFF); }
+
+static int fsl_dspi_xfer(struct udevice *dev, unsigned int bitlen,
+               const void *dout, void *din, unsigned long flags) {
+       struct fsl_dspi_priv *priv;
+       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

drivers/spi/fsl_dspi.c new file +1 -0
+       struct udevice *bus;

drivers/spi/fsl_dspi.c line 223

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       u16 *spi_rd16 = NULL, *spi_wr16 = NULL;
+       u8 *spi_rd = NULL, *spi_wr = NULL;
+       static u32 ctrl;
+       uint len = bitlen >> 3;
+
+       bus = dev->parent;
+       if (bus)
+               priv = dev_get_priv(bus);
+       else
+               return -ENODEV;

This must have a parent. There is no need for this check. If someone calls this with the root device they deserve trouble! If you like you could have

Quoted 1 line

assert(bus);

[] fine, I will remove.

Quoted 64 lines
Quoted 64 lines
drivers/spi/fsl_dspi.c new file +63 -0
+
+       if (priv->charbit == 16) {
+               bitlen >>= 1;
+               spi_wr16 = (u16 *)dout;
+               spi_rd16 = (u16 *)din;
+       } else {
+               spi_wr = (u8 *)dout;
+               spi_rd = (u8 *)din;
+       }
+
+       if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN)
+               ctrl |= DSPI_TFR_CONT;
+
+       ctrl = ctrl & DSPI_TFR_CONT;
+       ctrl = ctrl | DSPI_TFR_CTAS(0) | DSPI_TFR_PCS(slave_plat->cs);
+
+       if (len > 1) {
+               int tmp_len = len - 1;
+               while (tmp_len--) {
+                       if (dout != NULL) {
+                               if (priv->charbit == 16)
+                                       dspi_tx(bus, ctrl, *spi_wr16++);
+                               else
+                                       dspi_tx(bus, ctrl, *spi_wr++);
+                               dspi_rx(bus);
+                       }
+
+                       if (din != NULL) {
+                               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                               if (priv->charbit == 16)
+                                       *spi_rd16++ = dspi_rx(bus);
+                               else
+                                       *spi_rd++ = dspi_rx(bus);
+                       }
+               }
+
+               len = 1;        /* remaining byte */
+       }
+
+       if ((flags & SPI_XFER_END) == SPI_XFER_END)
+               ctrl &= ~DSPI_TFR_CONT;
+
+       if (len) {
+               if (dout != NULL) {
+                       if (priv->charbit == 16)
+                               dspi_tx(bus, ctrl, *spi_wr16);
+                       else
+                               dspi_tx(bus, ctrl, *spi_wr);
+                       dspi_rx(bus);
+               }
+
+               if (din != NULL) {
+                       dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                       if (priv->charbit == 16)
+                               *spi_rd16 = dspi_rx(bus);
+                       else
+                               *spi_rd = dspi_rx(bus);
+               }
+       } else {
+               /* dummy read */
+               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+               dspi_rx(bus);
+       }
Quoted 8 lines

drivers/spi/fsl_dspi.c line 292

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+
+       return 0;
+}
+
+static int fsl_dspi_hz_to_spi_baud(int *pbr, int *br,
+               int speed_hz, uint clkrate)

Should document args here.

[] fine, I will add.

Quoted 39 lines
Quoted 12 lines
drivers/spi/fsl_dspi.c new file +11 -0
+{
+       /* Valid baud rate pre-scaler values */
+       int pbr_tbl[4] = {2, 3, 5, 7};
+       int brs[16] = {2, 4, 6, 8,
+               16, 32, 64, 128,
+               256, 512, 1024, 2048,
+               4096, 8192, 16384, 32768};
+       int temp, i = 0, j = 0;
+
+       temp = clkrate / speed_hz;
+

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
+               for (j = 0; j < ARRAY_SIZE(brs); j++) {
+                       if (pbr_tbl[i] * brs[j] >= temp) {
+                               *pbr = i;
+                               *br = j;
+                               return 0;
+                       }
+               }
+
+       printf("Can not find valid baud rate,speed_hz is %d, ",

speed_hz);

Quoted 16 lines
drivers/spi/fsl_dspi.c new file +16 -0
+       printf("clkrate is %d, we use the max prescaler value.\n",
+ clkrate);
+
+       *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+       *br =  ARRAY_SIZE(brs) - 1;
+       return -EINVAL;
+}
+
+static int fsl_dspi_set_speed(struct udevice *bus, uint speed) {
+       u8 cs;
+       int ret;
+       uint bus_setup;
+       int best_i, best_j, bus_clk;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_slave_platdata *slave_plat =
+priv->cur_slave_plat;
Quoted 8 lines

drivers/spi/fsl_dspi.c

Quoted 2 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       cs = slave_plat->cs;

You can't do this. Is the problem that you have a different speed setting for each chip select? If so then we should either fix the uclass interface to support this, or you could store the speed and adjust it just before the transfer. But in this function you don't know the chip select and should not try to guess it.

[]fine, CS is really not needed in this function, I will improve.

Quoted 34 lines
Quoted 10 lines
drivers/spi/fsl_dspi.c new file +8 -0
+
+       bus_clk = priv->bus_clk;
+
+       debug("DSPI set_speed: expected SCK speed %u, bus_clk %u.\n",
+             speed, bus_clk);
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~(DSPI_CTAR_DBR | DSPI_CTAR_PBR(0x3) |

DSPI_CTAR_BR(0xf));

drivers/spi/fsl_dspi.c

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+       bus_setup |= priv->ctar_val[cs];
+
+       ret = fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
+       if (ret) {
+               speed = priv->baudrate;
+               debug("DSPI set_speed use default SCK rate %u.\n",

speed);

Quoted 1 line

+ fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed,

bus_clk);

Quoted 15 lines
drivers/spi/fsl_dspi.c new file +15 -0
+       }
+
+       bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       priv->baudrate = speed;
+
+       return 0;
+}
+
+static int fsl_dspi_set_mode(struct udevice *bus, uint mode) {
+       u8 cs;
+       uint bus_setup;
+       uint mcr_val;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
Quoted 8 lines

drivers/spi/fsl_dspi.c line 366

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+       struct dm_spi_slave_platdata *slave_plat =
+priv->cur_slave_plat;
+
+       debug("DSPI set_mode: mode 0x%x.\n", mode);
+
+       cs = slave_plat->cs;

Similar point here.

[] Here is different from the above function, I need know the cs here, or I remove some configuration to other function? There are two reasons about this.
A. We need configure transfer mode and clock attributes in CTAR register before transfer.
There are some other attributes except CPOL, CPHA, LSBFE in CTAR register.
And those attributes value may be different between every chipselect device.
I get CPOL, CPHA, LSBFE from SPI uclass.
I can get the rest attributes' value by two methods, defining macros or reading from device tree.
I adopt the first method in this version.
Later I plan to add a attribute in flash device dts node.
My current process flow:
1. define macro for CTAR pre-configure value, CTAR pre-configure values may be different between every chipselect device and I only define one in this version, need improve.
2. Save CTAR pre-configure value in function 'child_pre_probe' identify with chipselect number.
3. And then write the CTAR pre-register value to register in function 'set_mode' according corresponding chipselect number.

Quoted 2 lines

B. when configure the state of PCSx active, I also need know the chipselect number because DSPI have more than one chipselect signal and they need be configured independently.

The current driver model SPI uclass only supports a single speed/mode for the whole bus. It does not understand different modes.

One option is to stop the speed/mode in the set_mode/set_speed() function and then action it the in the activate() method. By that point, you know the chip select and can do the right thing.

If you do that, then fsl_dspi_set_mode() will only store the value in priv, it will not touch the hardware.

Quoted 80 lines
Quoted 32 lines
Quoted 32 lines
drivers/spi/fsl_dspi.c new file +31 -0
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~DSPI_CTAR_SET_MODE_MASK;
+       bus_setup |= priv->ctar_val[cs];
+       bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA |
+ DSPI_CTAR_LSBFE);
+
+       if (mode & SPI_CPOL)
+               bus_setup |= DSPI_CTAR_CPOL;
+       if (mode & SPI_CPHA)
+               bus_setup |= DSPI_CTAR_CPHA;
+       if (mode & SPI_LSB_FIRST)
+               bus_setup |= DSPI_CTAR_LSBFE;
+
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       if (mode & SPI_CS_HIGH) {
+               dspi_halt(bus, 1);
+               mcr_val = dspi_read32(bus, DSPI_MCR);
+               /* CSx inactive state is low */
+               mcr_val &= ~DSPI_MCR_PCSIS(cs);
+               dspi_write32(bus, DSPI_MCR, mcr_val);
+               dspi_halt(bus, 0);
+       }
+
+       priv->mode = mode;
+       priv->charbit = ((dspi_read32(bus, DSPI_CTAR(0)) & 0x78000000)
+                == 0x78000000) ? 16 : 8;
+
+       return 0;
+}
Quoted 8 lines

drivers/spi/fsl_dspi.c line 401

Quoted 4 lines
drivers/spi/fsl_dspi.c new file +4 -0
+
+static int fsl_dspi_bind(struct udevice *bus) {
+       debug("%s assigned req_seq %d.\n", bus->name, bus->req_seq);
+       return 0;

You can drop this unless you want it for debugging. If the latter, please add a comment like /* This doesn't do anything except help with debugging */

[] fine, I will add the comment.

Quoted 12 lines

drivers/spi/fsl_dspi.c line 411

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +9 -0
+}
+
+static int fsl_dspi_ofdata_to_platdata(struct udevice *bus) {
+       uint addr;
+       struct fsl_dspi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
+
+       plat->flag = 0;

It will already be zero. All data allocated by driver model is zeroed.

[] fine, will remove.

Quoted 6 lines

drivers/spi/fsl_dspi.c line 414

Quoted 4 lines
drivers/spi/fsl_dspi.c new file +3 -0
+       if (fdtdec_get_bool(blob, node, "big-endian"))
+               plat->flag |= DSPI_FLAG_REGMAP_ENDIAN_BIG;
+

Extra black line here

Quoted 8 lines

drivers/spi/fsl_dspi.c line 419

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +3 -0
+
+       plat->num_chipselect =
+               fdtdec_get_int(blob, node, "num-cs",

FSL_DSPI_MAX_CHIPSELECT);

drivers/spi/fsl_dspi.c new file +2 -0
+
+       addr = fdtdec_get_addr(blob, node, "reg");

You can use dev_get_addr(dev) if you like.

[] any difference?

Quoted 11 lines
Quoted 10 lines
drivers/spi/fsl_dspi.c new file +9 -0
+       if (addr == FDT_ADDR_T_NONE) {
+               printf("DSPI: Can't get base address or size\n");
+               return -ENOMEM;
+       }
+       plat->regs = addr;
+
+       plat->baudrate =
+               fdtdec_get_int(blob, node, "spi-max-frequency",
+ 10000000);
Quoted 3 lines
Quoted 2 lines

The name 'baudrate' bothers me, but that if that is what you normally call it on your hardware, then that is fine.

[] fine, I will rename with "speed_hz", how about?

Sure.

Quoted 75 lines
Quoted 67 lines
Quoted 67 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       debug("DSPI: regs=0x%x, max-frequency=%d, endianess=%s,

num-cs=%d\n",

drivers/spi/fsl_dspi.c new file +32 -0
+             plat->regs, plat->baudrate,
+             plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le",
+             plat->num_chipselect);
+
+       return 0;
+}
+static const struct dm_spi_ops fsl_dspi_ops = {
+       .claim_bus      = fsl_dspi_claim_bus,
+       .release_bus    = fsl_dspi_release_bus,
+       .xfer           = fsl_dspi_xfer,
+       .set_speed      = fsl_dspi_set_speed,
+       .set_mode       = fsl_dspi_set_mode,
+};
+
+static const struct udevice_id fsl_dspi_ids[] = {
+       { .compatible = "fsl,vf610-dspi" },
+       { }
+};
+
+U_BOOT_DRIVER(fsl_dspi) = {
+       .name   = "fsl_dspi",
+       .id     = UCLASS_SPI,
+       .of_match = fsl_dspi_ids,
+       .ops    = &fsl_dspi_ops,
+       .ofdata_to_platdata = fsl_dspi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct fsl_dspi_platdata),
+       .priv_auto_alloc_size = sizeof(struct fsl_dspi_priv),
+       .probe  = fsl_dspi_probe,
+       .child_pre_probe = fsl_dspi_child_pre_probe,
+       .child_post_remove = fsl_dspi_child_post_remove,
+       .bind = fsl_dspi_bind,
+};
include/fsl_dspi.h new file mode renamed from include/fsl_dspi.h +0 -0

100644 index 0000000..8cf02d3

include/fsl_dspi.h new file +26 -0
@@ -0,0 +1,156 @@
+/*
+ * Freescale DSPI Module Defines
+ *
+ * Copyright (C) 2004-2007, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com)
+ * Chao Fu (B44548 at freesacle.com)
+ * Haikun Wang (B53464 at freescale.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _FSL_DSPI_H_
+#define _FSL_DSPI_H_
+
+/* DMA Serial Peripheral Interface (DSPI) */ struct dspi {
+       u32 mcr;        /* 0x00 */
+       u32 resv0;      /* 0x04 */
+       u32 tcr;        /* 0x08 */
+       u32 ctar[8];    /* 0x0C - 0x28 */
+       u32 sr;         /* 0x2C */
+       u32 irsr;       /* 0x30 */
+       u32 tfr;        /* 0x34 - PUSHR */
+       u32 rfr;        /* 0x38 - POPR */
+#ifdef CONFIG_MCF547x_8x
+       u32 tfdr[4];    /* 0x3C */
+       u8 resv2[0x30]; /* 0x40 */
Quoted 8 lines

include/fsl_dspi.h line 32

Quoted 5 lines
include/fsl_dspi.h new file +5 -0
+       u32 rfdr[4];    /* 0x7C */
+#else
+       u32 tfdr[16];   /* 0x3C */
+       u32 rfdr[16];   /* 0x7C */
+#endif

Since you have this structure, can you not use it in your code for register access?

Quoted 2 lines

[] I copy it from the old driver. I will remove it if we keep the current registers access method.

Quoted 1 line

That seems to go against U-Boot style to me.

Regards,
Simon

#5 lore raw

PATCH 1/1 dm : spi: Convert Freescale DSPI to driver model

In reply to Haikun.Wang at freescale.com

Hi

Quoted 4 lines · Haikun.Wang at freescale.com

Move the Freescale DSPI driver over to driver model.

Signed-off-by Haikun Wang <B53464 at freescale.com<mailto:

[email protected]>>

Quoted 3 lines

---

This patch adds two new files drivers/spi/fsl_dspi.c and

include/fsl_dspi.h.

Quoted 1 line

They will replace files drivers/spi/cf_spi.c and

arch/m68k/include/asm/coldfire/dspi.h.

Quoted 7 lines

I need submit patch to remove them later.
Board dts files are also needed to make this change work.

Changes in v1: None

 drivers/spi/Makefile   |   1 +
 drivers/spi/fsl_dspi.c | 461

+++++++++++++++++++++++++++++++++++++++++++++++++

Quoted 23 lines
 include/fsl_dspi.h     | 156 +++++++++++++++++
 3 files changed, 618 insertions(+)
 create mode 100644 drivers/spi/fsl_dspi.c
 create mode 100644 include/fsl_dspi.h
drivers/spi/Makefile +1 -0
index edbd520..9c2b8de 100644
@@ -49,3 +49,4 @@ obj-$(CONFIG_TI_QSPI) += ti_qspi.o
 obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
 obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
+obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
drivers/spi/fsl_dspi.c new file +3 -0
new file mode 100644
index 0000000..69c037b
@@ -0,0 +1,461 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de<mailto:[email protected]
Quoted 4 lines

.
+ *
+ * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com<mailto:

[email protected]>)

Quoted 6 lines

+ * Chao Fu (B44548 at freescale.com<mailto:[email protected]>)
+ * Haikun Wang (B53464 at freescale.com<mailto:[email protected]>)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */

drivers/spi/fsl_dspi.c new file +1 -0
+#include <dm.h>

drivers/spi/fsl_dspi.c line 22

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+#include <errno.h>
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <fdtdec.h>
+#include <asm/arch/clock.h>
+#include <fsl_dspi.h>
+
+

Extra here

Quoted 43 lines
drivers/spi/fsl_dspi.c new file +43 -0
+DECLARE_GLOBAL_DATA_PTR;
+
+/* fsl_dspi_platdata flag */
+#define DSPI_FLAG_REGMAP_ENDIAN_BIG    (1 << 0)
+
+/* idle data value */
+#define DSPI_IDLE_VAL                 (0x0)
+
+/* max chipselect signals number */
+#define FSL_DSPI_MAX_CHIPSELECT        (6)
+
+/* CTAR register pre-configure value */
+#define DSPI_CTAR_DEFAULT_VALUE        (DSPI_CTAR_TRSZ(7) | \
+                                       DSPI_CTAR_PCSSCK_1CLK | \
+                                       DSPI_CTAR_PASC(0) | \
+                                       DSPI_CTAR_PDT(0) | \
+                                       DSPI_CTAR_CSSCK(0) | \
+                                       DSPI_CTAR_ASC(0) | \
+                                       DSPI_CTAR_DT(0))
+
+/* CTAR register pre-configure mask */
+#define DSPI_CTAR_SET_MODE_MASK        (DSPI_CTAR_TRSZ(15) | \
+                                       DSPI_CTAR_PCSSCK(3) | \
+                                       DSPI_CTAR_PASC(3) | \
+                                       DSPI_CTAR_PDT(3) | \
+                                       DSPI_CTAR_CSSCK(15) | \
+                                       DSPI_CTAR_ASC(15) | \
+                                       DSPI_CTAR_DT(15))
+
+struct fsl_dspi_platdata {
+       uint flag;
+       uint baudrate;
+       uint num_chipselect;
+       uint regs;
+};
+
+struct fsl_dspi_priv {
+       uint mode;
+       uint mcr_val;
+       uint bus_clk;
+       uint baudrate;
+       uint charbit;
+       uint num_chipselect;

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       uint ctar_val[FSL_DSPI_MAX_CHIPSELECT];
+       uint regs;
+       struct dm_spi_slave_platdata *cur_slave_plat;
+};
+
+static uint dspi_read32(struct udevice *bus, uint offset)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       return plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               in_be32(plat->regs + offset) : in_le32(plat->regs +

offset);

drivers/spi/fsl_dspi.c line 84

Quoted 9 lines
drivers/spi/fsl_dspi.c new file +9 -0
+}
+
+static void dspi_write32(struct udevice *bus, uint offset, uint val)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               out_be32(plat->regs + offset, val) :
+               out_le32(plat->regs + offset, val);
+       return;

Remove return

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+}
+
+static void dspi_halt(struct udevice *bus, u8 halt)
+{
+       uint mcr_val;
+

drivers/spi/fsl_dspi.c line 100

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+
+       if (halt)
+               mcr_val |= DSPI_MCR_HALT;
+       else
+               mcr_val &= ~DSPI_MCR_HALT;
+
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       return;

Ditto

drivers/spi/fsl_dspi.c

Quoted 5 lines
drivers/spi/fsl_dspi.c new file +5 -0
+}
+
+static int fsl_dspi_child_pre_probe(struct udevice *dev)
+{
+       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

drivers/spi/fsl_dspi.c

Quoted 13 lines
drivers/spi/fsl_dspi.c new file +13 -0
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+
+       if (slave_plat->cs >= priv->num_chipselect) {
+               printf("DSPI invalid chipselect number %d(max %d)!\n",
+                      slave_plat->cs, priv->num_chipselect - 1);
+               return -EINVAL;
+       }
+
+       priv->ctar_val[slave_plat->cs] = DSPI_CTAR_DEFAULT_VALUE;
+
+       priv->cur_slave_plat = slave_plat;
+
+       debug("DSPI pre_probe slave device on CS %u, max_hz %u, mode

0x%x.\n",

drivers/spi/fsl_dspi.c line 128

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+             slave_plat->cs, slave_plat->max_hz, slave_plat->mode);
+
+       return 0;
+}
+
+static int fsl_dspi_child_post_remove(struct udevice *dev)
+{
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+       priv->cur_slave_plat = NULL;
+       return 0;

Make it void?

Quoted 56 lines
drivers/spi/fsl_dspi.c new file +56 -0
+}
+
+static int fsl_dspi_probe(struct udevice *bus)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_bus *dm_spi_bus;
+       uint mcr_val = 0;
+
+       dm_spi_bus = bus->uclass_priv;
+
+       /* get input clk frequency */
+       priv->bus_clk = mxc_get_clock(MXC_DSPI_CLK);
+       priv->regs = plat->regs;
+       priv->num_chipselect = plat->num_chipselect;
+       priv->baudrate = plat->baudrate;
+       /* frame data length in bits, default 8bits */
+       priv->charbit = 8;
+
+       dm_spi_bus->max_hz = plat->baudrate;
+
+       /* halt DSPI module */
+       dspi_halt(bus, 1);
+
+       /* default: all CS inactive state is high */
+       mcr_val |= DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK |
+               DSPI_MCR_CRXF | DSPI_MCR_CTXF;
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       /* resume module */
+       dspi_halt(bus, 0);
+
+       priv->mcr_val = mcr_val;
+
+       debug("%s probe done, bus-num %d.\n", bus->name, bus->seq);
+
+       return 0;
+}
+
+static int fsl_dspi_claim_bus(struct udevice *bus)
+{
+       uint mcr_val;
+
+       dspi_halt(bus, 1);
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+       /* flush RX and TX FIFO */
+       mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF);
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       dspi_halt(bus, 0);
+
+       return 0;
+}
+
+static int fsl_dspi_release_bus(struct udevice *bus)
+{

drivers/spi/fsl_dspi.c line 194

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       /* halt module */
+       dspi_halt(bus, 1);
+       return 0;
+}
+
+static void dspi_tx(struct udevice *bus, u32 ctrl, u16 data)
+{
+       while (((dspi_read32(bus, DSPI_SR) & 0x0000F000) >> 12) >= 4)
+               ;
+

Remove inf loop

drivers/spi/fsl_dspi.c line 204

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       dspi_write32(bus, DSPI_TFR, (ctrl | data));
+
+       return;
+}
+
+static u16 dspi_rx(struct udevice *bus)
+{
+       while ((dspi_read32(bus, DSPI_SR) & 0x000000F0) == 0)
+               ;
+

Ditto

I stop here. I have reviewed with a mobile phone

Michael

drivers/spi/fsl_dspi.c

Quoted 8 lines
drivers/spi/fsl_dspi.c new file +8 -0
+       return (u16)(dspi_read32(bus, DSPI_RFR) & 0xFFFF);
+}
+
+static int fsl_dspi_xfer(struct udevice *dev, unsigned int bitlen,
+               const void *dout, void *din, unsigned long flags)
+{
+       struct fsl_dspi_priv *priv;
+       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

Quoted 92 lines
drivers/spi/fsl_dspi.c new file +92 -0
+       struct udevice *bus;
+       u16 *spi_rd16 = NULL, *spi_wr16 = NULL;
+       u8 *spi_rd = NULL, *spi_wr = NULL;
+       static u32 ctrl;
+       uint len = bitlen >> 3;
+
+       bus = dev->parent;
+       if (bus)
+               priv = dev_get_priv(bus);
+       else
+               return -ENODEV;
+
+       if (priv->charbit == 16) {
+               bitlen >>= 1;
+               spi_wr16 = (u16 *)dout;
+               spi_rd16 = (u16 *)din;
+       } else {
+               spi_wr = (u8 *)dout;
+               spi_rd = (u8 *)din;
+       }
+
+       if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN)
+               ctrl |= DSPI_TFR_CONT;
+
+       ctrl = ctrl & DSPI_TFR_CONT;
+       ctrl = ctrl | DSPI_TFR_CTAS(0) | DSPI_TFR_PCS(slave_plat->cs);
+
+       if (len > 1) {
+               int tmp_len = len - 1;
+               while (tmp_len--) {
+                       if (dout != NULL) {
+                               if (priv->charbit == 16)
+                                       dspi_tx(bus, ctrl, *spi_wr16++);
+                               else
+                                       dspi_tx(bus, ctrl, *spi_wr++);
+                               dspi_rx(bus);
+                       }
+
+                       if (din != NULL) {
+                               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                               if (priv->charbit == 16)
+                                       *spi_rd16++ = dspi_rx(bus);
+                               else
+                                       *spi_rd++ = dspi_rx(bus);
+                       }
+               }
+
+               len = 1;        /* remaining byte */
+       }
+
+       if ((flags & SPI_XFER_END) == SPI_XFER_END)
+               ctrl &= ~DSPI_TFR_CONT;
+
+       if (len) {
+               if (dout != NULL) {
+                       if (priv->charbit == 16)
+                               dspi_tx(bus, ctrl, *spi_wr16);
+                       else
+                               dspi_tx(bus, ctrl, *spi_wr);
+                       dspi_rx(bus);
+               }
+
+               if (din != NULL) {
+                       dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                       if (priv->charbit == 16)
+                               *spi_rd16 = dspi_rx(bus);
+                       else
+                               *spi_rd = dspi_rx(bus);
+               }
+       } else {
+               /* dummy read */
+               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+               dspi_rx(bus);
+       }
+
+       return 0;
+}
+
+static int fsl_dspi_hz_to_spi_baud(int *pbr, int *br,
+               int speed_hz, uint clkrate)
+{
+       /* Valid baud rate pre-scaler values */
+       int pbr_tbl[4] = {2, 3, 5, 7};
+       int brs[16] = {2, 4, 6, 8,
+               16, 32, 64, 128,
+               256, 512, 1024, 2048,
+               4096, 8192, 16384, 32768};
+       int temp, i = 0, j = 0;
+
+       temp = clkrate / speed_hz;
+
+       for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+               for (j = 0; j < ARRAY_SIZE(brs); j++) {
+                       if (pbr_tbl[i] * brs[j] >= temp) {
+                               *pbr = i;
+                               *br = j;
+                               return 0;
+                       }
+               }
+
+       printf("Can not find valid baud rate,speed_hz is %d, ", speed_hz);
+       printf("clkrate is %d, we use the max prescaler value.\n",

clkrate);

Quoted 14 lines
drivers/spi/fsl_dspi.c new file +14 -0
+
+       *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+       *br =  ARRAY_SIZE(brs) - 1;
+       return -EINVAL;
+}
+
+static int fsl_dspi_set_speed(struct udevice *bus, uint speed)
+{
+       u8 cs;
+       int ret;
+       uint bus_setup;
+       int best_i, best_j, bus_clk;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+
+       cs = slave_plat->cs;
+
+       bus_clk = priv->bus_clk;
+
+       debug("DSPI set_speed: expected SCK speed %u, bus_clk %u.\n",
+             speed, bus_clk);
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~(DSPI_CTAR_DBR | DSPI_CTAR_PBR(0x3) |

DSPI_CTAR_BR(0xf));

Quoted 69 lines
drivers/spi/fsl_dspi.c new file +69 -0
+       bus_setup |= priv->ctar_val[cs];
+
+       ret = fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
+       if (ret) {
+               speed = priv->baudrate;
+               debug("DSPI set_speed use default SCK rate %u.\n", speed);
+               fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
+       }
+
+       bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       priv->baudrate = speed;
+
+       return 0;
+}
+
+static int fsl_dspi_set_mode(struct udevice *bus, uint mode)
+{
+       u8 cs;
+       uint bus_setup;
+       uint mcr_val;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;
+
+       debug("DSPI set_mode: mode 0x%x.\n", mode);
+
+       cs = slave_plat->cs;
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~DSPI_CTAR_SET_MODE_MASK;
+       bus_setup |= priv->ctar_val[cs];
+       bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA | DSPI_CTAR_LSBFE);
+
+       if (mode & SPI_CPOL)
+               bus_setup |= DSPI_CTAR_CPOL;
+       if (mode & SPI_CPHA)
+               bus_setup |= DSPI_CTAR_CPHA;
+       if (mode & SPI_LSB_FIRST)
+               bus_setup |= DSPI_CTAR_LSBFE;
+
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       if (mode & SPI_CS_HIGH) {
+               dspi_halt(bus, 1);
+               mcr_val = dspi_read32(bus, DSPI_MCR);
+               /* CSx inactive state is low */
+               mcr_val &= ~DSPI_MCR_PCSIS(cs);
+               dspi_write32(bus, DSPI_MCR, mcr_val);
+               dspi_halt(bus, 0);
+       }
+
+       priv->mode = mode;
+       priv->charbit = ((dspi_read32(bus, DSPI_CTAR(0)) & 0x78000000)
+                == 0x78000000) ? 16 : 8;
+
+       return 0;
+}
+
+static int fsl_dspi_bind(struct udevice *bus)
+{
+       debug("%s assigned req_seq %d.\n", bus->name, bus->req_seq);
+       return 0;
+}
+
+static int fsl_dspi_ofdata_to_platdata(struct udevice *bus)
+{
+       uint addr;
+       struct fsl_dspi_platdata *plat = bus->platdata;

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
+
+       plat->flag = 0;
+       if (fdtdec_get_bool(blob, node, "big-endian"))
+               plat->flag |= DSPI_FLAG_REGMAP_ENDIAN_BIG;
+
+
+       plat->num_chipselect =
+               fdtdec_get_int(blob, node, "num-cs",

FSL_DSPI_MAX_CHIPSELECT);

drivers/spi/fsl_dspi.c

Quoted 12 lines
drivers/spi/fsl_dspi.c new file +12 -0
+
+       addr = fdtdec_get_addr(blob, node, "reg");
+       if (addr == FDT_ADDR_T_NONE) {
+               printf("DSPI: Can't get base address or size\n");
+               return -ENOMEM;
+       }
+       plat->regs = addr;
+
+       plat->baudrate =
+               fdtdec_get_int(blob, node, "spi-max-frequency", 10000000);
+
+       debug("DSPI: regs=0x%x, max-frequency=%d, endianess=%s,

num-cs=%d\n",

Quoted 38 lines
drivers/spi/fsl_dspi.c new file +32 -0
+             plat->regs, plat->baudrate,
+             plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le",
+             plat->num_chipselect);
+
+       return 0;
+}
+static const struct dm_spi_ops fsl_dspi_ops = {
+       .claim_bus      = fsl_dspi_claim_bus,
+       .release_bus    = fsl_dspi_release_bus,
+       .xfer           = fsl_dspi_xfer,
+       .set_speed      = fsl_dspi_set_speed,
+       .set_mode       = fsl_dspi_set_mode,
+};
+
+static const struct udevice_id fsl_dspi_ids[] = {
+       { .compatible = "fsl,vf610-dspi" },
+       { }
+};
+
+U_BOOT_DRIVER(fsl_dspi) = {
+       .name   = "fsl_dspi",
+       .id     = UCLASS_SPI,
+       .of_match = fsl_dspi_ids,
+       .ops    = &fsl_dspi_ops,
+       .ofdata_to_platdata = fsl_dspi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct fsl_dspi_platdata),
+       .priv_auto_alloc_size = sizeof(struct fsl_dspi_priv),
+       .probe  = fsl_dspi_probe,
+       .child_pre_probe = fsl_dspi_child_pre_probe,
+       .child_post_remove = fsl_dspi_child_post_remove,
+       .bind = fsl_dspi_bind,
+};
include/fsl_dspi.h new file +0 -0
new file mode 100644
index 0000000..8cf02d3

include/fsl_dspi.h line 5

Quoted 5 lines
include/fsl_dspi.h new file +5 -0
@@ -0,0 +1,156 @@
+/*
+ * Freescale DSPI Module Defines
+ *
+ * Copyright (C) 2004-2007, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com<mailto:

[email protected]>)

Quoted 158 lines
include/fsl_dspi.h new file +151 -1
+ * Chao Fu (B44548 at freesacle.com<mailto:[email protected]>)
+ * Haikun Wang (B53464 at freescale.com<mailto:[email protected]>)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _FSL_DSPI_H_
+#define _FSL_DSPI_H_
+
+/* DMA Serial Peripheral Interface (DSPI) */
+struct dspi {
+       u32 mcr;        /* 0x00 */
+       u32 resv0;      /* 0x04 */
+       u32 tcr;        /* 0x08 */
+       u32 ctar[8];    /* 0x0C - 0x28 */
+       u32 sr;         /* 0x2C */
+       u32 irsr;       /* 0x30 */
+       u32 tfr;        /* 0x34 - PUSHR */
+       u32 rfr;        /* 0x38 - POPR */
+#ifdef CONFIG_MCF547x_8x
+       u32 tfdr[4];    /* 0x3C */
+       u8 resv2[0x30]; /* 0x40 */
+       u32 rfdr[4];    /* 0x7C */
+#else
+       u32 tfdr[16];   /* 0x3C */
+       u32 rfdr[16];   /* 0x7C */
+#endif
+};
+
+/* Module configuration */
+#define DSPI_MCR                        (0x0)
+#define DSPI_MCR_MSTR                  (0x80000000)
+#define DSPI_MCR_CSCK                  (0x40000000)
+#define DSPI_MCR_DCONF(x)              (((x)&0x03)<<28)
+#define DSPI_MCR_FRZ                   (0x08000000)
+#define DSPI_MCR_MTFE                  (0x04000000)
+#define DSPI_MCR_PCSSE                 (0x02000000)
+#define DSPI_MCR_ROOE                  (0x01000000)
+#define DSPI_MCR_PCSIS(x)               (1<<(16+(x)))
+#define DSPI_MCR_PCSIS_MASK             (0xff<<16)
+#define DSPI_MCR_CSIS7                 (0x00800000)
+#define DSPI_MCR_CSIS6                 (0x00400000)
+#define DSPI_MCR_CSIS5                 (0x00200000)
+#define DSPI_MCR_CSIS4                 (0x00100000)
+#define DSPI_MCR_CSIS3                 (0x00080000)
+#define DSPI_MCR_CSIS2                 (0x00040000)
+#define DSPI_MCR_CSIS1                 (0x00020000)
+#define DSPI_MCR_CSIS0                 (0x00010000)
+#define DSPI_MCR_DOZE                  (0x00008000)
+#define DSPI_MCR_MDIS                  (0x00004000)
+#define DSPI_MCR_DTXF                  (0x00002000)
+#define DSPI_MCR_DRXF                  (0x00001000)
+#define DSPI_MCR_CTXF                  (0x00000800)
+#define DSPI_MCR_CRXF                  (0x00000400)
+#define DSPI_MCR_SMPL_PT(x)            (((x)&0x03)<<8)
+#define DSPI_MCR_FCPCS                 (0x00000001)
+#define DSPI_MCR_PES                   (0x00000001)
+#define DSPI_MCR_HALT                  (0x00000001)
+
+/* Transfer count */
+#define DSPI_TCR                        (0x8)
+#define DSPI_TCR_SPI_TCNT(x)           (((x)&0x0000FFFF)<<16)
+
+/* Clock and transfer attributes */
+#define DSPI_CTAR(x)                    (0x0c + (x * 4))
+#define DSPI_CTAR_DBR                  (0x80000000)
+#define DSPI_CTAR_TRSZ(x)              (((x)&0x0F)<<27)
+#define DSPI_CTAR_CPOL                 (0x04000000)
+#define DSPI_CTAR_CPHA                 (0x02000000)
+#define DSPI_CTAR_LSBFE                        (0x01000000)
+#define DSPI_CTAR_PCSSCK(x)            (((x)&0x03)<<22)
+#define DSPI_CTAR_PCSSCK_7CLK          (0x00A00000)
+#define DSPI_CTAR_PCSSCK_5CLK          (0x00800000)
+#define DSPI_CTAR_PCSSCK_3CLK          (0x00400000)
+#define DSPI_CTAR_PCSSCK_1CLK          (0x00000000)
+#define DSPI_CTAR_PASC(x)              (((x)&0x03)<<20)
+#define DSPI_CTAR_PASC_7CLK            (0x00300000)
+#define DSPI_CTAR_PASC_5CLK            (0x00200000)
+#define DSPI_CTAR_PASC_3CLK            (0x00100000)
+#define DSPI_CTAR_PASC_1CLK            (0x00000000)
+#define DSPI_CTAR_PDT(x)               (((x)&0x03)<<18)
+#define DSPI_CTAR_PDT_7CLK             (0x000A0000)
+#define DSPI_CTAR_PDT_5CLK             (0x00080000)
+#define DSPI_CTAR_PDT_3CLK             (0x00040000)
+#define DSPI_CTAR_PDT_1CLK             (0x00000000)
+#define DSPI_CTAR_PBR(x)               (((x)&0x03)<<16)
+#define DSPI_CTAR_PBR_7CLK             (0x00030000)
+#define DSPI_CTAR_PBR_5CLK             (0x00020000)
+#define DSPI_CTAR_PBR_3CLK             (0x00010000)
+#define DSPI_CTAR_PBR_1CLK             (0x00000000)
+#define DSPI_CTAR_CSSCK(x)             (((x)&0x0F)<<12)
+#define DSPI_CTAR_ASC(x)               (((x)&0x0F)<<8)
+#define DSPI_CTAR_DT(x)                        (((x)&0x0F)<<4)
+#define DSPI_CTAR_BR(x)                        (((x)&0x0F))
+
+/* Status */
+#define DSPI_SR                         (0x2c)
+#define DSPI_SR_TCF                    (0x80000000)
+#define DSPI_SR_TXRXS                  (0x40000000)
+#define DSPI_SR_EOQF                   (0x10000000)
+#define DSPI_SR_TFUF                   (0x08000000)
+#define DSPI_SR_TFFF                   (0x02000000)
+#define DSPI_SR_RFOF                   (0x00080000)
+#define DSPI_SR_RFDF                   (0x00020000)
+#define DSPI_SR_TXCTR(x)               (((x)&0x0F)<<12)
+#define DSPI_SR_TXPTR(x)               (((x)&0x0F)<<8)
+#define DSPI_SR_RXCTR(x)               (((x)&0x0F)<<4)
+#define DSPI_SR_RXPTR(x)               (((x)&0x0F))
+
+/* DMA/interrupt request selct and enable */
+#define DSPI_IRSR                       (0x30)
+#define DSPI_IRSR_TCFE                 (0x80000000)
+#define DSPI_IRSR_EOQFE                        (0x10000000)
+#define DSPI_IRSR_TFUFE                        (0x08000000)
+#define DSPI_IRSR_TFFFE                        (0x02000000)
+#define DSPI_IRSR_TFFFS                        (0x01000000)
+#define DSPI_IRSR_RFOFE                        (0x00080000)
+#define DSPI_IRSR_RFDFE                        (0x00020000)
+#define DSPI_IRSR_RFDFS                        (0x00010000)
+
+/* Transfer control - 32-bit access */
+#define DSPI_TFR                        (0x34)
+#define DSPI_TFR_PCS(x)                 (((1 << x) & 0x0000003f) << 16)
+#define DSPI_TFR_CONT                  (0x80000000)
+#define DSPI_TFR_CTAS(x)               (((x)&0x07)<<28)
+#define DSPI_TFR_EOQ                   (0x08000000)
+#define DSPI_TFR_CTCNT                 (0x04000000)
+#define DSPI_TFR_CS7                   (0x00800000)
+#define DSPI_TFR_CS6                   (0x00400000)
+#define DSPI_TFR_CS5                   (0x00200000)
+#define DSPI_TFR_CS4                   (0x00100000)
+#define DSPI_TFR_CS3                   (0x00080000)
+#define DSPI_TFR_CS2                   (0x00040000)
+#define DSPI_TFR_CS1                   (0x00020000)
+#define DSPI_TFR_CS0                   (0x00010000)
+
+/* Transfer Fifo */
+#define DSPI_TFR_TXDATA(x)             (((x)&0xFFFF))
+
+/* Bit definitions and macros for DRFR */
+#define DSPI_RFR                        (0x38)
+#define DSPI_RFR_RXDATA(x)             (((x)&0xFFFF))
+
+/* Bit definitions and macros for DTFDR group */
+#define DSPI_TFDR_TXDATA(x)            (((x)&0x0000FFFF))
+#define DSPI_TFDR_TXCMD(x)             (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for DRFDR group */
+#define DSPI_RFDR_RXDATA(x)            (((x)&0x0000FFFF))
+
+#endif                         /* _FSL_DSPI_H_ */
--

2.1.0.27.g96db324

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

#6 lore raw

PATCH 1/1 dm : spi: Convert Freescale DSPI to driver model

Quoted 130 lines · Michael Trimarchi

Hi

Quoted 4 lines · On 1 Mar 2015 22:09, "Haikun.Wang at freescale.com…

Move the Freescale DSPI driver over to driver model.

<mailto:[email protected]><mailto:[email protected] <mailto:[email protected]>>>

Quoted 3 lines

---

This patch adds two new files drivers/spi/fsl_dspi.c and

include/fsl_dspi.h.

Quoted 1 line

They will replace files drivers/spi/cf_spi.c and

arch/m68k/include/asm/coldfire/dspi.h.

Quoted 7 lines

I need submit patch to remove them later.
Board dts files are also needed to make this change work.

Changes in v1: None

 drivers/spi/Makefile   |   1 +
 drivers/spi/fsl_dspi.c | 461

+++++++++++++++++++++++++++++++++++++++++++++++++

Quoted 20 lines
 include/fsl_dspi.h     | 156 +++++++++++++++++
 3 files changed, 618 insertions(+)
 create mode 100644 drivers/spi/fsl_dspi.c
 create mode 100644 include/fsl_dspi.h
drivers/spi/Makefile +1 -0
index edbd520..9c2b8de 100644
@@ -49,3 +49,4 @@ obj-$(CONFIG_TI_QSPI) += ti_qspi.o
 obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
 obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
+obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
drivers/spi/fsl_dspi.c new file +0 -0
new file mode 100644
index 0000000..69c037b

drivers/spi/fsl_dspi.c line 3

Quoted 3 lines
drivers/spi/fsl_dspi.c new file +3 -0
@@ -0,0 +1,461 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de

<mailto:[email protected]><mailto:wd at denx.de <mailto:[email protected]>>.

drivers/spi/fsl_dspi.c

Quoted 3 lines
drivers/spi/fsl_dspi.c new file +3 -0
+ *
+ * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com

<mailto:[email protected]><mailto:Tsi-Chung.Liew at freescale.com <mailto:[email protected]>>)

drivers/spi/fsl_dspi.c line 7

Quoted 1 line
drivers/spi/fsl_dspi.c new file +1 -0
+ * Chao Fu (B44548 at freescale.com

<mailto:[email protected]><mailto:[email protected] <mailto:[email protected]>>)

drivers/spi/fsl_dspi.c line 8

Quoted 1 line
drivers/spi/fsl_dspi.c new file +1 -0
+ * Haikun Wang (B53464 at freescale.com

<mailto:[email protected]><mailto:[email protected] <mailto:[email protected]>>)

Quoted 4 lines
drivers/spi/fsl_dspi.c new file +4 -0
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#include <dm.h>

drivers/spi/fsl_dspi.c line 22

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+#include <errno.h>
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <fdtdec.h>
+#include <asm/arch/clock.h>
+#include <fsl_dspi.h>
+
+

Extra here

Quoted 43 lines
drivers/spi/fsl_dspi.c new file +43 -0
+DECLARE_GLOBAL_DATA_PTR;
+
+/* fsl_dspi_platdata flag */
+#define DSPI_FLAG_REGMAP_ENDIAN_BIG    (1 << 0)
+
+/* idle data value */
+#define DSPI_IDLE_VAL                 (0x0)
+
+/* max chipselect signals number */
+#define FSL_DSPI_MAX_CHIPSELECT        (6)
+
+/* CTAR register pre-configure value */
+#define DSPI_CTAR_DEFAULT_VALUE        (DSPI_CTAR_TRSZ(7) | \
+                                       DSPI_CTAR_PCSSCK_1CLK | \
+                                       DSPI_CTAR_PASC(0) | \
+                                       DSPI_CTAR_PDT(0) | \
+                                       DSPI_CTAR_CSSCK(0) | \
+                                       DSPI_CTAR_ASC(0) | \
+                                       DSPI_CTAR_DT(0))
+
+/* CTAR register pre-configure mask */
+#define DSPI_CTAR_SET_MODE_MASK        (DSPI_CTAR_TRSZ(15) | \
+                                       DSPI_CTAR_PCSSCK(3) | \
+                                       DSPI_CTAR_PASC(3) | \
+                                       DSPI_CTAR_PDT(3) | \
+                                       DSPI_CTAR_CSSCK(15) | \
+                                       DSPI_CTAR_ASC(15) | \
+                                       DSPI_CTAR_DT(15))
+
+struct fsl_dspi_platdata {
+       uint flag;
+       uint baudrate;
+       uint num_chipselect;
+       uint regs;
+};
+
+struct fsl_dspi_priv {
+       uint mode;
+       uint mcr_val;
+       uint bus_clk;
+       uint baudrate;
+       uint charbit;
+       uint num_chipselect;

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       uint ctar_val[FSL_DSPI_MAX_CHIPSELECT];
+       uint regs;
+       struct dm_spi_slave_platdata *cur_slave_plat;
+};
+
+static uint dspi_read32(struct udevice *bus, uint offset)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       return plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               in_be32(plat->regs + offset) : in_le32(plat->regs +

offset);

Quoted 11 lines

drivers/spi/fsl_dspi.c line 84

Quoted 9 lines
drivers/spi/fsl_dspi.c new file +9 -0
+}
+
+static void dspi_write32(struct udevice *bus, uint offset, uint val)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
+               out_be32(plat->regs + offset, val) :
+               out_le32(plat->regs + offset, val);
+       return;

Remove return

OK.

Quoted 40 lines
Quoted 7 lines
drivers/spi/fsl_dspi.c new file +6 -0
+}
+
+static void dspi_halt(struct udevice *bus, u8 halt)
+{
+       uint mcr_val;
+

drivers/spi/fsl_dspi.c line 100

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+
+       if (halt)
+               mcr_val |= DSPI_MCR_HALT;
+       else
+               mcr_val &= ~DSPI_MCR_HALT;
+
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       return;

Ditto

drivers/spi/fsl_dspi.c

Quoted 5 lines
drivers/spi/fsl_dspi.c new file +5 -0
+}
+
+static int fsl_dspi_child_pre_probe(struct udevice *dev)
+{
+       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

drivers/spi/fsl_dspi.c

Quoted 13 lines
drivers/spi/fsl_dspi.c new file +13 -0
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+
+       if (slave_plat->cs >= priv->num_chipselect) {
+               printf("DSPI invalid chipselect number %d(max %d)!\n",
+                      slave_plat->cs, priv->num_chipselect - 1);
+               return -EINVAL;
+       }
+
+       priv->ctar_val[slave_plat->cs] = DSPI_CTAR_DEFAULT_VALUE;
+
+       priv->cur_slave_plat = slave_plat;
+
+       debug("DSPI pre_probe slave device on CS %u, max_hz %u, mode

0x%x.\n",

Quoted 12 lines

drivers/spi/fsl_dspi.c line 128

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+             slave_plat->cs, slave_plat->max_hz, slave_plat->mode);
+
+       return 0;
+}
+
+static int fsl_dspi_child_post_remove(struct udevice *dev)
+{
+       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
+       priv->cur_slave_plat = NULL;
+       return 0;

Make it void?

priv->cur_slave_plat point to the current slave device's data, if the slave device is removed, the data is invalid and the memory may be released.

Quoted 61 lines
Quoted 61 lines
drivers/spi/fsl_dspi.c new file +60 -0
+}
+
+static int fsl_dspi_probe(struct udevice *bus)
+{
+       struct fsl_dspi_platdata *plat = dev_get_platdata(bus);
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_bus *dm_spi_bus;
+       uint mcr_val = 0;
+
+       dm_spi_bus = bus->uclass_priv;
+
+       /* get input clk frequency */
+       priv->bus_clk = mxc_get_clock(MXC_DSPI_CLK);
+       priv->regs = plat->regs;
+       priv->num_chipselect = plat->num_chipselect;
+       priv->baudrate = plat->baudrate;
+       /* frame data length in bits, default 8bits */
+       priv->charbit = 8;
+
+       dm_spi_bus->max_hz = plat->baudrate;
+
+       /* halt DSPI module */
+       dspi_halt(bus, 1);
+
+       /* default: all CS inactive state is high */
+       mcr_val |= DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK |
+               DSPI_MCR_CRXF | DSPI_MCR_CTXF;
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       /* resume module */
+       dspi_halt(bus, 0);
+
+       priv->mcr_val = mcr_val;
+
+       debug("%s probe done, bus-num %d.\n", bus->name, bus->seq);
+
+       return 0;
+}
+
+static int fsl_dspi_claim_bus(struct udevice *bus)
+{
+       uint mcr_val;
+
+       dspi_halt(bus, 1);
+       mcr_val = dspi_read32(bus, DSPI_MCR);
+       /* flush RX and TX FIFO */
+       mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF);
+       dspi_write32(bus, DSPI_MCR, mcr_val);
+
+       dspi_halt(bus, 0);
+
+       return 0;
+}
+
+static int fsl_dspi_release_bus(struct udevice *bus)
+{
+       /* halt module */
+       dspi_halt(bus, 1);
+       return 0;
+}
Quoted 8 lines

drivers/spi/fsl_dspi.c line 194

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+
+static void dspi_tx(struct udevice *bus, u32 ctrl, u16 data)
+{
+       while (((dspi_read32(bus, DSPI_SR) & 0x0000F000) >> 12) >= 4)
+               ;
+

Remove inf loop

OK.

Signature · 2 lines
Best regards,
Wang Haikun
Quoted 460 lines

drivers/spi/fsl_dspi.c line 204

Quoted 11 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       dspi_write32(bus, DSPI_TFR, (ctrl | data));
+
+       return;
+}
+
+static u16 dspi_rx(struct udevice *bus)
+{
+       while ((dspi_read32(bus, DSPI_SR) & 0x000000F0) == 0)
+               ;
+

Ditto

I stop here. I have reviewed with a mobile phone

Michael

drivers/spi/fsl_dspi.c

Quoted 8 lines
drivers/spi/fsl_dspi.c new file +8 -0
+       return (u16)(dspi_read32(bus, DSPI_RFR) & 0xFFFF);
+}
+
+static int fsl_dspi_xfer(struct udevice *dev, unsigned int bitlen,
+               const void *dout, void *din, unsigned long flags)
+{
+       struct fsl_dspi_priv *priv;
+       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

Quoted 91 lines
drivers/spi/fsl_dspi.c new file +91 -0
+       struct udevice *bus;
+       u16 *spi_rd16 = NULL, *spi_wr16 = NULL;
+       u8 *spi_rd = NULL, *spi_wr = NULL;
+       static u32 ctrl;
+       uint len = bitlen >> 3;
+
+       bus = dev->parent;
+       if (bus)
+               priv = dev_get_priv(bus);
+       else
+               return -ENODEV;
+
+       if (priv->charbit == 16) {
+               bitlen >>= 1;
+               spi_wr16 = (u16 *)dout;
+               spi_rd16 = (u16 *)din;
+       } else {
+               spi_wr = (u8 *)dout;
+               spi_rd = (u8 *)din;
+       }
+
+       if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN)
+               ctrl |= DSPI_TFR_CONT;
+
+       ctrl = ctrl & DSPI_TFR_CONT;
+       ctrl = ctrl | DSPI_TFR_CTAS(0) | DSPI_TFR_PCS(slave_plat->cs);
+
+       if (len > 1) {
+               int tmp_len = len - 1;
+               while (tmp_len--) {
+                       if (dout != NULL) {
+                               if (priv->charbit == 16)
+                                       dspi_tx(bus, ctrl, *spi_wr16++);
+                               else
+                                       dspi_tx(bus, ctrl, *spi_wr++);
+                               dspi_rx(bus);
+                       }
+
+                       if (din != NULL) {
+                               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                               if (priv->charbit == 16)
+                                       *spi_rd16++ = dspi_rx(bus);
+                               else
+                                       *spi_rd++ = dspi_rx(bus);
+                       }
+               }
+
+               len = 1;        /* remaining byte */
+       }
+
+       if ((flags & SPI_XFER_END) == SPI_XFER_END)
+               ctrl &= ~DSPI_TFR_CONT;
+
+       if (len) {
+               if (dout != NULL) {
+                       if (priv->charbit == 16)
+                               dspi_tx(bus, ctrl, *spi_wr16);
+                       else
+                               dspi_tx(bus, ctrl, *spi_wr);
+                       dspi_rx(bus);
+               }
+
+               if (din != NULL) {
+                       dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+                       if (priv->charbit == 16)
+                               *spi_rd16 = dspi_rx(bus);
+                       else
+                               *spi_rd = dspi_rx(bus);
+               }
+       } else {
+               /* dummy read */
+               dspi_tx(bus, ctrl, DSPI_IDLE_VAL);
+               dspi_rx(bus);
+       }
+
+       return 0;
+}
+
+static int fsl_dspi_hz_to_spi_baud(int *pbr, int *br,
+               int speed_hz, uint clkrate)
+{
+       /* Valid baud rate pre-scaler values */
+       int pbr_tbl[4] = {2, 3, 5, 7};
+       int brs[16] = {2, 4, 6, 8,
+               16, 32, 64, 128,
+               256, 512, 1024, 2048,
+               4096, 8192, 16384, 32768};
+       int temp, i = 0, j = 0;
+
+       temp = clkrate / speed_hz;
+

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
+               for (j = 0; j < ARRAY_SIZE(brs); j++) {
+                       if (pbr_tbl[i] * brs[j] >= temp) {
+                               *pbr = i;
+                               *br = j;
+                               return 0;
+                       }
+               }
+
+       printf("Can not find valid baud rate,speed_hz is %d, ",

speed_hz);

drivers/spi/fsl_dspi.c line 314

Quoted 1 line
drivers/spi/fsl_dspi.c new file +1 -0
+       printf("clkrate is %d, we use the max prescaler value.\n",

clkrate);

Quoted 14 lines
drivers/spi/fsl_dspi.c new file +14 -0
+
+       *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+       *br =  ARRAY_SIZE(brs) - 1;
+       return -EINVAL;
+}
+
+static int fsl_dspi_set_speed(struct udevice *bus, uint speed)
+{
+       u8 cs;
+       int ret;
+       uint bus_setup;
+       int best_i, best_j, bus_clk;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);
+       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+
+       cs = slave_plat->cs;
+
+       bus_clk = priv->bus_clk;
+
+       debug("DSPI set_speed: expected SCK speed %u, bus_clk %u.\n",
+             speed, bus_clk);
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~(DSPI_CTAR_DBR | DSPI_CTAR_PBR(0x3) |

DSPI_CTAR_BR(0xf));

drivers/spi/fsl_dspi.c

Quoted 6 lines
drivers/spi/fsl_dspi.c new file +6 -0
+       bus_setup |= priv->ctar_val[cs];
+
+       ret = fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
+       if (ret) {
+               speed = priv->baudrate;
+               debug("DSPI set_speed use default SCK rate %u.\n",

speed);

drivers/spi/fsl_dspi.c line 345

Quoted 1 line
drivers/spi/fsl_dspi.c new file +1 -0
+               fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed,

bus_clk);

Quoted 16 lines
drivers/spi/fsl_dspi.c new file +16 -0
+       }
+
+       bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       priv->baudrate = speed;
+
+       return 0;
+}
+
+static int fsl_dspi_set_mode(struct udevice *bus, uint mode)
+{
+       u8 cs;
+       uint bus_setup;
+       uint mcr_val;
+       struct fsl_dspi_priv *priv = dev_get_priv(bus);

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;
+
+       debug("DSPI set_mode: mode 0x%x.\n", mode);
+
+       cs = slave_plat->cs;
+
+       bus_setup = dspi_read32(bus, DSPI_CTAR(0));
+       bus_setup &= ~DSPI_CTAR_SET_MODE_MASK;
+       bus_setup |= priv->ctar_val[cs];
+       bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA |

DSPI_CTAR_LSBFE);

Quoted 36 lines
drivers/spi/fsl_dspi.c new file +36 -0
+
+       if (mode & SPI_CPOL)
+               bus_setup |= DSPI_CTAR_CPOL;
+       if (mode & SPI_CPHA)
+               bus_setup |= DSPI_CTAR_CPHA;
+       if (mode & SPI_LSB_FIRST)
+               bus_setup |= DSPI_CTAR_LSBFE;
+
+       dspi_write32(bus, DSPI_CTAR(0), bus_setup);
+
+       if (mode & SPI_CS_HIGH) {
+               dspi_halt(bus, 1);
+               mcr_val = dspi_read32(bus, DSPI_MCR);
+               /* CSx inactive state is low */
+               mcr_val &= ~DSPI_MCR_PCSIS(cs);
+               dspi_write32(bus, DSPI_MCR, mcr_val);
+               dspi_halt(bus, 0);
+       }
+
+       priv->mode = mode;
+       priv->charbit = ((dspi_read32(bus, DSPI_CTAR(0)) & 0x78000000)
+                == 0x78000000) ? 16 : 8;
+
+       return 0;
+}
+
+static int fsl_dspi_bind(struct udevice *bus)
+{
+       debug("%s assigned req_seq %d.\n", bus->name, bus->req_seq);
+       return 0;
+}
+
+static int fsl_dspi_ofdata_to_platdata(struct udevice *bus)
+{
+       uint addr;
+       struct fsl_dspi_platdata *plat = bus->platdata;

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
+
+       plat->flag = 0;
+       if (fdtdec_get_bool(blob, node, "big-endian"))
+               plat->flag |= DSPI_FLAG_REGMAP_ENDIAN_BIG;
+
+
+       plat->num_chipselect =
+               fdtdec_get_int(blob, node, "num-cs",

FSL_DSPI_MAX_CHIPSELECT);

drivers/spi/fsl_dspi.c

Quoted 10 lines
drivers/spi/fsl_dspi.c new file +10 -0
+
+       addr = fdtdec_get_addr(blob, node, "reg");
+       if (addr == FDT_ADDR_T_NONE) {
+               printf("DSPI: Can't get base address or size\n");
+               return -ENOMEM;
+       }
+       plat->regs = addr;
+
+       plat->baudrate =
+               fdtdec_get_int(blob, node, "spi-max-frequency",

10000000);

drivers/spi/fsl_dspi.c line 429

Quoted 2 lines
drivers/spi/fsl_dspi.c new file +2 -0
+
+       debug("DSPI: regs=0x%x, max-frequency=%d, endianess=%s,

num-cs=%d\n",

Quoted 38 lines
drivers/spi/fsl_dspi.c new file +32 -0
+             plat->regs, plat->baudrate,
+             plat->flag & DSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le",
+             plat->num_chipselect);
+
+       return 0;
+}
+static const struct dm_spi_ops fsl_dspi_ops = {
+       .claim_bus      = fsl_dspi_claim_bus,
+       .release_bus    = fsl_dspi_release_bus,
+       .xfer           = fsl_dspi_xfer,
+       .set_speed      = fsl_dspi_set_speed,
+       .set_mode       = fsl_dspi_set_mode,
+};
+
+static const struct udevice_id fsl_dspi_ids[] = {
+       { .compatible = "fsl,vf610-dspi" },
+       { }
+};
+
+U_BOOT_DRIVER(fsl_dspi) = {
+       .name   = "fsl_dspi",
+       .id     = UCLASS_SPI,
+       .of_match = fsl_dspi_ids,
+       .ops    = &fsl_dspi_ops,
+       .ofdata_to_platdata = fsl_dspi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct fsl_dspi_platdata),
+       .priv_auto_alloc_size = sizeof(struct fsl_dspi_priv),
+       .probe  = fsl_dspi_probe,
+       .child_pre_probe = fsl_dspi_child_pre_probe,
+       .child_post_remove = fsl_dspi_child_post_remove,
+       .bind = fsl_dspi_bind,
+};
include/fsl_dspi.h new file +0 -0
new file mode 100644
index 0000000..8cf02d3

include/fsl_dspi.h line 5

Quoted 5 lines
include/fsl_dspi.h new file +5 -0
@@ -0,0 +1,156 @@
+/*
+ * Freescale DSPI Module Defines
+ *
+ * Copyright (C) 2004-2007, 2015 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at freescale.com

<mailto:[email protected]><mailto:Tsi-Chung.Liew at freescale.com <mailto:[email protected]>>)

include/fsl_dspi.h line 6

Quoted 1 line
include/fsl_dspi.h new file +1 -0
+ * Chao Fu (B44548 at freesacle.com

<mailto:[email protected]><mailto:[email protected] <mailto:[email protected]>>)

include/fsl_dspi.h line 7

Quoted 1 line
include/fsl_dspi.h new file +1 -0
+ * Haikun Wang (B53464 at freescale.com

<mailto:[email protected]><mailto:[email protected] <mailto:[email protected]>>)

Quoted 156 lines
include/fsl_dspi.h new file +149 -1
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _FSL_DSPI_H_
+#define _FSL_DSPI_H_
+
+/* DMA Serial Peripheral Interface (DSPI) */
+struct dspi {
+       u32 mcr;        /* 0x00 */
+       u32 resv0;      /* 0x04 */
+       u32 tcr;        /* 0x08 */
+       u32 ctar[8];    /* 0x0C - 0x28 */
+       u32 sr;         /* 0x2C */
+       u32 irsr;       /* 0x30 */
+       u32 tfr;        /* 0x34 - PUSHR */
+       u32 rfr;        /* 0x38 - POPR */
+#ifdef CONFIG_MCF547x_8x
+       u32 tfdr[4];    /* 0x3C */
+       u8 resv2[0x30]; /* 0x40 */
+       u32 rfdr[4];    /* 0x7C */
+#else
+       u32 tfdr[16];   /* 0x3C */
+       u32 rfdr[16];   /* 0x7C */
+#endif
+};
+
+/* Module configuration */
+#define DSPI_MCR                        (0x0)
+#define DSPI_MCR_MSTR                  (0x80000000)
+#define DSPI_MCR_CSCK                  (0x40000000)
+#define DSPI_MCR_DCONF(x)              (((x)&0x03)<<28)
+#define DSPI_MCR_FRZ                   (0x08000000)
+#define DSPI_MCR_MTFE                  (0x04000000)
+#define DSPI_MCR_PCSSE                 (0x02000000)
+#define DSPI_MCR_ROOE                  (0x01000000)
+#define DSPI_MCR_PCSIS(x)               (1<<(16+(x)))
+#define DSPI_MCR_PCSIS_MASK             (0xff<<16)
+#define DSPI_MCR_CSIS7                 (0x00800000)
+#define DSPI_MCR_CSIS6                 (0x00400000)
+#define DSPI_MCR_CSIS5                 (0x00200000)
+#define DSPI_MCR_CSIS4                 (0x00100000)
+#define DSPI_MCR_CSIS3                 (0x00080000)
+#define DSPI_MCR_CSIS2                 (0x00040000)
+#define DSPI_MCR_CSIS1                 (0x00020000)
+#define DSPI_MCR_CSIS0                 (0x00010000)
+#define DSPI_MCR_DOZE                  (0x00008000)
+#define DSPI_MCR_MDIS                  (0x00004000)
+#define DSPI_MCR_DTXF                  (0x00002000)
+#define DSPI_MCR_DRXF                  (0x00001000)
+#define DSPI_MCR_CTXF                  (0x00000800)
+#define DSPI_MCR_CRXF                  (0x00000400)
+#define DSPI_MCR_SMPL_PT(x)            (((x)&0x03)<<8)
+#define DSPI_MCR_FCPCS                 (0x00000001)
+#define DSPI_MCR_PES                   (0x00000001)
+#define DSPI_MCR_HALT                  (0x00000001)
+
+/* Transfer count */
+#define DSPI_TCR                        (0x8)
+#define DSPI_TCR_SPI_TCNT(x)           (((x)&0x0000FFFF)<<16)
+
+/* Clock and transfer attributes */
+#define DSPI_CTAR(x)                    (0x0c + (x * 4))
+#define DSPI_CTAR_DBR                  (0x80000000)
+#define DSPI_CTAR_TRSZ(x)              (((x)&0x0F)<<27)
+#define DSPI_CTAR_CPOL                 (0x04000000)
+#define DSPI_CTAR_CPHA                 (0x02000000)
+#define DSPI_CTAR_LSBFE                        (0x01000000)
+#define DSPI_CTAR_PCSSCK(x)            (((x)&0x03)<<22)
+#define DSPI_CTAR_PCSSCK_7CLK          (0x00A00000)
+#define DSPI_CTAR_PCSSCK_5CLK          (0x00800000)
+#define DSPI_CTAR_PCSSCK_3CLK          (0x00400000)
+#define DSPI_CTAR_PCSSCK_1CLK          (0x00000000)
+#define DSPI_CTAR_PASC(x)              (((x)&0x03)<<20)
+#define DSPI_CTAR_PASC_7CLK            (0x00300000)
+#define DSPI_CTAR_PASC_5CLK            (0x00200000)
+#define DSPI_CTAR_PASC_3CLK            (0x00100000)
+#define DSPI_CTAR_PASC_1CLK            (0x00000000)
+#define DSPI_CTAR_PDT(x)               (((x)&0x03)<<18)
+#define DSPI_CTAR_PDT_7CLK             (0x000A0000)
+#define DSPI_CTAR_PDT_5CLK             (0x00080000)
+#define DSPI_CTAR_PDT_3CLK             (0x00040000)
+#define DSPI_CTAR_PDT_1CLK             (0x00000000)
+#define DSPI_CTAR_PBR(x)               (((x)&0x03)<<16)
+#define DSPI_CTAR_PBR_7CLK             (0x00030000)
+#define DSPI_CTAR_PBR_5CLK             (0x00020000)
+#define DSPI_CTAR_PBR_3CLK             (0x00010000)
+#define DSPI_CTAR_PBR_1CLK             (0x00000000)
+#define DSPI_CTAR_CSSCK(x)             (((x)&0x0F)<<12)
+#define DSPI_CTAR_ASC(x)               (((x)&0x0F)<<8)
+#define DSPI_CTAR_DT(x)                        (((x)&0x0F)<<4)
+#define DSPI_CTAR_BR(x)                        (((x)&0x0F))
+
+/* Status */
+#define DSPI_SR                         (0x2c)
+#define DSPI_SR_TCF                    (0x80000000)
+#define DSPI_SR_TXRXS                  (0x40000000)
+#define DSPI_SR_EOQF                   (0x10000000)
+#define DSPI_SR_TFUF                   (0x08000000)
+#define DSPI_SR_TFFF                   (0x02000000)
+#define DSPI_SR_RFOF                   (0x00080000)
+#define DSPI_SR_RFDF                   (0x00020000)
+#define DSPI_SR_TXCTR(x)               (((x)&0x0F)<<12)
+#define DSPI_SR_TXPTR(x)               (((x)&0x0F)<<8)
+#define DSPI_SR_RXCTR(x)               (((x)&0x0F)<<4)
+#define DSPI_SR_RXPTR(x)               (((x)&0x0F))
+
+/* DMA/interrupt request selct and enable */
+#define DSPI_IRSR                       (0x30)
+#define DSPI_IRSR_TCFE                 (0x80000000)
+#define DSPI_IRSR_EOQFE                        (0x10000000)
+#define DSPI_IRSR_TFUFE                        (0x08000000)
+#define DSPI_IRSR_TFFFE                        (0x02000000)
+#define DSPI_IRSR_TFFFS                        (0x01000000)
+#define DSPI_IRSR_RFOFE                        (0x00080000)
+#define DSPI_IRSR_RFDFE                        (0x00020000)
+#define DSPI_IRSR_RFDFS                        (0x00010000)
+
+/* Transfer control - 32-bit access */
+#define DSPI_TFR                        (0x34)
+#define DSPI_TFR_PCS(x)                 (((1 << x) & 0x0000003f) << 16)
+#define DSPI_TFR_CONT                  (0x80000000)
+#define DSPI_TFR_CTAS(x)               (((x)&0x07)<<28)
+#define DSPI_TFR_EOQ                   (0x08000000)
+#define DSPI_TFR_CTCNT                 (0x04000000)
+#define DSPI_TFR_CS7                   (0x00800000)
+#define DSPI_TFR_CS6                   (0x00400000)
+#define DSPI_TFR_CS5                   (0x00200000)
+#define DSPI_TFR_CS4                   (0x00100000)
+#define DSPI_TFR_CS3                   (0x00080000)
+#define DSPI_TFR_CS2                   (0x00040000)
+#define DSPI_TFR_CS1                   (0x00020000)
+#define DSPI_TFR_CS0                   (0x00010000)
+
+/* Transfer Fifo */
+#define DSPI_TFR_TXDATA(x)             (((x)&0xFFFF))
+
+/* Bit definitions and macros for DRFR */
+#define DSPI_RFR                        (0x38)
+#define DSPI_RFR_RXDATA(x)             (((x)&0xFFFF))
+
+/* Bit definitions and macros for DTFDR group */
+#define DSPI_TFDR_TXDATA(x)            (((x)&0x0000FFFF))
+#define DSPI_TFDR_TXCMD(x)             (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for DRFDR group */
+#define DSPI_RFDR_RXDATA(x)            (((x)&0x0000FFFF))
+
+#endif                         /* _FSL_DSPI_H_ */
--

2.1.0.27.g96db324

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de <mailto:[email protected]>
http://lists.denx.de/mailman/listinfo/u-boot