[U-Boot] [PATCH v1 2/3] spi: sh_spi: DM conversion

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


+ add relevant board mainatiners

On Thu, Apr 26, 2018 at 10:18 PM, Akash Gajjar <gajjar04akash at gmail.com> wrote:
> This patch adds support for DM to the sh_spi driver. legacy driver support is
> removed.
>
> Some TODOs are left over for later, These would be enhancements to the
> original functionality, and can come later. The legacy functionality is
> removed in this version.
>
> This patch is not tested on board as well compile tested yet.
>
> Signed-off-by: Akash Gajjar <akash at openedev.com>
> ---
>  drivers/spi/Kconfig               |  12 +--
>  drivers/spi/sh_spi.c              | 214 +++++++++++++++++++++-----------------
>  drivers/spi/sh_spi.h              |   3 +-
>  include/dm/platform_data/spi_sh.h |  20 ++++
>  4 files changed, 147 insertions(+), 102 deletions(-)
>  create mode 100644 include/dm/platform_data/spi_sh.h
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index ec92b84..be6ad22 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -155,6 +155,12 @@ config SANDBOX_SPI
>                 };
>           };
>
> +config SH_SPI
> +       bool "SuperH SPI driver"
> +       help
> +         Enable the SuperH SPI controller driver. This driver can be used
> +         on various SuperH SoCs, such as SH7757.
> +
>  config STM32_QSPI
>         bool "STM32F7 QSPI driver"
>         depends on STM32F7
> @@ -253,12 +259,6 @@ config DAVINCI_SPI
>         help
>           Enable the Davinci SPI driver
>
> -config SH_SPI
> -       bool "SuperH SPI driver"
> -       help
> -         Enable the SuperH SPI controller driver. This driver can be used
> -         on various SuperH SoCs, such as SH7757.
> -
>  config SH_QSPI
>         bool "Renesas Quad SPI driver"
>         help
> diff --git a/drivers/spi/sh_spi.c b/drivers/spi/sh_spi.c
> index fe394e3..b308ec8 100644
> --- a/drivers/spi/sh_spi.c
> +++ b/drivers/spi/sh_spi.c
> @@ -1,6 +1,10 @@
>  /*
>   * SH SPI driver
>   *
> + * Support for device model:
> + * Copyright (C) 2018  Akash Gajjar <akash at openedev.com>
> + *                     Harshit Shah <shahharshitr at gmail.com>
> + *
>   * Copyright (C) 2011-2012 Renesas Solutions Corp.
>   *
>   * SPDX-License-Identifier:    GPL-2.0
> @@ -11,6 +15,8 @@
>  #include <malloc.h>
>  #include <spi.h>
>  #include <asm/io.h>
> +#include <dm.h>
> +#include <dm/platform_data/spi_sh.h>
>  #include "sh_spi.h"
>
>  static void sh_spi_write(unsigned long data, unsigned long *reg)
> @@ -41,15 +47,15 @@ static void sh_spi_clear_bit(unsigned long val, unsigned long *reg)
>         sh_spi_write(tmp, reg);
>  }
>
> -static void clear_fifo(struct sh_spi *ss)
> +static void clear_fifo(struct sh_spi_regs *regs)
>  {
> -       sh_spi_set_bit(SH_SPI_RSTF, &ss->regs->cr2);
> -       sh_spi_clear_bit(SH_SPI_RSTF, &ss->regs->cr2);
> +       sh_spi_set_bit(SH_SPI_RSTF, &regs->cr2);
> +       sh_spi_clear_bit(SH_SPI_RSTF, &regs->cr2);
>  }
>
> -static int recvbuf_wait(struct sh_spi *ss)
> +static int recvbuf_wait(struct sh_spi_regs *regs)
>  {
> -       while (sh_spi_read(&ss->regs->cr1) & SH_SPI_RBE) {
> +       while (sh_spi_read(&regs->cr1) & SH_SPI_RBE) {
>                 if (ctrlc())
>                         return 1;
>                 udelay(10);
> @@ -57,9 +63,9 @@ static int recvbuf_wait(struct sh_spi *ss)
>         return 0;
>  }
>
> -static int write_fifo_empty_wait(struct sh_spi *ss)
> +static int write_fifo_empty_wait(struct sh_spi_regs *regs)
>  {
> -       while (!(sh_spi_read(&ss->regs->cr1) & SH_SPI_TBE)) {
> +       while (!(sh_spi_read(&regs->cr1) & SH_SPI_TBE)) {
>                 if (ctrlc())
>                         return 1;
>                 udelay(10);
> @@ -67,11 +73,7 @@ static int write_fifo_empty_wait(struct sh_spi *ss)
>         return 0;
>  }
>
> -void spi_init(void)
> -{
> -}
> -
> -static void sh_spi_set_cs(struct sh_spi *ss, unsigned int cs)
> +static void sh_spi_set_cs(struct sh_spi_regs *regs, unsigned int cs)
>  {
>         unsigned long val = 0;
>
> @@ -80,85 +82,53 @@ static void sh_spi_set_cs(struct sh_spi *ss, unsigned int cs)
>         if (cs & 0x02)
>                 val |= SH_SPI_SSS1;
>
> -       sh_spi_clear_bit(SH_SPI_SSS0 | SH_SPI_SSS1, &ss->regs->cr4);
> -       sh_spi_set_bit(val, &ss->regs->cr4);
> +       sh_spi_clear_bit(SH_SPI_SSS0 | SH_SPI_SSS1, &regs->cr4);
> +       sh_spi_set_bit(val, &regs->cr4);
>  }
>
> -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> -               unsigned int max_hz, unsigned int mode)
> +static void __spi_setup(struct sh_spi_regs *regs, uint cs)
>  {
> -       struct sh_spi *ss;
> -
> -       if (!spi_cs_is_valid(bus, cs))
> -               return NULL;
> -
> -       ss = spi_alloc_slave(struct sh_spi, bus, cs);
> -       if (!ss)
> -               return NULL;
> -
> -       ss->regs = (struct sh_spi_regs *)CONFIG_SH_SPI_BASE;
> -
> +       /* initialize spi */
> +       regs = (struct sh_spi_regs *)CONFIG_SH_SPI_BASE;

