[U-Boot] [PATCH 3/4] spi: omap3: Convert to DM

Christophe Ricard christophe.ricard at gmail.com
Sun Jan 17 11:56:49 CET 2016


Convert omap3_spi driver to DM and keep compatibility with previous
mode.

Signed-off-by: Christophe Ricard <christophe-h.ricard at st.com>
---

 drivers/spi/Kconfig     |   6 +
 drivers/spi/omap3_spi.c | 439 ++++++++++++++++++++++++++++++++++++++++++------
 drivers/spi/omap3_spi.h |  14 +-
 3 files changed, 402 insertions(+), 57 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2cdb110..b8c2498 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -155,6 +155,12 @@ config ZYNQ_QSPI
 	  Zynq QSPI IP core. This IP is used to connect the flash in
 	  4-bit qspi, 8-bit dual stacked and shared 4-bit dual parallel.
 
+config OMAP3_SPI
+	bool "McSPI driver for OMAP"
+	help
+	  SPI master controller for OMAP24XX and later Multichannel SPI
+	  (McSPI) modules.
+
 endif # if DM_SPI
 
 config FSL_ESPI
diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c
index 95cdfa3..09fb1ef 100644
--- a/drivers/spi/omap3_spi.c
+++ b/drivers/spi/omap3_spi.c
@@ -11,10 +11,14 @@
  *
  * Modified by Ruslan Araslanov <ruslan.araslanov at vitecmm.com>
  *
+ * Copyright (c) 2016 Christophe Ricard <christophe.ricard at gmail.com>
+ * - Added support for DM_SPI
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
+#include <dm.h>
 #include <spi.h>
 #include <malloc.h>
 #include <asm/io.h>
@@ -22,9 +26,17 @@
 
 #define SPI_WAIT_TIMEOUT 10
 
+#ifdef CONFIG_DM_SPI
+static void spi_reset(struct udevice *dev)
+#else
 static void spi_reset(struct omap3_spi_slave *ds)
+#endif
 {
 	unsigned int tmp;
+#ifdef CONFIG_DM_SPI
+	struct omap3_spi_slave *ds = dev_get_priv(dev->parent);
+
+#endif
 
 	writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &ds->regs->sysconfig);
 	do {
@@ -39,20 +51,50 @@ static void spi_reset(struct omap3_spi_slave *ds)
 	writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable);
 }
 
+#ifdef CONFIG_DM_SPI
+static void omap3_spi_write_chconf(struct udevice *dev, int val)
+#else
 static void omap3_spi_write_chconf(struct omap3_spi_slave *ds, int val)
+#endif
 {
-	writel(val, &ds->regs->channel[ds->slave.cs].chconf);
+	unsigned int cs;
+#ifdef CONFIG_DM_SPI
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+	struct omap3_spi_slave *ds = dev_get_priv(dev->parent);
+
+
+	cs = platdata->cs;
+#else
+	cs = ds->slave.cs;
+#endif
+
+	writel(val, &ds->regs->channel[cs].chconf);
 	/* Flash post writes to make immediate effect */
-	readl(&ds->regs->channel[ds->slave.cs].chconf);
+	readl(&ds->regs->channel[cs].chconf);
 }
 
+#ifdef CONFIG_DM_SPI
+static void omap3_spi_set_enable(struct udevice *dev, int enable)
+#else
 static void omap3_spi_set_enable(struct omap3_spi_slave *ds, int enable)
+#endif
 {
-	writel(enable, &ds->regs->channel[ds->slave.cs].chctrl);
+	unsigned int cs;
+#ifdef CONFIG_DM_SPI
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+	struct omap3_spi_slave *ds = dev_get_priv(dev->parent);
+
+	cs = platdata->cs;
+#else
+	cs = ds->slave.cs;
+#endif
+
+	writel(enable, &ds->regs->channel[cs].chctrl);
 	/* Flash post writes to make immediate effect */
-	readl(&ds->regs->channel[ds->slave.cs].chctrl);
+	readl(&ds->regs->channel[cs].chctrl);
 }
 
