public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Akash Gajjar <gajjar04akash@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v1 2/3] spi: sh_spi: DM conversion
Date: Thu, 26 Apr 2018 22:18:48 +0530	[thread overview]
Message-ID: <1524761329-8652-1-git-send-email-akash@openedev.com> (raw)
In-Reply-To: <akash@openedev.com>

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

  parent reply	other threads:[~2018-04-26 16:48 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [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 ` Akash Gajjar [this message]
2018-04-27  6:22   ` [U-Boot] [PATCH v1 2/3] spi: sh_spi: " 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1524761329-8652-1-git-send-email-akash@openedev.com \
    --to=gajjar04akash@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox