[U-Boot] [PATCH v1 1/3] spi: sh_qspi: DM conversion

Jagan Teki jagannadh.teki at gmail.com
Fri Apr 27 06:06:24 UTC 2018


On Thu, Apr 26, 2018 at 10:16 PM, Akash Gajjar <gajjar04akash at gmail.com> wrote:
> This patch adds support for DM to the sh_qspi SPI driver.
>
> The legacy functionality is removed in this version, so old boards in
> the tree is not working with legacy SPI driver functionality.
> Some TODOs are left over for later, These would be enhancements to the
> original functionality, and can come later.
>
> This patch is not tested on board as well compile tested yet.
>
> Signed-off-by: Akash Gajjar <akash at openedev.com>
> ---
>  drivers/spi/sh_qspi.c              | 199 ++++++++++++++++++-------------------
>  include/dm/platform_data/qspi_sh.h |  20 ++++
>  2 files changed, 119 insertions(+), 100 deletions(-)
>  create mode 100644 include/dm/platform_data/qspi_sh.h
>
> diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c
> index 5075be3..5fdd52e 100644
> --- a/drivers/spi/sh_qspi.c
> +++ b/drivers/spi/sh_qspi.c
> @@ -1,6 +1,10 @@
>  /*
>   * SH QSPI (Quad SPI) driver
>   *
> + * Support for device model:
> + * Copyright (C) 2018 Akash Gajjar <akash at openedev.com>
> + *                   Harshit Shah <shahharshitr at gmail.com>
> + *
>   * Copyright (C) 2013 Renesas Electronics Corporation
>   * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj at renesas.com>
>   *
> @@ -14,6 +18,8 @@
>  #include <wait_bit.h>
>  #include <asm/arch/rmobile.h>
>  #include <asm/io.h>
> +#include <dm.h>
> +#include <dm/platform_data/qspi_sh.h>
>
>  /* SH QSPI register bit masks <REG>_<BIT> */
>  #define SPCR_MSTR      0x08
> @@ -67,151 +73,90 @@ struct sh_qspi_regs {
>         u32     spbmul3;
>  };
>
> -struct sh_qspi_slave {
> -       struct spi_slave        slave;
> -       struct sh_qspi_regs     *regs;
> +struct sh_qspi_priv {
> +       struct sh_qspi_regs *regs;
>  };
>
> -static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave)
> -{
> -       return container_of(slave, struct sh_qspi_slave, slave);
> -}
> -
> -static void sh_qspi_init(struct sh_qspi_slave *ss)
> +static int __sh_qspi_setup(struct sh_qspi_priv *priv)

Use the old function name, it has meaning on it like sh hw init.

