121cdd2..ce02f50 100644
@@ -37,10 +37,11 @@
#include <plat/dma.h>
#include <plat/clock.h>
+#include <plat/mcspi.h>
#define OMAP2_MCSPI_MAX_FREQ 48000000
-
+#define OMAP2_MCSPI_MAX_FIFODEPTH 64
/* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */
#define OMAP2_MCSPI_MAX_CTRL 4
@@ -52,6 +53,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_CHCONF0 0x2c
@@ -88,11 +90,15 @@
#define OMAP2_MCSPI_CHCONF_IS BIT(18)
#define OMAP2_MCSPI_CHCONF_TURBO BIT(19)
#define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
+#define OMAP2_MCSPI_CHCONF_FFET BIT(27)
+#define OMAP2_MCSPI_CHCONF_FFER BIT(28)
#define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
#define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
#define OMAP2_MCSPI_CHSTAT_EOT BIT(2)
+#define OMAP2_MCSPI_IRQ_EOW BIT(17)
+
#define OMAP2_MCSPI_CHCTRL_EN BIT(0)
#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0)
@@ -128,6 +134,10 @@ struct omap2_mcspi {
unsigned long phys;
/* SPI1 has 4 channels, while SPI2 has 2 */
struct omap2_mcspi_dma *dma_channels;
+ u8 mcspi_mode;
+ u8 dma_mode;
+ u8 force_cs_mode;
+ u16 fifo_depth;
};
struct omap2_mcspi_cs {
@@ -151,6 +161,37 @@ struct omap2_mcspi_regs {
static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL];
+#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 { \
@@ -221,6 +262,39 @@ static void omap2_mcspi_set_dma_req(const struct
spi_device *spi,
mcspi_write_chconf0(spi, 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 = ®_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;
@@ -238,22 +312,135 @@ static void omap2_mcspi_force_cs(struct spi_device *spi,
int cs_active)
mcspi_write_chconf0(spi, 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)
+ return -EPERM;
+
+ /* Channel needs to be disabled and enabled
+ * for FIFO setting to take affect
+ */
+ if (s & OMAP2_MCSPI_CHCTRL_EN) {
+ omap2_mcspi_set_enable(spi, 0);
+ revert = 1;
+ }
+
+ if (buf_size < mcspi->fifo_depth)
+ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL,
+ ((buf_size << 16) |
+ (buf_size - 1) << 0));
+ else
+ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL,
+ ((buf_size << 16) |
+ (mcspi->fifo_depth - 1) << 0));
+ }
+
+ rw = OMAP2_MCSPI_CHCONF_FFET;
+ MOD_REG_BIT(l, rw, enable);
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+
+ if (revert)
+ omap2_mcspi_set_enable(spi, 1);
+
+ return 0;
+
+}
+
+static int omap2_mcspi_set_rxfifo(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_FFET)
+ return -EPERM;
+
+ /* Channel needs to be disabled and enabled
+ * for FIFO setting to take affect
+ */
+ if (s & OMAP2_MCSPI_CHCTRL_EN) {
+ omap2_mcspi_set_enable(spi, 0);
+ revert = 1;
+ }
+
+ if (buf_size < mcspi->fifo_depth)
+ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL,
+ ((buf_size << 16) |
+ (buf_size - 1) << 8));
+ else
+ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL,
+ ((buf_size << 16) |
+ (mcspi->fifo_depth - 1) << 8));
+ }
+
+ rw = OMAP2_MCSPI_CHCONF_FFER;
+ MOD_REG_BIT(l, rw, enable);
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+
+ if (revert)
+ omap2_mcspi_set_enable(spi, 1);
+
+ return 0;
+
+}
+
static void omap2_mcspi_set_master_mode(struct spi_master *master) {
u32 l;
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
/* setup when switching from (reset default) slave mode
- * to single-channel master mode
+ * to single-channel master mode based on config value
*/
l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
- MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+
+ if (mcspi->force_cs_mode)
+ MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l;
}
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) +{
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(1000);
+ while (!(__raw_readl(reg) & bit)) {
+ if (time_after(jiffies, timeout))
+ return -1;
+ cpu_relax();
+ }
+ return 0;
+}
+
static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
{
struct spi_master *spi_cntrl;
@@ -298,14 +485,17 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct