[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 = ®s->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(®s->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(®s->spsr, SPSR_SPTEF,
> true, 1000, true);
> if (ret)
> return ret;
>
> for (i = 0; i < chunk; i++) {
> - writeb(*tdata, &ss->regs->spdr);
> + writeb(*tdata, ®s->spdr);
> if (dout != NULL)
> tdata++;
> }
>
> - ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPRFF,
> + ret = wait_for_bit_8(®s->spsr, SPSR_SPRFF,
> true, 1000, true);
> if (ret)
> return ret;
>
> for (i = 0; i < chunk; i++) {
> - *rdata = readb(&ss->regs->spdr);
> + *rdata = readb(®s->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