All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] TI DaVinci: Driver for the davinci SPI controller
@ 2009-12-23  7:44 Sudhakar Rajashekhara
  2009-12-24  1:34 ` Mike Frysinger
                   ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Sudhakar Rajashekhara @ 2009-12-23  7:44 UTC (permalink / raw)
  To: u-boot

From: Sekhar Nori <nsekhar@ti.com>

This adds a driver for the SPI controller found on davinci
based SoCs from Texas Instruments.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
---
 drivers/spi/Makefile      |    1 +
 drivers/spi/davinci_spi.c |  205 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/spi/davinci_spi.h |   84 ++++++++++++++++++
 3 files changed, 290 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/davinci_spi.c
 create mode 100644 drivers/spi/davinci_spi.h

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 824d8e7..07b9611 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
+COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
new file mode 100644
index 0000000..1c988bb
--- /dev/null
+++ b/drivers/spi/davinci_spi.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Driver for SPI controller on DaVinci. Based on atmel_spi.c
+ * by Atmel Corporation
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/hardware.h>
+
+#include "davinci_spi.h"
+
+static unsigned int data1_reg_val;
+
+void spi_init()
+{
+	/* do nothing */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+			unsigned int max_hz, unsigned int mode)
+{
+	struct davinci_spi_slave	*ds;
+
+	ds = malloc(sizeof(struct davinci_spi_slave));
+	if (!ds)
+		return NULL;
+
+	ds->slave.bus = bus;
+	ds->slave.cs = cs;
+	ds->regs = (void *)CONFIG_SYS_SPI_BASE;
+	ds->freq = max_hz;
+
+	return &ds->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct davinci_spi_slave *ds = to_davinci_spi(slave);
+
+	free(ds);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct davinci_spi_slave *ds = to_davinci_spi(slave);
+	unsigned int scalar;
+
+	/* Enable the SPI hardware */
+	spi_writel(ds, GCR0, SPIGCR0_SPIRST_MASK);
+	udelay(1000);
+	spi_writel(ds, GCR0, SPIGCR0_SPIENA_MASK);
+
+	/* Set master mode, powered up and not activated */
+	spi_writel(ds, GCR1, SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK);
+
+	/* CS, CLK, SIMO and SOMI are functional pins */
+	spi_writel(ds, PC0, (SPIPC0_EN0FUN_MASK) | (SPIPC0_CLKFUN_MASK) |
+				(SPIPC0_DOFUN_MASK) | (SPIPC0_DIFUN_MASK));
+
+	/* setup format */
+	scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+
+	spi_writel(ds, FMT0, 8 |	/* character length */
+			(scalar << SPIFMT_PRESCALE_SHIFT)	|
+			/* clock signal delayed by half clk cycle */
+			(1 << SPIFMT_PHASE_SHIFT)		|
+			/* clock low in idle state - Mode 0 */
+			(0 << SPIFMT_POLARITY_SHIFT) 		|
+			/* MSB shifted out first */
+			(0 << SPIFMT_SHIFTDIR_SHIFT));
+
+	/* hold cs active@end of transfer until explicitly de-asserted */
+	data1_reg_val = (1 << SPIDAT1_CSHOLD_SHIFT) |
+			(slave->cs << SPIDAT1_CSNR_SHIFT);
+	spi_writel(ds, DAT1, data1_reg_val);
+
+	/*
+	 * Including a minor delay. No science here. Should be good even with
+	 * no delay
+	 */
+	spi_writel(ds, DELAY, (50 << SPI_C2TDELAY_SHIFT) |
+				(50 << SPI_T2CDELAY_SHIFT));
+
+	/* default chip select register */
+	spi_writel(ds, DEF, SPIDEF_CSDEF0_MASK);
+
+	/* no interrupts */
+	spi_writel(ds, INT0, 0);
+	spi_writel(ds, LVL, 0);
+
+	/* enable SPI */
+	spi_writel(ds, GCR1, spi_readl(ds, GCR1) | (SPIGCR1_SPIENA_MASK));
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	struct davinci_spi_slave *ds = to_davinci_spi(slave);
+
+	/* Disable the SPI hardware */
+	spi_writel(ds, GCR0, SPIGCR0_SPIRST_MASK);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct davinci_spi_slave *ds = to_davinci_spi(slave);
+	unsigned int	len;
+	int		ret, i;
+	const u8	*txp = dout;
+	u8		*rxp = din;
+
+	ret = 0;
+
+	if (bitlen == 0)
+		/* Finish any previously submitted transfers */
+		goto out;
+
+	/*
+	 * It's not clear how non-8-bit-aligned transfers are supposed to be
+	 * represented as a stream of bytes...this is a limitation of
+	 * the current SPI interface - here we terminate on receiving such a
+	 * transfer request.
+	 */
+	if (bitlen % 8) {
+		/* Errors always terminate an ongoing transfer */
+		flags |= SPI_XFER_END;
+		goto out;
+	}
+
+	len = bitlen / 8;
+
+	/* do an empty read to clear the current contents */
+	spi_readl(ds, BUF);
+
+	/* keep writing and reading 1 byte until done */
+	for (i = 0; i < len; i++) {
+		/* wait till TXFULL is asserted */
+		while (spi_readl(ds, BUF) & (SPIBUF_TXFULL_MASK));
+
+		/* write the data */
+		data1_reg_val &= ~0xFFFF;
+		if (txp) {
+			data1_reg_val |= *txp & 0xFF;
+			txp++;
+		}
+
+		/*
+		 * Write to DAT1 is required to keep the serial transfer going.
+		 * We just terminate when we reach the end.
+		 */
+		if ((i == (len - 1)) && (flags & SPI_XFER_END)) {
+			/* clear CS hold */
+			spi_writel(ds, DAT1, data1_reg_val &
+					~(1 << SPIDAT1_CSHOLD_SHIFT));
+		} else {
+			spi_writel(ds, DAT1, data1_reg_val);
+		}
+
+		/* read the data - wait for data availability */
+		while (spi_readl(ds, BUF) & (SPIBUF_RXEMPTY_MASK));
+
+		if (rxp) {
+			*rxp = spi_readl(ds, BUF) & 0xFF;
+			rxp++;
+		} else {
+			spi_readl(ds, BUF); /* simply drop the read character */
+		}
+	}
+	return 0;
+
+out:
+	if (flags & SPI_XFER_END) {
+		spi_writel(ds, DAT1, data1_reg_val &
+				~(1 << SPIDAT1_CSHOLD_SHIFT));
+	}
+	return 0;
+}
+
diff --git a/drivers/spi/davinci_spi.h b/drivers/spi/davinci_spi.h
new file mode 100644
index 0000000..b3bf916
--- /dev/null
+++ b/drivers/spi/davinci_spi.h
@@ -0,0 +1,84 @@
+/*
+ * Register definitions for the DaVinci SPI Controller
+ */
+
+/* Register offsets */
+#define DAVINCI_SPI_GCR0	0x0000
+#define DAVINCI_SPI_GCR1	0x0004
+#define DAVINCI_SPI_INT0	0x0008
+#define DAVINCI_SPI_LVL		0x000c
+#define DAVINCI_SPI_FLG		0x0010
+#define DAVINCI_SPI_PC0		0x0014
+#define DAVINCI_SPI_PC1		0x0018
+#define DAVINCI_SPI_PC2		0x001c
+#define DAVINCI_SPI_PC3		0x0020
+#define DAVINCI_SPI_PC4		0x0024
+#define DAVINCI_SPI_PC5		0x0028
+#define DAVINCI_SPI_DAT0	0x0038
+#define DAVINCI_SPI_DAT1	0x003c
+#define DAVINCI_SPI_BUF		0x0040
+#define DAVINCI_SPI_EMU		0x0044
+#define DAVINCI_SPI_DELAY	0x0048
+#define DAVINCI_SPI_DEF		0x004c
+#define DAVINCI_SPI_FMT0	0x0050
+#define DAVINCI_SPI_FMT1	0x0054
+#define DAVINCI_SPI_FMT2	0x0058
+#define DAVINCI_SPI_FMT3	0x005c
+#define DAVINCI_SPI_INTVEC0	0x0060
+#define DAVINCI_SPI_INTVEC1	0x0064
+
+#define BIT(x)			(1 << (x))
+
+/* SPIGCR0 */
+#define SPIGCR0_SPIENA_MASK	0x1
+#define SPIGCR0_SPIRST_MASK	0x0
+
+/* SPIGCR0 */
+#define SPIGCR1_CLKMOD_MASK	BIT(1)
+#define SPIGCR1_MASTER_MASK	BIT(0)
+#define SPIGCR1_SPIENA_MASK	BIT(24)
+
+/* SPIPC0 */
+#define SPIPC0_DIFUN_MASK	BIT(11)		/* SIMO */
+#define SPIPC0_DOFUN_MASK	BIT(10)		/* SOMI */
+#define SPIPC0_CLKFUN_MASK	BIT(9)		/* CLK */
+#define SPIPC0_EN0FUN_MASK	BIT(0)
+
+/* SPIFMT0 */
+#define SPIFMT_SHIFTDIR_SHIFT	20
+#define SPIFMT_POLARITY_SHIFT	17
+#define SPIFMT_PHASE_SHIFT	16
+#define SPIFMT_PRESCALE_SHIFT	8
+
+/* SPIDAT1 */
+#define SPIDAT1_CSHOLD_SHIFT	28
+#define SPIDAT1_CSNR_SHIFT	16
+
+/* SPIDELAY */
+#define SPI_C2TDELAY_SHIFT	24
+#define SPI_T2CDELAY_SHIFT	16
+
+/* SPIBUF */
+#define SPIBUF_RXEMPTY_MASK	BIT(31)
+#define SPIBUF_TXFULL_MASK	BIT(29)
+
+/* SPIDEF */
+#define SPIDEF_CSDEF0_MASK	BIT(0)
+
+struct davinci_spi_slave {
+	struct spi_slave slave;
+	void		*regs;
+	u32		mr;
+	unsigned int freq;
+};
+
+static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
+{
+	return container_of(slave, struct davinci_spi_slave, slave);
+}
+
+#define spi_readl(ds, reg)					\
+	readl(ds->regs + DAVINCI_SPI_##reg)
+#define spi_writel(ds, reg, value)				\
+	writel(value, ds->regs + DAVINCI_SPI_##reg)
+
-- 
1.5.6

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

end of thread, other threads:[~2010-03-07 12:38 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-23  7:44 [U-Boot] [PATCH] TI DaVinci: Driver for the davinci SPI controller Sudhakar Rajashekhara
2009-12-24  1:34 ` Mike Frysinger
2009-12-24  2:52   ` Sudhakar Rajashekhara
2009-12-25 17:11 ` Dirk Behme
2010-01-04  9:42   ` Sudhakar Rajashekhara
2010-01-04  9:46   ` Sudhakar Rajashekhara
2010-01-05  6:01     ` Mike Frysinger
2010-01-05  7:14       ` [U-Boot] NS16550 Register structure Pedanekar, Hemant
2010-01-05  7:35         ` Wolfgang Denk
2010-01-05  8:55           ` Pedanekar, Hemant
2010-01-05  9:58             ` Wolfgang Denk
2010-01-18 14:51               ` Pedanekar, Hemant
2010-01-19 13:04                 ` Detlev Zundel
2010-01-21 11:58                   ` Pedanekar, Hemant
2010-01-28  9:54                   ` Pedanekar, Hemant
2010-01-28 11:00                     ` Wolfgang Denk
2010-01-04  9:47 ` [U-Boot] [PATCH] TI DaVinci: Driver for the davinci SPI controller Nick Thompson
2010-01-04 10:42   ` Sudhakar Rajashekhara
2010-01-04 19:50     ` Dirk Behme
2010-01-05  0:20       ` Mike Frysinger
2010-03-05  6:47       ` Mansoor
2010-03-07 12:38         ` [U-Boot] OMAP3 SPI driver ( was Re: [PATCH] TI DaVinci: Driver for the davinci SPI controller) Dirk Behme

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.