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

Akash Gajjar gajjar04akash at gmail.com
Thu Apr 26 16:48:48 UTC 2018


This patch adds support for DM to the sh_spi driver. legacy driver support is
removed.

Some TODOs are left over for later, These would be enhancements to the
original functionality, and can come later. The legacy functionality is
removed in this version.

This patch is not tested on board as well compile tested yet.

Signed-off-by: Akash Gajjar <akash at openedev.com>
---
 drivers/spi/Kconfig               |  12 +--
 drivers/spi/sh_spi.c              | 214 +++++++++++++++++++++-----------------
 drivers/spi/sh_spi.h              |   3 +-
 include/dm/platform_data/spi_sh.h |  20 ++++
 4 files changed, 147 insertions(+), 102 deletions(-)
 create mode 100644 include/dm/platform_data/spi_sh.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ec92b84..be6ad22 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -155,6 +155,12 @@ config SANDBOX_SPI
 		};
 	  };
 
+config SH_SPI
+	bool "SuperH SPI driver"
+	help
+	  Enable the SuperH SPI controller driver. This driver can be used
+	  on various SuperH SoCs, such as SH7757.
+
 config STM32_QSPI
 	bool "STM32F7 QSPI driver"
 	depends on STM32F7
@@ -253,12 +259,6 @@ config DAVINCI_SPI
 	help
 	  Enable the Davinci SPI driver
 
-config SH_SPI
-	bool "SuperH SPI driver"
-	help
-	  Enable the SuperH SPI controller driver. This driver can be used
-	  on various SuperH SoCs, such as SH7757.
-
 config SH_QSPI
 	bool "Renesas Quad SPI driver"
 	help
diff --git a/drivers/spi/sh_spi.c b/drivers/spi/sh_spi.c
index fe394e3..b308ec8 100644
--- a/drivers/spi/sh_spi.c
+++ b/drivers/spi/sh_spi.c
@@ -1,6 +1,10 @@
 /*
  * SH SPI driver
  *
+ * Support for device model:
+ * Copyright (C) 2018 	Akash Gajjar <akash at openedev.com>
+ *			Harshit Shah <shahharshitr at gmail.com>
+ *
  * Copyright (C) 2011-2012 Renesas Solutions Corp.
  *
  * SPDX-License-Identifier:	GPL-2.0
@@ -11,6 +15,8 @@
 #include <malloc.h>
 #include <spi.h>
 #include <asm/io.h>
+#include <dm.h>
+#include <dm/platform_data/spi_sh.h>
 #include "sh_spi.h"
 
 static void sh_spi_write(unsigned long data, unsigned long *reg)
@@ -41,15 +47,15 @@ static void sh_spi_clear_bit(unsigned long val, unsigned long *reg)
 	sh_spi_write(tmp, reg);
 }
 
-static void clear_fifo(struct sh_spi *ss)
+static void clear_fifo(struct sh_spi_regs *regs)
 {
-	sh_spi_set_bit(SH_SPI_RSTF, &ss->regs->cr2);
-	sh_spi_clear_bit(SH_SPI_RSTF, &ss->regs->cr2);
+	sh_spi_set_bit(SH_SPI_RSTF, &regs->cr2);
+	sh_spi_clear_bit(SH_SPI_RSTF, &regs->cr2);
 }
 
-static int recvbuf_wait(struct sh_spi *ss)
+static int recvbuf_wait(struct sh_spi_regs *regs)
 {
-	while (sh_spi_read(&ss->regs->cr1) & SH_SPI_RBE) {
+	while (sh_spi_read(&regs->cr1) & SH_SPI_RBE) {
 		if (ctrlc())
 			return 1;
 		udelay(10);
@@ -57,9 +63,9 @@ static int recvbuf_wait(struct sh_spi *ss)
 	return 0;
 }
 
-static int write_fifo_empty_wait(struct sh_spi *ss)
+static int write_fifo_empty_wait(struct sh_spi_regs *regs)
 {
-	while (!(sh_spi_read(&ss->regs->cr1) & SH_SPI_TBE)) {
+	while (!(sh_spi_read(&regs->cr1) & SH_SPI_TBE)) {
 		if (ctrlc())
 			return 1;
 		udelay(10);
@@ -67,11 +73,7 @@ static int write_fifo_empty_wait(struct sh_spi *ss)
 	return 0;
 }
 
-void spi_init(void)
-{
-}
-
-static void sh_spi_set_cs(struct sh_spi *ss, unsigned int cs)
+static void sh_spi_set_cs(struct sh_spi_regs *regs, unsigned int cs)
 {
 	unsigned long val = 0;
 
@@ -80,85 +82,53 @@ static void sh_spi_set_cs(struct sh_spi *ss, unsigned int cs)
 	if (cs & 0x02)
 		val |= SH_SPI_SSS1;
 
-	sh_spi_clear_bit(SH_SPI_SSS0 | SH_SPI_SSS1, &ss->regs->cr4);
-	sh_spi_set_bit(val, &ss->regs->cr4);
+	sh_spi_clear_bit(SH_SPI_SSS0 | SH_SPI_SSS1, &regs->cr4);
+	sh_spi_set_bit(val, &regs->cr4);
 }
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int mode)
+static void __spi_setup(struct sh_spi_regs *regs, uint cs)
 {
-	struct sh_spi *ss;
-
-	if (!spi_cs_is_valid(bus, cs))
-		return NULL;
-
-	ss = spi_alloc_slave(struct sh_spi, bus, cs);
-	if (!ss)
-		return NULL;
-
-	ss->regs = (struct sh_spi_regs *)CONFIG_SH_SPI_BASE;
-
+	/* initialize spi */
+	regs = (struct sh_spi_regs *)CONFIG_SH_SPI_BASE;
 	/* 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 at 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



More information about the U-Boot mailing list