wrong, we have plat->regs

>         /* SPI sycle stop */
> -       sh_spi_write(0xfe, &ss->regs->cr1);
> +       sh_spi_write(0xfe, &regs->cr1);
>         /* CR1 init */
> -       sh_spi_write(0x00, &ss->regs->cr1);
> +       sh_spi_write(0x00, &regs->cr1);
>         /* CR3 init */
> -       sh_spi_write(0x00, &ss->regs->cr3);
> -       sh_spi_set_cs(ss, cs);
> +       sh_spi_write(0x00, &regs->cr3);
> +       sh_spi_set_cs(regs, cs);
>
> -       clear_fifo(ss);
> +       clear_fifo(regs);
>
>         /* 1/8 clock */
> -       sh_spi_write(sh_spi_read(&ss->regs->cr2) | 0x07, &ss->regs->cr2);
> +       sh_spi_write(sh_spi_read(&regs->cr2) | 0x07, &regs->cr2);
>         udelay(10);
> -
> -       return &ss->slave;
> -}
> -
> -void spi_free_slave(struct spi_slave *slave)
> -{
> -       struct sh_spi *spi = to_sh_spi(slave);
> -
> -       free(spi);
> -}
> -
> -int spi_claim_bus(struct spi_slave *slave)
> -{
> -       return 0;
>  }
>
> -void spi_release_bus(struct spi_slave *slave)
> -{
> -       struct sh_spi *ss = to_sh_spi(slave);
> -
> -       sh_spi_write(sh_spi_read(&ss->regs->cr1) &
> -               ~(SH_SPI_SSA | SH_SPI_SSDB | SH_SPI_SSD), &ss->regs->cr1);
> -}
> -
> -static int sh_spi_send(struct sh_spi *ss, const unsigned char *tx_data,
> +static int sh_spi_send(struct sh_spi_regs *regs, const unsigned char *tx_data,
>                         unsigned int len, unsigned long flags)
>  {
>         int i, cur_len, ret = 0;
>         int remain = (int)len;
>
>         if (len >= SH_SPI_FIFO_SIZE)
> -               sh_spi_set_bit(SH_SPI_SSA, &ss->regs->cr1);
> +               sh_spi_set_bit(SH_SPI_SSA, &regs->cr1);
>
>         while (remain > 0) {
>                 cur_len = (remain < SH_SPI_FIFO_SIZE) ?
>                                 remain : SH_SPI_FIFO_SIZE;
>                 for (i = 0; i < cur_len &&
> -                       !(sh_spi_read(&ss->regs->cr4) & SH_SPI_WPABRT) &&
> -                       !(sh_spi_read(&ss->regs->cr1) & SH_SPI_TBF);
> +                       !(sh_spi_read(&regs->cr4) & SH_SPI_WPABRT) &&
> +                       !(sh_spi_read(&regs->cr1) & SH_SPI_TBF);
>                                 i++)
> -                       sh_spi_write(tx_data[i], &ss->regs->tbr_rbr);
> +                       sh_spi_write(tx_data[i], &regs->tbr_rbr);
>
>                 cur_len = i;
>
> -               if (sh_spi_read(&ss->regs->cr4) & SH_SPI_WPABRT) {
> +               if (sh_spi_read(&regs->cr4) & SH_SPI_WPABRT) {
>                         /* Abort the transaction */
>                         flags |= SPI_XFER_END;
> -                       sh_spi_set_bit(SH_SPI_WPABRT, &ss->regs->cr4);
> +                       sh_spi_set_bit(SH_SPI_WPABRT, &regs->cr4);
>                         ret = 1;
>                         break;
>                 }
> @@ -167,88 +137,144 @@ static int sh_spi_send(struct sh_spi *ss, const unsigned char *tx_data,
>                 tx_data += cur_len;
>
>                 if (remain > 0)
> -                       write_fifo_empty_wait(ss);
> +                       write_fifo_empty_wait(regs);
>         }
>
>         if (flags & SPI_XFER_END) {
> -               sh_spi_clear_bit(SH_SPI_SSD | SH_SPI_SSDB, &ss->regs->cr1);
> -               sh_spi_set_bit(SH_SPI_SSA, &ss->regs->cr1);
> +               sh_spi_clear_bit(SH_SPI_SSD | SH_SPI_SSDB, &regs->cr1);
> +               sh_spi_set_bit(SH_SPI_SSA, &regs->cr1);
>                 udelay(100);
> -               write_fifo_empty_wait(ss);
> +               write_fifo_empty_wait(regs);
>         }
>
>         return ret;
>  }
>
> -static int sh_spi_receive(struct sh_spi *ss, unsigned char *rx_data,
> -                         unsigned int len, unsigned long flags)
> +static int sh_spi_receive(struct sh_spi_regs *regs, unsigned char *rx_data,
> +                               unsigned int len, unsigned long flags)
>  {
>         int i;
>
>         if (len > SH_SPI_MAX_BYTE)
> -               sh_spi_write(SH_SPI_MAX_BYTE, &ss->regs->cr3);
> +               sh_spi_write(SH_SPI_MAX_BYTE, &regs->cr3);
>         else
> -               sh_spi_write(len, &ss->regs->cr3);
> +               sh_spi_write(len, &regs->cr3);
>
> -       sh_spi_clear_bit(SH_SPI_SSD | SH_SPI_SSDB, &ss->regs->cr1);
> -       sh_spi_set_bit(SH_SPI_SSA, &ss->regs->cr1);
> +       sh_spi_clear_bit(SH_SPI_SSD | SH_SPI_SSDB, &regs->cr1);
> +       sh_spi_set_bit(SH_SPI_SSA, &regs->cr1);
>
>         for (i = 0; i < len; i++) {
> -               if (recvbuf_wait(ss))
> +               if (recvbuf_wait(regs))
>                         return 0;
>
> -               rx_data[i] = (unsigned char)sh_spi_read(&ss->regs->tbr_rbr);
> +               rx_data[i] = (unsigned char)sh_spi_read(&regs->tbr_rbr);
>         }
> -       sh_spi_write(0, &ss->regs->cr3);
> +       sh_spi_write(0, &regs->cr3);
>
>         return 0;
>  }
>
> -int  spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
> -               void *din, unsigned long flags)
> +static int sh_spi_set_speed(struct udevice *bus, uint hz)
>  {
> -       struct sh_spi *ss = to_sh_spi(slave);
> +       return 0;
> +}
> +
> +static int sh_spi_set_mode(struct udevice *bus, uint mode)
> +{
> +       return 0;
> +}
> +
> +static int sh_spi_release_bus(struct udevice *dev)
> +{
> +       struct sh_spi_priv *priv = dev_get_priv(bus);
> +       struct sh_spi_regs *regs = priv->regs;
> +
> +       sh_spi_write(sh_spi_read(&regs->cr1) &
> +               ~(SH_SPI_SSA | SH_SPI_SSDB | SH_SPI_SSD), &regs->cr1);
> +
> +       return 0;
> +}
> +
> +static int sh_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +                       const void *dout, void *din, unsigned long flags)
> +{
> +       struct udevice *bus = dev_get_parent(dev);
> +       struct sh_spi_priv *priv = dev_get_priv(bus);
> +       struct sh_spi_regs *regs = priv->regs;
>         const unsigned char *tx_data = dout;
>         unsigned char *rx_data = din;
>         unsigned int len = bitlen / 8;
>         int ret = 0;
>
>         if (flags & SPI_XFER_BEGIN)
> -               sh_spi_write(sh_spi_read(&ss->regs->cr1) & ~SH_SPI_SSA,
> -                               &ss->regs->cr1);
> +               sh_spi_write(sh_spi_read(&regs->cr1) & ~SH_SPI_SSA, &regs->cr1);
>
>         if (tx_data)
> -               ret = sh_spi_send(ss, tx_data, len, flags);
> +               ret = sh_spi_send(regs, tx_data, len, flags);
>
>         if (ret == 0 && rx_data)
> -               ret = sh_spi_receive(ss, rx_data, len, flags);
> +               ret = sh_spi_receive(regs, rx_data, len, flags);
>
>         if (flags & SPI_XFER_END) {
> -               sh_spi_set_bit(SH_SPI_SSD, &ss->regs->cr1);
> +               sh_spi_set_bit(SH_SPI_SSD, &regs->cr1);
>                 udelay(100);
>
>                 sh_spi_clear_bit(SH_SPI_SSA | SH_SPI_SSDB | SH_SPI_SSD,
> -                                &ss->regs->cr1);
> -               clear_fifo(ss);
> +                                &regs->cr1);
> +               clear_fifo(regs);
>         }
>
>         return ret;
>  }
>
> -int  spi_cs_is_valid(unsigned int bus, unsigned int cs)
> +static int sh_spi_probe(struct udevice *bus)
>  {
> -       if (!bus && cs < SH_SPI_NUM_CS)
> -               return 1;
> -       else
> -               return 0;
> -}
> +       struct sh_spi_priv *priv = dev_get_priv(bus);
> +       struct sh_spi_regs *regs = priv->regs;
>
> -void spi_cs_activate(struct spi_slave *slave)
> -{
> +       __spi_setup(regs, priv->cs);

Don't use another function, do it like old code.

>
> +       return 0;
>  }
>
> -void spi_cs_deactivate(struct spi_slave *slave)
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +static int sh_spi_ofdata_to_platadata(struct udevice *bus)
>  {
> +       struct sh_spi_platdata *plat = bus->platdata;
> +       struct sh_spi_priv *priv = dev_get_priv(bus);
> +       fdt_addr_t addr;
> +
> +       addr = devfdt_get_addr(bus);
> +       if (addr == FDT_ADDR_T_NONE)
> +               return -EINVAL;

Missing plat->regs?

> +
> +       plat->cs = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
> +                                       "num-cs", 4);
>
> +       return 0;
>  }
> +
> +static const struct dm_spi_ops mvebu_spi_ops = {
> +       .release_bus    = sh_spi_release_bus,
> +       .xfer           = sh_spi_xfer,
> +       .set_speed      = sh_spi_set_speed,
> +       .set_mode       = sh_spi_set_mode,
> +};
> +
> +static const struct udevice_id sh_spi_ids[] = {
> +       { .compatible = "sh,sh_spi" },

Same like sh_qspi we need to use proper/existing binding from Linux.

> +};
> +#endif
> +
> +U_BOOT_DRIVER(sh_spi) = {
> +       .name = "sh_spi",
> +       .id = UCLASS_SPI,
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +       .of_match = sh_spi_ids,
> +       .ofdata_to_platdata = sh_spi_ofdata_to_platadata,
> +       .platdata_auto_alloc_size = sizeof(struct sh_spi_platdata),
> +#endif
> +       .priv_auto_alloc_size = sizeof(struct sh_spi_priv),
> +       .probe = sh_spi_probe,
> +       .ops = &sh_spi_ops,
> +};
> diff --git a/drivers/spi/sh_spi.h b/drivers/spi/sh_spi.h
> index a0e949f..87a253f 100644
> --- a/drivers/spi/sh_spi.h
> +++ b/drivers/spi/sh_spi.h
> @@ -55,8 +55,7 @@ struct sh_spi_regs {
>  #define SH_SPI_FIFO_SIZE       32
>  #define SH_SPI_NUM_CS          4
>
> -struct sh_spi {
> -       struct spi_slave        slave;
> +struct sh_spi_priv {
>         struct sh_spi_regs      *regs;
>  };

Move this header code into .c file and drop sh_spi_priv just retrive
regs using plat->regs anywhere in the code.


>
> diff --git a/include/dm/platform_data/spi_sh.h b/include/dm/platform_data/spi_sh.h
> new file mode 100644
> index 0000000..b4d63dc
> --- /dev/null
> +++ b/include/dm/platform_data/spi_sh.h
> @@ -0,0 +1,20 @@
> +/*
> + * Copyright (C) 2018 Akash Gajjar <akash at openedev.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + *

no space require.

> + */
> +
> +#ifndef __spi_sh_h
> +#define __spi_sh_h
> +
> +/*
> + * struct sh_spi_platdata - information about a sh spi module
> + *
> + */

no need of these comments.

Jagan.

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


More information about the U-Boot mailing list