>  {
>         /* QSPI initialize */
> +       priv->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;
> +
>         /* Set master mode only */
> -       writeb(SPCR_MSTR, &ss->regs->spcr);
> +       writeb(SPCR_MSTR, &priv->regs->spcr);
>
>         /* Set SSL signal level */
> -       writeb(0x00, &ss->regs->sslp);
> +       writeb(0x00, &priv->regs->sslp);
>
>         /* Set MOSI signal value when transfer is in idle state */
> -       writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr);
> +       writeb(SPPCR_IO3FV | SPPCR_IO2FV, &priv->regs->sppcr);
>
>         /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
> -       writeb(0x01, &ss->regs->spbr);
> +       writeb(0x01, &priv->regs->spbr);
>
>         /* Disable Dummy Data Transmission */
> -       writeb(0x00, &ss->regs->spdcr);
> +       writeb(0x00, &priv->regs->spdcr);
>
>         /* Set clock delay value */
> -       writeb(0x00, &ss->regs->spckd);
> +       writeb(0x00, &priv->regs->spckd);
>
>         /* Set SSL negation delay value */
> -       writeb(0x00, &ss->regs->sslnd);
> +       writeb(0x00, &priv->regs->sslnd);
>
>         /* Set next-access delay value */
> -       writeb(0x00, &ss->regs->spnd);
> +       writeb(0x00, &priv->regs->spnd);
>
>         /* Set equence command */
> -       writew(SPCMD_INIT2, &ss->regs->spcmd0);
> +       writew(SPCMD_INIT2, &priv->regs->spcmd0);
>
>         /* Reset transfer and receive Buffer */
> -       setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
> +       setbits_8(&priv->regs->spbfcr, SPBFCR_TXRST | SPBFCR_RXRST);
>
>         /* Clear transfer and receive Buffer control bit */
> -       clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
> +       clrbits_8(&priv->regs->spbfcr, SPBFCR_TXRST | SPBFCR_RXRST);
>
>         /* Set equence control method. Use equence0 only */
> -       writeb(0x00, &ss->regs->spscr);
> +       writeb(0x00, &priv->regs->spscr);
>
>         /* Enable SPI function */
> -       setbits_8(&ss->regs->spcr, SPCR_SPE);
> -}
> -
> -int spi_cs_is_valid(unsigned int bus, unsigned int cs)
> -{
> -       return 1;
> -}
> -
> -void spi_cs_activate(struct spi_slave *slave)
> -{
> -       struct sh_qspi_slave *ss = to_sh_qspi(slave);
> -
> -       /* Set master mode only */
> -       writeb(SPCR_MSTR, &ss->regs->spcr);
> -
> -       /* Set command */
> -       writew(SPCMD_INIT1, &ss->regs->spcmd0);
> -
> -       /* Reset transfer and receive Buffer */
> -       setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
> -
> -       /* Clear transfer and receive Buffer control bit */
> -       clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
> -
> -       /* Set equence control method. Use equence0 only */
> -       writeb(0x00, &ss->regs->spscr);
> -
> -       /* Enable SPI function */
> -       setbits_8(&ss->regs->spcr, SPCR_SPE);
> -}
> -
> -void spi_cs_deactivate(struct spi_slave *slave)
> -{
> -       struct sh_qspi_slave *ss = to_sh_qspi(slave);
> -
> -       /* Disable SPI Function */
> -       clrbits_8(&ss->regs->spcr, SPCR_SPE);
> -}
> -
> -void spi_init(void)
> -{
> -       /* nothing to do */
> +       setbits_8(&priv->regs->spcr, SPCR_SPE);
>  }
>
> -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> -               unsigned int max_hz, unsigned int mode)
> +static int sh_qspi_set_speed(struct udevice *bus, uint hz)
>  {
> -       struct sh_qspi_slave *ss;
> -
> -       if (!spi_cs_is_valid(bus, cs))
> -               return NULL;
> -
> -       ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs);
> -       if (!ss) {
> -               printf("SPI_error: Fail to allocate sh_qspi_slave\n");
> -               return NULL;
> -       }
> -
> -       ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;
> -
> -       /* Init SH QSPI */
> -       sh_qspi_init(ss);
> -
> -       return &ss->slave;
> +       return 0;
>  }
>
> -void spi_free_slave(struct spi_slave *slave)
> +static int sh_qspi_set_mode(struct udevice *bus, uint mode)
>  {
> -       struct sh_qspi_slave *spi = to_sh_qspi(slave);
> -
> -       free(spi);
> +       return 0;
>  }
>
> -int spi_claim_bus(struct spi_slave *slave)
> +static int sh_qspi_claim_bus(struct udevice *dev)
>  {
>         return 0;
>  }
>
> -void spi_release_bus(struct spi_slave *slave)
> +static int sh_qspi_release_bus(struct udevice *dev)
>  {
> +       return 0;
>  }
>
> -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
> -            void *din, unsigned long flags)
> +static int sh_qspi_xfer(struct udevice *dev, unsigned int bitlen,
> +                         const void *dout, void *din, unsigned long flags)
>  {
> -       struct sh_qspi_slave *ss = to_sh_qspi(slave);
> +       struct udevice *bus = dev_get_parent(dev);
> +       struct sh_qspi_priv *priv = dev_get_priv(bus);
> +       struct sh_qspi_regs *regs = priv->regs;
>         u32 nbyte, chunk;
>         int i, ret = 0;
>         u8 dtdata = 0, drdata;
>         u8 *tdata = &dtdata, *rdata = &drdata;
> -       u32 *spbmul0 = &ss->regs->spbmul0;
> +       u32 *spbmul0 = &regs->spbmul0;
>
>         if (dout == NULL && din == NULL) {
>                 if (flags & SPI_XFER_END)
> -                       spi_cs_deactivate(slave);
> +                       spi_cs_deactivate(regs);
>                 return 0;
>         }
>
> @@ -223,7 +168,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
>         nbyte = bitlen / 8;
>
>         if (flags & SPI_XFER_BEGIN) {
> -               spi_cs_activate(slave);
> +               spi_cs_activate(regs);
>
>                 /* Set 1048576 byte */
>                 writel(0x100000, spbmul0);
> @@ -245,27 +190,27 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
>                  */
>                 chunk = (nbyte >= 32) ? 32 : 1;
>
> -               clrsetbits_8(&ss->regs->spbfcr, SPBFCR_TXTRG | SPBFCR_RXTRG,
> +               clrsetbits_8(&regs->spbfcr, SPBFCR_TXTRG | SPBFCR_RXTRG,
>                              chunk == 32 ? SPBFCR_TXTRG | SPBFCR_RXTRG : 0);
>
> -               ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPTEF,
> +               ret = wait_for_bit_8(&regs->spsr, SPSR_SPTEF,
>                                      true, 1000, true);
>                 if (ret)
>                         return ret;
>
>                 for (i = 0; i < chunk; i++) {
> -                       writeb(*tdata, &ss->regs->spdr);
> +                       writeb(*tdata, &regs->spdr);
>                         if (dout != NULL)
>                                 tdata++;
>                 }
>
> -               ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPRFF,
> +               ret = wait_for_bit_8(&regs->spsr, SPSR_SPRFF,
>                                      true, 1000, true);
>                 if (ret)
>                         return ret;
>
>                 for (i = 0; i < chunk; i++) {
> -                       *rdata = readb(&ss->regs->spdr);
> +                       *rdata = readb(&regs->spdr);
>                         if (din != NULL)
>                                 rdata++;
>                 }
> @@ -274,7 +219,61 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
>         }
>
>         if (flags & SPI_XFER_END)
> -               spi_cs_deactivate(slave);
> +               spi_cs_deactivate(regs);
>
>         return ret;
>  }
> +
> +static int sh_qspi_probe(struct udevice *bus)
> +{
> +       struct sh_qspi_platdata *plat = bus->platdata;
> +       struct sh_qspi_priv *priv = dev_get_priv(bus);
> +
> +       __sh_qspi_setup(priv);

Call sh_qspi_init and don't remove the comment as well.

> +
> +       return 0;
> +}
> +
> +static const struct dm_spi_ops sh_qspi_ops = {
> +       .claim_bus      = sh_qspi_claim_bus,
> +       .release_bus    = sh_qspi_release_bus,
> +       .xfer           = sh_qspi_xfer,
> +       .set_speed      = sh_qspi_set_speed,
> +       .set_mode       = sh_qspi_set_mode,
> +};
> +
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +static int sh_qspi_ofdata_to_platadata(struct udevice *bus)
> +{
> +       struct sh_qspi_platdata *plat = bus->platdata;
> +       fdt_addr_t addr;
> +
> +       addr = devfdt_get_addr(bus);
> +       if (addr == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       plat->cs = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
> +                       "num-cs", 4);
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id davinci_spi_ids[] = {
> +       { .compatible = "sh,sh-qspi" },

Do we have any equavlent driver for this in Linux? if so we need to
use the same(couldn't find either).

Nohuhiro, any help?

Jagan.

-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.


More information about the U-Boot mailing list