diff options
Diffstat (limited to 'drivers/spi/omap3_spi.c')
| -rw-r--r-- | drivers/spi/omap3_spi.c | 76 | 
1 files changed, 44 insertions, 32 deletions
| diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 6791a7e0e..344d5b8a7 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -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 { |