All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2] spi: add support SuperH SPI module
Date: Tue, 18 Jan 2011 17:53:42 +0900	[thread overview]
Message-ID: <4D355516.6020906@renesas.com> (raw)

SH7757 has SPI module. This patch supports it.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 about v2:
  - add prefix of "SH_" to some defines.
  - modify spi_cs_is_valid()

 drivers/spi/Makefile |    1 +
 drivers/spi/sh_spi.c |  301 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 302 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/sh_spi.c

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e34a124..d582fbb 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -37,6 +37,7 @@ COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
 COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
+COBJS-$(CONFIG_SH_SPI) += sh_spi.o

 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/spi/sh_spi.c b/drivers/spi/sh_spi.c
new file mode 100644
index 0000000..633450c
--- /dev/null
+++ b/drivers/spi/sh_spi.c
@@ -0,0 +1,301 @@
+/*
+ * SH SPI driver
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+
+#define SH_SPI_TBR	0x00
+#define SH_SPI_RBR	0x00
+#define SH_SPI_CR1	0x08
+#define SH_SPI_CR2	0x10
+#define SH_SPI_CR3	0x18
+#define SH_SPI_CR4	0x20
+
+/* CR1 */
+#define SH_SPI_TBE	0x80
+#define SH_SPI_TBF	0x40
+#define SH_SPI_RBE	0x20
+#define SH_SPI_RBF	0x10
+#define SH_SPI_PFONRD	0x08
+#define SH_SPI_SSDB	0x04
+#define SH_SPI_SSD	0x02
+#define SH_SPI_SSA	0x01
+
+/* CR2 */
+#define SH_SPI_RSTF	0x80
+#define SH_SPI_LOOPBK	0x40
+#define SH_SPI_CPOL	0x20
+#define SH_SPI_CPHA	0x10
+#define SH_SPI_L1M0	0x08
+
+/* CR3 */
+#define SH_SPI_MAX_BYTE	0xFF
+
+/* CR4 */
+#define SH_SPI_TBEI	0x80
+#define SH_SPI_TBFI	0x40
+#define SH_SPI_RBEI	0x20
+#define SH_SPI_RBFI	0x10
+#define SH_SPI_WPABRT	0x04
+#define SH_SPI_SSS	0x01
+
+#define SH_SPI_FIFO_SIZE	32
+
+static void sh_spi_write(unsigned long data, unsigned long offset)
+{
+	writel(data, CONFIG_SH_SPI_BASE + offset);
+}
+
+static unsigned long sh_spi_read(unsigned long offset)
+{
+	return readl(CONFIG_SH_SPI_BASE + offset);
+}
+
+static void sh_spi_set_bit(unsigned long val, unsigned long offset)
+{
+	unsigned long tmp;
+
+	tmp = sh_spi_read(offset);
+	tmp |= val;
+	sh_spi_write(tmp, offset);
+}
+
+static void sh_spi_clear_bit(unsigned long val, unsigned long offset)
+{
+	unsigned long tmp;
+
+	tmp = sh_spi_read(offset);
+	tmp &= ~val;
+	sh_spi_write(tmp, offset);
+}
+
+static void clear_fifo(void)
+{
+	sh_spi_set_bit(SH_SPI_RSTF, SH_SPI_CR2);
+	sh_spi_clear_bit(SH_SPI_RSTF, SH_SPI_CR2);
+}
+
+static int recvbuf_wait(void)
+{
+	while (sh_spi_read(SH_SPI_CR1) & SH_SPI_RBE) {
+		if (ctrlc())
+			return 1;
+		udelay(10);
+	}
+	return 0;
+}
+
+static int write_fifo_full_wait(void)
+{
+	while (sh_spi_read(SH_SPI_CR1) & SH_SPI_TBF) {
+		udelay(10);
+		if (ctrlc())
+			return 1;
+	}
+	return 0;
+}
+
+static int write_fifo_empty_wait(void)
+{
+	while (!(sh_spi_read(SH_SPI_CR1) & SH_SPI_TBE)) {
+		if (ctrlc())
+			return 1;
+		udelay(10);
+	}
+	return 0;
+}
+
+void spi_init(void)
+{
+
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	struct spi_slave *slave;
+
+	if (!spi_cs_is_valid(bus, cs))
+		return NULL;
+
+	slave = malloc(sizeof(struct spi_slave));
+	if (!slave)
+		return NULL;
+
+	slave->bus = bus;
+	slave->cs = cs;
+
+	/* SPI sycle stop */
+	sh_spi_write(0xfe, SH_SPI_CR1);
+	/* CR1 init */
+	sh_spi_write(0x00, SH_SPI_CR1);
+	/* CR3 init */
+	sh_spi_write(0x00, SH_SPI_CR3);
+
+	clear_fifo();
+
+	/* 1/8 clock */
+	sh_spi_write(sh_spi_read(SH_SPI_CR2) | 0x07, SH_SPI_CR2);
+	udelay(10);
+
+	return slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	free(slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	sh_spi_write(sh_spi_read(SH_SPI_CR1) &
+			~(SH_SPI_SSA | SH_SPI_SSDB | SH_SPI_SSD), SH_SPI_CR1);
+}
+
+static int sh_spi_send(const unsigned char *tx_data, unsigned int len,
+			unsigned long flags)
+{
+	int i, cur_len, ret = 0;
+	int remain = (int)len;
+	unsigned long tmp;
+
+	if (len >= SH_SPI_FIFO_SIZE)
+		sh_spi_set_bit(SH_SPI_SSA, SH_SPI_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(SH_SPI_CR4) & SH_SPI_WPABRT) &&
+				!(sh_spi_read(SH_SPI_CR1) & SH_SPI_TBF);
+				i++)
+			sh_spi_write(tx_data[i], SH_SPI_TBR);
+
+		cur_len = i;
+
+		if (sh_spi_read(SH_SPI_CR4) & SH_SPI_WPABRT) {
+			/* Abort the transaction */
+			flags |= SPI_XFER_END;
+			sh_spi_set_bit(SH_SPI_WPABRT, SH_SPI_CR4);
+			ret = 1;
+			break;
+		}
+
+		remain -= cur_len;
+		tx_data += cur_len;
+
+		if (remain > 0)
+			write_fifo_empty_wait();
+	}
+
+	if (flags & SPI_XFER_END) {
+		tmp = sh_spi_read(SH_SPI_CR1);
+		tmp = tmp & ~(SH_SPI_SSD | SH_SPI_SSDB);
+		sh_spi_write(tmp, SH_SPI_CR1);
+		sh_spi_set_bit(SH_SPI_SSA, SH_SPI_CR1);
+		udelay(100);
+		write_fifo_empty_wait();
+	}
+
+	return ret;
+}
+
+static int sh_spi_receive(unsigned char *rx_data, unsigned int len,
+			  unsigned long flags)
+{
+	int i;
+	unsigned long tmp;
+
+	if (len > SH_SPI_MAX_BYTE)
+		sh_spi_write(SH_SPI_MAX_BYTE, SH_SPI_CR3);
+	else
+		sh_spi_write(len, SH_SPI_CR3);
+
+	tmp = sh_spi_read(SH_SPI_CR1);
+	tmp = tmp & ~(SH_SPI_SSD | SH_SPI_SSDB);
+	sh_spi_write(tmp, SH_SPI_CR1);
+	sh_spi_set_bit(SH_SPI_SSA, SH_SPI_CR1);
+
+	for (i = 0; i < len; i++) {
+		if (recvbuf_wait())
+			return 0;
+
+		rx_data[i] = (unsigned char)sh_spi_read(SH_SPI_RBR);
+	}
+	sh_spi_write(0, SH_SPI_CR3);
+
+	return 0;
+}
+
+int  spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+		void *din, unsigned long flags)
+{
+	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(SH_SPI_CR1) & ~SH_SPI_SSA, SH_SPI_CR1);
+
+	if (tx_data)
+		ret = sh_spi_send(tx_data, len, flags);
+
+	if (ret == 0 && rx_data)
+		ret = sh_spi_receive(rx_data, len, flags);
+
+	if (flags & SPI_XFER_END) {
+		sh_spi_set_bit(SH_SPI_SSD, SH_SPI_CR1);
+		udelay(100);
+
+		sh_spi_clear_bit(SH_SPI_SSA | SH_SPI_SSDB | SH_SPI_SSD,
+				 SH_SPI_CR1);
+		clear_fifo();
+	}
+
+	return ret;
+}
+
+int  spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	/* This driver supports "bus = 0" and "cs = 0" only. */
+	if (!bus && !cs)
+		return 1;
+	else
+		return 0;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+
+}
+
-- 
1.7.1

             reply	other threads:[~2011-01-18  8:53 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-18  8:53 Yoshihiro Shimoda [this message]
2011-01-18  9:45 ` [U-Boot] [PATCH v2] spi: add support SuperH SPI module Wolfgang Denk

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=4D355516.6020906@renesas.com \
    --to=yoshihiro.shimoda.uh@renesas.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 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.