All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v1 1/3] spi: sh_qspi: DM conversion
       [not found] <akash@openedev.com>
@ 2018-04-26 16:46 ` Akash Gajjar
  2018-04-27  6:06   ` Jagan Teki
  2018-04-26 16:48 ` [U-Boot] [PATCH v1 2/3] spi: sh_spi: " Akash Gajjar
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Akash Gajjar @ 2018-04-26 16:46 UTC (permalink / raw)
  To: u-boot

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@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@openedev.com>
+ *		      Harshit Shah <shahharshitr@gmail.com>
+ *
  * Copyright (C) 2013 Renesas Electronics Corporation
  * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@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)
 {
 	/* 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);
+
+	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" },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(sh_qspi) = {
+	.name = "sh_qspi",
+	.id = UCLASS_SPI,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.of_match = sh_qspi_ids,
+	.ofdata_to_platdata = sh_qspi_ofdata_to_platadata,
+	.platdata_auto_alloc_size = sizeof(struct sh_qspi_platdata),
+#endif
+	.ops = &sh_qspi_ops,
+	.priv_auto_alloc_size = sizeof(struct sh_qspi_priv),
+	.probe = sh_qspi_probe,
+};
+#endif
diff --git a/include/dm/platform_data/qspi_sh.h b/include/dm/platform_data/qspi_sh.h
new file mode 100644
index 0000000..1a8529c
--- /dev/null
+++ b/include/dm/platform_data/qspi_sh.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018  Akash Gajjar <akash@openedev.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __qspi_sh_h
+#define __qspi_sh_h
+
+/*
+ * struct sh_qspi_platdata - information about a sh qspi module
+ *
+ */
+struct sh_qspi_platdata {
+	struct sh_qspi_regs *regs;
+	uint cs;
+};
+
+#endif /* __qspi_sh_h */
+
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 2/3] spi: sh_spi: DM conversion
       [not found] <akash@openedev.com>
  2018-04-26 16:46 ` [U-Boot] [PATCH v1 1/3] spi: sh_qspi: DM conversion Akash Gajjar
@ 2018-04-26 16:48 ` Akash Gajjar
  2018-04-27  6:22   ` Jagan Teki
  2018-04-26 16:50 ` [U-Boot] [PATCH v1 3/3] spi: mxs_spi: " Akash Gajjar
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Akash Gajjar @ 2018-04-26 16:48 UTC (permalink / raw)
  To: u-boot

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@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@openedev.com>
+ *			Harshit Shah <shahharshitr@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;
 	/* 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);
 
+	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;
+
+	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" },
+};
+#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;
 };
 
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@openedev.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#ifndef __spi_sh_h
+#define __spi_sh_h
+
+/*
+ * struct sh_spi_platdata - information about a sh spi module
+ *
+ */
+struct sh_spi_platdata {
+	struct sh_spi_regs  *regs;
+	u8 cs;
+};
+
+#endif /* __spi_sh_h */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 3/3] spi: mxs_spi: DM conversion
       [not found] <akash@openedev.com>
  2018-04-26 16:46 ` [U-Boot] [PATCH v1 1/3] spi: sh_qspi: DM conversion Akash Gajjar
  2018-04-26 16:48 ` [U-Boot] [PATCH v1 2/3] spi: sh_spi: " Akash Gajjar
@ 2018-04-26 16:50 ` Akash Gajjar
  2018-04-27  6:40   ` Jagan Teki
  2018-05-09  6:36 ` [U-Boot] [PATCH v2 1/3] spi: sh_qspi: full " Akash Gajjar
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Akash Gajjar @ 2018-04-26 16:50 UTC (permalink / raw)
  To: u-boot

This patch adds support for DM to the mxs spi driver.

Some TODOs are left over for later, These would be enhancements to the
original functionality, and can come later.

The legacy functionality is present in this version, so old boards in the tree
is working with legacy SPI driver functionality.

Signed-off-by: Akash Gajjar <akash@openedev.com>
---
 drivers/spi/Kconfig                |  12 +-
 drivers/spi/mxs_spi.c              | 257 +++++++++++++++++++++++--------------
 include/dm/platform_data/spi_mxs.h |  18 +++
 3 files changed, 186 insertions(+), 101 deletions(-)
 create mode 100644 include/dm/platform_data/spi_mxs.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ec92b84..5d3e152 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -106,6 +106,12 @@ config MVEBU_A3700_SPI
 	  used to access the SPI NOR flash on platforms embedding this
 	  Marvell IP core.
 
+config MXS_SPI
+	bool "MXS SPI Driver"
+	help
+	  Enable the MXS SPI controller driver. This driver can be used
+	  on the i.MX23 and i.MX28 SoCs.
+
 config PIC32_SPI
 	bool "Microchip PIC32 SPI driver"
 	depends on MACH_PIC32
@@ -299,12 +305,6 @@ config MXC_SPI
 	  Enable the MXC SPI controller driver. This driver can be used
 	  on various i.MX SoCs such as i.MX31/35/51/6/7.
 
-config MXS_SPI
-	bool "MXS SPI Driver"
-	help
-	  Enable the MXS SPI controller driver. This driver can be used
-	  on the i.MX23 and i.MX28 SoCs.
-
 config OMAP3_SPI
 	bool "McSPI driver for OMAP"
 	help
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
index 790db78..b48ecbf 100644
--- a/drivers/spi/mxs_spi.c
+++ b/drivers/spi/mxs_spi.c
@@ -1,6 +1,9 @@
 /*
  * Freescale i.MX28 SPI driver
  *
+ * Support for device model:
+ * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
+ *
  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  * on behalf of DENX Software Engineering GmbH
  *
@@ -20,6 +23,8 @@
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/dma.h>
+#include <dm.h>
+#include <dm/platform_data/spi_mxs.h>
 
 #define	MXS_SPI_MAX_TIMEOUT	1000000
 #define	MXS_SPI_PORT_OFFSET	0x2000
@@ -28,93 +33,14 @@
 
 #define MXSSSP_SMALL_TRANSFER	512
 
-struct mxs_spi_slave {
-	struct spi_slave	slave;
-	uint32_t		max_khz;
-	uint32_t		mode;
-	struct mxs_ssp_regs	*regs;
+struct mxs_spi_priv {
+	struct mxs_ssp_regs *regs;
+	u32	max_khz;
+	u32 	mode;
+	u32	bus;
+	u32	cs;
 };
 
-static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
-{
-	return container_of(slave, struct mxs_spi_slave, slave);
-}
-
-void spi_init(void)
-{
-}
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-	/* MXS SPI: 4 ports and 3 chip selects maximum */
-	if (!mxs_ssp_bus_id_valid(bus) || cs > 2)
-		return 0;
-	else
-		return 1;
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-				  unsigned int max_hz, unsigned int mode)
-{
-	struct mxs_spi_slave *mxs_slave;
-
-	if (!spi_cs_is_valid(bus, cs)) {
-		printf("mxs_spi: invalid bus %d / chip select %d\n", bus, cs);
-		return NULL;
-	}
-
-	mxs_slave = spi_alloc_slave(struct mxs_spi_slave, bus, cs);
-	if (!mxs_slave)
-		return NULL;
-
-	if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + bus))
-		goto err_init;
-
-	mxs_slave->max_khz = max_hz / 1000;
-	mxs_slave->mode = mode;
-	mxs_slave->regs = mxs_ssp_regs_by_bus(bus);
-
-	return &mxs_slave->slave;
-
-err_init:
-	free(mxs_slave);
-	return NULL;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
-	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
-	free(mxs_slave);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
-	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
-	struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
-	uint32_t reg = 0;
-
-	mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
-
-	writel((slave->cs << MXS_SSP_CHIPSELECT_SHIFT) |
-	       SSP_CTRL0_BUS_WIDTH_ONE_BIT,
-	       &ssp_regs->hw_ssp_ctrl0);
-
-	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
-	reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
-	reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
-	writel(reg, &ssp_regs->hw_ssp_ctrl1);
-
-	writel(0, &ssp_regs->hw_ssp_cmd0);
-
-	mxs_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
-
-	return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-}
-
 static void mxs_spi_start_xfer(struct mxs_ssp_regs *ssp_regs)
 {
 	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
@@ -127,10 +53,10 @@ static void mxs_spi_end_xfer(struct mxs_ssp_regs *ssp_regs)
 	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
 }
 
-static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
+static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv,
 			char *data, int length, int write, unsigned long flags)
 {
-	struct mxs_ssp_regs *ssp_regs = slave->regs;
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
 
 	if (flags & SPI_XFER_BEGIN)
 		mxs_spi_start_xfer(ssp_regs);
@@ -186,12 +112,12 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
 	return 0;
 }
 
-static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
+static int mxs_spi_xfer_dma(struct mxs_spi_priv *priv,
 			char *data, int length, int write, unsigned long flags)
 {
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
 	const int xfer_max_sz = 0xff00;
 	const int desc_count = DIV_ROUND_UP(length, xfer_max_sz) + 1;
-	struct mxs_ssp_regs *ssp_regs = slave->regs;
 	struct mxs_dma_desc *dp;
 	uint32_t ctrl0;
 	uint32_t cache_data_count;
@@ -230,7 +156,7 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
 	/* Invalidate the area, so no writeback into the RAM races with DMA */
 	invalidate_dcache_range(dstart, dstart + cache_data_count);
 
-	dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + slave->slave.bus;
+	dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus;
 
 	dp = desc;
 	while (length) {
@@ -307,11 +233,10 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
 	return ret;
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+static int __spi_xfer(struct mxs_spi_priv *priv, unsigned int bitlen,
 		const void *dout, void *din, unsigned long flags)
 {
-	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
-	struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
 	int len = bitlen / 8;
 	char dummy;
 	int write = 0;
@@ -355,9 +280,151 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
 	if (!dma || (len < MXSSSP_SMALL_TRANSFER)) {
 		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
-		return mxs_spi_xfer_pio(mxs_slave, data, len, write, flags);
+		return mxs_spi_xfer_pio(priv, data, len, write, flags);
 	} else {
 		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
-		return mxs_spi_xfer_dma(mxs_slave, data, len, write, flags);
+		return mxs_spi_xfer_dma(priv, data, len, write, flags);
 	}
 }
+
+static int __mxs_spi_setup(struct mxs_spi_priv *mxs_spi, uint bus)
+{
+	struct mxs_spi_priv *priv = mxs_spi;
+	int err;
+
+	priv->max_khz = max_hz / 1000;
+	priv->mode = mode;
+	priv->regs = mxs_ssp_regs_by_bus(bus);
+	priv->bus = bus;
+
+	if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus)) {
+		printf("%s: DMA init channel error %d\n", __func__, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int mxs_spi_claim_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+	struct mxs_spi_platdata *plat = dev_get_platdata(bus);
+
+	writel(((plat->cs) << MXS_SSP_CHIPSELECT_SHIFT) |
+			SSP_CTRL0_BUS_WIDTH_ONE_BIT,
+			&ssp_regs->hw_ssp_ctrl0);
+
+	return 0;
+}
+
+static int mxs_spi_release_bus(struct udevice *dev)
+{
+	/* TODO */
+
+	return 0;
+}
+
+static int mxs_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_spi_platdata *plat = dev_get_platdata(bus);
+
+	if (speed > plat->max_khz)
+		speed = plat->max_khz;
+
+	priv->max_khz = speed;
+	printf("%s speed %u\n", __func__, speed);
+
+	mxs_set_ssp_busclock(plat->bus, priv->max_khz);
+
+	return 0;
+}
+
+static int mxs_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+	u32 reg;
+
+	printf("%s mode %u\n", __func__, mode);
+	priv->mode = mode;
+
+	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
+	reg |= (priv->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
+	reg |= (priv->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
+	writel(reg, &ssp_regs->hw_ssp_ctrl1);
+
+	/* go in idle state */
+	writel(0, &ssp_regs->hw_ssp_cmd0);
+
+	return 0;
+}
+
+static int mxs_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+
+	return __spi_xfer(priv, bitlen, dout, din, flags);
+}
+
+static int mxs_spi_probe(struct udevice *dev)
+{
+	struct mxs_spi_platdata *plat = dev_get_platdata(dev);
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_spi_priv *priv = mxs_spi;
+	int err;
+
+	priv->max_khz = max_hz / 1000;
+	priv->mode = mode;
+	priv->bus = bus;
+	priv->regs = mxs_ssp_regs_by_bus(bus);
+
+	if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus)) {
+		printf("%s: DMA init channel error %d\n", __func__, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops mxs_spi_ops = {
+	.claim_bus      = mxs_spi_claim_bus,
+	.release_bus    = mxs_spi_release_bus,
+	.xfer           = mxs_spi_xfer,
+	.set_speed      = mxs_spi_set_speed,
+	.set_mode       = mxs_spi_set_mode,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int mxs_ofdata_to_platadata(struct udevice *bus)
+{
+	struct mxs_spi_platdata *plat = bus->platdata;
+
+	plat->cs = fdtdec_get_int(gd->fdt_blob, 
+			dev_of_offset(bus), "num-cs", 4);
+
+	return 0;
+}
+
+static const struct udevice_id mxs_spi_ids[] = {
+	{ .compatible = "fsl,mxs-spi" },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(mxs_spi) = {
+	.name	= "mxs_spi",
+	.id     = UCLASS_SPI,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.of_match = mxs_spi_ids,
+	.ofdata_to_platdata = mxs_ofdata_to_platadata,
+	.platdata_auto_alloc_size = sizeof(struct mxs_spi_platdata),
+#endif
+	.ops    = &mxs_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct mxs_spi_priv),
+	.probe  = mxs_spi_probe,
+};
diff --git a/include/dm/platform_data/spi_mxs.h b/include/dm/platform_data/spi_mxs.h
new file mode 100644
index 0000000..5164834
--- /dev/null
+++ b/include/dm/platform_data/spi_mxs.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#ifndef __SPI_MXS_H
+#define __SPI_MXS_H
+
+struct mxs_spi_platdata {
+	struct mxs_ssp_regs *regs;
+	u32 bus;
+	u32 max_hz;
+	u32 cs;
+};
+
+#endif /* __SPI_MXS_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 1/3] spi: sh_qspi: DM conversion
  2018-04-26 16:46 ` [U-Boot] [PATCH v1 1/3] spi: sh_qspi: DM conversion Akash Gajjar
@ 2018-04-27  6:06   ` Jagan Teki
  0 siblings, 0 replies; 22+ messages in thread
From: Jagan Teki @ 2018-04-27  6:06 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 26, 2018 at 10:16 PM, Akash Gajjar <gajjar04akash@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@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@openedev.com>
> + *                   Harshit Shah <shahharshitr@gmail.com>
> + *
>   * Copyright (C) 2013 Renesas Electronics Corporation
>   * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@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.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 2/3] spi: sh_spi: DM conversion
  2018-04-26 16:48 ` [U-Boot] [PATCH v1 2/3] spi: sh_spi: " Akash Gajjar
@ 2018-04-27  6:22   ` Jagan Teki
  0 siblings, 0 replies; 22+ messages in thread
From: Jagan Teki @ 2018-04-27  6:22 UTC (permalink / raw)
  To: u-boot

+ add relevant board mainatiners

On Thu, Apr 26, 2018 at 10:18 PM, Akash Gajjar <gajjar04akash@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@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@openedev.com>
> + *                     Harshit Shah <shahharshitr@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@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.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 3/3] spi: mxs_spi: DM conversion
  2018-04-26 16:50 ` [U-Boot] [PATCH v1 3/3] spi: mxs_spi: " Akash Gajjar
@ 2018-04-27  6:40   ` Jagan Teki
  0 siblings, 0 replies; 22+ messages in thread
From: Jagan Teki @ 2018-04-27  6:40 UTC (permalink / raw)
  To: u-boot

+ add relevant board maintainers

On Thu, Apr 26, 2018 at 10:20 PM, Akash Gajjar <gajjar04akash@gmail.com> wrote:
> This patch adds support for DM to the mxs spi driver.
>
> Some TODOs are left over for later, These would be enhancements to the
> original functionality, and can come later.
>
> The legacy functionality is present in this version, so old boards in the tree
> is working with legacy SPI driver functionality.
>
> Signed-off-by: Akash Gajjar <akash@openedev.com>
> ---
>  drivers/spi/Kconfig                |  12 +-
>  drivers/spi/mxs_spi.c              | 257 +++++++++++++++++++++++--------------
>  include/dm/platform_data/spi_mxs.h |  18 +++
>  3 files changed, 186 insertions(+), 101 deletions(-)
>  create mode 100644 include/dm/platform_data/spi_mxs.h
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index ec92b84..5d3e152 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -106,6 +106,12 @@ config MVEBU_A3700_SPI
>           used to access the SPI NOR flash on platforms embedding this
>           Marvell IP core.
>
> +config MXS_SPI
> +       bool "MXS SPI Driver"
> +       help
> +         Enable the MXS SPI controller driver. This driver can be used
> +         on the i.MX23 and i.MX28 SoCs.
> +
>  config PIC32_SPI
>         bool "Microchip PIC32 SPI driver"
>         depends on MACH_PIC32
> @@ -299,12 +305,6 @@ config MXC_SPI
>           Enable the MXC SPI controller driver. This driver can be used
>           on various i.MX SoCs such as i.MX31/35/51/6/7.
>
> -config MXS_SPI
> -       bool "MXS SPI Driver"
> -       help
> -         Enable the MXS SPI controller driver. This driver can be used
> -         on the i.MX23 and i.MX28 SoCs.
> -
>  config OMAP3_SPI
>         bool "McSPI driver for OMAP"
>         help
> diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
> index 790db78..b48ecbf 100644
> --- a/drivers/spi/mxs_spi.c
> +++ b/drivers/spi/mxs_spi.c
> @@ -1,6 +1,9 @@
>  /*
>   * Freescale i.MX28 SPI driver
>   *
> + * Support for device model:
> + * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
> + *
>   * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
>   * on behalf of DENX Software Engineering GmbH
>   *
> @@ -20,6 +23,8 @@
>  #include <asm/arch/imx-regs.h>
>  #include <asm/arch/sys_proto.h>
>  #include <asm/mach-imx/dma.h>
> +#include <dm.h>
> +#include <dm/platform_data/spi_mxs.h>
>
>  #define        MXS_SPI_MAX_TIMEOUT     1000000
>  #define        MXS_SPI_PORT_OFFSET     0x2000
> @@ -28,93 +33,14 @@
>
>  #define MXSSSP_SMALL_TRANSFER  512
>
> -struct mxs_spi_slave {
> -       struct spi_slave        slave;
> -       uint32_t                max_khz;
> -       uint32_t                mode;
> -       struct mxs_ssp_regs     *regs;
> +struct mxs_spi_priv {
> +       struct mxs_ssp_regs *regs;
> +       u32     max_khz;
> +       u32     mode;
> +       u32     bus;
> +       u32     cs;

I think we can't maintain this private structure since we have
platdata both in DT and PLATDATA. just assign regs to plat->regs or
any other members.

>  };
>
> -static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
> -{
> -       return container_of(slave, struct mxs_spi_slave, slave);
> -}
> -
> -void spi_init(void)
> -{
> -}
> -
> -int spi_cs_is_valid(unsigned int bus, unsigned int cs)
> -{
> -       /* MXS SPI: 4 ports and 3 chip selects maximum */
> -       if (!mxs_ssp_bus_id_valid(bus) || cs > 2)
> -               return 0;
> -       else
> -               return 1;
> -}

No, we need to maintain this with .cs_info

> -
> -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> -                                 unsigned int max_hz, unsigned int mode)
> -{
> -       struct mxs_spi_slave *mxs_slave;
> -
> -       if (!spi_cs_is_valid(bus, cs)) {
> -               printf("mxs_spi: invalid bus %d / chip select %d\n", bus, cs);
> -               return NULL;
> -       }
> -
> -       mxs_slave = spi_alloc_slave(struct mxs_spi_slave, bus, cs);
> -       if (!mxs_slave)
> -               return NULL;
> -
> -       if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + bus))
> -               goto err_init;
> -
> -       mxs_slave->max_khz = max_hz / 1000;
> -       mxs_slave->mode = mode;
> -       mxs_slave->regs = mxs_ssp_regs_by_bus(bus);
> -
> -       return &mxs_slave->slave;
> -
> -err_init:
> -       free(mxs_slave);
> -       return NULL;
> -}
> -
> -void spi_free_slave(struct spi_slave *slave)
> -{
> -       struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
> -       free(mxs_slave);
> -}
> -
> -int spi_claim_bus(struct spi_slave *slave)
> -{
> -       struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
> -       struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
> -       uint32_t reg = 0;
> -
> -       mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
> -
> -       writel((slave->cs << MXS_SSP_CHIPSELECT_SHIFT) |
> -              SSP_CTRL0_BUS_WIDTH_ONE_BIT,
> -              &ssp_regs->hw_ssp_ctrl0);
> -
> -       reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> -       reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> -       reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> -       writel(reg, &ssp_regs->hw_ssp_ctrl1);
> -
> -       writel(0, &ssp_regs->hw_ssp_cmd0);
> -
> -       mxs_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
> -
> -       return 0;
> -}
> -
> -void spi_release_bus(struct spi_slave *slave)
> -{
> -}
> -
>  static void mxs_spi_start_xfer(struct mxs_ssp_regs *ssp_regs)
>  {
>         writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
> @@ -127,10 +53,10 @@ static void mxs_spi_end_xfer(struct mxs_ssp_regs *ssp_regs)
>         writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
>  }
>
> -static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
> +static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv,
>                         char *data, int length, int write, unsigned long flags)
>  {
> -       struct mxs_ssp_regs *ssp_regs = slave->regs;
> +       struct mxs_ssp_regs *ssp_regs = priv->regs;
>
>         if (flags & SPI_XFER_BEGIN)
>                 mxs_spi_start_xfer(ssp_regs);
> @@ -186,12 +112,12 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
>         return 0;
>  }
>
> -static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
> +static int mxs_spi_xfer_dma(struct mxs_spi_priv *priv,
>                         char *data, int length, int write, unsigned long flags)
>  {
> +       struct mxs_ssp_regs *ssp_regs = priv->regs;
>         const int xfer_max_sz = 0xff00;
>         const int desc_count = DIV_ROUND_UP(length, xfer_max_sz) + 1;
> -       struct mxs_ssp_regs *ssp_regs = slave->regs;
>         struct mxs_dma_desc *dp;
>         uint32_t ctrl0;
>         uint32_t cache_data_count;
> @@ -230,7 +156,7 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
>         /* Invalidate the area, so no writeback into the RAM races with DMA */
>         invalidate_dcache_range(dstart, dstart + cache_data_count);
>
> -       dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + slave->slave.bus;
> +       dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus;
>
>         dp = desc;
>         while (length) {
> @@ -307,11 +233,10 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
>         return ret;
>  }
>
> -int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> +static int __spi_xfer(struct mxs_spi_priv *priv, unsigned int bitlen,
>                 const void *dout, void *din, unsigned long flags)
>  {
> -       struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
> -       struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
> +       struct mxs_ssp_regs *ssp_regs = priv->regs;
>         int len = bitlen / 8;
>         char dummy;
>         int write = 0;
> @@ -355,9 +280,151 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>
>         if (!dma || (len < MXSSSP_SMALL_TRANSFER)) {
>                 writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
> -               return mxs_spi_xfer_pio(mxs_slave, data, len, write, flags);
> +               return mxs_spi_xfer_pio(priv, data, len, write, flags);
>         } else {
>                 writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
> -               return mxs_spi_xfer_dma(mxs_slave, data, len, write, flags);
> +               return mxs_spi_xfer_dma(priv, data, len, write, flags);
>         }
>  }
> +
> +static int __mxs_spi_setup(struct mxs_spi_priv *mxs_spi, uint bus)

who is calling this?

> +{
> +       struct mxs_spi_priv *priv = mxs_spi;
> +       int err;
> +
> +       priv->max_khz = max_hz / 1000;
> +       priv->mode = mode;
> +       priv->regs = mxs_ssp_regs_by_bus(bus);
> +       priv->bus = bus;
> +
> +       if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus)) {
> +               printf("%s: DMA init channel error %d\n", __func__, err);
> +               return err;
> +       }
> +
> +       return 0;
> +}
> +
> +static int mxs_spi_claim_bus(struct udevice *dev)
> +{
> +       struct udevice *bus = dev_get_parent(dev);
> +       struct mxs_spi_priv *priv = dev_get_priv(bus);
> +       struct mxs_ssp_regs *ssp_regs = priv->regs;
> +       struct mxs_spi_platdata *plat = dev_get_platdata(bus);
> +
> +       writel(((plat->cs) << MXS_SSP_CHIPSELECT_SHIFT) |
> +                       SSP_CTRL0_BUS_WIDTH_ONE_BIT,
> +                       &ssp_regs->hw_ssp_ctrl0);
> +
> +       return 0;
> +}
> +
> +static int mxs_spi_release_bus(struct udevice *dev)
> +{
> +       /* TODO */
> +
> +       return 0;
> +}
> +
> +static int mxs_spi_set_speed(struct udevice *bus, uint speed)
> +{
> +       struct mxs_spi_priv *priv = dev_get_priv(bus);
> +       struct mxs_spi_platdata *plat = dev_get_platdata(bus);
> +
> +       if (speed > plat->max_khz)
> +               speed = plat->max_khz;
> +
> +       priv->max_khz = speed;

assign this at last

> +       printf("%s speed %u\n", __func__, speed);
> +

make it debug

> +       mxs_set_ssp_busclock(plat->bus, priv->max_khz);
> +
> +       return 0;
> +}
> +
> +static int mxs_spi_set_mode(struct udevice *bus, uint mode)
> +{
> +       struct mxs_spi_priv *priv = dev_get_priv(bus);
> +       struct mxs_ssp_regs *ssp_regs = priv->regs;
> +       u32 reg;
> +
> +       printf("%s mode %u\n", __func__, mode);
> +       priv->mode = mode;

same comments like .set_speed

> +
> +       reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> +       reg |= (priv->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> +       reg |= (priv->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> +       writel(reg, &ssp_regs->hw_ssp_ctrl1);
> +
> +       /* go in idle state */
> +       writel(0, &ssp_regs->hw_ssp_cmd0);
> +
> +       return 0;
> +}
> +
> +static int mxs_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +                       const void *dout, void *din, unsigned long flags)
> +{
> +       struct udevice *bus = dev_get_parent(dev);
> +       struct mxs_spi_priv *priv = dev_get_priv(bus);
> +
> +       return __spi_xfer(priv, bitlen, dout, din, flags);

Don't use another function, place the old code.

> +}
> +
> +static int mxs_spi_probe(struct udevice *dev)
> +{
> +       struct mxs_spi_platdata *plat = dev_get_platdata(dev);
> +       struct mxs_spi_priv *priv = dev_get_priv(bus);
> +       struct mxs_spi_priv *priv = mxs_spi;
> +       int err;
> +
> +       priv->max_khz = max_hz / 1000;
> +       priv->mode = mode;
> +       priv->bus = bus;
> +       priv->regs = mxs_ssp_regs_by_bus(bus);

These will go out, if we retrive platdata, and remember don't use
mxs_ssp_regs_by_bus you have get this from DT.

> +
> +       if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus)) {
> +               printf("%s: DMA init channel error %d\n", __func__, err);
> +               return err;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct dm_spi_ops mxs_spi_ops = {
> +       .claim_bus      = mxs_spi_claim_bus,
> +       .release_bus    = mxs_spi_release_bus,
> +       .xfer           = mxs_spi_xfer,
> +       .set_speed      = mxs_spi_set_speed,
> +       .set_mode       = mxs_spi_set_mode,
> +};
> +
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +static int mxs_ofdata_to_platadata(struct udevice *bus)
> +{
> +       struct mxs_spi_platdata *plat = bus->platdata;
> +
> +       plat->cs = fdtdec_get_int(gd->fdt_blob,
> +                       dev_of_offset(bus), "num-cs", 4);

Missing other plat members assignment?

> +
> +       return 0;
> +}
> +
> +static const struct udevice_id mxs_spi_ids[] = {
> +       { .compatible = "fsl,mxs-spi" },

wrong use, use Linux driver binding?

> +       { }
> +};
> +#endif
> +
> +U_BOOT_DRIVER(mxs_spi) = {
> +       .name   = "mxs_spi",
> +       .id     = UCLASS_SPI,
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +       .of_match = mxs_spi_ids,
> +       .ofdata_to_platdata = mxs_ofdata_to_platadata,
> +       .platdata_auto_alloc_size = sizeof(struct mxs_spi_platdata),
> +#endif
> +       .ops    = &mxs_spi_ops,
> +       .priv_auto_alloc_size = sizeof(struct mxs_spi_priv),
> +       .probe  = mxs_spi_probe,
> +};
> diff --git a/include/dm/platform_data/spi_mxs.h b/include/dm/platform_data/spi_mxs.h
> new file mode 100644
> index 0000000..5164834
> --- /dev/null
> +++ b/include/dm/platform_data/spi_mxs.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + *

no space.

Jagan.

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v2 1/3] spi: sh_qspi: full DM conversion
       [not found] <akash@openedev.com>
                   ` (2 preceding siblings ...)
  2018-04-26 16:50 ` [U-Boot] [PATCH v1 3/3] spi: mxs_spi: " Akash Gajjar
@ 2018-05-09  6:36 ` Akash Gajjar
  2018-05-09 11:21   ` Jagan Teki
  2018-05-09  6:57 ` [U-Boot] [PATCH v2 2/3] spi: sh_spi: " Akash Gajjar
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Akash Gajjar @ 2018-05-09  6:36 UTC (permalink / raw)
  To: u-boot

v1->v2
New in v2
update Kconfig
replace __sh_qspi_setup to sh_qspi_setup
add missing memeber of platform data

Signed-off-by: Akash Gajjar <akash@openedev.com>
---
 drivers/spi/Kconfig                | 12 +++++-----
 drivers/spi/sh_qspi.c              | 49 +++++++++++++++++++-------------------
 include/dm/platform_data/qspi_sh.h |  4 ----
 3 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ec92b84..81079c5 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -155,6 +155,12 @@ config SANDBOX_SPI
 		};
 	  };
 
+config SH_QSPI
+	bool "Renesas Quad SPI driver"
+	help
+	  Enable the Renesas Quad SPI controller driver. This driver can be
+	  used on Renesas SoCs.
+
 config STM32_QSPI
 	bool "STM32F7 QSPI driver"
 	depends on STM32F7
@@ -259,12 +265,6 @@ config SH_SPI
 	  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
-	  Enable the Renesas Quad SPI controller driver. This driver can be
-	  used on Renesas SoCs.
-
 config TI_QSPI
 	bool "TI QSPI driver"
 	help
diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c
index 5fdd52e..b81cee5 100644
--- a/drivers/spi/sh_qspi.c
+++ b/drivers/spi/sh_qspi.c
@@ -77,49 +77,48 @@ struct sh_qspi_priv {
 	struct sh_qspi_regs *regs;
 };
 
-static int __sh_qspi_setup(struct sh_qspi_priv *priv)
+static void sh_qspi_setup(struct sh_qspi_priv *priv)
 {
-	/* QSPI initialize */
-	priv->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;
+	struct sh_qspi_regs *regs = priv->regs;
 
 	/* Set master mode only */
-	writeb(SPCR_MSTR, &priv->regs->spcr);
+	writeb(SPCR_MSTR, &regs->spcr);
 
 	/* Set SSL signal level */
-	writeb(0x00, &priv->regs->sslp);
+	writeb(0x00, &regs->sslp);
 
 	/* Set MOSI signal value when transfer is in idle state */
-	writeb(SPPCR_IO3FV | SPPCR_IO2FV, &priv->regs->sppcr);
+	writeb(SPPCR_IO3FV | SPPCR_IO2FV, &regs->sppcr);
 
 	/* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
-	writeb(0x01, &priv->regs->spbr);
+	writeb(0x01, &regs->spbr);
 
 	/* Disable Dummy Data Transmission */
-	writeb(0x00, &priv->regs->spdcr);
+	writeb(0x00, &regs->spdcr);
 
 	/* Set clock delay value */
-	writeb(0x00, &priv->regs->spckd);
+	writeb(0x00, &regs->spckd);
 
 	/* Set SSL negation delay value */
-	writeb(0x00, &priv->regs->sslnd);
+	writeb(0x00, &regs->sslnd);
 
 	/* Set next-access delay value */
-	writeb(0x00, &priv->regs->spnd);
+	writeb(0x00, &regs->spnd);
 
 	/* Set equence command */
-	writew(SPCMD_INIT2, &priv->regs->spcmd0);
+	writew(SPCMD_INIT2, &regs->spcmd0);
 
 	/* Reset transfer and receive Buffer */
-	setbits_8(&priv->regs->spbfcr, SPBFCR_TXRST | SPBFCR_RXRST);
+	setbits_8(&regs->spbfcr, SPBFCR_TXRST | SPBFCR_RXRST);
 
 	/* Clear transfer and receive Buffer control bit */
-	clrbits_8(&priv->regs->spbfcr, SPBFCR_TXRST | SPBFCR_RXRST);
+	clrbits_8(&regs->spbfcr, SPBFCR_TXRST | SPBFCR_RXRST);
 
 	/* Set equence control method. Use equence0 only */
-	writeb(0x00, &priv->regs->spscr);
+	writeb(0x00, &regs->spscr);
 
 	/* Enable SPI function */
-	setbits_8(&priv->regs->spcr, SPCR_SPE);
+	setbits_8(&regs->spcr, SPCR_SPE);
 }
 
 static int sh_qspi_set_speed(struct udevice *bus, uint hz)
@@ -156,7 +155,7 @@ static int sh_qspi_xfer(struct udevice *dev, unsigned int bitlen,
 
 	if (dout == NULL && din == NULL) {
 		if (flags & SPI_XFER_END)
-			spi_cs_deactivate(regs);
+			spi_cs_deactivate(regs);	/* TODO */
 		return 0;
 	}
 
@@ -168,7 +167,7 @@ static int sh_qspi_xfer(struct udevice *dev, unsigned int bitlen,
 	nbyte = bitlen / 8;
 
 	if (flags & SPI_XFER_BEGIN) {
-		spi_cs_activate(regs);
+		spi_cs_activate(regs);			/* TODO */
 
 		/* Set 1048576 byte */
 		writel(0x100000, spbmul0);
@@ -219,7 +218,7 @@ static int sh_qspi_xfer(struct udevice *dev, unsigned int bitlen,
 	}
 
 	if (flags & SPI_XFER_END)
-		spi_cs_deactivate(regs);
+		spi_cs_deactivate(regs);		/* TODO */
 
 	return ret;
 }
@@ -229,7 +228,9 @@ 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);
+	priv->regs = plat->regs;
+
+	sh_qspi_setup(priv);
 
 	return 0;
 }
@@ -252,14 +253,14 @@ static int sh_qspi_ofdata_to_platadata(struct udevice *bus)
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	plat->cs = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
-			"num-cs", 4);
+	plat->regs = (struct sh_qspi_regs *regs)addr;
 
 	return 0;
 }
 
-static const struct udevice_id davinci_spi_ids[] = {
-	{ .compatible = "sh,sh-qspi" },
+/* TODO: update comptaible device tree binding */
+static const struct udevice_id sh_qspi_ids[] = {
+	{ .compatible = " " },
 	{ }
 };
 #endif
diff --git a/include/dm/platform_data/qspi_sh.h b/include/dm/platform_data/qspi_sh.h
index 1a8529c..14479ad 100644
--- a/include/dm/platform_data/qspi_sh.h
+++ b/include/dm/platform_data/qspi_sh.h
@@ -7,10 +7,6 @@
 #ifndef __qspi_sh_h
 #define __qspi_sh_h
 
-/*
- * struct sh_qspi_platdata - information about a sh qspi module
- *
- */
 struct sh_qspi_platdata {
 	struct sh_qspi_regs *regs;
 	uint cs;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v2 2/3] spi: sh_spi: full DM conversion
       [not found] <akash@openedev.com>
                   ` (3 preceding siblings ...)
  2018-05-09  6:36 ` [U-Boot] [PATCH v2 1/3] spi: sh_qspi: full " Akash Gajjar
@ 2018-05-09  6:57 ` Akash Gajjar
  2018-05-09  7:04 ` [U-Boot] [PATCH v2 3/3] spi: mxs_spi: full dm conversion Akash Gajjar
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Akash Gajjar @ 2018-05-09  6:57 UTC (permalink / raw)
  To: u-boot

v1->v2
New in v2
add cs_info method
remove fixed regs address
add missing platform struct missing member
moved priv struct into sh_spi.c
remove unnecessary space and comments

Signed-off-by: Akash Gajjar <akash@openedev.com>
---
 drivers/spi/sh_spi.c              | 44 +++++++++++++++++++++++++++++++--------
 drivers/spi/sh_spi.h              |  4 ----
 include/dm/platform_data/spi_sh.h |  5 -----
 3 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/sh_spi.c b/drivers/spi/sh_spi.c
index b308ec8..db14031 100644
--- a/drivers/spi/sh_spi.c
+++ b/drivers/spi/sh_spi.c
@@ -2,7 +2,7 @@
  * SH SPI driver
  *
  * Support for device model:
- * Copyright (C) 2018 	Akash Gajjar <akash@openedev.com>
+ * Copyright (C) 2018	Akash Gajjar <akash@openedev.com>
  *			Harshit Shah <shahharshitr@gmail.com>
  *
  * Copyright (C) 2011-2012 Renesas Solutions Corp.
@@ -19,6 +19,11 @@
 #include <dm/platform_data/spi_sh.h>
 #include "sh_spi.h"
 
+struct sh_spi_priv {
+	struct sh_spi_regs	*regs;
+	u32	cs;
+};
+
 static void sh_spi_write(unsigned long data, unsigned long *reg)
 {
 	writel(data, reg);
@@ -86,10 +91,11 @@ static void sh_spi_set_cs(struct sh_spi_regs *regs, unsigned int cs)
 	sh_spi_set_bit(val, &regs->cr4);
 }
 
-static void __spi_setup(struct sh_spi_regs *regs, uint cs)
+static void spi_setup(struct sh_spi_priv *priv)
 {
-	/* initialize spi */
-	regs = (struct sh_spi_regs *)CONFIG_SH_SPI_BASE;
+	struct sh_spi_regs *regs = priv->regs;
+	u32 cs = priv->cs;
+
 	/* SPI sycle stop */
 	sh_spi_write(0xfe, &regs->cr1);
 	/* CR1 init */
@@ -106,7 +112,7 @@ static void __spi_setup(struct sh_spi_regs *regs, uint cs)
 }
 
 static int sh_spi_send(struct sh_spi_regs *regs, const unsigned char *tx_data,
-			unsigned int len, unsigned long flags)
+					unsigned int len, unsigned long flags)
 {
 	int i, cur_len, ret = 0;
 	int remain = (int)len;
@@ -151,7 +157,7 @@ static int sh_spi_send(struct sh_spi_regs *regs, const unsigned char *tx_data,
 }
 
 static int sh_spi_receive(struct sh_spi_regs *regs, unsigned char *rx_data,
-				unsigned int len, unsigned long flags)
+					unsigned int len, unsigned long flags)
 {
 	int i;
 
@@ -227,12 +233,29 @@ static int sh_spi_xfer(struct udevice *dev, unsigned int bitlen,
 	return ret;
 }
 
+static int sh_spi_cs_info(struct udevice *bus, uint cs,
+					struct spi_cs_info *info)
+{
+	struct sh_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->cs) {
+		printf("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int sh_spi_probe(struct udevice *bus)
 {
+	struct sh_spi_platdata *plat = bus->platdata;
 	struct sh_spi_priv *priv = dev_get_priv(bus);
 	struct sh_spi_regs *regs = priv->regs;
 
-	__spi_setup(regs, priv->cs);
+	priv->regs = plat->regs;
+	priv->cs = plat->cs;
+
+	spi_setup(priv);
 
 	return 0;
 }
@@ -248,8 +271,9 @@ static int sh_spi_ofdata_to_platadata(struct udevice *bus)
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
+	plat->regs = (struct sh_spi_regs *regs)addr;
 	plat->cs = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
-					"num-cs", 4);
+							"num-cs", 4);
 
 	return 0;
 }
@@ -259,10 +283,12 @@ static const struct dm_spi_ops mvebu_spi_ops = {
 	.xfer		= sh_spi_xfer,
 	.set_speed	= sh_spi_set_speed,
 	.set_mode	= sh_spi_set_mode,
+	.cs_info	= sh_spi_cs_info,
 };
 
+/* TODO: update compatible device tree */
 static const struct udevice_id sh_spi_ids[] = {
-	{ .compatible = "sh,sh_spi" },
+	{ .compatible = " " },
 };
 #endif
 
diff --git a/drivers/spi/sh_spi.h b/drivers/spi/sh_spi.h
index 87a253f..f945744 100644
--- a/drivers/spi/sh_spi.h
+++ b/drivers/spi/sh_spi.h
@@ -55,10 +55,6 @@ struct sh_spi_regs {
 #define SH_SPI_FIFO_SIZE	32
 #define SH_SPI_NUM_CS		4
 
-struct sh_spi_priv {
-	struct sh_spi_regs	*regs;
-};
-
 static inline struct sh_spi *to_sh_spi(struct spi_slave *slave)
 {
 	return container_of(slave, struct sh_spi, slave);
diff --git a/include/dm/platform_data/spi_sh.h b/include/dm/platform_data/spi_sh.h
index b4d63dc..c6d0ac5 100644
--- a/include/dm/platform_data/spi_sh.h
+++ b/include/dm/platform_data/spi_sh.h
@@ -2,16 +2,11 @@
  * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
- *
  */
 
 #ifndef __spi_sh_h
 #define __spi_sh_h
 
-/*
- * struct sh_spi_platdata - information about a sh spi module
- *
- */
 struct sh_spi_platdata {
 	struct sh_spi_regs  *regs;
 	u8 cs;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v2 3/3] spi: mxs_spi: full dm conversion
       [not found] <akash@openedev.com>
                   ` (4 preceding siblings ...)
  2018-05-09  6:57 ` [U-Boot] [PATCH v2 2/3] spi: sh_spi: " Akash Gajjar
@ 2018-05-09  7:04 ` Akash Gajjar
  2018-05-09  7:07 ` [U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion Akash Gajjar
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Akash Gajjar @ 2018-05-09  7:04 UTC (permalink / raw)
  To: u-boot

v1->v2
register cs_info method
remove unused function __mxs_spi_setup
merged __spi_xfer function to spi_xfer
printf replaced by debug

Signed-off-by: Akash Gajjar <akash@openedev.com>
---
 drivers/spi/mxs_spi.c | 169 ++++++++++++++++++++++++--------------------------
 1 file changed, 81 insertions(+), 88 deletions(-)

diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
index 0af2eee..3054438 100644
--- a/drivers/spi/mxs_spi.c
+++ b/drivers/spi/mxs_spi.c
@@ -82,7 +82,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv,
 
 		if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
 			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
-			printf("MXS SPI: Timeout waiting for start\n");
+			debug("MXS SPI: Timeout waiting for start\n");
 			return -ETIMEDOUT;
 		}
 
@@ -94,7 +94,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv,
 		if (!write) {
 			if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_status_reg,
 				SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) {
-				printf("MXS SPI: Timeout waiting for data\n");
+				debug("MXS SPI: Timeout waiting for data\n");
 				return -ETIMEDOUT;
 			}
 
@@ -104,7 +104,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv,
 
 		if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg,
 			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
-			printf("MXS SPI: Timeout waiting for finish\n");
+			debug("MXS SPI: Timeout waiting for finish\n");
 			return -ETIMEDOUT;
 		}
 	}
@@ -233,78 +233,6 @@ static int mxs_spi_xfer_dma(struct mxs_spi_priv *priv,
 	return ret;
 }
 
-static int __spi_xfer(struct mxs_spi_priv *priv, unsigned int bitlen,
-		const void *dout, void *din, unsigned long flags)
-{
-	struct mxs_ssp_regs *ssp_regs = priv->regs;
-	int len = bitlen / 8;
-	char dummy;
-	int write = 0;
-	char *data = NULL;
-	int dma = 1;
-
-	if (bitlen == 0) {
-		if (flags & SPI_XFER_END) {
-			din = (void *)&dummy;
-			len = 1;
-		} else
-			return 0;
-	}
-
-	/* Half-duplex only */
-	if (din && dout)
-		return -EINVAL;
-	/* No data */
-	if (!din && !dout)
-		return 0;
-
-	if (dout) {
-		data = (char *)dout;
-		write = 1;
-	} else if (din) {
-		data = (char *)din;
-		write = 0;
-	}
-
-	/*
-	 * Check for alignment, if the buffer is aligned, do DMA transfer,
-	 * PIO otherwise. This is a temporary workaround until proper bounce
-	 * buffer is in place.
-	 */
-	if (dma) {
-		if (((uint32_t)data) & (ARCH_DMA_MINALIGN - 1))
-			dma = 0;
-		if (((uint32_t)len) & (ARCH_DMA_MINALIGN - 1))
-			dma = 0;
-	}
-
-	if (!dma || (len < MXSSSP_SMALL_TRANSFER)) {
-		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
-		return mxs_spi_xfer_pio(priv, data, len, write, flags);
-	} else {
-		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
-		return mxs_spi_xfer_dma(priv, data, len, write, flags);
-	}
-}
-
-static int __mxs_spi_setup(struct mxs_spi_priv *mxs_spi, uint bus)
-{
-	struct mxs_spi_priv *priv = mxs_spi;
-	int err;
-
-	priv->max_khz = max_hz / 1000;
-	priv->mode = mode;
-	priv->regs = mxs_ssp_regs_by_bus(bus);
-	priv->bus = bus;
-
-	if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus)) {
-		printf("%s: DMA init channel error %d\n", __func__, err);
-		return err;
-	}
-
-	return 0;
-}
-
 static int mxs_spi_claim_bus(struct udevice *dev)
 {
 	struct udevice *bus = dev_get_parent(dev);
@@ -321,8 +249,6 @@ static int mxs_spi_claim_bus(struct udevice *dev)
 
 static int mxs_spi_release_bus(struct udevice *dev)
 {
-	/* TODO */
-
 	return 0;
 }
 
@@ -335,7 +261,7 @@ static int mxs_spi_set_speed(struct udevice *bus, uint speed)
 		speed = plat->max_khz;
 
 	priv->max_khz = speed;
-	printf("%s speed %u\n", __func__, speed);
+	debug("%s speed %u\n", __func__, speed);
 
 	mxs_set_ssp_busclock(plat->bus, priv->max_khz);
 
@@ -348,8 +274,8 @@ static int mxs_spi_set_mode(struct udevice *bus, uint mode)
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
 	u32 reg;
 
-	printf("%s mode %u\n", __func__, mode);
 	priv->mode = mode;
+	debug("%s mode %u\n", __func__, mode);
 
 	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
 	reg |= (priv->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
@@ -367,24 +293,83 @@ static int mxs_spi_xfer(struct udevice *dev, unsigned int bitlen,
 {
 	struct udevice *bus = dev_get_parent(dev);
 	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+	int len = bitlen / 8;
+	char dummy;
+	int write = 0;
+	char *data = NULL;
+	int dma = 1;
+
+	if (bitlen == 0) {
+		if (flags & SPI_XFER_END) {
+			din = (void *)&dummy;
+			len = 1;
+		} else
+			return 0;
+	}
+
+	/* Half-duplex only */
+	if (din && dout)
+		return -EINVAL;
+	/* No data */
+	if (!din && !dout)
+		return 0;
+
+	if (dout) {
+		data = (char *)dout;
+		write = 1;
+	} else if (din) {
+		data = (char *)din;
+		write = 0;
+	}
 
-	return __spi_xfer(priv, bitlen, dout, din, flags);
+	/*
+	 * Check for alignment, if the buffer is aligned, do DMA transfer,
+	 * PIO otherwise. This is a temporary workaround until proper bounce
+	 * buffer is in place.
+	 */
+	if (dma) {
+		if (((uint32_t)data) & (ARCH_DMA_MINALIGN - 1))
+			dma = 0;
+		if (((uint32_t)len) & (ARCH_DMA_MINALIGN - 1))
+			dma = 0;
+	}
+
+	if (!dma || (len < MXSSSP_SMALL_TRANSFER)) {
+		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
+		return mxs_spi_xfer_pio(priv, data, len, write, flags);
+	} else {
+		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
+		return mxs_spi_xfer_dma(priv, data, len, write, flags);
+	}
+}
+
+static int mxs_spi_cs_info(struct udevice *bus, uint cs,
+				struct spi_cs_info *info)
+{
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->cs) {
+		printf("%s: no cs %u\n", __func__, cs);
+		return -ENODEV;
+	}
+
+	return 0;
 }
 
 static int mxs_spi_probe(struct udevice *dev)
 {
 	struct mxs_spi_platdata *plat = dev_get_platdata(dev);
 	struct mxs_spi_priv *priv = dev_get_priv(bus);
-	struct mxs_spi_priv *priv = mxs_spi;
 	int err;
 
-	priv->max_khz = max_hz / 1000;
-	priv->mode = mode;
-	priv->bus = bus;
-	priv->regs = mxs_ssp_regs_by_bus(bus);
+	priv->max_khz = (plat->max_hz) / 1000;
+	priv->mode = plat->mode;
+	priv->bus = plat->bus;
 
-	if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus)) {
-		printf("%s: DMA init channel error %d\n", __func__, err);
+	err = mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus);
+	if (err) {
+		debug("%s: DMA init channel error %d\n", __func__, err);
 		return err;
 	}
 
@@ -397,21 +382,29 @@ static const struct dm_spi_ops mxs_spi_ops = {
 	.xfer           = mxs_spi_xfer,
 	.set_speed      = mxs_spi_set_speed,
 	.set_mode       = mxs_spi_set_mode,
+	.cs_info 	= mxs_spi_cs_info,
 };
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 static int mxs_ofdata_to_platadata(struct udevice *bus)
 {
 	struct mxs_spi_platdata *plat = bus->platdata;
+	fdt_addr_t addr;
+
+	addr = devfdt_get_addr(bus);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
 
+	plat->regs = (struct mxs_ssp_regs *)addr;
 	plat->cs = fdtdec_get_int(gd->fdt_blob,
 			dev_of_offset(bus), "num-cs", 4);
 
 	return 0;
 }
 
+/* TODO: update compatible device tree */
 static const struct udevice_id mxs_spi_ids[] = {
-	{ .compatible = "fsl,mxs-spi" },
+	{ .compatible = " " },
 	{ }
 };
 #endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion
       [not found] <akash@openedev.com>
                   ` (5 preceding siblings ...)
  2018-05-09  7:04 ` [U-Boot] [PATCH v2 3/3] spi: mxs_spi: full dm conversion Akash Gajjar
@ 2018-05-09  7:07 ` Akash Gajjar
  2018-09-04  6:33   ` Jagan Teki
  2018-05-10 14:13 ` [U-Boot] [PATCH v3 1/3] spi: sh_qspi: " Akash Gajjar
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Akash Gajjar @ 2018-05-09  7:07 UTC (permalink / raw)
  To: u-boot

From: Akash Gajjar <gajjar04akash@gmail.com>

This patch adds support for DM to the LPC32xx SSP SPI driver.

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.

Signed-off-by: Akash Gajjar <akash@openedev.com>
---
 drivers/spi/Kconfig                        |  10 +-
 drivers/spi/lpc32xx_ssp.c                  | 145 +++++++++++++++--------------
 include/dm/platform_data/spi_lpc32xx_ssp.h |  15 +++
 3 files changed, 93 insertions(+), 77 deletions(-)
 create mode 100644 include/dm/platform_data/spi_lpc32xx_ssp.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ec92b84..2297d4a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -99,6 +99,11 @@ config ICH_SPI
 	  access the SPI NOR flash on platforms embedding this Intel
 	  ICH IP core.
 
+config LPC32XX_SSP
+	bool "LPC32XX SPI Driver"
+	help
+	  Enable support for SPI on LPC32xx
+
 config MVEBU_A3700_SPI
 	bool "Marvell Armada 3700 SPI driver"
 	help
@@ -277,11 +282,6 @@ config KIRKWOOD_SPI
 	  Enable support for SPI on various Marvell SoCs, such as
 	  Kirkwood and Armada 375.
 
-config LPC32XX_SSP
-	bool "LPC32XX SPI Driver"
-	help
-	  Enable support for SPI on LPC32xx
-
 config MPC8XX_SPI
 	bool "MPC8XX SPI Driver"
 	depends on MPC8xx
diff --git a/drivers/spi/lpc32xx_ssp.c b/drivers/spi/lpc32xx_ssp.c
index e2a593b..ae41b57 100644
--- a/drivers/spi/lpc32xx_ssp.c
+++ b/drivers/spi/lpc32xx_ssp.c
@@ -4,6 +4,9 @@
  * (C) Copyright 2014  DENX Software Engineering GmbH
  * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
  *
+ * Support for device model:
+ * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
+ *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
@@ -13,6 +16,8 @@
 #include <malloc.h>
 #include <spi.h>
 #include <asm/arch/clk.h>
+#include <dm.h>
+#include <dm/platform_data/spi_lpc32xx_ssp.h>
 
 /* SSP chip registers */
 struct ssp_regs {
@@ -36,90 +41,36 @@ struct ssp_regs {
 /* SSP status RX FIFO not empty bit */
 #define SSP_SR_RNE 0x0004
 
-/* lpc32xx spi slave */
-struct lpc32xx_spi_slave {
-	struct spi_slave slave;
+struct lpc32xx_ssp_spi_priv {
 	struct ssp_regs *regs;
 };
 
-static inline struct lpc32xx_spi_slave *to_lpc32xx_spi_slave(
-	struct spi_slave *slave)
+static int lpc32xx_ssp_spi_claim_bus(struct udevice *dev)
 {
-	return container_of(slave, struct lpc32xx_spi_slave, slave);
-}
-
-/* spi_init is called during boot when CONFIG_CMD_SPI is defined */
-void spi_init(void)
-{
-	/*
-	 *  nothing to do: clocking was enabled in lpc32xx_ssp_enable()
-	 * and configuration will be done in spi_setup_slave()
-	*/
+	return 0;
 }
 
-/* the following is called in sequence by do_spi_xfer() */
-
-struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode)
+static int lpc32xx_ssp_spi_release_bus(struct udevice *dev)
 {
-	struct lpc32xx_spi_slave *lslave;
-
-	/* we only set up SSP0 for now, so ignore bus */
-
-	if (mode & SPI_3WIRE) {
-		pr_err("3-wire mode not supported");
-		return NULL;
-	}
-
-	if (mode & SPI_SLAVE) {
-		pr_err("slave mode not supported\n");
-		return NULL;
-	}
-
-	if (mode & SPI_PREAMBLE) {
-		pr_err("preamble byte skipping not supported\n");
-		return NULL;
-	}
-
-	lslave = spi_alloc_slave(struct lpc32xx_spi_slave, bus, cs);
-	if (!lslave) {
-		printf("SPI_error: Fail to allocate lpc32xx_spi_slave\n");
-		return NULL;
-	}
-
-	lslave->regs = (struct ssp_regs *)SSP0_BASE;
-
-	/*
-	 * 8 bit frame, SPI fmt, 500kbps -> clock divider is 26.
-	 * Set SCR to 0 and CPSDVSR to 26.
-	 */
-
-	writel(0x7, &lslave->regs->cr0); /* 8-bit chunks, SPI, 1 clk/bit */
-	writel(26, &lslave->regs->cpsr); /* SSP clock = HCLK/26 = 500kbps */
-	writel(0, &lslave->regs->imsc); /* do not raise any interrupts */
-	writel(0, &lslave->regs->icr); /* clear any pending interrupt */
-	writel(0, &lslave->regs->dmacr); /* do not do DMAs */
-	writel(SSP_CR1_SSP_ENABLE, &lslave->regs->cr1); /* enable SSP0 */
-	return &lslave->slave;
+	return 0;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+static int lpc32xx_ssp_spi_set_speed(struct udevice *bus, uint hz)
 {
-	struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
-
-	debug("(lpc32xx) spi_free_slave: 0x%08x\n", (u32)lslave);
-	free(lslave);
+	return 0;
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+static int lpc32xx_ssp_spi_set_mode(struct udevice *bus, uint mode)
 {
-	/* only one bus and slave so far, always available */
 	return 0;
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-	const void *dout, void *din, unsigned long flags)
+static int lpc32xx_ssp_spi_xfer(struct udevice *dev, uint bitlen,
+				const void *dout, void *din, ulong flags)
 {
-	struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
+	struct udevice *bus = dev->parent;
+	struct lpc32xx_ssp_priv *priv = dev_get_priv(bus);
+	struct ssp_regs *regs = priv->regs;
 	int bytelen = bitlen >> 3;
 	int idx_out = 0;
 	int idx_in = 0;
@@ -127,18 +78,68 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
 	start_time = get_timer(0);
 	while ((idx_out < bytelen) || (idx_in < bytelen)) {
-		int status = readl(&lslave->regs->sr);
+		int status = readl(&regs->sr);
 		if ((idx_out < bytelen) && (status & SSP_SR_TNF))
-			writel(((u8 *)dout)[idx_out++], &lslave->regs->data);
+			writel(((u8 *)dout)[idx_out++], &regs->data);
 		if ((idx_in < bytelen) && (status & status & SSP_SR_RNE))
-			((u8 *)din)[idx_in++] = readl(&lslave->regs->data);
+			((u8 *)din)[idx_in++] = readl(&regs->data);
 		if (get_timer(start_time) >= CONFIG_LPC32XX_SSP_TIMEOUT)
 			return -1;
 	}
+
+	return 0;
+}
+
+static int lpc32xx_ssp_spi_probe(struct udevice *bus)
+{
+	struct lpc32xx_ssp_spi_platdata *plat = bus->platdata;
+	struct lpc32xx_ssp_spi_priv = dev_get_priv(bus);
+
+	priv->regs = plat->regs;
+
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
+static const struct dm_spi_ops lpc32xx_ssp_spi_ops = {
+	.claim_bus	= lpc32xx_ssp_spi_claim_bus,
+	.release_bus	= lpc32xx_ssp_spi_release_bus,
+	.xfer		= lpc32xx_ssp_spi_xfer,
+	.set_speed	= lpc32xx_ssp_spi_set_speed,
+	.set_mode	= lpc32xx_ssp_spi_set_mode,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int lpc32xx_ssp_spi_ofdata_to_platadata(struct udevice *bus)
 {
-	/* do nothing */
+	struct lpc32xx_ssp_spi_platdata *plat = bus->platdata;
+	fdt_addr_t addr;
+
+	addr = devfdt_get_addr(bus);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	plat->regs = (struct struct ssp_regs *)addr;
+
+	return 0;
 }
+
+/* TODO: update compatibel device tree */
+static const struct udevice_id lpc32xx_ssp_spi_ids[] = {
+	{ .compatible = "" },
+	{}
+};
+#endif
+
+U_BOOT_DRIVER(lpc32xx_ssp_spi) = {
+	.name = "lpc32xx_ssp_spi",
+	.id = UCLASS_SPI,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.of_match = lpc32xx_ssp_spi_ids,
+	.ofdata_to_platdata = lpc32xx_ssp_spi_ofdata_to_platadata,
+	.platdata_auto_alloc_size = sizeof(struct lpc32xx_ssp_spi_platdata),
+#endif
+	.ops = &lpc32xx_ssp_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct lpc32xx_ssp_spi_priv),
+	.probe = lpc32xx_ssp_spi_probe,
+};
+#endif
diff --git a/include/dm/platform_data/spi_lpc32xx_ssp.h b/include/dm/platform_data/spi_lpc32xx_ssp.h
new file mode 100644
index 0000000..ea5cccf
--- /dev/null
+++ b/include/dm/platform_data/spi_lpc32xx_ssp.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018  Akash Gajjar <akash@openedev.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __lpc32xx_ssp_h
+#define __lpc32xx_ssp_h
+
+struct lpc32xx_ssp_spi_platdata {
+	struct ssp_regs *regs;
+};
+
+#endif /* __lpc32xx_ssp_h */
+
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v2 1/3] spi: sh_qspi: full DM conversion
  2018-05-09  6:36 ` [U-Boot] [PATCH v2 1/3] spi: sh_qspi: full " Akash Gajjar
@ 2018-05-09 11:21   ` Jagan Teki
  0 siblings, 0 replies; 22+ messages in thread
From: Jagan Teki @ 2018-05-09 11:21 UTC (permalink / raw)
  To: u-boot

What I understand from this is you made changes on top of your
previous patch which is wrong. Since the first patch is not accepted
and request for changes you need to make changes on top. Since this is
v2 you mentioned 'changes for v2' what is been fixed/updated with this
version.

On Wed, May 9, 2018 at 12:06 PM, Akash Gajjar <gajjar04akash@gmail.com> wrote:
> v1->v2
> New in v2
> update Kconfig
> replace __sh_qspi_setup to sh_qspi_setup
> add missing memeber of platform data
>
> Signed-off-by: Akash Gajjar <akash@openedev.com>
> ---

Changes you need to write it here?

>  drivers/spi/Kconfig                | 12 +++++-----
>  drivers/spi/sh_qspi.c              | 49 +++++++++++++++++++-------------------
>  include/dm/platform_data/qspi_sh.h |  4 ----
>  3 files changed, 31 insertions(+), 34 deletions(-)
>

Send v3.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 1/3] spi: sh_qspi: DM conversion
       [not found] <akash@openedev.com>
                   ` (6 preceding siblings ...)
  2018-05-09  7:07 ` [U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion Akash Gajjar
@ 2018-05-10 14:13 ` Akash Gajjar
  2018-05-10 14:15 ` [U-Boot] [PATCH v3 2/3] spi: sh_spi: " Akash Gajjar
  2018-05-10 14:17 ` [U-Boot] [PATCH v3 3/3] spi: mxs_spi: " Akash Gajjar
  9 siblings, 0 replies; 22+ messages in thread
From: Akash Gajjar @ 2018-05-10 14:13 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Akash Gajjar <akash@openedev.com>
---
changes in v2:
 Update Kconfig
 Replace __sh_qspi_setup to sh_qspi_setup
 Add missing memeber of platform data

changes in v3:
 Changes made on top of previous patch is merged in v3
---
 drivers/spi/Kconfig                |  12 +--
 drivers/spi/sh_qspi.c              | 199 ++++++++++++++++++-------------------
 include/dm/platform_data/qspi_sh.h |  15 +++
 3 files changed, 120 insertions(+), 106 deletions(-)
 create mode 100644 include/dm/platform_data/qspi_sh.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ec92b84..81079c5 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -155,6 +155,12 @@ config SANDBOX_SPI
 		};
 	  };
 
+config SH_QSPI
+	bool "Renesas Quad SPI driver"
+	help
+	  Enable the Renesas Quad SPI controller driver. This driver can be
+	  used on Renesas SoCs.
+
 config STM32_QSPI
 	bool "STM32F7 QSPI driver"
 	depends on STM32F7
@@ -259,12 +265,6 @@ config SH_SPI
 	  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
-	  Enable the Renesas Quad SPI controller driver. This driver can be
-	  used on Renesas SoCs.
-
 config TI_QSPI
 	bool "TI QSPI driver"
 	help
diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c
index 5075be3..1ea24ce 100644
--- a/drivers/spi/sh_qspi.c
+++ b/drivers/spi/sh_qspi.c
@@ -1,6 +1,9 @@
 /*
  * SH QSPI (Quad SPI) driver
  *
+ * Support for device model:
+ * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
+ *
  * Copyright (C) 2013 Renesas Electronics Corporation
  * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
  *
@@ -14,6 +17,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 +72,89 @@ 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)
+static void sh_qspi_setup(struct sh_qspi_priv *priv)
 {
-	return container_of(slave, struct sh_qspi_slave, slave);
-}
+	struct sh_qspi_regs *regs = priv->regs;
 
-static void sh_qspi_init(struct sh_qspi_slave *ss)
-{
-	/* QSPI initialize */
 	/* Set master mode only */
-	writeb(SPCR_MSTR, &ss->regs->spcr);
+	writeb(SPCR_MSTR, &regs->spcr);
 
 	/* Set SSL signal level */
-	writeb(0x00, &ss->regs->sslp);
+	writeb(0x00, &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, &regs->sppcr);
 
 	/* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
-	writeb(0x01, &ss->regs->spbr);
+	writeb(0x01, &regs->spbr);
 
 	/* Disable Dummy Data Transmission */
-	writeb(0x00, &ss->regs->spdcr);
+	writeb(0x00, &regs->spdcr);
 
 	/* Set clock delay value */
-	writeb(0x00, &ss->regs->spckd);
+	writeb(0x00, &regs->spckd);
 
 	/* Set SSL negation delay value */
-	writeb(0x00, &ss->regs->sslnd);
+	writeb(0x00, &regs->sslnd);
 
 	/* Set next-access delay value */
-	writeb(0x00, &ss->regs->spnd);
+	writeb(0x00, &regs->spnd);
 
 	/* Set equence command */
-	writew(SPCMD_INIT2, &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);
-}
-
-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);
+	writew(SPCMD_INIT2, &regs->spcmd0);
 
 	/* Reset transfer and receive Buffer */
-	setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
+	setbits_8(&regs->spbfcr, SPBFCR_TXRST | SPBFCR_RXRST);
 
 	/* Clear transfer and receive Buffer control bit */
-	clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
+	clrbits_8(&regs->spbfcr, SPBFCR_TXRST | SPBFCR_RXRST);
 
 	/* Set equence control method. Use equence0 only */
-	writeb(0x00, &ss->regs->spscr);
+	writeb(0x00, &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);
+	setbits_8(&regs->spcr, SPCR_SPE);
 }
 
-void spi_init(void)
+static int sh_qspi_set_speed(struct udevice *bus, uint hz)
 {
-	/* nothing to do */
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int mode)
-{
-	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);	/* TODO */
 		return 0;
 	}
 
@@ -223,7 +166,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);			/* TODO */
 
 		/* Set 1048576 byte */
 		writel(0x100000, spbmul0);
@@ -245,27 +188,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 +217,63 @@ 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);		/* TODO */
 
 	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);
+
+	priv->regs = plat->regs;
+
+	sh_qspi_setup(priv);
+
+	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->regs = (struct sh_qspi_regs *regs)addr;
+
+	return 0;
+}
+
+/* TODO: update comptaible device tree binding */
+static const struct udevice_id sh_qspi_ids[] = {
+	{ .compatible = " " },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(sh_qspi) = {
+	.name = "sh_qspi",
+	.id = UCLASS_SPI,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.of_match = sh_qspi_ids,
+	.ofdata_to_platdata = sh_qspi_ofdata_to_platadata,
+	.platdata_auto_alloc_size = sizeof(struct sh_qspi_platdata),
+#endif
+	.ops = &sh_qspi_ops,
+	.priv_auto_alloc_size = sizeof(struct sh_qspi_priv),
+	.probe = sh_qspi_probe,
+};
+#endif
diff --git a/include/dm/platform_data/qspi_sh.h b/include/dm/platform_data/qspi_sh.h
new file mode 100644
index 0000000..4e24e51
--- /dev/null
+++ b/include/dm/platform_data/qspi_sh.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018  Akash Gajjar <akash@openedev.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __qspi_sh_h
+#define __qspi_sh_h
+
+struct sh_qspi_platdata {
+	struct sh_qspi_regs *regs;
+	uint cs;
+};
+
+#endif /* __qspi_sh_h */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 2/3] spi: sh_spi: DM conversion
       [not found] <akash@openedev.com>
                   ` (7 preceding siblings ...)
  2018-05-10 14:13 ` [U-Boot] [PATCH v3 1/3] spi: sh_qspi: " Akash Gajjar
@ 2018-05-10 14:15 ` Akash Gajjar
  2018-05-10 14:17 ` [U-Boot] [PATCH v3 3/3] spi: mxs_spi: " Akash Gajjar
  9 siblings, 0 replies; 22+ messages in thread
From: Akash Gajjar @ 2018-05-10 14:15 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Akash Gajjar <akash@openedev.com>
---
Changes in v2:
 Add cs_info method
 Remove fixed regs address
 Add missing platform struct missing member
 Moved priv struct into sh_spi.c
 Remove unnecessary space and comments

Changes in v3:
 Changes made on top of previous patch is merged in v3
---
 drivers/spi/Kconfig               |  12 +-
 drivers/spi/sh_spi.c              | 235 +++++++++++++++++++++++---------------
 drivers/spi/sh_spi.h              |   5 -
 include/dm/platform_data/spi_sh.h |  15 +++
 4 files changed, 164 insertions(+), 103 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..ba92bfb 100644
--- a/drivers/spi/sh_spi.c
+++ b/drivers/spi/sh_spi.c
@@ -1,6 +1,9 @@
 /*
  * SH SPI driver
  *
+ * Support for device model:
+ * Copyright (C) 2018	Akash Gajjar <akash@openedev.com>
+ *
  * Copyright (C) 2011-2012 Renesas Solutions Corp.
  *
  * SPDX-License-Identifier:	GPL-2.0
@@ -11,8 +14,15 @@
 #include <malloc.h>
 #include <spi.h>
 #include <asm/io.h>
+#include <dm.h>
+#include <dm/platform_data/spi_sh.h>
 #include "sh_spi.h"
 
+struct sh_spi_priv {
+	struct sh_spi_regs	*regs;
+	u32	cs;
+};
+
 static void sh_spi_write(unsigned long data, unsigned long *reg)
 {
 	writel(data, reg);
@@ -41,15 +51,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 +67,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 +77,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 +86,54 @@ 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_priv *priv)
 {
-	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;
+	struct sh_spi_regs *regs = priv->regs;
+	u32 cs = priv->cs;
 
 	/* 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,
-			unsigned int len, unsigned long flags)
+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 +142,164 @@ 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_cs_info(struct udevice *bus, uint cs,
+					struct spi_cs_info *info)
 {
-	if (!bus && cs < SH_SPI_NUM_CS)
-		return 1;
-	else
-		return 0;
+	struct sh_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->cs) {
+		printf("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
 }
 
-void spi_cs_activate(struct spi_slave *slave)
+static int sh_spi_probe(struct udevice *bus)
 {
+	struct sh_spi_platdata *plat = bus->platdata;
+	struct sh_spi_priv *priv = dev_get_priv(bus);
+	struct sh_spi_regs *regs = priv->regs;
+
+	priv->regs = plat->regs;
+	priv->cs = plat->cs;
+
+	spi_setup(priv);
 
+	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;
+
+	plat->regs = (struct sh_spi_regs *regs)addr;
+	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,
+	.cs_info	= sh_spi_cs_info,
+};
+
+/* TODO: update compatible device tree */
+static const struct udevice_id sh_spi_ids[] = {
+	{ .compatible = " " },
+};
+#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..f945744 100644
--- a/drivers/spi/sh_spi.h
+++ b/drivers/spi/sh_spi.h
@@ -55,11 +55,6 @@ 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_regs	*regs;
-};
-
 static inline struct sh_spi *to_sh_spi(struct spi_slave *slave)
 {
 	return container_of(slave, struct sh_spi, slave);
diff --git a/include/dm/platform_data/spi_sh.h b/include/dm/platform_data/spi_sh.h
new file mode 100644
index 0000000..c6d0ac5
--- /dev/null
+++ b/include/dm/platform_data/spi_sh.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __spi_sh_h
+#define __spi_sh_h
+
+struct sh_spi_platdata {
+	struct sh_spi_regs  *regs;
+	u8 cs;
+};
+
+#endif /* __spi_sh_h */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 3/3] spi: mxs_spi: DM conversion
       [not found] <akash@openedev.com>
                   ` (8 preceding siblings ...)
  2018-05-10 14:15 ` [U-Boot] [PATCH v3 2/3] spi: sh_spi: " Akash Gajjar
@ 2018-05-10 14:17 ` Akash Gajjar
  2018-05-10 14:30   ` Marek Vasut
  9 siblings, 1 reply; 22+ messages in thread
From: Akash Gajjar @ 2018-05-10 14:17 UTC (permalink / raw)
  To: u-boot

This patch adds support for DM driver model to the mxs spi driver. 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.

Signed-off-by: Akash Gajjar <akash@openedev.com>
---
changes in v2:
 Register cs_info method 
 Remove unused function __mxs_spi_setup
 Merged __spi_xfer function to spi_xfer
 printf replaced by debug

changes in v3:
 changes made on top of previous patch is merged in v3
---
 drivers/spi/Kconfig                |  12 +-
 drivers/spi/mxs_spi.c              | 258 +++++++++++++++++++++++--------------
 include/dm/platform_data/spi_mxs.h |  18 +++
 3 files changed, 183 insertions(+), 105 deletions(-)
 create mode 100644 include/dm/platform_data/spi_mxs.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ec92b84..5d3e152 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -106,6 +106,12 @@ config MVEBU_A3700_SPI
 	  used to access the SPI NOR flash on platforms embedding this
 	  Marvell IP core.
 
+config MXS_SPI
+	bool "MXS SPI Driver"
+	help
+	  Enable the MXS SPI controller driver. This driver can be used
+	  on the i.MX23 and i.MX28 SoCs.
+
 config PIC32_SPI
 	bool "Microchip PIC32 SPI driver"
 	depends on MACH_PIC32
@@ -299,12 +305,6 @@ config MXC_SPI
 	  Enable the MXC SPI controller driver. This driver can be used
 	  on various i.MX SoCs such as i.MX31/35/51/6/7.
 
-config MXS_SPI
-	bool "MXS SPI Driver"
-	help
-	  Enable the MXS SPI controller driver. This driver can be used
-	  on the i.MX23 and i.MX28 SoCs.
-
 config OMAP3_SPI
 	bool "McSPI driver for OMAP"
 	help
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
index 790db78..3054438 100644
--- a/drivers/spi/mxs_spi.c
+++ b/drivers/spi/mxs_spi.c
@@ -1,6 +1,9 @@
 /*
  * Freescale i.MX28 SPI driver
  *
+ * Support for device model:
+ * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
+ *
  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  * on behalf of DENX Software Engineering GmbH
  *
@@ -20,6 +23,8 @@
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/dma.h>
+#include <dm.h>
+#include <dm/platform_data/spi_mxs.h>
 
 #define	MXS_SPI_MAX_TIMEOUT	1000000
 #define	MXS_SPI_PORT_OFFSET	0x2000
@@ -28,93 +33,14 @@
 
 #define MXSSSP_SMALL_TRANSFER	512
 
-struct mxs_spi_slave {
-	struct spi_slave	slave;
-	uint32_t		max_khz;
-	uint32_t		mode;
-	struct mxs_ssp_regs	*regs;
+struct mxs_spi_priv {
+	struct mxs_ssp_regs *regs;
+	u32	max_khz;
+	u32	mode;
+	u32	bus;
+	u32	cs;
 };
 
-static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
-{
-	return container_of(slave, struct mxs_spi_slave, slave);
-}
-
-void spi_init(void)
-{
-}
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-	/* MXS SPI: 4 ports and 3 chip selects maximum */
-	if (!mxs_ssp_bus_id_valid(bus) || cs > 2)
-		return 0;
-	else
-		return 1;
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-				  unsigned int max_hz, unsigned int mode)
-{
-	struct mxs_spi_slave *mxs_slave;
-
-	if (!spi_cs_is_valid(bus, cs)) {
-		printf("mxs_spi: invalid bus %d / chip select %d\n", bus, cs);
-		return NULL;
-	}
-
-	mxs_slave = spi_alloc_slave(struct mxs_spi_slave, bus, cs);
-	if (!mxs_slave)
-		return NULL;
-
-	if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + bus))
-		goto err_init;
-
-	mxs_slave->max_khz = max_hz / 1000;
-	mxs_slave->mode = mode;
-	mxs_slave->regs = mxs_ssp_regs_by_bus(bus);
-
-	return &mxs_slave->slave;
-
-err_init:
-	free(mxs_slave);
-	return NULL;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
-	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
-	free(mxs_slave);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
-	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
-	struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
-	uint32_t reg = 0;
-
-	mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
-
-	writel((slave->cs << MXS_SSP_CHIPSELECT_SHIFT) |
-	       SSP_CTRL0_BUS_WIDTH_ONE_BIT,
-	       &ssp_regs->hw_ssp_ctrl0);
-
-	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
-	reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
-	reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
-	writel(reg, &ssp_regs->hw_ssp_ctrl1);
-
-	writel(0, &ssp_regs->hw_ssp_cmd0);
-
-	mxs_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
-
-	return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-}
-
 static void mxs_spi_start_xfer(struct mxs_ssp_regs *ssp_regs)
 {
 	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
@@ -127,10 +53,10 @@ static void mxs_spi_end_xfer(struct mxs_ssp_regs *ssp_regs)
 	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
 }
 
-static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
+static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv,
 			char *data, int length, int write, unsigned long flags)
 {
-	struct mxs_ssp_regs *ssp_regs = slave->regs;
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
 
 	if (flags & SPI_XFER_BEGIN)
 		mxs_spi_start_xfer(ssp_regs);
@@ -156,7 +82,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
 
 		if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
 			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
-			printf("MXS SPI: Timeout waiting for start\n");
+			debug("MXS SPI: Timeout waiting for start\n");
 			return -ETIMEDOUT;
 		}
 
@@ -168,7 +94,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
 		if (!write) {
 			if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_status_reg,
 				SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) {
-				printf("MXS SPI: Timeout waiting for data\n");
+				debug("MXS SPI: Timeout waiting for data\n");
 				return -ETIMEDOUT;
 			}
 
@@ -178,7 +104,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
 
 		if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg,
 			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
-			printf("MXS SPI: Timeout waiting for finish\n");
+			debug("MXS SPI: Timeout waiting for finish\n");
 			return -ETIMEDOUT;
 		}
 	}
@@ -186,12 +112,12 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
 	return 0;
 }
 
-static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
+static int mxs_spi_xfer_dma(struct mxs_spi_priv *priv,
 			char *data, int length, int write, unsigned long flags)
 {
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
 	const int xfer_max_sz = 0xff00;
 	const int desc_count = DIV_ROUND_UP(length, xfer_max_sz) + 1;
-	struct mxs_ssp_regs *ssp_regs = slave->regs;
 	struct mxs_dma_desc *dp;
 	uint32_t ctrl0;
 	uint32_t cache_data_count;
@@ -230,7 +156,7 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
 	/* Invalidate the area, so no writeback into the RAM races with DMA */
 	invalidate_dcache_range(dstart, dstart + cache_data_count);
 
-	dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + slave->slave.bus;
+	dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus;
 
 	dp = desc;
 	while (length) {
@@ -307,11 +233,67 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
 	return ret;
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-		const void *dout, void *din, unsigned long flags)
+static int mxs_spi_claim_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+	struct mxs_spi_platdata *plat = dev_get_platdata(bus);
+
+	writel(((plat->cs) << MXS_SSP_CHIPSELECT_SHIFT) |
+			SSP_CTRL0_BUS_WIDTH_ONE_BIT,
+			&ssp_regs->hw_ssp_ctrl0);
+
+	return 0;
+}
+
+static int mxs_spi_release_bus(struct udevice *dev)
 {
-	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
-	struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
+	return 0;
+}
+
+static int mxs_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_spi_platdata *plat = dev_get_platdata(bus);
+
+	if (speed > plat->max_khz)
+		speed = plat->max_khz;
+
+	priv->max_khz = speed;
+	debug("%s speed %u\n", __func__, speed);
+
+	mxs_set_ssp_busclock(plat->bus, priv->max_khz);
+
+	return 0;
+}
+
+static int mxs_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+	u32 reg;
+
+	priv->mode = mode;
+	debug("%s mode %u\n", __func__, mode);
+
+	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
+	reg |= (priv->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
+	reg |= (priv->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
+	writel(reg, &ssp_regs->hw_ssp_ctrl1);
+
+	/* go in idle state */
+	writel(0, &ssp_regs->hw_ssp_cmd0);
+
+	return 0;
+}
+
+static int mxs_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
 	int len = bitlen / 8;
 	char dummy;
 	int write = 0;
@@ -355,9 +337,87 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
 	if (!dma || (len < MXSSSP_SMALL_TRANSFER)) {
 		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
-		return mxs_spi_xfer_pio(mxs_slave, data, len, write, flags);
+		return mxs_spi_xfer_pio(priv, data, len, write, flags);
 	} else {
 		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
-		return mxs_spi_xfer_dma(mxs_slave, data, len, write, flags);
+		return mxs_spi_xfer_dma(priv, data, len, write, flags);
 	}
 }
+
+static int mxs_spi_cs_info(struct udevice *bus, uint cs,
+				struct spi_cs_info *info)
+{
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->cs) {
+		printf("%s: no cs %u\n", __func__, cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int mxs_spi_probe(struct udevice *dev)
+{
+	struct mxs_spi_platdata *plat = dev_get_platdata(dev);
+	struct mxs_spi_priv *priv = dev_get_priv(bus);
+	int err;
+
+	priv->max_khz = (plat->max_hz) / 1000;
+	priv->mode = plat->mode;
+	priv->bus = plat->bus;
+
+	err = mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus);
+	if (err) {
+		debug("%s: DMA init channel error %d\n", __func__, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops mxs_spi_ops = {
+	.claim_bus      = mxs_spi_claim_bus,
+	.release_bus    = mxs_spi_release_bus,
+	.xfer           = mxs_spi_xfer,
+	.set_speed      = mxs_spi_set_speed,
+	.set_mode       = mxs_spi_set_mode,
+	.cs_info 	= mxs_spi_cs_info,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int mxs_ofdata_to_platadata(struct udevice *bus)
+{
+	struct mxs_spi_platdata *plat = bus->platdata;
+	fdt_addr_t addr;
+
+	addr = devfdt_get_addr(bus);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	plat->regs = (struct mxs_ssp_regs *)addr;
+	plat->cs = fdtdec_get_int(gd->fdt_blob,
+			dev_of_offset(bus), "num-cs", 4);
+
+	return 0;
+}
+
+/* TODO: update compatible device tree */
+static const struct udevice_id mxs_spi_ids[] = {
+	{ .compatible = " " },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(mxs_spi) = {
+	.name	= "mxs_spi",
+	.id     = UCLASS_SPI,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.of_match = mxs_spi_ids,
+	.ofdata_to_platdata = mxs_ofdata_to_platadata,
+	.platdata_auto_alloc_size = sizeof(struct mxs_spi_platdata),
+#endif
+	.ops    = &mxs_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct mxs_spi_priv),
+	.probe  = mxs_spi_probe,
+};
diff --git a/include/dm/platform_data/spi_mxs.h b/include/dm/platform_data/spi_mxs.h
new file mode 100644
index 0000000..5164834
--- /dev/null
+++ b/include/dm/platform_data/spi_mxs.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#ifndef __SPI_MXS_H
+#define __SPI_MXS_H
+
+struct mxs_spi_platdata {
+	struct mxs_ssp_regs *regs;
+	u32 bus;
+	u32 max_hz;
+	u32 cs;
+};
+
+#endif /* __SPI_MXS_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 3/3] spi: mxs_spi: DM conversion
  2018-05-10 14:17 ` [U-Boot] [PATCH v3 3/3] spi: mxs_spi: " Akash Gajjar
@ 2018-05-10 14:30   ` Marek Vasut
  2018-05-11 10:08     ` Gajjar Akash
  0 siblings, 1 reply; 22+ messages in thread
From: Marek Vasut @ 2018-05-10 14:30 UTC (permalink / raw)
  To: u-boot

On 05/10/2018 04:17 PM, Akash Gajjar wrote:
> This patch adds support for DM driver model to the mxs spi driver. 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.
> 
> Signed-off-by: Akash Gajjar <akash@openedev.com>
> ---
> changes in v2:
>  Register cs_info method 
>  Remove unused function __mxs_spi_setup
>  Merged __spi_xfer function to spi_xfer
>  printf replaced by debug
> 
> changes in v3:
>  changes made on top of previous patch is merged in v3
> ---
>  drivers/spi/Kconfig                |  12 +-
>  drivers/spi/mxs_spi.c              | 258 +++++++++++++++++++++++--------------
>  include/dm/platform_data/spi_mxs.h |  18 +++
>  3 files changed, 183 insertions(+), 105 deletions(-)
>  create mode 100644 include/dm/platform_data/spi_mxs.h
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index ec92b84..5d3e152 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -106,6 +106,12 @@ config MVEBU_A3700_SPI
>  	  used to access the SPI NOR flash on platforms embedding this
>  	  Marvell IP core.
>  
> +config MXS_SPI
> +	bool "MXS SPI Driver"
> +	help
> +	  Enable the MXS SPI controller driver. This driver can be used
> +	  on the i.MX23 and i.MX28 SoCs.
> +
>  config PIC32_SPI
>  	bool "Microchip PIC32 SPI driver"
>  	depends on MACH_PIC32
> @@ -299,12 +305,6 @@ config MXC_SPI
>  	  Enable the MXC SPI controller driver. This driver can be used
>  	  on various i.MX SoCs such as i.MX31/35/51/6/7.
>  
> -config MXS_SPI
> -	bool "MXS SPI Driver"
> -	help
> -	  Enable the MXS SPI controller driver. This driver can be used
> -	  on the i.MX23 and i.MX28 SoCs.
> -
>  config OMAP3_SPI
>  	bool "McSPI driver for OMAP"
>  	help
> diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
> index 790db78..3054438 100644
> --- a/drivers/spi/mxs_spi.c
> +++ b/drivers/spi/mxs_spi.c
> @@ -1,6 +1,9 @@
>  /*
>   * Freescale i.MX28 SPI driver
>   *
> + * Support for device model:
> + * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
> + *
>   * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
>   * on behalf of DENX Software Engineering GmbH
>   *
> @@ -20,6 +23,8 @@
>  #include <asm/arch/imx-regs.h>
>  #include <asm/arch/sys_proto.h>
>  #include <asm/mach-imx/dma.h>
> +#include <dm.h>
> +#include <dm/platform_data/spi_mxs.h>
>  
>  #define	MXS_SPI_MAX_TIMEOUT	1000000
>  #define	MXS_SPI_PORT_OFFSET	0x2000
> @@ -28,93 +33,14 @@
>  
>  #define MXSSSP_SMALL_TRANSFER	512
>  
> -struct mxs_spi_slave {
> -	struct spi_slave	slave;
> -	uint32_t		max_khz;
> -	uint32_t		mode;
> -	struct mxs_ssp_regs	*regs;
> +struct mxs_spi_priv {
> +	struct mxs_ssp_regs *regs;
> +	u32	max_khz;
> +	u32	mode;
> +	u32	bus;
> +	u32	cs;

Type cleanup should be a separate patch

>  };
>  
> -static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
> -{
> -	return container_of(slave, struct mxs_spi_slave, slave);
> -}
> -
> -void spi_init(void)
> -{
> -}
> -
> -int spi_cs_is_valid(unsigned int bus, unsigned int cs)
> -{
> -	/* MXS SPI: 4 ports and 3 chip selects maximum */
> -	if (!mxs_ssp_bus_id_valid(bus) || cs > 2)
> -		return 0;
> -	else
> -		return 1;
> -}
> -
> -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> -				  unsigned int max_hz, unsigned int mode)
> -{
> -	struct mxs_spi_slave *mxs_slave;
> -
> -	if (!spi_cs_is_valid(bus, cs)) {
> -		printf("mxs_spi: invalid bus %d / chip select %d\n", bus, cs);
> -		return NULL;
> -	}
> -
> -	mxs_slave = spi_alloc_slave(struct mxs_spi_slave, bus, cs);
> -	if (!mxs_slave)
> -		return NULL;
> -
> -	if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + bus))
> -		goto err_init;
> -
> -	mxs_slave->max_khz = max_hz / 1000;
> -	mxs_slave->mode = mode;
> -	mxs_slave->regs = mxs_ssp_regs_by_bus(bus);
> -
> -	return &mxs_slave->slave;
> -
> -err_init:
> -	free(mxs_slave);
> -	return NULL;
> -}
> -
> -void spi_free_slave(struct spi_slave *slave)
> -{
> -	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
> -	free(mxs_slave);
> -}
> -
> -int spi_claim_bus(struct spi_slave *slave)
> -{
> -	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
> -	struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
> -	uint32_t reg = 0;
> -
> -	mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
> -
> -	writel((slave->cs << MXS_SSP_CHIPSELECT_SHIFT) |
> -	       SSP_CTRL0_BUS_WIDTH_ONE_BIT,
> -	       &ssp_regs->hw_ssp_ctrl0);
> -
> -	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> -	reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> -	reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> -	writel(reg, &ssp_regs->hw_ssp_ctrl1);
> -
> -	writel(0, &ssp_regs->hw_ssp_cmd0);
> -
> -	mxs_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
> -
> -	return 0;
> -}
> -
> -void spi_release_bus(struct spi_slave *slave)
> -{
> -}
> -
>  static void mxs_spi_start_xfer(struct mxs_ssp_regs *ssp_regs)
>  {
>  	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
> @@ -127,10 +53,10 @@ static void mxs_spi_end_xfer(struct mxs_ssp_regs *ssp_regs)
>  	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
>  }
>  
> -static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
> +static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv,
>  			char *data, int length, int write, unsigned long flags)
>  {
> -	struct mxs_ssp_regs *ssp_regs = slave->regs;
> +	struct mxs_ssp_regs *ssp_regs = priv->regs;
>  
>  	if (flags & SPI_XFER_BEGIN)
>  		mxs_spi_start_xfer(ssp_regs);
> @@ -156,7 +82,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
>  
>  		if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
>  			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
> -			printf("MXS SPI: Timeout waiting for start\n");
> +			debug("MXS SPI: Timeout waiting for start\n");

printf , we don't want to hide errors

>  			return -ETIMEDOUT;
>  		}
>  
> @@ -168,7 +94,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
>  		if (!write) {
>  			if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_status_reg,
>  				SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) {
> -				printf("MXS SPI: Timeout waiting for data\n");
> +				debug("MXS SPI: Timeout waiting for data\n");

DTTO

>  				return -ETIMEDOUT;
>  			}
>  
> @@ -178,7 +104,7 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
>  
>  		if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg,
>  			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
> -			printf("MXS SPI: Timeout waiting for finish\n");
> +			debug("MXS SPI: Timeout waiting for finish\n");

