[U-Boot] [PATCH v2] dm: spi: Convert Freescale DSPI driver to driver model

Simon Glass sjg at chromium.org
Mon Mar 9 21:54:53 CET 2015


Hi,

On 8 March 2015 at 23:35, Haikun Wang <haikun.wang at freescale.com> wrote:
> Move the Freescale DSPI driver over to driver model.
>
> Signed-off-by: Haikun Wang <Haikun.Wang at freescale.com>
> ---
>
> Changes in v2:
>         - Coding style cleanup
>         - Add some comments
>         - Use structures for I/O access
>         - Handle timeout case in 'dspi_tx' and 'dspi_rx'
>         - Move some register configurations from 'set_mode' to 'claim_bus'
>         - Rename structure fsl_dspi_platdata's member baudrate
>         - Remove some redundancy code
>
> Changes in v1: None
>
>  drivers/spi/Makefile   |   1 +
>  drivers/spi/fsl_dspi.c | 530 +++++++++++++++++++++++++++++++++++++++++++++++++
>  include/fsl_dspi.h     | 150 ++++++++++++++
>  3 files changed, 681 insertions(+)
>  create mode 100644 drivers/spi/fsl_dspi.c
>  create mode 100644 include/fsl_dspi.h
>
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index edbd520..9c2b8de 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -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
> diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c
> new file mode 100644
> index 0000000..6108041
> --- /dev/null
> +++ b/drivers/spi/fsl_dspi.c
> @@ -0,0 +1,530 @@
> +/*
> + * (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>
> +#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>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* fsl_dspi_platdata flags */
> +#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
> +
> +/* default SCK frequency, unit: HZ */
> +#define FSL_DSPI_DEFAULT_SCK_FREQ      10000000
> +
> +/* tx/rx data wait timeout value, unit: us */
> +#define DSPI_TXRX_WAIT_TIMEOUT         1000000
> +
> +/* 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 - platform data for Freescale DSPI
> + *
> + * @flags: Flags for DSPI DSPI_FLAG_...
> + * @speed_hz: Default SCK frequency
> + * @num_chipselect: Number of DSPI chipselect signals
> + * @regs_addr: Base address of DSPI registers
> + */
> +struct fsl_dspi_platdata {
> +       uint flags;
> +       uint speed_hz;
> +       uint num_chipselect;
> +       fdt_addr_t regs_addr;
> +};
> +
> +struct fsl_dspi_priv {

Comments on these members?

> +       uint flags;
> +       uint mode;
> +       uint mcr_val;
> +       uint bus_clk;
> +       uint speed_hz;
> +       uint charbit;
> +       uint num_chipselect;
> +       uint ctar_val[FSL_DSPI_MAX_CHIPSELECT];
> +       struct dspi *regs;
> +       struct dm_spi_slave_platdata *cur_slave_plat;
> +};
> +
> +static uint dspi_read32(uint flags, uint *addr)
> +{
> +       return flags & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
> +               in_be32(addr) : in_le32(addr);
> +}
> +
> +static void dspi_write32(uint flags, uint *addr, uint val)
> +{
> +       flags & DSPI_FLAG_REGMAP_ENDIAN_BIG ?
> +               out_be32(addr, val) : out_le32(addr, val);
> +}
> +
> +static void dspi_halt(struct udevice *bus, u8 halt)

nit: Should pass in priv instead of bus

> +{
> +       uint mcr_val;
> +       struct fsl_dspi_priv *priv = dev_get_priv(bus);
> +
> +       mcr_val = dspi_read32(priv->flags, &priv->regs->mcr);
> +
> +       if (halt)
> +               mcr_val |= DSPI_MCR_HALT;
> +       else
> +               mcr_val &= ~DSPI_MCR_HALT;
> +
> +       dspi_write32(priv->flags, &priv->regs->mcr, mcr_val);
> +}
> +
> +static int fsl_dspi_child_pre_probe(struct udevice *dev)
> +{
> +       struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
> +       struct fsl_dspi_priv *priv = dev_get_priv(dev->parent);
> +
> +       if (slave_plat->cs >= priv->num_chipselect) {
> +               debug("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;

You don't need to store this pointer. Just use
dev_get_parent_platdata(dev) whenever you need it. This function will
only be called once in general, to probe the device. If another device
is probed after this one, then you go back and use the first, the
pointer will still be pointing to the second.

A key point to note is that devices are typically only probed once.
You may see that 'sf probe' removes the old device first, but that is
to keep existing legacy behaviour, and is not done in general.

> +
> +       debug("DSPI pre_probe slave device on CS %u, max_hz %u, mode 0x%x.\n",
> +             slave_plat->cs, slave_plat->max_hz, slave_plat->mode);
> +
> +       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;
> +}
> +
> +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->regs = (struct dspi *)plat->regs_addr;
> +       priv->flags = plat->flags;
> +       priv->bus_clk = mxc_get_clock(MXC_DSPI_CLK);
> +       priv->num_chipselect = plat->num_chipselect;
> +       priv->speed_hz = plat->speed_hz;
> +       /* frame data length in bits, default 8bits */
> +       priv->charbit = 8;
> +
> +       dm_spi_bus->max_hz = plat->speed_hz;
> +
> +       /* halt DSPI module */
> +       dspi_halt(bus, 1);
> +
> +       /* default: all CS signals inactive state is high */
> +       mcr_val |= DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK |
> +               DSPI_MCR_CRXF | DSPI_MCR_CTXF;
> +       dspi_write32(priv->flags, &priv->regs->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 void fsl_dspi_cfg_cs_active_state(struct udevice *bus,
> +               uint cs, uint state)
> +{
> +       uint mcr_val;
> +       struct fsl_dspi_priv *priv = dev_get_priv(bus);
> +
> +       dspi_halt(bus, 1);
> +
> +       mcr_val = dspi_read32(priv->flags, &priv->regs->mcr);
> +       if (state & SPI_CS_HIGH)
> +               /* CSx inactive state is low */
> +               mcr_val &= ~DSPI_MCR_PCSIS(cs);
> +       else
> +               /* CSx inactive state is high */
> +               mcr_val |= DSPI_MCR_PCSIS(cs);
> +       dspi_write32(priv->flags, &priv->regs->mcr, mcr_val);
> +
> +       dspi_halt(bus, 0);
> +}
> +
> +static int fsl_dspi_cfg_ctar_mode(struct udevice *bus, uint mode)
> +{
> +       u8 cs;
> +       uint bus_setup;
> +       struct fsl_dspi_priv *priv = dev_get_priv(bus);
> +       struct dm_spi_slave_platdata *slave_plat = priv->cur_slave_plat;
> +
> +       cs = slave_plat->cs;
> +
> +       bus_setup = dspi_read32(priv->flags, &priv->regs->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(priv->flags, &priv->regs->ctar[0], bus_setup);
> +
> +       priv->charbit =
> +               ((dspi_read32(priv->flags, &priv->regs->ctar[0]) &
> +                 DSPI_CTAR_TRSZ(15)) == DSPI_CTAR_TRSZ(15)) ? 16 : 8;
> +
> +       return 0;
> +}
> +
> +static int fsl_dspi_claim_bus(struct udevice *bus)
> +{
> +       uint mcr_val, sr_val;
> +       struct fsl_dspi_priv *priv;
> +
> +       priv = dev_get_priv(bus);
> +
> +       /* configure transfer mode */
> +       fsl_dspi_cfg_ctar_mode(bus, priv->mode);
> +
> +       /* configure active state of CSX */
> +       fsl_dspi_cfg_cs_active_state(bus, priv->cur_slave_plat->cs,
> +                                    priv->mode);

Does this actually work? It seems broken to me.

The parameter to the function is the slave device, not the bus device.
I see that the header file is completely confusing on this point
(comments say one thing, but the parameter name 'bus' says another).

Please consider sending a patch to change 'bus' in the claim_bus() and
release_bus() methods in dm_spi_ops to 'slave'.

I think you want to do something like this:

static int fsl_dspi_claim_bus(struct udevice *slave)
       struct dm_spi_slave_platdata *slave_plat =
dev_get_parent_platdata(slave);

      then use slave_plat->cs

If you want the bus:

   struct udevice *bus = slave->parent;

> +
> +       dspi_halt(bus, 1);
> +       mcr_val = dspi_read32(priv->flags, &priv->regs->mcr);
> +       /* flush RX and TX FIFO */
> +       mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF);
> +       dspi_write32(priv->flags, &priv->regs->mcr, mcr_val);
> +       dspi_halt(bus, 0);
> +
> +       /* check module TX and RX status */
> +       sr_val = dspi_read32(priv->flags, &priv->regs->sr);
> +       if ((sr_val & DSPI_SR_TXRXS) != DSPI_SR_TXRXS) {
> +               debug("DSPI RX/TX not ready!\n");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static int fsl_dspi_release_bus(struct udevice *bus)
> +{
> +       /* halt module */
> +       dspi_halt(bus, 1);
> +       return 0;
> +}

Similar comments.

> +
> +static void dspi_tx(struct fsl_dspi_priv *priv, u32 ctrl, u16 data)
> +{
> +       int timeout = DSPI_TXRX_WAIT_TIMEOUT;
> +
> +       /* wait for empty entries in TXFIFO or timeout */
> +       while (DSPI_SR_TXCTR(dspi_read32(priv->flags, &priv->regs->sr)) >= 4 &&
> +                       timeout--)
> +               udelay(1);
> +
> +       if (timeout >= 0)
> +               dspi_write32(priv->flags, &priv->regs->tfr, (ctrl | data));
> +       else
> +               debug("dspi_tx: waiting timeout!\n");
> +}
> +
> +static u16 dspi_rx(struct fsl_dspi_priv *priv)
> +{
> +       int timeout = DSPI_TXRX_WAIT_TIMEOUT;
> +
> +       /* wait for valid entries in RXFIFO or timeout */
> +       while (DSPI_SR_RXCTR(dspi_read32(priv->flags, &priv->regs->sr)) == 0 &&
> +                       timeout--)
> +               udelay(1);
> +
> +       if (timeout >= 0)
> +               return (u16)DSPI_RFR_RXDATA(
> +                               dspi_read32(priv->flags, &priv->regs->rfr));
> +       else {
> +               debug("dspi_rx: waiting timeout!\n");
> +               return (u16)(~0);
> +       }
> +}
> +
> +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);
> +       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;
> +       priv = dev_get_priv(bus);
> +
> +       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(priv, ctrl, *spi_wr16++);
> +                               else
> +                                       dspi_tx(priv, ctrl, *spi_wr++);
> +                               dspi_rx(priv);
> +                       }
> +
> +                       if (din != NULL) {
> +                               dspi_tx(priv, ctrl, DSPI_IDLE_VAL);
> +                               if (priv->charbit == 16)
> +                                       *spi_rd16++ = dspi_rx(priv);
> +                               else
> +                                       *spi_rd++ = dspi_rx(priv);
> +                       }
> +               }
> +
> +               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(priv, ctrl, *spi_wr16);
> +                       else
> +                               dspi_tx(priv, ctrl, *spi_wr);
> +                       dspi_rx(priv);
> +               }
> +
> +               if (din != NULL) {
> +                       dspi_tx(priv, ctrl, DSPI_IDLE_VAL);
> +                       if (priv->charbit == 16)
> +                               *spi_rd16 = dspi_rx(priv);
> +                       else
> +                               *spi_rd = dspi_rx(priv);
> +               }
> +       } else {
> +               /* dummy read */
> +               dspi_tx(priv, ctrl, DSPI_IDLE_VAL);
> +               dspi_rx(priv);
> +       }
> +
> +       return 0;
> +}
> +
> +/**
> + * Calculate the divide value between input clk frequency and expected SCK frequency
> + * Formula: SCK = (clkrate/pbr) x ((1+dbr)/br)
> + * Dbr: use default value 0
> + *
> + * @pbr: return Baud Rate Prescaler value
> + * @br: return Baud Rate Scaler value
> + * @speed_hz: expected SCK frequency
> + * @clkrate: input clk frequency
> + */
> +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++)
> +               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)
> +{
> +       int ret;
> +       uint bus_setup;
> +       int best_i, best_j, bus_clk;
> +       struct fsl_dspi_priv *priv = dev_get_priv(bus);
> +
> +       bus_clk = priv->bus_clk;
> +
> +       debug("DSPI set_speed: expected SCK speed %u, bus_clk %u.\n",
> +             speed, bus_clk);
> +
> +       bus_setup = dspi_read32(priv->flags, &priv->regs->ctar[0]);
> +       bus_setup &= ~(DSPI_CTAR_DBR | DSPI_CTAR_PBR(0x3) | DSPI_CTAR_BR(0xf));
> +
> +       ret = fsl_dspi_hz_to_spi_baud(&best_i, &best_j, speed, bus_clk);
> +       if (ret) {
> +               speed = priv->speed_hz;
> +               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(priv->flags, &priv->regs->ctar[0], bus_setup);
> +
> +       priv->speed_hz = speed;
> +
> +       return 0;
> +}
> +
> +static int fsl_dspi_set_mode(struct udevice *bus, uint mode)
> +{
> +       struct fsl_dspi_priv *priv = dev_get_priv(bus);
> +
> +       debug("DSPI set_mode: mode 0x%x.\n", mode);
> +
> +       /* We store some chipselect special configure value in priv->ctar_val,

Comment style

> +          and we can't get the correct chipselect number here,
> +          so just store mode value.
> +          Do really configuration when claim_bus. */
> +       priv->mode = mode;
> +
> +       return 0;
> +}
> +
> +/**
> + * This function doesn't do anything except help with debugging
> + */
> +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)
> +{
> +       fdt_addr_t addr;
> +       struct fsl_dspi_platdata *plat = bus->platdata;
> +       const void *blob = gd->fdt_blob;
> +       int node = bus->of_offset;
> +
> +       if (fdtdec_get_bool(blob, node, "big-endian"))
> +               plat->flags |= DSPI_FLAG_REGMAP_ENDIAN_BIG;
> +
> +       plat->num_chipselect =
> +               fdtdec_get_int(blob, node, "num-cs", FSL_DSPI_MAX_CHIPSELECT);
> +
> +       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 = addr;
> +
> +       plat->speed_hz = fdtdec_get_int(blob,
> +                       node, "spi-max-frequency", FSL_DSPI_DEFAULT_SCK_FREQ);
> +
> +       debug("DSPI: regs=0x%x, max-frequency=%d, endianess=%s, num-cs=%d\n",
> +             plat->regs_addr, plat->speed_hz,
> +             plat->flags & 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,
> +};
> diff --git a/include/fsl_dspi.h b/include/fsl_dspi.h
> new file mode 100644
> index 0000000..b569b4d
> --- /dev/null
> +++ b/include/fsl_dspi.h
> @@ -0,0 +1,150 @@
> +/*
> + * 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 */
> +       u32 rfdr[4];    /* 0x7C */
> +#else
> +       u32 tfdr[16];   /* 0x3C */
> +       u32 rfdr[16];   /* 0x7C */
> +#endif
> +};
> +
> +/* Module configuration */
> +#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_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_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) & 0x0000F000) >> 12)
> +#define DSPI_SR_TXPTR(x)               (((x) & 0x00000F00) >> 8)
> +#define DSPI_SR_RXCTR(x)               (((x) & 0x000000F0) >> 4)
> +#define DSPI_SR_RXPTR(x)               ((x) & 0x0000000F)
> +
> +/* DMA/interrupt request selct and enable */
> +#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_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) & 0x0000FFFF)
> +
> +/* Bit definitions and macros for DRFR */
> +#define DSPI_RFR_RXDATA(x)             ((x) & 0x0000FFFF)
> +
> +/* 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
>

Regards,
Simon


More information about the U-Boot mailing list