@ -6,6 +6,8 @@
*/
# include <common.h>
# include <dm.h>
# include <errno.h>
# include <malloc.h>
# include <spi.h>
# include <fdtdec.h>
@ -19,176 +21,35 @@
DECLARE_GLOBAL_DATA_PTR ;
/* Information about each SPI controller */
struct spi_bus {
struct exynos_spi_platdata {
enum periph_id periph_id ;
s32 frequency ; /* Default clock frequency, -1 for none */
struct exynos_spi * regs ;
int inited ; /* 1 if this bus is ready for use */
int node ;
uint deactivate_delay_us ; /* Delay to wait after deactivate */
} ;
/* A list of spi buses that we know about */
static struct spi_bus spi_bus [ EXYNOS5_SPI_NUM_CONTROLLERS ] ;
static unsigned int bus_count ;
struct exynos_spi_slave {
struct spi_slave slave ;
struct exynos_spi_priv {
struct exynos_spi * regs ;
unsigned int freq ; /* Default frequency */
unsigned int mode ;
enum periph_id periph_id ; /* Peripheral ID for this device */
unsigned int fifo_size ;
int skip_preamble ;
struct spi_bus * bus ; /* Pointer to our SPI bus info */
ulong last_transaction_us ; /* Time of last transaction end */
} ;
static struct spi_bus * spi_get_bus ( unsigned dev_index )
{
if ( dev_index < bus_count )
return & spi_bus [ dev_index ] ;
debug ( " %s: invalid bus %d " , __func__ , dev_index ) ;
return NULL ;
}
static inline struct exynos_spi_slave * to_exynos_spi ( struct spi_slave * slave )
{
return container_of ( slave , struct exynos_spi_slave , slave ) ;
}
/**
* Setup the driver private data
*
* @ param bus ID of the bus that the slave is attached to
* @ param cs ID of the chip select connected to the slave
* @ param max_hz Required spi frequency
* @ param mode Required spi mode ( clk polarity , clk phase and
* master or slave )
* @ return new device or NULL
*/
struct spi_slave * spi_setup_slave ( unsigned int busnum , unsigned int cs ,
unsigned int max_hz , unsigned int mode )
{
struct exynos_spi_slave * spi_slave ;
struct spi_bus * bus ;
if ( ! spi_cs_is_valid ( busnum , cs ) ) {
debug ( " %s: Invalid bus/chip select %d, %d \n " , __func__ ,
busnum , cs ) ;
return NULL ;
}
spi_slave = spi_alloc_slave ( struct exynos_spi_slave , busnum , cs ) ;
if ( ! spi_slave ) {
debug ( " %s: Could not allocate spi_slave \n " , __func__ ) ;
return NULL ;
}
bus = & spi_bus [ busnum ] ;
spi_slave - > bus = bus ;
spi_slave - > regs = bus - > regs ;
spi_slave - > mode = mode ;
spi_slave - > periph_id = bus - > periph_id ;
if ( bus - > periph_id = = PERIPH_ID_SPI1 | |
bus - > periph_id = = PERIPH_ID_SPI2 )
spi_slave - > fifo_size = 64 ;
else
spi_slave - > fifo_size = 256 ;
spi_slave - > skip_preamble = 0 ;
spi_slave - > last_transaction_us = timer_get_us ( ) ;
spi_slave - > freq = bus - > frequency ;
if ( max_hz )
spi_slave - > freq = min ( max_hz , spi_slave - > freq ) ;
return & spi_slave - > slave ;
}
/**
* Free spi controller
*
* @ param slave Pointer to spi_slave to which controller has to
* communicate with
*/
void spi_free_slave ( struct spi_slave * slave )
{
struct exynos_spi_slave * spi_slave = to_exynos_spi ( slave ) ;
free ( spi_slave ) ;
}
/**
* Flush spi tx , rx fifos and reset the SPI controller
*
* @ param slave Pointer to spi_slave to which controller has to
* communicate with
* @ param regs Pointer to SPI registers
*/
static void spi_flush_fifo ( struct spi_slave * slave )
static void spi_flush_fifo ( struct exynos_spi * regs )
{
struct exynos_spi_slave * spi_slave = to_exynos_spi ( slave ) ;
struct exynos_spi * regs = spi_slave - > regs ;
clrsetbits_le32 ( & regs - > ch_cfg , SPI_CH_HS_EN , SPI_CH_RST ) ;
clrbits_le32 ( & regs - > ch_cfg , SPI_CH_RST ) ;
setbits_le32 ( & regs - > ch_cfg , SPI_TX_CH_ON | SPI_RX_CH_ON ) ;
}
/**
* Initialize the spi base registers , set the required clock frequency and
* initialize the gpios
*
* @ param slave Pointer to spi_slave to which controller has to
* communicate with
* @ return zero on success else a negative value
*/
int spi_claim_bus ( struct spi_slave * slave )
{
struct exynos_spi_slave * spi_slave = to_exynos_spi ( slave ) ;
struct exynos_spi * regs = spi_slave - > regs ;
u32 reg = 0 ;
int ret ;
ret = set_spi_clk ( spi_slave - > periph_id ,
spi_slave - > freq ) ;
if ( ret < 0 ) {
debug ( " %s: Failed to setup spi clock \n " , __func__ ) ;
return ret ;
}
exynos_pinmux_config ( spi_slave - > periph_id , PINMUX_FLAG_NONE ) ;
spi_flush_fifo ( slave ) ;
reg = readl ( & regs - > ch_cfg ) ;
reg & = ~ ( SPI_CH_CPHA_B | SPI_CH_CPOL_L ) ;
if ( spi_slave - > mode & SPI_CPHA )
reg | = SPI_CH_CPHA_B ;
if ( spi_slave - > mode & SPI_CPOL )
reg | = SPI_CH_CPOL_L ;
writel ( reg , & regs - > ch_cfg ) ;
writel ( SPI_FB_DELAY_180 , & regs - > fb_clk ) ;
return 0 ;
}
/**
* Reset the spi H / W and flush the tx and rx fifos
*
* @ param slave Pointer to spi_slave to which controller has to
* communicate with
*/
void spi_release_bus ( struct spi_slave * slave )
{
spi_flush_fifo ( slave ) ;
}
static void spi_get_fifo_levels ( struct exynos_spi * regs ,
int * rx_lvl , int * tx_lvl )
{
@ -208,6 +69,8 @@ static void spi_get_fifo_levels(struct exynos_spi *regs,
*/
static void spi_request_bytes ( struct exynos_spi * regs , int count , int step )
{
debug ( " %s: regs=%p, count=%d, step=%d \n " , __func__ , regs , count , step ) ;
/* For word address we need to swap bytes */
if ( step = = 4 ) {
setbits_le32 ( & regs - > mode_cfg ,
@ -230,10 +93,10 @@ static void spi_request_bytes(struct exynos_spi *regs, int count, int step)
writel ( count | SPI_PACKET_CNT_EN , & regs - > pkt_cnt ) ;
}
static int spi_rx_tx ( struct exynos_spi_slave * spi_slave , int todo ,
static int spi_rx_tx ( struct exynos_spi_priv * priv , int todo ,
void * * dinp , void const * * doutp , unsigned long flags )
{
struct exynos_spi * regs = s pi_sla ve - > regs ;
struct exynos_spi * regs = pr iv - > regs ;
uchar * rxp = * dinp ;
const uchar * txp = * doutp ;
int rx_lvl , tx_lvl ;
@ -245,8 +108,8 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
out_bytes = in_bytes = todo ;
stopping = s pi_sla ve - > skip_preamble & & ( flags & SPI_XFER_END ) & &
! ( s pi_sla ve - > mode & SPI_SLAVE ) ;
stopping = pr iv - > skip_preamble & & ( flags & SPI_XFER_END ) & &
! ( pr iv - > mode & SPI_SLAVE ) ;
/*
* Try to transfer words if we can . This helps read performance at
@ -254,7 +117,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
*/
step = 1 ;
if ( ! ( ( todo | ( uintptr_t ) rxp | ( uintptr_t ) txp ) & 3 ) & &
! s pi_sla ve - > skip_preamble )
! pr iv - > skip_preamble )
step = 4 ;
/*
@ -279,7 +142,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
* Don ' t completely fill the txfifo , since we don ' t want our
* rxfifo to overflow , and it may already contain data .
*/
while ( tx_lvl < s pi_sla ve - > fifo_size / 2 & & out_bytes ) {
while ( tx_lvl < pr iv - > fifo_size / 2 & & out_bytes ) {
if ( ! txp )
temp = - 1 ;
else if ( step = = 4 )
@ -295,9 +158,9 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
if ( rx_lvl > = step ) {
while ( rx_lvl > = step ) {
temp = readl ( & regs - > rx_data ) ;
if ( s pi_sla ve - > skip_preamble ) {
if ( pr iv - > skip_preamble ) {
if ( temp = = SPI_PREAMBLE_END_BYTE ) {
s pi_sla ve - > skip_preamble = 0 ;
pr iv - > skip_preamble = 0 ;
stopping = 0 ;
}
} else {
@ -326,7 +189,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
txp = NULL ;
spi_request_bytes ( regs , toread , step ) ;
}
if ( s pi_sla ve - > skip_preamble & & get_timer ( start ) > 100 ) {
if ( pr iv - > skip_preamble & & get_timer ( start ) > 100 ) {
printf ( " SPI timeout: in_bytes=%d, out_bytes=%d, " ,
in_bytes , out_bytes ) ;
return - 1 ;
@ -340,94 +203,29 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
}
/**
* Transfer and receive data
*
* @ param slave Pointer to spi_slave to which controller has to
* communicate with
* @ param bitlen No of bits to tranfer or receive
* @ param dout Pointer to transfer buffer
* @ param din Pointer to receive buffer
* @ param flags Flags for transfer begin and end
* @ return zero on success else a negative value
*/
int spi_xfer ( struct spi_slave * slave , unsigned int bitlen , const void * dout ,
void * din , unsigned long flags )
{
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 ) {
debug ( " Non byte aligned SPI transfer. \n " ) ;
return - 1 ;
}
/* Start the transaction, if necessary. */
if ( ( flags & SPI_XFER_BEGIN ) )
spi_cs_activate ( slave ) ;
/*
* Exynos SPI limits each transfer to 65535 transfers . To keep
* things simple , allow a maximum of 65532 bytes . We could allow
* more in word mode , but the performance difference is small .
*/
bytelen = bitlen / 8 ;
for ( upto = 0 ; ! ret & & upto < bytelen ; upto + = todo ) {
todo = min ( bytelen - upto , ( 1 < < 16 ) - 4 ) ;
ret = spi_rx_tx ( spi_slave , todo , & din , & dout , flags ) ;
if ( ret )
break ;
}
/* Stop the transaction, if necessary. */
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 ret ;
}
/**
* Validates the bus and chip select numbers
*
* @ param bus ID of the bus that the slave is attached to
* @ param cs ID of the chip select connected to the slave
* @ return one on success else zero
*/
int spi_cs_is_valid ( unsigned int bus , unsigned int cs )
{
return spi_get_bus ( bus ) & & cs = = 0 ;
}
/**
* Activate the CS by driving it LOW
*
* @ param slave Pointer to spi_slave to which controller has to
* communicate with
*/
void spi_cs_activate ( struct spi_slave * slave )
static void spi_cs_activate ( struct udevice * dev )
{
struct exynos_spi_slave * spi_slave = to_exynos_spi ( slave ) ;
struct udevice * bus = dev - > parent ;
struct exynos_spi_platdata * pdata = dev_get_platdata ( bus ) ;
struct exynos_spi_priv * priv = dev_get_priv ( bus ) ;
/* If it's too soon to do another transaction, wait */
if ( spi_slave - > bus - > deactivate_delay_us & &
s pi_sla ve - > last_transaction_us ) {
if ( pdata - > deactivate_delay_us & &
priv - > last_transaction_us ) {
ulong delay_us ; /* The delay completed so far */
delay_us = timer_get_us ( ) - s pi_sla ve - > last_transaction_us ;
if ( delay_us < spi_slave - > bus - > deactivate_delay_us )
udelay ( spi_slave - > bus - > deactivate_delay_us - delay_us ) ;
delay_us = timer_get_us ( ) - priv - > last_transaction_us ;
if ( delay_us < pdata - > deactivate_delay_us )
udelay ( pdata - > deactivate_delay_us - delay_us ) ;
}
clrbits_le32 ( & s pi_sla ve - > regs - > cs_reg , SPI_SLAVE_SIG_INACT ) ;
debug ( " Activate CS, bus %d \n " , spi_slave - > slave . bus ) ;
s pi_sla ve - > skip_preamble = s pi_sla ve - > mode & SPI_PREAMBLE ;
clrbits_le32 ( & priv - > regs - > cs_reg , SPI_SLAVE_SIG_INACT ) ;
debug ( " Activate CS, bus '%s' \n " , bus - > name ) ;
priv - > skip_preamble = priv - > mode & SPI_PREAMBLE ;
}
/**
@ -436,148 +234,197 @@ void spi_cs_activate(struct spi_slave *slave)
* @ param slave Pointer to spi_slave to which controller has to
* communicate with
*/
void spi_cs_deactivate ( struct spi_slave * slave )
static void spi_cs_deactivate ( struct udevice * dev )
{
struct exynos_spi_slave * spi_slave = to_exynos_spi ( slave ) ;
struct udevice * bus = dev - > parent ;
struct exynos_spi_platdata * pdata = dev_get_platdata ( bus ) ;
struct exynos_spi_priv * priv = dev_get_priv ( bus ) ;
setbits_le32 ( & spi_slave - > regs - > cs_reg , SPI_SLAVE_SIG_INACT ) ;
setbits_le32 ( & pr iv - > regs - > cs_reg , SPI_SLAVE_SIG_INACT ) ;
/* Remember time of this transaction so we can honour the bus delay */
if ( spi_slave - > bus - > deactivate_delay_us )
s pi_sla ve - > last_transaction_us = timer_get_us ( ) ;
if ( pdata - > deactivate_delay_us )
pr iv - > last_transaction_us = timer_get_us ( ) ;
debug ( " Deactivate CS, bus %d \n " , spi_slave - > slave . bus ) ;
debug ( " Deactivate CS, bus '%s' \n " , bus - > name ) ;
}
static inline struct exynos_spi * get_spi_base ( int dev_index )
static int exynos_spi_ofdata_to_platdata ( struct udevice * bus )
{
if ( dev_index < 3 )
return ( struct exynos_spi * ) samsung_get_base_spi ( ) + dev_index ;
else
return ( struct exynos_spi * ) samsung_get_base_spi_isp ( ) +
( dev_index - 3 ) ;
}
struct exynos_spi_platdata * plat = bus - > platdata ;
const void * blob = gd - > fdt_blob ;
int node = bus - > of_offset ;
/*
* Read the SPI config from the device tree node .
*
* @ param blob FDT blob to read from
* @ param node Node offset to read from
* @ param bus SPI bus structure to fill with information
* @ return 0 if ok , or - FDT_ERR_NOTFOUND if something was missing
*/
# ifdef CONFIG_OF_CONTROL
static int spi_get_config ( const void * blob , int node , struct spi_bus * bus )
{
bus - > node = node ;
bus - > regs = ( struct exynos_spi * ) fdtdec_get_addr ( blob , node , " reg " ) ;
bus - > periph_id = pinmux_decode_periph_id ( blob , node ) ;
plat - > regs = ( struct exynos_spi * ) fdtdec_get_addr ( blob , node , " reg " ) ;
plat - > periph_id = pinmux_decode_periph_id ( blob , node ) ;
if ( bus - > periph_id = = PERIPH_ID_NONE ) {
if ( plat - > periph_id = = PERIPH_ID_NONE ) {
debug ( " %s: Invalid peripheral ID %d \n " , __func__ ,
bus - > periph_id ) ;
plat - > periph_id ) ;
return - FDT_ERR_NOTFOUND ;
}
/* Use 500KHz as a suitable default */
bus - > frequency = fdtdec_get_int ( blob , node , " spi-max-frequency " ,
plat - > frequency = fdtdec_get_int ( blob , node , " spi-max-frequency " ,
500000 ) ;
bus - > deactivate_delay_us = fdtdec_get_int ( blob , node ,
plat - > deactivate_delay_us = fdtdec_get_int ( blob , node ,
" spi-deactivate-delay " , 0 ) ;
debug ( " %s: regs=%p, periph_id=%d, max-frequency=%d, deactivate_delay=%d \n " ,
__func__ , plat - > regs , plat - > periph_id , plat - > frequency ,
plat - > deactivate_delay_us ) ;
return 0 ;
}
/*
* Process a list of nodes , adding them to our list of SPI ports .
*
* @ param blob fdt blob
* @ param node_list list of nodes to process ( any < = 0 are ignored )
* @ param count number of nodes to process
* @ param is_dvc 1 if these are DVC ports , 0 if standard I2C
* @ return 0 if ok , - 1 on error
*/
static int process_nodes ( const void * blob , int node_list [ ] , int count )
static int exynos_spi_probe ( struct udevice * bus )
{
int i ;
struct exynos_spi_platdata * plat = dev_get_platdata ( bus ) ;
struct exynos_spi_priv * priv = dev_get_priv ( bus ) ;
/* build the i2c_controllers[] for each controller */
for ( i = 0 ; i < count ; i + + ) {
int node = node_list [ i ] ;
struct spi_bus * bus ;
priv - > regs = plat - > regs ;
if ( plat - > periph_id = = PERIPH_ID_SPI1 | |
plat - > periph_id = = PERIPH_ID_SPI2 )
priv - > fifo_size = 64 ;
else
priv - > fifo_size = 256 ;
if ( node < = 0 )
continue ;
priv - > skip_preamble = 0 ;
priv - > last_transaction_us = timer_get_us ( ) ;
priv - > freq = plat - > frequency ;
priv - > periph_id = plat - > periph_id ;
bus = & spi_bus [ i ] ;
if ( spi_get_config ( blob , node , bus ) ) {
printf ( " exynos spi_init: failed to decode bus %d \n " ,
i ) ;
return - 1 ;
}
return 0 ;
}
debug ( " spi: controller bus %d at %p, periph_id %d \n " ,
i , bus - > regs , bus - > periph_id ) ;
bus - > inited = 1 ;
bus_count + + ;
}
static int exynos_spi_claim_bus ( struct udevice * bus )
{
struct exynos_spi_priv * priv = dev_get_priv ( bus ) ;
exynos_pinmux_config ( priv - > periph_id , PINMUX_FLAG_NONE ) ;
spi_flush_fifo ( priv - > regs ) ;
writel ( SPI_FB_DELAY_180 , & priv - > regs - > fb_clk ) ;
return 0 ;
}
# endif
/**
* Set up a new SPI slave for an fdt node
*
* @ param blob Device tree blob
* @ param node SPI peripheral node to use
* @ return 0 if ok , - 1 on error
*/
struct spi_slave * spi_setup_slave_fdt ( const void * blob , int slave_node ,
int spi_node )
static int exynos_spi_release_bus ( struct udevice * bus )
{
struct spi_bus * bus ;
unsigned int i ;
struct exynos_spi_priv * priv = dev_get_priv ( bus ) ;
spi_flush_fifo ( priv - > regs ) ;
return 0 ;
}
static int exynos_spi_xfer ( struct udevice * dev , unsigned int bitlen ,
const void * dout , void * din , unsigned long flags )
{
struct udevice * bus = dev - > parent ;
struct exynos_spi_priv * priv = dev_get_priv ( bus ) ;
int upto , todo ;
int bytelen ;
int ret = 0 ;
/* spi core configured to do 8 bit transfers */
if ( bitlen % 8 ) {
debug ( " Non byte aligned SPI transfer. \n " ) ;
return - 1 ;
}
/* Start the transaction, if necessary. */
if ( ( flags & SPI_XFER_BEGIN ) )
spi_cs_activate ( dev ) ;
/*
* Exynos SPI limits each transfer to 65535 transfers . To keep
* things simple , allow a maximum of 65532 bytes . We could allow
* more in word mode , but the performance difference is small .
*/
bytelen = bitlen / 8 ;
for ( upto = 0 ; ! ret & & upto < bytelen ; upto + = todo ) {
todo = min ( bytelen - upto , ( 1 < < 16 ) - 4 ) ;
ret = spi_rx_tx ( priv , todo , & din , & dout , flags ) ;
if ( ret )
break ;
}
for ( i = 0 , bus = spi_bus ; i < bus_count ; i + + , bus + + ) {
if ( bus - > node = = spi_node )
return spi_base_setup_slave_fdt ( blob , i , slave_node ) ;
/* Stop the transaction, if necessary. */
if ( ( flags & SPI_XFER_END ) & & ! ( priv - > mode & SPI_SLAVE ) ) {
spi_cs_deactivate ( dev ) ;
if ( priv - > skip_preamble ) {
assert ( ! priv - > skip_preamble ) ;
debug ( " Failed to complete premable transaction \n " ) ;
ret = - 1 ;
}
}
debug ( " %s: Failed to find bus node %d \n " , __func__ , spi_node ) ;
return NULL ;
return ret ;
}
/* Sadly there is no error return from this function */
void spi_init ( void )
static int exynos_spi_set_speed ( struct udevice * bus , uint speed )
{
int count ;
struct exynos_spi_platdata * plat = bus - > platdata ;
struct exynos_spi_priv * priv = dev_get_priv ( bus ) ;
int ret ;
# ifdef CONFIG_OF_CONTROL
int node_list [ EXYNOS5_SPI_NUM_CONTROLLERS ] ;
const void * blob = gd - > fdt_blob ;
if ( speed > plat - > frequency )
speed = plat - > frequency ;
ret = set_spi_clk ( priv - > periph_id , speed ) ;
if ( ret )
return ret ;
priv - > freq = speed ;
debug ( " %s: regs=%p, speed=%d \n " , __func__ , priv - > regs , priv - > freq ) ;
return 0 ;
}
count = fdtdec_find_aliases_for_id ( blob , " spi " ,
COMPAT_SAMSUNG_EXYNOS_SPI , node_list ,
EXYNOS5_SPI_NUM_CONTROLLERS ) ;
if ( process_nodes ( blob , node_list , count ) )
return ;
static int exynos_spi_set_mode ( struct udevice * bus , uint mode )
{
struct exynos_spi_priv * priv = dev_get_priv ( bus ) ;
uint32_t reg ;
# else
struct spi_bus * bus ;
reg = readl ( & priv - > regs - > ch_cfg ) ;
reg & = ~ ( SPI_CH_CPHA_B | SPI_CH_CPOL_L ) ;
for ( count = 0 ; count < EXYNOS5_SPI_NUM_CONTROLLERS ; count + + ) {
bus = & spi_bus [ count ] ;
bus - > regs = get_spi_base ( count ) ;
bus - > periph_id = PERIPH_ID_SPI0 + count ;
if ( mode & SPI_CPHA )
reg | = SPI_CH_CPHA_B ;
/* Although Exynos5 supports upto 50Mhz speed,
* we are setting it to 10 Mhz for safe side
*/
bus - > frequency = 10000000 ;
bus - > inited = 1 ;
bus - > node = 0 ;
bus_count = EXYNOS5_SPI_NUM_CONTROLLERS ;
}
# endif
if ( mode & SPI_CPOL )
reg | = SPI_CH_CPOL_L ;
writel ( reg , & priv - > regs - > ch_cfg ) ;
priv - > mode = mode ;
debug ( " %s: regs=%p, mode=%d \n " , __func__ , priv - > regs , priv - > mode ) ;
return 0 ;
}
static const struct dm_spi_ops exynos_spi_ops = {
. claim_bus = exynos_spi_claim_bus ,
. release_bus = exynos_spi_release_bus ,
. xfer = exynos_spi_xfer ,
. set_speed = exynos_spi_set_speed ,
. set_mode = exynos_spi_set_mode ,
/*
* cs_info is not needed , since we require all chip selects to be
* in the device tree explicitly
*/
} ;
static const struct udevice_id exynos_spi_ids [ ] = {
{ . compatible = " samsung,exynos-spi " } ,
{ }
} ;
U_BOOT_DRIVER ( exynos_spi ) = {
. name = " exynos_spi " ,
. id = UCLASS_SPI ,
. of_match = exynos_spi_ids ,
. ops = & exynos_spi_ops ,
. ofdata_to_platdata = exynos_spi_ofdata_to_platdata ,
. platdata_auto_alloc_size = sizeof ( struct exynos_spi_platdata ) ,
. priv_auto_alloc_size = sizeof ( struct exynos_spi_priv ) ,
. per_child_auto_alloc_size = sizeof ( struct spi_slave ) ,
. probe = exynos_spi_probe ,
} ;