[v4,8/9] spi: davinci: add support for multiple bus and chip select

Message ID 1395935952-11542-9-git-send-email-m-karicheri2@ti.com
State New
Headers show

Commit Message

Murali Karicheri March 27, 2014, 3:59 p.m.
Currently davinci spi driver supports only bus 0 cs 0.
This patch allows driver to support bus 1 and bus 2 with
configurable number of chip selects. Also defaults are
selected in a way to avoid regression on other platforms
that uses davinci spi driver and has only one spi bus.

Signed-off-by: Rex Chang <rchang@ti.com>
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Acked-by: Tom Rini <trini@ti.com>
---
 drivers/spi/davinci_spi.c |   60 ++++++++++++++++++++++++++++++++++++++++++---
 drivers/spi/davinci_spi.h |   33 +++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 3 deletions(-)

Patch

diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index e3fb321..b682bc4 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -32,7 +32,27 @@  struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	if (!ds)
 		return NULL;
 
-	ds->regs = (struct davinci_spi_regs *)CONFIG_SYS_SPI_BASE;
+	ds->slave.bus = bus;
+	ds->slave.cs = cs;
+
+	switch (bus) {
+	case SPI0_BUS:
+		ds->regs = (struct davinci_spi_regs *)SPI0_BASE;
+		break;
+#ifdef CONFIG_SYS_SPI1
+	case SPI1_BUS:
+		ds->regs = (struct davinci_spi_regs *)SPI0_BASE;
+		break;
+#endif
+#ifdef CONFIG_SYS_SPI2
+	case SPI2_BUS:
+		ds->regs = (struct davinci_spi_regs *)SPI2_BASE;
+		break;
+#endif
+	default: /* Invalid bus number */
+		return NULL;
+	}
+
 	ds->freq = max_hz;
 
 	return &ds->slave;
@@ -59,7 +79,7 @@  int spi_claim_bus(struct spi_slave *slave)
 	writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
 
 	/* CS, CLK, SIMO and SOMI are functional pins */
-	writel((SPIPC0_EN0FUN_MASK | SPIPC0_CLKFUN_MASK |
+	writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
 		SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
 
 	/* setup format */
@@ -262,9 +282,43 @@  out:
 	return 0;
 }
 
+#ifdef CONFIG_SYS_SPI1
+static int bus1_cs_valid(unsigned int bus, unsigned int cs)
+{
+	if ((bus == SPI1_BUS) && (cs < SPI1_NUM_CS))
+		return 1;
+	return 0;
+}
+#else
+static int bus1_cs_valid(unsigned int bus, unsigned int cs)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SYS_SPI2
+static int bus2_cs_valid(unsigned int bus, unsigned int cs)
+{
+	if ((bus == SPI2_BUS) && (cs < SPI2_NUM_CS))
+		return 1;
+	return 0;
+}
+#else
+static int bus2_cs_valid(unsigned int bus, unsigned int cs)
+{
+	return 0;
+}
+#endif
+
 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 {
-	return bus == 0 && cs == 0;
+	if ((bus == SPI0_BUS) && (cs < SPI0_NUM_CS))
+		return 1;
+	else if (bus1_cs_valid(bus, cs))
+		return 1;
+	else if (bus2_cs_valid(bus, cs))
+		return 1;
+	return 0;
 }
 
 void spi_cs_activate(struct spi_slave *slave)
diff --git a/drivers/spi/davinci_spi.h b/drivers/spi/davinci_spi.h
index 33f69b5..d4612d3 100644
--- a/drivers/spi/davinci_spi.h
+++ b/drivers/spi/davinci_spi.h
@@ -74,6 +74,39 @@  struct davinci_spi_regs {
 /* SPIDEF */
 #define SPIDEF_CSDEF0_MASK	BIT(0)
 
+#define SPI0_BUS		0
+#define SPI0_BASE		CONFIG_SYS_SPI_BASE
+/*
+ * Define default SPI0_NUM_CS as 1 for existing platforms that uses this
+ * driver. Platform can configure number of CS using CONFIG_SYS_SPI0_NUM_CS
+ * if more than one CS is supported and by defining CONFIG_SYS_SPI0.
+ */
+#ifndef CONFIG_SYS_SPI0
+#define SPI0_NUM_CS		1
+#else
+#define SPI0_NUM_CS		CONFIG_SYS_SPI0_NUM_CS
+#endif
+
+/*
+ * define CONFIG_SYS_SPI1 when platform has spi-1 device (bus #1) and
+ * CONFIG_SYS_SPI1_NUM_CS defines number of CS on this bus
+ */
+#ifdef CONFIG_SYS_SPI1
+#define SPI1_BUS		1
+#define SPI1_NUM_CS		CONFIG_SYS_SPI1_NUM_CS
+#define SPI1_BASE		CONFIG_SYS_SPI1_BASE
+#endif
+
+/*
+ * define CONFIG_SYS_SPI2 when platform has spi-2 device (bus #2) and
+ * CONFIG_SYS_SPI2_NUM_CS defines number of CS on this bus
+ */
+#ifdef CONFIG_SYS_SPI2
+#define SPI2_BUS		2
+#define SPI2_NUM_CS		CONFIG_SYS_SPI2_NUM_CS
+#define SPI2_BASE		CONFIG_SYS_SPI2_BASE
+#endif
+
 struct davinci_spi_slave {
 	struct spi_slave slave;
 	struct davinci_spi_regs *regs;