@ -51,6 +51,7 @@ struct exynos_spi_slave {
unsigned int mode ;
enum periph_id periph_id ; /* Peripheral ID for this device */
unsigned int fifo_size ;
int skip_preamble ;
} ;
static struct spi_bus * spi_get_bus ( unsigned dev_index )
@ -105,6 +106,8 @@ struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
else
spi_slave - > fifo_size = 256 ;
spi_slave - > skip_preamble = 0 ;
spi_slave - > freq = bus - > frequency ;
if ( max_hz )
spi_slave - > freq = min ( max_hz , spi_slave - > freq ) ;
@ -217,17 +220,23 @@ static void spi_request_bytes(struct exynos_spi *regs, int count)
writel ( count | SPI_PACKET_CNT_EN , & regs - > pkt_cnt ) ;
}
static void spi_rx_tx ( struct exynos_spi_slave * spi_slave , int todo ,
void * * dinp , void const * * doutp )
static int spi_rx_tx ( struct exynos_spi_slave * spi_slave , int todo ,
void * * dinp , void const * * doutp , unsigned long flags )
{
struct exynos_spi * regs = spi_slave - > regs ;
uchar * rxp = * dinp ;
const uchar * txp = * doutp ;
int rx_lvl , tx_lvl ;
uint out_bytes , in_bytes ;
int toread ;
unsigned start = get_timer ( 0 ) ;
int stopping ;
out_bytes = in_bytes = todo ;
stopping = spi_slave - > skip_preamble & & ( flags & SPI_XFER_END ) & &
! ( spi_slave - > mode & SPI_SLAVE ) ;
/*
* If there ' s something to send , do a software reset and set a
* transaction size .
@ -238,6 +247,8 @@ static void spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
* Bytes are transmitted / received in pairs . Wait to receive all the
* data because then transmission will be done as well .
*/
toread = in_bytes ;
while ( in_bytes ) {
int temp ;
@ -248,15 +259,43 @@ static void spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
writel ( temp , & regs - > tx_data ) ;
out_bytes - - ;
}
if ( rx_lvl > 0 & & in_bytes ) {
if ( rx_lvl > 0 ) {
temp = readl ( & regs - > rx_data ) ;
if ( rxp )
* rxp + + = temp ;
in_bytes - - ;
if ( spi_slave - > skip_preamble ) {
if ( temp = = SPI_PREAMBLE_END_BYTE ) {
spi_slave - > skip_preamble = 0 ;
stopping = 0 ;
}
} else {
if ( rxp | | stopping )
* rxp + + = temp ;
in_bytes - - ;
}
toread - - ;
} else if ( ! toread ) {
/*
* We have run out of input data , but haven ' t read
* enough bytes after the preamble yet . Read some more ,
* and make sure that we transmit dummy bytes too , to
* keep things going .
*/
assert ( ! out_bytes ) ;
out_bytes = in_bytes ;
toread = in_bytes ;
txp = NULL ;
spi_request_bytes ( regs , toread ) ;
}
if ( spi_slave - > skip_preamble & & get_timer ( start ) > 100 ) {
printf ( " SPI timeout: in_bytes=%d, out_bytes=%d, " ,
in_bytes , out_bytes ) ;
return - 1 ;
}
}
* dinp = rxp ;
* doutp = txp ;
return 0 ;
}
/**
@ -276,6 +315,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
struct exynos_spi_slave * spi_slave = to_exynos_spi ( slave ) ;
int upto , todo ;
int bytelen ;
int ret = 0 ;
/* spi core configured to do 8 bit transfers */
if ( bitlen % 8 ) {
@ -289,16 +329,24 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
/* Exynos SPI limits each transfer to 65535 bytes */
bytelen = bitlen / 8 ;
for ( upto = 0 ; upto < bytelen ; upto + = todo ) {
for ( upto = 0 ; ! ret & & upto < bytelen ; upto + = todo ) {
todo = min ( bytelen - upto , ( 1 < < 16 ) - 1 ) ;
spi_rx_tx ( spi_slave , todo , & din , & dout ) ;
ret = spi_rx_tx ( spi_slave , todo , & din , & dout , flags ) ;
if ( ret )
break ;
}
/* Stop the transaction, if necessary. */
if ( ( flags & SPI_XFER_END ) )
if ( ( flags & SPI_XFER_END ) & & ! ( spi_slave - > mode & SPI_SLAVE ) ) {
spi_cs_deactivate ( slave ) ;
if ( spi_slave - > skip_preamble ) {
assert ( ! spi_slave - > skip_preamble ) ;
debug ( " Failed to complete premable transaction \n " ) ;
ret = - 1 ;
}
}
return 0 ;
return ret ;
}
/**
@ -325,6 +373,7 @@ void spi_cs_activate(struct spi_slave *slave)
clrbits_le32 ( & spi_slave - > regs - > cs_reg , SPI_SLAVE_SIG_INACT ) ;
debug ( " Activate CS, bus %d \n " , spi_slave - > slave . bus ) ;
spi_slave - > skip_preamble = spi_slave - > mode & SPI_PREAMBLE ;
}
/**