DTTO

>  			return -ETIMEDOUT;
>  		}
>  	}
> @@ -186,12 +112,12 @@ static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
>  	return 0;
>  }
>  
> -static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
> +static int mxs_spi_xfer_dma(struct mxs_spi_priv *priv,
>  			char *data, int length, int write, unsigned long flags)
>  {
> +	struct mxs_ssp_regs *ssp_regs = priv->regs;
>  	const int xfer_max_sz = 0xff00;
>  	const int desc_count = DIV_ROUND_UP(length, xfer_max_sz) + 1;
> -	struct mxs_ssp_regs *ssp_regs = slave->regs;
>  	struct mxs_dma_desc *dp;
>  	uint32_t ctrl0;
>  	uint32_t cache_data_count;
> @@ -230,7 +156,7 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
>  	/* Invalidate the area, so no writeback into the RAM races with DMA */
>  	invalidate_dcache_range(dstart, dstart + cache_data_count);
>  
> -	dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + slave->slave.bus;
> +	dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus;
>  
>  	dp = desc;
>  	while (length) {
> @@ -307,11 +233,67 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
>  	return ret;
>  }
>  
> -int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> -		const void *dout, void *din, unsigned long flags)
> +static int mxs_spi_claim_bus(struct udevice *dev)
> +{
> +	struct udevice *bus = dev_get_parent(dev);
> +	struct mxs_spi_priv *priv = dev_get_priv(bus);
> +	struct mxs_ssp_regs *ssp_regs = priv->regs;
> +	struct mxs_spi_platdata *plat = dev_get_platdata(bus);
> +
> +	writel(((plat->cs) << MXS_SSP_CHIPSELECT_SHIFT) |

plat->cs doesnt need parenthesis

> +			SSP_CTRL0_BUS_WIDTH_ONE_BIT,
> +			&ssp_regs->hw_ssp_ctrl0);
> +
> +	return 0;
> +}
> +
> +static int mxs_spi_release_bus(struct udevice *dev)
>  {
> -	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
> -	struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
> +	return 0;
> +}
> +
> +static int mxs_spi_set_speed(struct udevice *bus, uint speed)
> +{
> +	struct mxs_spi_priv *priv = dev_get_priv(bus);
> +	struct mxs_spi_platdata *plat = dev_get_platdata(bus);
> +
> +	if (speed > plat->max_khz)
> +		speed = plat->max_khz;
> +
> +	priv->max_khz = speed;
> +	debug("%s speed %u\n", __func__, speed);
> +
> +	mxs_set_ssp_busclock(plat->bus, priv->max_khz);
> +
> +	return 0;
> +}
> +
> +static int mxs_spi_set_mode(struct udevice *bus, uint mode)
> +{
> +	struct mxs_spi_priv *priv = dev_get_priv(bus);
> +	struct mxs_ssp_regs *ssp_regs = priv->regs;
> +	u32 reg;
> +
> +	priv->mode = mode;
> +	debug("%s mode %u\n", __func__, mode);
> +
> +	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> +	reg |= (priv->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> +	reg |= (priv->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> +	writel(reg, &ssp_regs->hw_ssp_ctrl1);
> +
> +	/* go in idle state */
> +	writel(0, &ssp_regs->hw_ssp_cmd0);
> +
> +	return 0;
> +}
> +
> +static int mxs_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +			const void *dout, void *din, unsigned long flags)
> +{
> +	struct udevice *bus = dev_get_parent(dev);
> +	struct mxs_spi_priv *priv = dev_get_priv(bus);
> +	struct mxs_ssp_regs *ssp_regs = priv->regs;
>  	int len = bitlen / 8;
>  	char dummy;
>  	int write = 0;
> @@ -355,9 +337,87 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>  
>  	if (!dma || (len < MXSSSP_SMALL_TRANSFER)) {
>  		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
> -		return mxs_spi_xfer_pio(mxs_slave, data, len, write, flags);
> +		return mxs_spi_xfer_pio(priv, data, len, write, flags);
>  	} else {
>  		writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
> -		return mxs_spi_xfer_dma(mxs_slave, data, len, write, flags);
> +		return mxs_spi_xfer_dma(priv, data, len, write, flags);
>  	}
>  }
> +
> +static int mxs_spi_cs_info(struct udevice *bus, uint cs,
> +				struct spi_cs_info *info)
> +{
> +	struct mxs_spi_priv *priv = dev_get_priv(bus);
> +
> +	if (cs >= priv->cs) {
> +		printf("%s: no cs %u\n", __func__, cs);
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mxs_spi_probe(struct udevice *dev)
> +{
> +	struct mxs_spi_platdata *plat = dev_get_platdata(dev);
> +	struct mxs_spi_priv *priv = dev_get_priv(bus);
> +	int err;
> +
> +	priv->max_khz = (plat->max_hz) / 1000;
> +	priv->mode = plat->mode;
> +	priv->bus = plat->bus;
> +
> +	err = mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->bus);
> +	if (err) {
> +		debug("%s: DMA init channel error %d\n", __func__, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dm_spi_ops mxs_spi_ops = {
> +	.claim_bus      = mxs_spi_claim_bus,
> +	.release_bus    = mxs_spi_release_bus,
> +	.xfer           = mxs_spi_xfer,
> +	.set_speed      = mxs_spi_set_speed,
> +	.set_mode       = mxs_spi_set_mode,
> +	.cs_info 	= mxs_spi_cs_info,
> +};
> +
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +static int mxs_ofdata_to_platadata(struct udevice *bus)
> +{
> +	struct mxs_spi_platdata *plat = bus->platdata;
> +	fdt_addr_t addr;
> +
> +	addr = devfdt_get_addr(bus);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	plat->regs = (struct mxs_ssp_regs *)addr;
> +	plat->cs = fdtdec_get_int(gd->fdt_blob,
> +			dev_of_offset(bus), "num-cs", 4);
> +
> +	return 0;
> +}
> +
> +/* TODO: update compatible device tree */
> +static const struct udevice_id mxs_spi_ids[] = {
> +	{ .compatible = " " },
> +	{ }
> +};
> +#endif
> +
> +U_BOOT_DRIVER(mxs_spi) = {
> +	.name	= "mxs_spi",
> +	.id     = UCLASS_SPI,
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +	.of_match = mxs_spi_ids,
> +	.ofdata_to_platdata = mxs_ofdata_to_platadata,
> +	.platdata_auto_alloc_size = sizeof(struct mxs_spi_platdata),
> +#endif
> +	.ops    = &mxs_spi_ops,
> +	.priv_auto_alloc_size = sizeof(struct mxs_spi_priv),
> +	.probe  = mxs_spi_probe,
> +};
> diff --git a/include/dm/platform_data/spi_mxs.h b/include/dm/platform_data/spi_mxs.h
> new file mode 100644
> index 0000000..5164834
> --- /dev/null
> +++ b/include/dm/platform_data/spi_mxs.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + *
> + */
> +
> +#ifndef __SPI_MXS_H
> +#define __SPI_MXS_H
> +
> +struct mxs_spi_platdata {
> +	struct mxs_ssp_regs *regs;
> +	u32 bus;
> +	u32 max_hz;
> +	u32 cs;

Why is this header here at all ?

> +};
> +
> +#endif /* __SPI_MXS_H */
> 


-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 3/3] spi: mxs_spi: DM conversion
  2018-05-10 14:30   ` Marek Vasut
@ 2018-05-11 10:08     ` Gajjar Akash
  2018-05-11 10:39       ` Marek Vasut
  0 siblings, 1 reply; 22+ messages in thread
From: Gajjar Akash @ 2018-05-11 10:08 UTC (permalink / raw)
  To: u-boot

Hi Marek,

Thanks for the review comments.

> -struct mxs_spi_slave {
> > -     struct spi_slave        slave;
> > -     uint32_t                max_khz;
> > -     uint32_t                mode;
> > -     struct mxs_ssp_regs     *regs;
> > +struct mxs_spi_priv {
> > +     struct mxs_ssp_regs *regs;
> > +     u32     max_khz;
> > +     u32     mode;
> > +     u32     bus;
> > +     u32     cs;
>
> Type cleanup should be a separate patch
>

Okay, I will prepare seperate patch for type cleanup.


> >  };
> >               if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
> >                       SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
> > -                     printf("MXS SPI: Timeout waiting for start\n");
> > +                     debug("MXS SPI: Timeout waiting for start\n");
>
> printf , we don't want to hide errors
>

okay, will revert it back to printf.


> >                       return -ETIMEDOUT;
> >               }

> +
> > +#ifndef __SPI_MXS_H
> > +#define __SPI_MXS_H
> > +
> > +struct mxs_spi_platdata {
> > +     struct mxs_ssp_regs *regs;
> > +     u32 bus;
> > +     u32 max_hz;
> > +     u32 cs;
>
> Why is this header here at all ?
>

I didnt get this comment. do I need to place it somewhere else?

> +};
> > +
> > +#endif /* __SPI_MXS_H */
> >
>
>
> --
> Best regards,
> Marek Vasut
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
>

Thanks,
Akash

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 3/3] spi: mxs_spi: DM conversion
  2018-05-11 10:08     ` Gajjar Akash
@ 2018-05-11 10:39       ` Marek Vasut
  2018-05-11 11:09         ` Akash Gajjar
  0 siblings, 1 reply; 22+ messages in thread
From: Marek Vasut @ 2018-05-11 10:39 UTC (permalink / raw)
  To: u-boot

On 05/11/2018 12:08 PM, Gajjar Akash wrote:
> Hi Marek,
> 
> Thanks for the review comments.
> 
>     > -struct mxs_spi_slave {
>     > -     struct spi_slave        slave;
>     > -     uint32_t                max_khz;
>     > -     uint32_t                mode;
>     > -     struct mxs_ssp_regs     *regs;
>     > +struct mxs_spi_priv {
>     > +     struct mxs_ssp_regs *regs;
>     > +     u32     max_khz;
>     > +     u32     mode;
>     > +     u32     bus;
>     > +     u32     cs;
> 
>     Type cleanup should be a separate patch
> 
>  
> Okay, I will prepare seperate patch for type cleanup.
> 
> 
>     >  };
>     >               if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
>     >                       SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
>     > -                     printf("MXS SPI: Timeout waiting for start\n");
>     > +                     debug("MXS SPI: Timeout waiting for start\n");
> 
>     printf , we don't want to hide errors
> 
>  
> okay, will revert it back to printf.
> 
> 
>     >                       return -ETIMEDOUT;
>     >               }
> 
>     > +
>     > +#ifndef __SPI_MXS_H
>     > +#define __SPI_MXS_H
>     > +
>     > +struct mxs_spi_platdata {
>     > +     struct mxs_ssp_regs *regs;
>     > +     u32 bus;
>     > +     u32 max_hz;
>     > +     u32 cs;
> 
>     Why is this header here at all ?
> 
>  
> I didnt get this comment. do I need to place it somewhere else?

See the beginning of this email, it seems the same structure exists twice.

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 3/3] spi: mxs_spi: DM conversion
  2018-05-11 10:39       ` Marek Vasut
@ 2018-05-11 11:09         ` Akash Gajjar
  2018-05-11 11:31           ` Marek Vasut
  0 siblings, 1 reply; 22+ messages in thread
From: Akash Gajjar @ 2018-05-11 11:09 UTC (permalink / raw)
  To: u-boot

Hello Marek,

On Fri, May 11, 2018 at 4:09 PM, Marek Vasut <marek.vasut@gmail.com> wrote:

> On 05/11/2018 12:08 PM, Gajjar Akash wrote:
> > Hi Marek,
> >
> > Thanks for the review comments.
> >
> >     > -struct mxs_spi_slave {
> >     > -     struct spi_slave        slave;
> >     > -     uint32_t                max_khz;
> >     > -     uint32_t                mode;
> >     > -     struct mxs_ssp_regs     *regs;
> >     > +struct mxs_spi_priv {
> >     > +     struct mxs_ssp_regs *regs;
> >     > +     u32     max_khz;
> >     > +     u32     mode;
> >     > +     u32     bus;
> >     > +     u32     cs;
> >
> >     Type cleanup should be a separate patch
> >
> >
> > Okay, I will prepare seperate patch for type cleanup.
> >
> >
> >     >  };
> >     >               if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
> >     >                       SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
> >     > -                     printf("MXS SPI: Timeout waiting for
> start\n");
> >     > +                     debug("MXS SPI: Timeout waiting for
> start\n");
> >
> >     printf , we don't want to hide errors
> >
> >
> > okay, will revert it back to printf.
> >
> >
> >     >                       return -ETIMEDOUT;
> >     >               }
> >
> >     > +
> >     > +#ifndef __SPI_MXS_H
> >     > +#define __SPI_MXS_H
> >     > +
> >     > +struct mxs_spi_platdata {
> >     > +     struct mxs_ssp_regs *regs;
> >     > +     u32 bus;
> >     > +     u32 max_hz;
> >     > +     u32 cs;
> >
> >     Why is this header here at all ?
> >
> >
> > I didnt get this comment. do I need to place it somewhere else?
>
> See the beginning of this email, it seems the same structure exists twice.
>

​My intention was to have two individual structure for private and platform
data.​
But now I could use one structre and access its members using two structure
variables(one for private and one for platadata).

Is That looks okay?


>
> --
> Best regards,
> Marek Vasut
>


​Thanks,

*​Akash Gajjar*

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 3/3] spi: mxs_spi: DM conversion
  2018-05-11 11:09         ` Akash Gajjar
@ 2018-05-11 11:31           ` Marek Vasut
  0 siblings, 0 replies; 22+ messages in thread
From: Marek Vasut @ 2018-05-11 11:31 UTC (permalink / raw)
  To: u-boot

On 05/11/2018 01:09 PM, Akash Gajjar wrote:
> Hello Marek,
> 
> On Fri, May 11, 2018 at 4:09 PM, Marek Vasut <marek.vasut@gmail.com
> <mailto:marek.vasut@gmail.com>> wrote:
> 
>     On 05/11/2018 12:08 PM, Gajjar Akash wrote:
>     > Hi Marek,
>     >
>     > Thanks for the review comments.
>     >
>     >     > -struct mxs_spi_slave {
>     >     > -     struct spi_slave        slave;
>     >     > -     uint32_t                max_khz;
>     >     > -     uint32_t                mode;
>     >     > -     struct mxs_ssp_regs     *regs;
>     >     > +struct mxs_spi_priv {
>     >     > +     struct mxs_ssp_regs *regs;
>     >     > +     u32     max_khz;
>     >     > +     u32     mode;
>     >     > +     u32     bus;
>     >     > +     u32     cs;
>     >
>     >     Type cleanup should be a separate patch
>     >
>     >  
>     > Okay, I will prepare seperate patch for type cleanup.
>     >
>     >
>     >     >  };
>     >     >               if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
>     >     >                       SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
>     >     > -                     printf("MXS SPI: Timeout waiting for
>     start\n");
>     >     > +                     debug("MXS SPI: Timeout waiting for
>     start\n");
>     >
>     >     printf , we don't want to hide errors
>     >
>     >  
>     > okay, will revert it back to printf.
>     >
>     >
>     >     >                       return -ETIMEDOUT;
>     >     >               }
>     >
>     >     > +
>     >     > +#ifndef __SPI_MXS_H
>     >     > +#define __SPI_MXS_H
>     >     > +
>     >     > +struct mxs_spi_platdata {
>     >     > +     struct mxs_ssp_regs *regs;
>     >     > +     u32 bus;
>     >     > +     u32 max_hz;
>     >     > +     u32 cs;
>     >
>     >     Why is this header here at all ?
>     >
>     >  
>     > I didnt get this comment. do I need to place it somewhere else?
> 
>     See the beginning of this email, it seems the same structure exists
>     twice.
> 
> 
> ​My intention was to have two individual structure for private and
> platform data.​
> But now I could use one structre and access its members using two
> structure variables(one for private and one for platadata).
> 
> Is That looks okay?

I do not quite understand what you mean, but there is a duplication of
information here. That's a problem and should be fixed.

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion
  2018-05-09  7:07 ` [U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion Akash Gajjar
@ 2018-09-04  6:33   ` Jagan Teki
  2018-09-19 11:32     ` Vladimir Zapolskiy
  0 siblings, 1 reply; 22+ messages in thread
From: Jagan Teki @ 2018-09-04  6:33 UTC (permalink / raw)
  To: u-boot

On Wed, May 9, 2018 at 12:37 PM, Akash Gajjar <gajjar04akash@gmail.com> wrote:
> From: Akash Gajjar <gajjar04akash@gmail.com>
>
> This patch adds support for DM to the LPC32xx SSP SPI driver.
>
> 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.
>
> Signed-off-by: Akash Gajjar <akash@openedev.com>
> ---
>  drivers/spi/Kconfig                        |  10 +-
>  drivers/spi/lpc32xx_ssp.c                  | 145 +++++++++++++++--------------
>  include/dm/platform_data/spi_lpc32xx_ssp.h |  15 +++
>  3 files changed, 93 insertions(+), 77 deletions(-)
>  create mode 100644 include/dm/platform_data/spi_lpc32xx_ssp.h
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index ec92b84..2297d4a 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -99,6 +99,11 @@ config ICH_SPI
>           access the SPI NOR flash on platforms embedding this Intel
>           ICH IP core.
>
> +config LPC32XX_SSP
> +       bool "LPC32XX SPI Driver"
> +       help
> +         Enable support for SPI on LPC32xx
> +
>  config MVEBU_A3700_SPI
>         bool "Marvell Armada 3700 SPI driver"
>         help
> @@ -277,11 +282,6 @@ config KIRKWOOD_SPI
>           Enable support for SPI on various Marvell SoCs, such as
>           Kirkwood and Armada 375.
>
> -config LPC32XX_SSP
> -       bool "LPC32XX SPI Driver"
> -       help
> -         Enable support for SPI on LPC32xx
> -
>  config MPC8XX_SPI
>         bool "MPC8XX SPI Driver"
>         depends on MPC8xx
> diff --git a/drivers/spi/lpc32xx_ssp.c b/drivers/spi/lpc32xx_ssp.c
> index e2a593b..ae41b57 100644
> --- a/drivers/spi/lpc32xx_ssp.c
> +++ b/drivers/spi/lpc32xx_ssp.c
> @@ -4,6 +4,9 @@
>   * (C) Copyright 2014  DENX Software Engineering GmbH
>   * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
>   *
> + * Support for device model:
> + * Copyright (C) 2018 Akash Gajjar <akash@openedev.com>
> + *
>   * SPDX-License-Identifier:     GPL-2.0+
>   */
>
> @@ -13,6 +16,8 @@
>  #include <malloc.h>
>  #include <spi.h>
>  #include <asm/arch/clk.h>
> +#include <dm.h>
> +#include <dm/platform_data/spi_lpc32xx_ssp.h>
>
>  /* SSP chip registers */
>  struct ssp_regs {
> @@ -36,90 +41,36 @@ struct ssp_regs {
>  /* SSP status RX FIFO not empty bit */
>  #define SSP_SR_RNE 0x0004
>
> -/* lpc32xx spi slave */
> -struct lpc32xx_spi_slave {
> -       struct spi_slave slave;
> +struct lpc32xx_ssp_spi_priv {
>         struct ssp_regs *regs;
>  };
>
> -static inline struct lpc32xx_spi_slave *to_lpc32xx_spi_slave(
> -       struct spi_slave *slave)
> +static int lpc32xx_ssp_spi_claim_bus(struct udevice *dev)
>  {
> -       return container_of(slave, struct lpc32xx_spi_slave, slave);
> -}
> -
> -/* spi_init is called during boot when CONFIG_CMD_SPI is defined */
> -void spi_init(void)
> -{
> -       /*
> -        *  nothing to do: clocking was enabled in lpc32xx_ssp_enable()
> -        * and configuration will be done in spi_setup_slave()
> -       */
> +       return 0;
>  }
>
> -/* the following is called in sequence by do_spi_xfer() */
> -
> -struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode)
> +static int lpc32xx_ssp_spi_release_bus(struct udevice *dev)
>  {
> -       struct lpc32xx_spi_slave *lslave;
> -
> -       /* we only set up SSP0 for now, so ignore bus */
> -
> -       if (mode & SPI_3WIRE) {
> -               pr_err("3-wire mode not supported");
> -               return NULL;
> -       }
> -
> -       if (mode & SPI_SLAVE) {
> -               pr_err("slave mode not supported\n");
> -               return NULL;
> -       }
> -
> -       if (mode & SPI_PREAMBLE) {
> -               pr_err("preamble byte skipping not supported\n");
> -               return NULL;
> -       }
> -
> -       lslave = spi_alloc_slave(struct lpc32xx_spi_slave, bus, cs);
> -       if (!lslave) {
> -               printf("SPI_error: Fail to allocate lpc32xx_spi_slave\n");
> -               return NULL;
> -       }
> -
> -       lslave->regs = (struct ssp_regs *)SSP0_BASE;
> -
> -       /*
> -        * 8 bit frame, SPI fmt, 500kbps -> clock divider is 26.
> -        * Set SCR to 0 and CPSDVSR to 26.
> -        */
> -
> -       writel(0x7, &lslave->regs->cr0); /* 8-bit chunks, SPI, 1 clk/bit */
> -       writel(26, &lslave->regs->cpsr); /* SSP clock = HCLK/26 = 500kbps */
> -       writel(0, &lslave->regs->imsc); /* do not raise any interrupts */
> -       writel(0, &lslave->regs->icr); /* clear any pending interrupt */
> -       writel(0, &lslave->regs->dmacr); /* do not do DMAs */
> -       writel(SSP_CR1_SSP_ENABLE, &lslave->regs->cr1); /* enable SSP0 */
> -       return &lslave->slave;
> +       return 0;
>  }
>
> -void spi_free_slave(struct spi_slave *slave)
> +static int lpc32xx_ssp_spi_set_speed(struct udevice *bus, uint hz)
>  {
> -       struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
> -
> -       debug("(lpc32xx) spi_free_slave: 0x%08x\n", (u32)lslave);
> -       free(lslave);
> +       return 0;
>  }
>
> -int spi_claim_bus(struct spi_slave *slave)
> +static int lpc32xx_ssp_spi_set_mode(struct udevice *bus, uint mode)
>  {
> -       /* only one bus and slave so far, always available */
>         return 0;
>  }
>
> -int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> -       const void *dout, void *din, unsigned long flags)
> +static int lpc32xx_ssp_spi_xfer(struct udevice *dev, uint bitlen,
> +                               const void *dout, void *din, ulong flags)
>  {
> -       struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
> +       struct udevice *bus = dev->parent;
> +       struct lpc32xx_ssp_priv *priv = dev_get_priv(bus);
> +       struct ssp_regs *regs = priv->regs;
>         int bytelen = bitlen >> 3;
>         int idx_out = 0;
>         int idx_in = 0;
> @@ -127,18 +78,68 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>
>         start_time = get_timer(0);
>         while ((idx_out < bytelen) || (idx_in < bytelen)) {
> -               int status = readl(&lslave->regs->sr);
> +               int status = readl(&regs->sr);
>                 if ((idx_out < bytelen) && (status & SSP_SR_TNF))
> -                       writel(((u8 *)dout)[idx_out++], &lslave->regs->data);
> +                       writel(((u8 *)dout)[idx_out++], &regs->data);
>                 if ((idx_in < bytelen) && (status & status & SSP_SR_RNE))
> -                       ((u8 *)din)[idx_in++] = readl(&lslave->regs->data);
> +                       ((u8 *)din)[idx_in++] = readl(&regs->data);
>                 if (get_timer(start_time) >= CONFIG_LPC32XX_SSP_TIMEOUT)
>                         return -1;
>         }
> +
> +       return 0;
> +}
> +
> +static int lpc32xx_ssp_spi_probe(struct udevice *bus)
> +{
> +       struct lpc32xx_ssp_spi_platdata *plat = bus->platdata;
> +       struct lpc32xx_ssp_spi_priv = dev_get_priv(bus);
> +
> +       priv->regs = plat->regs;
> +
>         return 0;
>  }
>
> -void spi_release_bus(struct spi_slave *slave)
> +static const struct dm_spi_ops lpc32xx_ssp_spi_ops = {
> +       .claim_bus      = lpc32xx_ssp_spi_claim_bus,
> +       .release_bus    = lpc32xx_ssp_spi_release_bus,
> +       .xfer           = lpc32xx_ssp_spi_xfer,
> +       .set_speed      = lpc32xx_ssp_spi_set_speed,
> +       .set_mode       = lpc32xx_ssp_spi_set_mode,
> +};
> +
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +static int lpc32xx_ssp_spi_ofdata_to_platadata(struct udevice *bus)
>  {
> -       /* do nothing */
> +       struct lpc32xx_ssp_spi_platdata *plat = bus->platdata;
> +       fdt_addr_t addr;
> +
> +       addr = devfdt_get_addr(bus);
> +       if (addr == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       plat->regs = (struct struct ssp_regs *)addr;
> +
> +       return 0;
>  }
> +
> +/* TODO: update compatibel device tree */
> +static const struct udevice_id lpc32xx_ssp_spi_ids[] = {
> +       { .compatible = "" },

Don't we have DTS for this platform on Linux?

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion
  2018-09-04  6:33   ` Jagan Teki
@ 2018-09-19 11:32     ` Vladimir Zapolskiy
  2018-11-05 10:09       ` Jagan Teki
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir Zapolskiy @ 2018-09-19 11:32 UTC (permalink / raw)
  To: u-boot

On 09/04/2018 09:33 AM, Jagan Teki wrote:
> On Wed, May 9, 2018 at 12:37 PM, Akash Gajjar <gajjar04akash@gmail.com> wrote:
>> From: Akash Gajjar <gajjar04akash@gmail.com>
>>
>> This patch adds support for DM to the LPC32xx SSP SPI driver.
>>
>> 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.
>>
>> Signed-off-by: Akash Gajjar <akash@openedev.com>
>> ---

[snip]

>> +
>> +/* TODO: update compatibel device tree */
>> +static const struct udevice_id lpc32xx_ssp_spi_ids[] = {
>> +       { .compatible = "" },
> 
> Don't we have DTS for this platform on Linux?

We have, but it makes little sense to add platform OF support to U-Boot
at the moment.

In other words, all #if CONFIG_IS_ENABLED(OF_CONTROL) code sections
shall be removed.

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion
  2018-09-19 11:32     ` Vladimir Zapolskiy
@ 2018-11-05 10:09       ` Jagan Teki
  0 siblings, 0 replies; 22+ messages in thread
From: Jagan Teki @ 2018-11-05 10:09 UTC (permalink / raw)
  To: u-boot

On Wed, Sep 19, 2018 at 5:02 PM Vladimir Zapolskiy <vz@mleia.com> wrote:
>
> On 09/04/2018 09:33 AM, Jagan Teki wrote:
> > On Wed, May 9, 2018 at 12:37 PM, Akash Gajjar <gajjar04akash@gmail.com> wrote:
> >> From: Akash Gajjar <gajjar04akash@gmail.com>
> >>
> >> This patch adds support for DM to the LPC32xx SSP SPI driver.
> >>
> >> 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.
> >>
> >> Signed-off-by: Akash Gajjar <akash@openedev.com>
> >> ---
>
> [snip]
>
> >> +
> >> +/* TODO: update compatibel device tree */
> >> +static const struct udevice_id lpc32xx_ssp_spi_ids[] = {
> >> +       { .compatible = "" },
> >
> > Don't we have DTS for this platform on Linux?
>
> We have, but it makes little sense to add platform OF support to U-Boot
> at the moment.
>
> In other words, all #if CONFIG_IS_ENABLED(OF_CONTROL) code sections
> shall be removed.

But few core ops should depends on fdt lib functions, any plan on
adding OF_CONTROL to it?

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2018-11-05 10:09 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <akash@openedev.com>
2018-04-26 16:46 ` [U-Boot] [PATCH v1 1/3] spi: sh_qspi: DM conversion Akash Gajjar
2018-04-27  6:06   ` Jagan Teki
2018-04-26 16:48 ` [U-Boot] [PATCH v1 2/3] spi: sh_spi: " Akash Gajjar
2018-04-27  6:22   ` Jagan Teki
2018-04-26 16:50 ` [U-Boot] [PATCH v1 3/3] spi: mxs_spi: " Akash Gajjar
2018-04-27  6:40   ` Jagan Teki
2018-05-09  6:36 ` [U-Boot] [PATCH v2 1/3] spi: sh_qspi: full " Akash Gajjar
2018-05-09 11:21   ` Jagan Teki
2018-05-09  6:57 ` [U-Boot] [PATCH v2 2/3] spi: sh_spi: " Akash Gajjar
2018-05-09  7:04 ` [U-Boot] [PATCH v2 3/3] spi: mxs_spi: full dm conversion Akash Gajjar
2018-05-09  7:07 ` [U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion Akash Gajjar
2018-09-04  6:33   ` Jagan Teki
2018-09-19 11:32     ` Vladimir Zapolskiy
2018-11-05 10:09       ` Jagan Teki
2018-05-10 14:13 ` [U-Boot] [PATCH v3 1/3] spi: sh_qspi: " Akash Gajjar
2018-05-10 14:15 ` [U-Boot] [PATCH v3 2/3] spi: sh_spi: " Akash Gajjar
2018-05-10 14:17 ` [U-Boot] [PATCH v3 3/3] spi: mxs_spi: " Akash Gajjar
2018-05-10 14:30   ` Marek Vasut
2018-05-11 10:08     ` Gajjar Akash
2018-05-11 10:39       ` Marek Vasut
2018-05-11 11:09         ` Akash Gajjar
2018-05-11 11:31           ` Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.