+#ifndef CONFIG_DM_SPI
 void spi_init()
 {
 	/* do nothing */
@@ -138,10 +180,32 @@ void spi_free_slave(struct spi_slave *slave)
 	free(ds);
 }
 
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	return 1;
+}
+#endif
+
+#ifdef CONFIG_DM_SPI
+static int omap3_spi_claim_bus(struct udevice *dev)
+#else
 int spi_claim_bus(struct spi_slave *slave)
+#endif
 {
-	struct omap3_spi_slave *ds = to_omap3_spi(slave);
+	unsigned int cs;
+	struct omap3_spi_slave *ds;
 	unsigned int conf, div = 0;
+#ifdef CONFIG_DM_SPI
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+
+	ds = dev_get_priv(dev->parent);
+	cs = platdata->cs;
+	ds->freq = slave->max_hz;
+#else
+	ds = to_omap3_spi(slave);
+	cs = ds->slave.cs;
+#endif
 
 	/* McSPI global module configuration */
 
@@ -149,7 +213,11 @@ int spi_claim_bus(struct spi_slave *slave)
 	 * setup when switching from (reset default) slave mode
 	 * to single-channel master mode
 	 */
+#ifdef CONFIG_DM_SPI
+	spi_reset(dev);
+#else
 	spi_reset(ds);
+#endif
 	conf = readl(&ds->regs->modulctrl);
 	conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS);
 	conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
@@ -165,8 +233,7 @@ int spi_claim_bus(struct spi_slave *slave)
 	} else
 		div = 0xC;
 
-	conf = readl(&ds->regs->channel[ds->slave.cs].chconf);
-
+	conf = readl(&ds->regs->channel[cs].chconf);
 	/* standard 4-wire master mode:	SCK, MOSI/out, MISO/in, nCS
 	 * REVISIT: this controller could support SPI_3WIRE mode.
 	 */
@@ -184,7 +251,7 @@ int spi_claim_bus(struct spi_slave *slave)
 
 	/* wordlength */
 	conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
-	conf |= (ds->slave.wordlen - 1) << 7;
+	conf |= (slave->wordlen - 1) << 7;
 
 	/* set chipselect polarity; manage with FORCE */
 	if (!(ds->mode & SPI_CS_HIGH))
@@ -209,113 +276,222 @@ int spi_claim_bus(struct spi_slave *slave)
 	/* Transmit & receive mode */
 	conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
 
+#ifdef CONFIG_DM_SPI
+	omap3_spi_write_chconf(dev, conf);
+#else
 	omap3_spi_write_chconf(ds,conf);
+#endif
 
 	return 0;
 }
 
+#ifdef CONFIG_DM_SPI
+int omap3_spi_release_bus(struct udevice *dev)
+#else
 void spi_release_bus(struct spi_slave *slave)
+#endif
 {
+#ifndef CONFIG_DM_SPI
 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
-
+#endif
 	/* Reset the SPI hardware */
+#ifdef CONFIG_DM_SPI
+	spi_reset(dev);
+#else
 	spi_reset(ds);
+#endif
+
+#ifdef CONFIG_DM_SPI
+	return 0;
+#endif
 }
 
+#ifdef CONFIG_DM_SPI
+int omap3_spi_write(struct udevice *dev, unsigned int len, const void *txp,
+		    unsigned long flags)
+#else
 int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp,
 		    unsigned long flags)
+#endif
 {
-	struct omap3_spi_slave *ds = to_omap3_spi(slave);
-	int i;
+	struct omap3_spi_slave *ds;
+	int i, chconf;
 	ulong start;
-	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+	unsigned int cs;
+#ifdef CONFIG_DM_SPI
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+
 
+	ds = dev_get_priv(dev->parent);
+	cs = platdata->cs;
+#else
+	ds = to_omap3_spi(slave);
+	cs = ds->slave.cs;
+#endif
+
+	chconf = readl(&ds->regs->channel[cs].chconf);
+
+#ifdef CONFIG_DM_SPI
 	/* Enable the channel */
-	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
+	omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_EN);
+#else
+	/* Enable the channel */
+	omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_EN);
+#endif
 
 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
+#ifdef CONFIG_DM_SPI
+	chconf |= (slave->wordlen - 1) << 7;
+#else
 	chconf |= (ds->slave.wordlen - 1) << 7;
+#endif
 	chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
-	omap3_spi_write_chconf(ds,chconf);
+#ifdef CONFIG_DM_SPI
+	omap3_spi_write_chconf(dev, chconf);
+#else
+	omap3_spi_write_chconf(ds, chconf);
+#endif
 
 	for (i = 0; i < len; i++) {
 		/* wait till TX register is empty (TXS == 1) */
 		start = get_timer(0);
-		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+		while (!(readl(&ds->regs->channel[cs].chstat) &
 			 OMAP3_MCSPI_CHSTAT_TXS)) {
 			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
 				printf("SPI TXS timed out, status=0x%08x\n",
-				       readl(&ds->regs->channel[ds->slave.cs].chstat));
+				       readl(&ds->regs->channel[cs].chstat));
 				return -1;
 			}
 		}
+
 		/* Write the data */
-		unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
+		unsigned int *tx = &ds->regs->channel[cs].tx;
+#ifdef CONFIG_DM_SPI
+		if (slave->wordlen > 16)
+#else
 		if (ds->slave.wordlen > 16)
+#endif
 			writel(((u32 *)txp)[i], tx);
+#ifdef CONFIG_DM_SPI
+		else if (slave->wordlen > 8)
+#else
 		else if (ds->slave.wordlen > 8)
+#endif
 			writel(((u16 *)txp)[i], tx);
 		else
 			writel(((u8 *)txp)[i], tx);
 	}
 
 	/* wait to finish of transfer */
-	while ((readl(&ds->regs->channel[ds->slave.cs].chstat) &
+	while ((readl(&ds->regs->channel[cs].chstat) &
 			 (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) !=
-			 (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS));
+			 (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS))
+		;
 
+#ifdef CONFIG_DM_SPI
+	/* Disable the channel otherwise the next immediate RX will get affected */
+	omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_DIS);
+#else
 	/* Disable the channel otherwise the next immediate RX will get affected */
-	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+	omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_DIS);
+#endif
 
 	if (flags & SPI_XFER_END) {
 
 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
-		omap3_spi_write_chconf(ds,chconf);
+#ifdef CONFIG_DM_SPI
+		omap3_spi_write_chconf(dev, chconf);
+#else
+		omap3_spi_write_chconf(ds, chconf);
+#endif
 	}
+
 	return 0;
 }
 
+#ifdef CONFIG_DM_SPI
+int omap3_spi_read(struct udevice *dev, unsigned int len, void *rxp,
+		   unsigned long flags)
+#else
 int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
 		   unsigned long flags)
+#endif
 {
-	struct omap3_spi_slave *ds = to_omap3_spi(slave);
-	int i;
+	struct omap3_spi_slave *ds;
+	int i, chconf;
 	ulong start;
-	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+	unsigned int cs;
+#ifdef CONFIG_DM_SPI
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
 
+
+	ds = dev_get_priv(dev->parent);
+	cs = platdata->cs;
+#else
+	ds = to_omap3_spi(slave);
+	cs = ds->slave.cs;
+#endif
+	chconf = readl(&ds->regs->channel[cs].chconf);
+
+#ifdef CONFIG_DM_SPI
+	/* Enable the channel */
+	omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_EN);
+#else
 	/* Enable the channel */
-	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
+	omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_EN);
+#endif
 
 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
+#ifdef CONFIG_DM_SPI
+	chconf |= (slave->wordlen - 1) << 7;
+#else
 	chconf |= (ds->slave.wordlen - 1) << 7;
+#endif
 	chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
-	omap3_spi_write_chconf(ds,chconf);
+#ifdef CONFIG_DM_SPI
+	omap3_spi_write_chconf(dev, chconf);
+#else
+	omap3_spi_write_chconf(ds, chconf);
+#endif
 
-	writel(0, &ds->regs->channel[ds->slave.cs].tx);
+	writel(0, &ds->regs->channel[cs].tx);
 
 	for (i = 0; i < len; i++) {
 		start = get_timer(0);
 		/* Wait till RX register contains data (RXS == 1) */
-		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+		while (!(readl(&ds->regs->channel[cs].chstat) &
 			 OMAP3_MCSPI_CHSTAT_RXS)) {
 			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
 				printf("SPI RXS timed out, status=0x%08x\n",
-				       readl(&ds->regs->channel[ds->slave.cs].chstat));
+				       readl(&ds->regs->channel[cs].chstat));
 				return -1;
 			}
 		}
