@ -21,6 +21,7 @@
# include <common.h>
# include <malloc.h>
# include <spi.h>
# include <asm/errno.h>
# include <asm/io.h>
# ifdef CONFIG_MX27
@ -32,6 +33,8 @@
# else
# include <asm/arch/mx31.h>
# define MXC_CSPIRXDATA 0x00
# define MXC_CSPITXDATA 0x04
# define MXC_CSPICTRL 0x08
@ -68,6 +71,7 @@ struct mxc_spi_slave {
struct spi_slave slave ;
unsigned long base ;
u32 ctrl_reg ;
int gpio ;
} ;
static inline struct mxc_spi_slave * to_mxc_spi_slave ( struct spi_slave * slave )
@ -85,7 +89,8 @@ static inline void reg_write(unsigned long addr, u32 val)
* ( volatile unsigned long * ) addr = val ;
}
static u32 spi_xchg_single ( struct spi_slave * slave , u32 data , int bitlen )
static u32 spi_xchg_single ( struct spi_slave * slave , u32 data , int bitlen ,
unsigned long flags )
{
struct mxc_spi_slave * mxcs = to_mxc_spi_slave ( slave ) ;
unsigned int cfg_reg = reg_read ( mxcs - > base + MXC_CSPICTRL ) ;
@ -96,6 +101,9 @@ static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen)
if ( cfg_reg ! = mxcs - > ctrl_reg )
reg_write ( mxcs - > base + MXC_CSPICTRL , mxcs - > ctrl_reg ) ;
if ( mxcs - > gpio > 0 & & ( flags & SPI_XFER_BEGIN ) )
mx31_gpio_set ( mxcs - > gpio , mxcs - > ctrl_reg & MXC_CSPICTRL_SSPOL ) ;
reg_write ( mxcs - > base + MXC_CSPITXDATA , data ) ;
reg_write ( mxcs - > base + MXC_CSPICTRL , mxcs - > ctrl_reg | MXC_CSPICTRL_XCH ) ;
@ -103,6 +111,11 @@ static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen)
while ( reg_read ( mxcs - > base + MXC_CSPICTRL ) & MXC_CSPICTRL_XCH )
;
if ( mxcs - > gpio > 0 & & ( flags & SPI_XFER_END ) ) {
mx31_gpio_set ( mxcs - > gpio ,
! ( mxcs - > ctrl_reg & MXC_CSPICTRL_SSPOL ) ) ;
}
return reg_read ( mxcs - > base + MXC_CSPIRXDATA ) ;
}
@ -121,7 +134,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
for ( i = 0 , in_l = ( u32 * ) din , out_l = ( u32 * ) dout ;
i < n_blks ;
i + + , in_l + + , out_l + + , bitlen - = 32 ) {
u32 data = spi_xchg_single ( slave , * out_l , bitlen ) ;
u32 data = spi_xchg_single ( slave , * out_l , bitlen , flags ) ;
/* Check if we're only transfering 8 or 16 bits */
if ( ! i ) {
@ -139,15 +152,54 @@ void spi_init(void)
{
}
static int decode_cs ( struct mxc_spi_slave * mxcs , unsigned int cs )
{
int ret ;
/*
* Some SPI devices require active chip - select over multiple
* transactions , we achieve this using a GPIO . Still , the SPI
* controller has to be configured to use one of its own chipselects .
* To use this feature you have to call spi_setup_slave ( ) with
* cs = internal_cs | ( gpio < < 8 ) , and you have to use some unused
* on this SPI controller cs between 0 and 3.
*/
if ( cs > 3 ) {
mxcs - > gpio = cs > > 8 ;
cs & = 3 ;
ret = mx31_gpio_direction ( mxcs - > gpio , MX31_GPIO_DIRECTION_OUT ) ;
if ( ret ) {
printf ( " mxc_spi: cannot setup gpio %d \n " , mxcs - > gpio ) ;
return - EINVAL ;
}
} else {
mxcs - > gpio = - 1 ;
}
return cs ;
}
struct spi_slave * spi_setup_slave ( unsigned int bus , unsigned int cs ,
unsigned int max_hz , unsigned int mode )
{
unsigned int ctrl_reg ;
struct mxc_spi_slave * mxcs ;
int ret ;
if ( bus > = ARRAY_SIZE ( spi_bases ) )
return NULL ;
mxcs = malloc ( sizeof ( struct mxc_spi_slave ) ) ;
if ( ! mxcs )
return NULL ;
if ( bus > = sizeof ( spi_bases ) / sizeof ( spi_bases [ 0 ] ) | |
cs > 3 )
ret = decode_cs ( mxcs , cs ) ;
if ( ret < 0 ) {
free ( mxcs ) ;
return NULL ;
}
cs = ret ;
ctrl_reg = MXC_CSPICTRL_CHIPSELECT ( cs ) |
MXC_CSPICTRL_BITCOUNT ( 31 ) |
@ -162,10 +214,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if ( mode & SPI_CS_HIGH )
ctrl_reg | = MXC_CSPICTRL_SSPOL ;
mxcs = malloc ( sizeof ( struct mxc_spi_slave ) ) ;
if ( ! mxcs )
return NULL ;
mxcs - > slave . bus = bus ;
mxcs - > slave . cs = cs ;
mxcs - > base = spi_bases [ bus ] ;