Added posted writes (read after writes) to effect the
change immediately for channel confiuration and channel
enable register
Disable the channel to purge receieve data in TX_ONLY
mode transfer otherwise rx data will get affected by
the next immediate RX_ONLY mode transfer
Wait for the EOT bit to be set after last byte has been
loaded to TX shift register in the the TX_ONLY mode.This
ensures TX data has been completely shifted out
Disable the channel in RX_ONLY mode before reading the
last data from RXX register to prevent the SPI slave
to transmit next word
Signed-off-by: Ajoy Kumar Das <akdas75@yahoo.in>
Cc: Tom Rini <trini@ti.com>
Cc: jacopo mondi <j.mondi@voltaelectronics.com>
writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable);
}
writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable);
}
+static void omap3_spi_write_chconf(struct omap3_spi_slave *ds, int val)
+{
+ writel(val, &ds->regs->channel[ds->slave.cs].chconf);
+ /* Flash post writes to make immediate effect */
+ readl(&ds->regs->channel[ds->slave.cs].chconf);
+}
+
+static void omap3_spi_set_enable(struct omap3_spi_slave *ds, int enable)
+{
+ writel(enable, &ds->regs->channel[ds->slave.cs].chctrl);
+ /* Flash post writes to make immediate effect */
+ readl(&ds->regs->channel[ds->slave.cs].chctrl);
+}
+
void spi_init()
{
/* do nothing */
void spi_init()
{
/* do nothing */
/* Transmit & receive mode */
conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
/* Transmit & receive mode */
conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
- writel(conf, &ds->regs->channel[ds->slave.cs].chconf);
+ omap3_spi_write_chconf(ds,conf);
int timeout = SPI_WAIT_TIMEOUT;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
int timeout = SPI_WAIT_TIMEOUT;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
- if (flags & SPI_XFER_BEGIN)
- writel(OMAP3_MCSPI_CHCTRL_EN,
- &ds->regs->channel[ds->slave.cs].chctrl);
+ /* Enable the channel */
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
chconf |= OMAP3_MCSPI_CHCONF_FORCE;
chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
chconf |= OMAP3_MCSPI_CHCONF_FORCE;
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
+ omap3_spi_write_chconf(ds,chconf);
for (i = 0; i < len; i++) {
/* wait till TX register is empty (TXS == 1) */
for (i = 0; i < len; i++) {
/* wait till TX register is empty (TXS == 1) */
writel(txp[i], &ds->regs->channel[ds->slave.cs].tx);
}
writel(txp[i], &ds->regs->channel[ds->slave.cs].tx);
}
+ /* wait to finish of transfer */
+ while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+ OMAP3_MCSPI_CHSTAT_EOT));
+
+ /* Disable the channel otherwise the next immediate RX will get affected */
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+
if (flags & SPI_XFER_END) {
if (flags & SPI_XFER_END) {
- /* wait to finish of transfer */
- while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
- OMAP3_MCSPI_CHSTAT_EOT));
chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
-
- writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
+ omap3_spi_write_chconf(ds,chconf);
int timeout = SPI_WAIT_TIMEOUT;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
int timeout = SPI_WAIT_TIMEOUT;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
- if (flags & SPI_XFER_BEGIN)
- writel(OMAP3_MCSPI_CHCTRL_EN,
- &ds->regs->channel[ds->slave.cs].chctrl);
+ /* Enable the channel */
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
chconf |= OMAP3_MCSPI_CHCONF_FORCE;
chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
chconf |= OMAP3_MCSPI_CHCONF_FORCE;
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
+ omap3_spi_write_chconf(ds,chconf);
writel(0, &ds->regs->channel[ds->slave.cs].tx);
writel(0, &ds->regs->channel[ds->slave.cs].tx);
+
+ /* Disable the channel to prevent furher receiving */
+ if(i == (len - 1))
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+
/* Read the data */
rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx);
}
if (flags & SPI_XFER_END) {
chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
/* Read the data */
rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx);
}
if (flags & SPI_XFER_END) {
chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
-
- writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
+ omap3_spi_write_chconf(ds,chconf);
int i=0;
/*Enable SPI channel*/
int i=0;
/*Enable SPI channel*/
- if (flags & SPI_XFER_BEGIN)
- writel(OMAP3_MCSPI_CHCTRL_EN,
- &ds->regs->channel[ds->slave.cs].chctrl);
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
/*set TRANSMIT-RECEIVE Mode*/
chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
chconf |= OMAP3_MCSPI_CHCONF_FORCE;
/*set TRANSMIT-RECEIVE Mode*/
chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
chconf |= OMAP3_MCSPI_CHCONF_FORCE;
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
+ omap3_spi_write_chconf(ds,chconf);
/*Shift in and out 1 byte at time*/
for (i=0; i < len; i++){
/*Shift in and out 1 byte at time*/
for (i=0; i < len; i++){
/* Read the data */
rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx);
}
/* Read the data */
rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx);
}
+ /* Disable the channel */
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
/*if transfer must be terminated disable the channel*/
if (flags & SPI_XFER_END) {
chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
/*if transfer must be terminated disable the channel*/
if (flags & SPI_XFER_END) {
chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
-
- writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
+ omap3_spi_write_chconf(ds,chconf);
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
if (flags & SPI_XFER_BEGIN) {
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
if (flags & SPI_XFER_BEGIN) {
- writel(OMAP3_MCSPI_CHCTRL_EN,
- &ds->regs->channel[ds->slave.cs].chctrl);
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
chconf |= OMAP3_MCSPI_CHCONF_FORCE;
chconf |= OMAP3_MCSPI_CHCONF_FORCE;
- writel(chconf,
- &ds->regs->channel[ds->slave.cs].chconf);
+ omap3_spi_write_chconf(ds,chconf);
}
if (flags & SPI_XFER_END) {
chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
}
if (flags & SPI_XFER_END) {
chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
- writel(chconf,
- &ds->regs->channel[ds->slave.cs].chconf);
- writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
+ omap3_spi_write_chconf(ds,chconf);
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
#define OMAP3_MCSPI_CHSTAT_EOT (1 << 2)
#define OMAP3_MCSPI_CHCTRL_EN (1 << 0)
#define OMAP3_MCSPI_CHSTAT_EOT (1 << 2)
#define OMAP3_MCSPI_CHCTRL_EN (1 << 0)
+#define OMAP3_MCSPI_CHCTRL_DIS (0 << 0)
#define OMAP3_MCSPI_WAKEUPENABLE_WKEN (1 << 0)
#define OMAP3_MCSPI_WAKEUPENABLE_WKEN (1 << 0)