-
 		/* Disable the channel to prevent furher receiving */
 		if(i == (len - 1))
-			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+#ifdef CONFIG_DM_SPI
+			omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_DIS);
+#else
+			omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_DIS);
+#endif
 
 		/* Read the data */
-		unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
+		unsigned int *rx = &ds->regs->channel[cs].rx;
+#ifdef CONFIG_DM_SPI
+		if (slave->wordlen > 16)
+#else
 		if (ds->slave.wordlen > 16)
+#endif
 			((u32 *)rxp)[i] = readl(rx);
+#ifdef CONFIG_DM_SPI
+		else if (slave->wordlen > 8)
+#else
 		else if (ds->slave.wordlen > 8)
+#endif
 			((u16 *)rxp)[i] = (u16)readl(rx);
 		else
 			((u8 *)rxp)[i] = (u8)readl(rx);
@@ -323,89 +499,177 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
 
 	if (flags & SPI_XFER_END) {
 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
-		omap3_spi_write_chconf(ds,chconf);
+#ifdef CONFIG_DM_SPI
+		omap3_spi_write_chconf(dev, chconf);
+#else
+		omap3_spi_write_chconf(ds, chconf);
+#endif
 	}
 
 	return 0;
 }
 
+#ifdef CONFIG_DM_SPI
+/*McSPI Transmit Receive Mode*/
+int omap3_spi_txrx(struct udevice *dev, unsigned int len,
+		   const void *txp, void *rxp, unsigned long flags)
+#else
 /*McSPI Transmit Receive Mode*/
 int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
 		   const void *txp, void *rxp, unsigned long flags)
+#endif
 {
-	struct omap3_spi_slave *ds = to_omap3_spi(slave);
+	struct omap3_spi_slave *ds;
 	ulong start;
-	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+	int chconf;
 	int i=0;
+	unsigned int cs;
+#ifdef CONFIG_DM_SPI
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+
 
+	ds = dev_get_priv(dev->parent);
+	cs = platdata->cs;
+#else
+	ds = to_omap3_spi(slave);
+	cs = ds->slave.cs;
+#endif
+	chconf = readl(&ds->regs->channel[cs].chconf);
+
+#ifdef CONFIG_DM_SPI
+	/*Enable SPI channel*/
+	omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_EN);
+#else
 	/*Enable SPI channel*/
-	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
+	omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_EN);
+#endif
 
 	/*set TRANSMIT-RECEIVE Mode*/
 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
+#ifdef CONFIG_DM_SPI
+	chconf |= (slave->wordlen - 1) << 7;
+#else
 	chconf |= (ds->slave.wordlen - 1) << 7;
+#endif
 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
-	omap3_spi_write_chconf(ds,chconf);
+#ifdef CONFIG_DM_SPI
+	omap3_spi_write_chconf(dev, chconf);
+#else
+	omap3_spi_write_chconf(ds, chconf);
+#endif
 
 	/*Shift in and out 1 byte at time*/
 	for (i=0; i < len; i++){
 		/* Write: wait for TX empty (TXS == 1)*/
 		start = get_timer(0);
-		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+		while (!(readl(&ds->regs->channel[cs].chstat) &
 			 OMAP3_MCSPI_CHSTAT_TXS)) {
 			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
 				printf("SPI TXS timed out, status=0x%08x\n",
-				       readl(&ds->regs->channel[ds->slave.cs].chstat));
+				       readl(&ds->regs->channel[cs].chstat));
 				return -1;
 			}
 		}
 		/* Write the data */
-		unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
+		unsigned int *tx = &ds->regs->channel[cs].tx;
+#ifdef CONFIG_DM_SPI
+		if (slave->wordlen > 16)
+#else
 		if (ds->slave.wordlen > 16)
+#endif
 			writel(((u32 *)txp)[i], tx);
+#ifdef CONFIG_DM_SPI
+		else if (slave->wordlen > 8)
+#else
 		else if (ds->slave.wordlen > 8)
