|
@@ -57,6 +57,20 @@ static void spi_reset(struct omap3_spi_slave *ds)
|
|
|
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 */
|
|
@@ -212,7 +226,7 @@ int spi_claim_bus(struct spi_slave *slave)
|
|
|
/* Transmit & receive mode */
|
|
|
conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
|
|
|
|
|
|
- writel(conf, &ds->regs->channel[ds->slave.cs].chconf);
|
|
|
+ omap3_spi_write_chconf(ds,conf);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -233,14 +247,13 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const u8 *txp,
|
|
|
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;
|
|
|
- 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) */
|
|
@@ -256,15 +269,17 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const u8 *txp,
|
|
|
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) {
|
|
|
- /* wait to finish of transfer */
|
|
|
- while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
|
|
|
- OMAP3_MCSPI_CHSTAT_EOT));
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
@@ -277,14 +292,13 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, u8 *rxp,
|
|
|
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;
|
|
|
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
|
|
|
+ omap3_spi_write_chconf(ds,chconf);
|
|
|
|
|
|
writel(0, &ds->regs->channel[ds->slave.cs].tx);
|
|
|
|
|
@@ -298,15 +312,18 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, u8 *rxp,
|
|
|
return -1;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /* 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;
|
|
|
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
|
|
|
-
|
|
|
- writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
|
|
|
+ omap3_spi_write_chconf(ds,chconf);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -323,14 +340,12 @@ int omap3_spi_txrx(struct spi_slave *slave,
|
|
|
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;
|
|
|
- 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++){
|
|
@@ -359,13 +374,13 @@ int omap3_spi_txrx(struct spi_slave *slave,
|
|
|
/* 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;
|
|
|
- writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
|
|
|
-
|
|
|
- writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
|
|
|
+ omap3_spi_write_chconf(ds,chconf);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -389,17 +404,14 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
|
|
|
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;
|
|
|
- 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;
|
|
|
- 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);
|
|
|
}
|
|
|
ret = 0;
|
|
|
} else {
|