From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] spi: add support SuperH SPI module
Date: Mon, 17 Jan 2011 13:07:37 +0900 [thread overview]
Message-ID: <4D33C089.8040007@renesas.com> (raw)
SH7757 has SPI module. This patch supports it.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
drivers/spi/Makefile | 1 +
drivers/spi/sh_spi.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 296 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..89ea5e2
--- /dev/null
+++ b/drivers/spi/sh_spi.c
@@ -0,0 +1,295 @@
+/*
+ * 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 SPI_TBR 0x00
+#define SPI_RBR 0x00
+#define SPI_CR1 0x08
+#define SPI_CR2 0x10
+#define SPI_CR3 0x18
+#define SPI_CR4 0x20
+
+/* CR1 */
+#define SPI_TBE 0x80
+#define SPI_TBF 0x40
+#define SPI_RBE 0x20
+#define SPI_RBF 0x10
+#define SPI_PFONRD 0x08
+#define SPI_SSDB 0x04
+#define SPI_SSD 0x02
+#define SPI_SSA 0x01
+
+/* CR2 */
+#define SPI_RSTF 0x80
+#define SPI_LOOPBK 0x40
+#define SH_SPI_CPOL 0x20
+#define SH_SPI_CPHA 0x10
+#define SPI_L1M0 0x08
+
+/* CR3 */
+#define SPI_MAX_BYTE 0xFF
+
+/* CR4 */
+#define SPI_TBEI 0x80
+#define SPI_TBFI 0x40
+#define SPI_RBEI 0x20
+#define SPI_RBFI 0x10
+#define SPI_WPABRT 0x04
+#define SPI_SSS 0x01
+
+#define 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(SPI_RSTF, SPI_CR2);
+ sh_spi_clear_bit(SPI_RSTF, SPI_CR2);
+}
+
+static int recvbuf_wait(void)
+{
+ while (sh_spi_read(SPI_CR1) & SPI_RBE) {
+ if (ctrlc())
+ return 1;
+ udelay(10);
+ }
+ return 0;
+}
+
+static int write_fifo_full_wait(void)
+{
+ while (sh_spi_read(SPI_CR1) & SPI_TBF) {
+ udelay(10);
+ if (ctrlc())
+ return 1;
+ }
+ return 0;
+}
+
+static int write_fifo_empty_wait(void)
+{
+ while (!(sh_spi_read(SPI_CR1) & 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, SPI_CR1);
+ /* CR1 init */
+ sh_spi_write(0x00, SPI_CR1);
+ /* CR3 init */
+ sh_spi_write(0x00, SPI_CR3);
+
+ clear_fifo();
+
+ /* 1/8 clock */
+ sh_spi_write(sh_spi_read(SPI_CR2) | 0x07, 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(SPI_CR1) & ~(SPI_SSA | SPI_SSDB | SPI_SSD),
+ 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 >= SPI_FIFO_SIZE)
+ sh_spi_set_bit(SPI_SSA, SPI_CR1);
+
+ while (remain > 0) {
+ cur_len = (remain < SPI_FIFO_SIZE) ? remain : SPI_FIFO_SIZE;
+ for (i = 0; i < cur_len &&
+ !(sh_spi_read(SPI_CR4) & SPI_WPABRT) &&
+ !(sh_spi_read(SPI_CR1) & SPI_TBF);
+ i++)
+ sh_spi_write(tx_data[i], SPI_TBR);
+
+ cur_len = i;
+
+ if (sh_spi_read(SPI_CR4) & SPI_WPABRT) {
+ /* Abort the transaction */
+ flags |= SPI_XFER_END;
+ sh_spi_set_bit(SPI_WPABRT, 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(SPI_CR1);
+ tmp = tmp & ~(SPI_SSD | SPI_SSDB);
+ sh_spi_write(tmp, SPI_CR1);
+ sh_spi_set_bit(SPI_SSA, 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 > SPI_MAX_BYTE)
+ sh_spi_write(SPI_MAX_BYTE, SPI_CR3);
+ else
+ sh_spi_write(len, SPI_CR3);
+
+ tmp = sh_spi_read(SPI_CR1);
+ tmp = tmp & ~(SPI_SSD | SPI_SSDB);
+ sh_spi_write(tmp, SPI_CR1);
+ sh_spi_set_bit(SPI_SSA, SPI_CR1);
+
+ for (i = 0; i < len; i++) {
+ if (recvbuf_wait())
+ return 0;
+
+ rx_data[i] = (unsigned char)sh_spi_read(SPI_RBR);
+ }
+ sh_spi_write(0, 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(SPI_CR1) & ~SPI_SSA, 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(SPI_SSD, SPI_CR1);
+ udelay(100);
+
+ sh_spi_clear_bit(SPI_SSA | SPI_SSDB | SPI_SSD, SPI_CR1);
+ clear_fifo();
+ }
+
+ return ret;
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return 1;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+
+}
+
--
1.7.1
next reply other threads:[~2011-01-17 4:07 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-17 4:07 Yoshihiro Shimoda [this message]
2011-01-17 10:28 ` [U-Boot] [PATCH] spi: add support SuperH SPI module Nobuhiro Iwamatsu
2011-01-18 7:40 ` Yoshihiro Shimoda
2011-01-18 9:28 ` Wolfgang Denk
2011-01-19 8:16 ` Yoshihiro Shimoda
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=4D33C089.8040007@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.