+#endif
 			writel(((u16 *)txp)[i], tx);
 		else
 			writel(((u8 *)txp)[i], tx);
 
 		/*Read: wait for RX containing data (RXS == 1)*/
 		start = get_timer(0);
-		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+		while (!(readl(&ds->regs->channel[cs].chstat) &
 			 OMAP3_MCSPI_CHSTAT_RXS)) {
 			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
 				printf("SPI RXS timed out, status=0x%08x\n",
-				       readl(&ds->regs->channel[ds->slave.cs].chstat));
+				       readl(&ds->regs->channel[cs].chstat));
 				return -1;
 			}
 		}
 		/* Read the data */
-		unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
+		unsigned int *rx = &ds->regs->channel[cs].rx;
+#ifdef CONFIG_DM_SPI
+		if (slave->wordlen > 16)
+#else
 		if (ds->slave.wordlen > 16)
+#endif
 			((u32 *)rxp)[i] = readl(rx);
+#ifdef CONFIG_DM_SPI
+		else if (slave->wordlen > 8)
+#else
 		else if (ds->slave.wordlen > 8)
+#endif
 			((u16 *)rxp)[i] = (u16)readl(rx);
 		else
 			((u8 *)rxp)[i] = (u8)readl(rx);
 	}
+
+#ifdef CONFIG_DM_SPI
+	/* Disable the channel */
+	omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_DIS);
+#else
 	/* Disable the channel */
-	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+	omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_DIS);
+#endif
 
 	/*if transfer must be terminated disable the channel*/
 	if (flags & SPI_XFER_END) {
 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
-		omap3_spi_write_chconf(ds,chconf);
+#ifdef CONFIG_DM_SPI
+		omap3_spi_write_chconf(dev, chconf);
+#else
+		omap3_spi_write_chconf(ds, chconf);
+#endif
 	}
 
 	return 0;
 }
 
+#ifdef CONFIG_DM_SPI
+int omap3_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		   const void *dout, void *din, unsigned long flags)
+#else
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 	     const void *dout, void *din, unsigned long flags)
+#endif
 {
-	struct omap3_spi_slave *ds = to_omap3_spi(slave);
-	unsigned int	len;
+	struct omap3_spi_slave *ds;
+	unsigned int len, cs;
 	int ret = -1;
+#ifdef CONFIG_DM_SPI
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+
+	ds = dev_get_priv(dev->parent);
+	cs = platdata->cs;
+#else
+	ds = to_omap3_spi(slave);
+	cs = ds->slave.cs;
+#endif
 
+#ifdef CONFIG_DM_SPI
+	if (slave->wordlen < 4 || slave->wordlen > 32) {
+		printf("omap3_spi: invalid wordlen %d\n", slave->wordlen);
+		return -1;
+	}
+
+	if (bitlen % slave->wordlen)
+		return -1;
+
+	len = bitlen / slave->wordlen;
+#else
 	if (ds->slave.wordlen < 4 || ds->slave.wordlen > 32) {
 		printf("omap3_spi: invalid wordlen %d\n", ds->slave.wordlen);
 		return -1;
@@ -415,41 +679,104 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 		return -1;
 
 	len = bitlen / ds->slave.wordlen;
+#endif
 
 	if (bitlen == 0) {	 /* only change CS */
-		int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+		int chconf = readl(&ds->regs->channel[cs].chconf);
 
 		if (flags & SPI_XFER_BEGIN) {
-			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
+#ifdef CONFIG_DM_SPI
+			omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_EN);
+#else
+			omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_EN);
+#endif
 			chconf |= OMAP3_MCSPI_CHCONF_FORCE;
-			omap3_spi_write_chconf(ds,chconf);
+#ifdef CONFIG_DM_SPI
+			omap3_spi_write_chconf(dev, chconf);
+#else
+			omap3_spi_write_chconf(ds, chconf);
+#endif
 		}
 		if (flags & SPI_XFER_END) {
 			chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
-			omap3_spi_write_chconf(ds,chconf);
-			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+#ifdef CONFIG_DM_SPI
+			omap3_spi_write_chconf(dev, chconf);
+			omap3_spi_set_enable(dev, OMAP3_MCSPI_CHCTRL_DIS);
+#else
+			omap3_spi_write_chconf(ds, chconf);
+			omap3_spi_set_enable(ds, OMAP3_MCSPI_CHCTRL_DIS);
+#endif
 		}
 		ret = 0;
 	} else {
+#ifdef CONFIG_DM_SPI
+		if (dout != NULL && din != NULL)
+			ret = omap3_spi_txrx(dev, len, dout, din, flags);
+		else if (dout != NULL)
+			ret = omap3_spi_write(dev, len, dout, flags);
+		else if (din != NULL)
+			ret = omap3_spi_read(dev, len, din, flags);
+#else
 		if (dout != NULL && din != NULL)
 			ret = omap3_spi_txrx(slave, len, dout, din, flags);
 		else if (dout != NULL)
 			ret = omap3_spi_write(slave, len, dout, flags);
 		else if (din != NULL)
 			ret = omap3_spi_read(slave, len, din, flags);
+#endif
 	}
 	return ret;
 }
 
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+void spi_cs_activate(struct spi_slave *slave)
 {
-	return 1;
 }
 
