This patch adds support for McSPI slave and FIFO. DMA and FIFO
could be enabled together for better throughput.
This has a dependency on patch
[RESEND][PATCH 1/2] McSPI Slave and DMA,FIFO support
Signed-off-by: Hemanth V heman...@ti.com
drivers/spi/omap2_mcspi.c | 353 --
1 files changed, 314 insertions(+), 39 deletions(-)
Index: linux-omap-2.6/drivers/spi/omap2_mcspi.c
===
--- linux-omap-2.6.orig/drivers/spi/omap2_mcspi.c 2009-06-23
16:46:19.0
+0530
+++ linux-omap-2.6/drivers/spi/omap2_mcspi.c2009-06-23 18:38:40.0
+0530
@@ -37,9 +37,11 @@
#include mach/dma.h
#include mach/clock.h
+#include mach/mcspi.h
#define OMAP2_MCSPI_MAX_FREQ 4800
+#define OMAP2_MCSPI_MAX_FIFODEPTH 64
#define OMAP2_MCSPI_REVISION 0x00
#define OMAP2_MCSPI_SYSCONFIG 0x10
@@ -49,6 +51,7 @@
#define OMAP2_MCSPI_WAKEUPENABLE 0x20
#define OMAP2_MCSPI_SYST 0x24
#define OMAP2_MCSPI_MODULCTRL 0x28
+#define OMAP2_MCSPI_XFERLEVEL 0x7c
/* per-channel banks, 0x14 bytes each, first is: */
#define OMAP2_MCSPI_CHCONF00x2c
@@ -83,10 +86,13 @@
#define OMAP2_MCSPI_CHCONF_IS (1 18)
#define OMAP2_MCSPI_CHCONF_TURBO (1 19)
#define OMAP2_MCSPI_CHCONF_FORCE (1 20)
+#define OMAP2_MCSPI_CHCONF_FFET(1 27)
+#define OMAP2_MCSPI_CHCONF_FFER(1 28)
#define OMAP2_MCSPI_CHSTAT_RXS (1 0)
#define OMAP2_MCSPI_CHSTAT_TXS (1 1)
#define OMAP2_MCSPI_CHSTAT_EOT (1 2)
+#define OMAP2_MCSPI_IRQ_EOW(1 17)
#define OMAP2_MCSPI_CHCTRL_EN (1 0)
@@ -122,6 +128,10 @@
unsigned long phys;
/* SPI1 has 4 channels, while SPI2 has 2 */
struct omap2_mcspi_dma *dma_channels;
+ unsigned short mcspi_mode;
+ unsigned short dma_mode;
+ unsigned short force_cs_mode;
+ unsigned short fifo_depth;
};
struct omap2_mcspi_cs {
@@ -130,6 +140,37 @@
int word_len;
};
+#ifdef CONFIG_SPI_DEBUG
+struct reg_type {
+ char name[40];
+ int offset;
+};
+
+static struct reg_type reg_map[] = {
+ {MCSPI_REV, 0x0},
+ {MCSPI_SYSCONFIG, 0x10},
+ {MCSPI_SYSSTATUS, 0x14},
+ {MCSPI_IRQSTATUS, 0x18},
+ {MCSPI_IRQENABLE, 0x1C},
+ {MCSPI_WAKEUPENABLE, 0x20},
+ {MCSPI_SYST, 0x24},
+ {MCSPI_MODULCTRL, 0x28},
+ {MCSPI_XFERLEVEL, 0x7c},
+ {CH0, 0x2C},
+ {CH1, 0x40},
+ {CH2, 0x54},
+ {CH3, 0x68}
+};
+
+static struct reg_type ch_reg_type[] = {
+ {CONF, 0x00},
+ {STAT, 0x04},
+ {CTRL, 0x08},
+ {TX, 0x0C},
+ {RX, 0x10},
+};
+#endif
+
static struct workqueue_struct *omap2_mcspi_wq;
#define MOD_REG_BIT(val, mask, set) do { \
@@ -185,6 +226,39 @@
mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
}
+#ifdef CONFIG_SPI_DEBUG
+static int
+omap2_mcspi_dump_regs(struct spi_master *master)
+{
+ u32 spi_base;
+ u32 reg;
+ u32 channel;
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+ spi_base = (u32)mcspi-base;
+
+ for (reg = 0; (reg ARRAY_SIZE(reg_map)); reg++) {
+ struct reg_type *reg_d = reg_map[reg];
+ u32 base1 = spi_base + reg_d-offset;
+ if (reg_d-name[0] == 'C') {
+ for (channel = 0; (channel (ARRAY_SIZE(ch_reg_type)));
+ channel++) {
+ struct reg_type *reg_c = ch_reg_type[channel];
+ u32 base2 = base1 + reg_c-offset;
+ pr_debug(MCSPI_%s%s [0x%08X] = 0x%08X\n,
+ reg_d-name, reg_c-name, base2,
+ __raw_readl(base2));
+ }
+ } else {
+ pr_debug(%s : [0x%08X] = 0x%08X\n,
+ reg_d-name, base1, __raw_readl(base1));
+ }
+
+ }
+ return 0;
+}
+#endif
+
static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
{
u32 l;
@@ -202,34 +276,160 @@
mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
}
+static int omap2_mcspi_set_txfifo(const struct spi_device *spi, int buf_size,
+ int enable)
+{
+ u32 l, rw, s;
+ unsigned short revert = 0;
+ struct spi_master *master = spi-master;
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+ l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+ s = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
+
+ if (enable == 1) {
+
+ /* FIFO cannot be enabled for both TX and RX
+* simultaneously
+*/
+ if (l OMAP2_MCSPI_CHCONF_FFER