-void spi_cs_activate(struct spi_slave *slave)
+void spi_cs_deactivate(struct spi_slave *slave)
 {
 }
 
-void spi_cs_deactivate(struct spi_slave *slave)
+#ifdef CONFIG_DM_SPI
+static int omap3_spi_probe(struct udevice *dev)
 {
+	struct omap3_spi_slave *ds = dev_get_priv(dev);
+
+	ds->regs = (struct mcspi *)dev_get_addr(dev);
+
+	return 0;
 }
+
+static int omap3_spi_set_speed(struct udevice *dev, unsigned int speed)
+{
+	return 0;
+}
+
+static int omap3_spi_set_mode(struct udevice *bus, uint mode)
+{
+	return 0;
+}
+
+
+static const struct dm_spi_ops omap3_spi_ops = {
+	.claim_bus	= omap3_spi_claim_bus,
+	.release_bus	= omap3_spi_release_bus,
+	.xfer		= omap3_spi_xfer,
+	.set_speed	= omap3_spi_set_speed,
+	.set_mode	= omap3_spi_set_mode,
+};
+
+static const struct udevice_id omap3_spi_ids[] = {
+	{ .compatible = "ti,omap2-mcspi" },
+	{ .compatible = "ti,omap4-mcspi" },
+	{ }
+};
+
+U_BOOT_DRIVER(omap3_spi) = {
+	.name   = "omap3_spi",
+	.id     = UCLASS_SPI,
+	.of_match = omap3_spi_ids,
+	.probe = omap3_spi_probe,
+	.ops    = &omap3_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct omap3_spi_slave),
+};
+#endif
diff --git a/drivers/spi/omap3_spi.h b/drivers/spi/omap3_spi.h
index 6a07c6d..a974ca3 100644
--- a/drivers/spi/omap3_spi.h
+++ b/drivers/spi/omap3_spi.h
@@ -88,22 +88,34 @@ struct mcspi {
 #define OMAP3_MCSPI_WAKEUPENABLE_WKEN	BIT(0)
 
 struct omap3_spi_slave {
+#ifndef CONFIG_DM_SPI
 	struct spi_slave slave;
+#endif
 	struct mcspi *regs;
 	unsigned int freq;
 	unsigned int mode;
 };
 
+#ifndef CONFIG_DM_SPI
 static inline struct omap3_spi_slave *to_omap3_spi(struct spi_slave *slave)
 {
 	return container_of(slave, struct omap3_spi_slave, slave);
 }
+#endif
 
+#ifdef CONFIG_DM_SPI
+int omap3_spi_txrx(struct udevice *dev, unsigned int len, const void *txp,
+			void *rxp, unsigned long flags);
+int omap3_spi_write(struct udevice *dev, unsigned int len, const void *txp,
+		    unsigned long flags);
+int omap3_spi_read(struct udevice *dev, unsigned int len, void *rxp,
+		   unsigned long flags);
+#else
 int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, const void *txp,
 			void *rxp, unsigned long flags);
 int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp,
 		    unsigned long flags);
 int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
 		   unsigned long flags);
-
+#endif
 #endif /* _OMAP3_SPI_H_ */
-- 
2.5.0



More information about the U-Boot mailing list