2020-03-06 22:41:18 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (C) IBM Corporation 2020
# include <linux/bitfield.h>
# include <linux/bits.h>
# include <linux/fsi.h>
# include <linux/jiffies.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/spi/spi.h>
# define FSI_ENGID_SPI 0x23
# define FSI_MBOX_ROOT_CTRL_8 0x2860
2020-09-10 01:28:57 +03:00
# define FSI_MBOX_ROOT_CTRL_8_SPI_MUX 0xf0000000
2020-03-06 22:41:18 +03:00
# define FSI2SPI_DATA0 0x00
# define FSI2SPI_DATA1 0x04
# define FSI2SPI_CMD 0x08
# define FSI2SPI_CMD_WRITE BIT(31)
# define FSI2SPI_RESET 0x18
# define FSI2SPI_STATUS 0x1c
# define FSI2SPI_STATUS_ANY_ERROR BIT(31)
# define FSI2SPI_IRQ 0x20
# define SPI_FSI_BASE 0x70000
2022-06-23 17:05:47 +03:00
# define SPI_FSI_TIMEOUT_MS 1000
2021-07-16 16:39:14 +03:00
# define SPI_FSI_MAX_RX_SIZE 8
# define SPI_FSI_MAX_TX_SIZE 40
2020-03-06 22:41:18 +03:00
# define SPI_FSI_ERROR 0x0
# define SPI_FSI_COUNTER_CFG 0x1
# define SPI_FSI_CFG1 0x2
# define SPI_FSI_CLOCK_CFG 0x3
# define SPI_FSI_CLOCK_CFG_MM_ENABLE BIT_ULL(32)
# define SPI_FSI_CLOCK_CFG_ECC_DISABLE (BIT_ULL(35) | BIT_ULL(33))
# define SPI_FSI_CLOCK_CFG_RESET1 (BIT_ULL(36) | BIT_ULL(38))
# define SPI_FSI_CLOCK_CFG_RESET2 (BIT_ULL(37) | BIT_ULL(39))
# define SPI_FSI_CLOCK_CFG_MODE (BIT_ULL(41) | BIT_ULL(42))
# define SPI_FSI_CLOCK_CFG_SCK_RECV_DEL GENMASK_ULL(51, 44)
# define SPI_FSI_CLOCK_CFG_SCK_NO_DEL BIT_ULL(51)
# define SPI_FSI_CLOCK_CFG_SCK_DIV GENMASK_ULL(63, 52)
# define SPI_FSI_MMAP 0x4
# define SPI_FSI_DATA_TX 0x5
# define SPI_FSI_DATA_RX 0x6
# define SPI_FSI_SEQUENCE 0x7
# define SPI_FSI_SEQUENCE_STOP 0x00
# define SPI_FSI_SEQUENCE_SEL_SLAVE(x) (0x10 | ((x) & 0xf))
# define SPI_FSI_SEQUENCE_SHIFT_OUT(x) (0x30 | ((x) & 0xf))
# define SPI_FSI_SEQUENCE_SHIFT_IN(x) (0x40 | ((x) & 0xf))
# define SPI_FSI_SEQUENCE_COPY_DATA_TX 0xc0
# define SPI_FSI_SEQUENCE_BRANCH(x) (0xe0 | ((x) & 0xf))
# define SPI_FSI_STATUS 0x8
# define SPI_FSI_STATUS_ERROR \
( GENMASK_ULL ( 31 , 21 ) | GENMASK_ULL ( 15 , 12 ) )
# define SPI_FSI_STATUS_SEQ_STATE GENMASK_ULL(55, 48)
# define SPI_FSI_STATUS_SEQ_STATE_IDLE BIT_ULL(48)
# define SPI_FSI_STATUS_TDR_UNDERRUN BIT_ULL(57)
# define SPI_FSI_STATUS_TDR_OVERRUN BIT_ULL(58)
# define SPI_FSI_STATUS_TDR_FULL BIT_ULL(59)
# define SPI_FSI_STATUS_RDR_UNDERRUN BIT_ULL(61)
# define SPI_FSI_STATUS_RDR_OVERRUN BIT_ULL(62)
# define SPI_FSI_STATUS_RDR_FULL BIT_ULL(63)
# define SPI_FSI_STATUS_ANY_ERROR \
2020-09-10 01:28:54 +03:00
( SPI_FSI_STATUS_ERROR | \
2020-03-06 22:41:18 +03:00
SPI_FSI_STATUS_TDR_OVERRUN | SPI_FSI_STATUS_RDR_UNDERRUN | \
SPI_FSI_STATUS_RDR_OVERRUN )
# define SPI_FSI_PORT_CTRL 0x9
2021-10-26 22:33:27 +03:00
struct fsi2spi {
struct fsi_device * fsi ; /* FSI2SPI CFAM engine device */
struct mutex lock ; /* lock access to the device */
} ;
2020-03-06 22:41:18 +03:00
struct fsi_spi {
struct device * dev ; /* SPI controller device */
2021-10-26 22:33:27 +03:00
struct fsi2spi * bridge ; /* FSI2SPI device */
2020-03-06 22:41:18 +03:00
u32 base ;
} ;
struct fsi_spi_sequence {
int bit ;
u64 data ;
} ;
2020-09-10 01:28:57 +03:00
static int fsi_spi_check_mux ( struct fsi_device * fsi , struct device * dev )
{
int rc ;
u32 root_ctrl_8 ;
__be32 root_ctrl_8_be ;
rc = fsi_slave_read ( fsi - > slave , FSI_MBOX_ROOT_CTRL_8 , & root_ctrl_8_be ,
sizeof ( root_ctrl_8_be ) ) ;
if ( rc )
return rc ;
root_ctrl_8 = be32_to_cpu ( root_ctrl_8_be ) ;
dev_dbg ( dev , " Root control register 8: %08x \n " , root_ctrl_8 ) ;
if ( ( root_ctrl_8 & FSI_MBOX_ROOT_CTRL_8_SPI_MUX ) = =
FSI_MBOX_ROOT_CTRL_8_SPI_MUX )
return 0 ;
return - ENOLINK ;
}
2020-03-06 22:41:18 +03:00
static int fsi_spi_check_status ( struct fsi_spi * ctx )
{
int rc ;
u32 sts ;
__be32 sts_be ;
2021-10-26 22:33:27 +03:00
rc = fsi_device_read ( ctx - > bridge - > fsi , FSI2SPI_STATUS , & sts_be ,
2020-03-06 22:41:18 +03:00
sizeof ( sts_be ) ) ;
if ( rc )
return rc ;
sts = be32_to_cpu ( sts_be ) ;
if ( sts & FSI2SPI_STATUS_ANY_ERROR ) {
dev_err ( ctx - > dev , " Error with FSI2SPI interface: %08x. \n " , sts ) ;
return - EIO ;
}
return 0 ;
}
static int fsi_spi_read_reg ( struct fsi_spi * ctx , u32 offset , u64 * value )
{
2021-10-26 22:33:27 +03:00
int rc = 0 ;
2020-03-06 22:41:18 +03:00
__be32 cmd_be ;
__be32 data_be ;
u32 cmd = offset + ctx - > base ;
2021-10-26 22:33:27 +03:00
struct fsi2spi * bridge = ctx - > bridge ;
2020-03-06 22:41:18 +03:00
* value = 0ULL ;
if ( cmd & FSI2SPI_CMD_WRITE )
return - EINVAL ;
2021-10-26 22:33:27 +03:00
rc = mutex_lock_interruptible ( & bridge - > lock ) ;
2020-03-06 22:41:18 +03:00
if ( rc )
return rc ;
2021-10-26 22:33:27 +03:00
cmd_be = cpu_to_be32 ( cmd ) ;
rc = fsi_device_write ( bridge - > fsi , FSI2SPI_CMD , & cmd_be ,
sizeof ( cmd_be ) ) ;
if ( rc )
goto unlock ;
2020-03-06 22:41:18 +03:00
rc = fsi_spi_check_status ( ctx ) ;
if ( rc )
2021-10-26 22:33:27 +03:00
goto unlock ;
2020-03-06 22:41:18 +03:00
2021-10-26 22:33:27 +03:00
rc = fsi_device_read ( bridge - > fsi , FSI2SPI_DATA0 , & data_be ,
2020-03-06 22:41:18 +03:00
sizeof ( data_be ) ) ;
if ( rc )
2021-10-26 22:33:27 +03:00
goto unlock ;
2020-03-06 22:41:18 +03:00
* value | = ( u64 ) be32_to_cpu ( data_be ) < < 32 ;
2021-10-26 22:33:27 +03:00
rc = fsi_device_read ( bridge - > fsi , FSI2SPI_DATA1 , & data_be ,
2020-03-06 22:41:18 +03:00
sizeof ( data_be ) ) ;
if ( rc )
2021-10-26 22:33:27 +03:00
goto unlock ;
2020-03-06 22:41:18 +03:00
* value | = ( u64 ) be32_to_cpu ( data_be ) ;
dev_dbg ( ctx - > dev , " Read %02x[%016llx]. \n " , offset , * value ) ;
2021-10-26 22:33:27 +03:00
unlock :
mutex_unlock ( & bridge - > lock ) ;
return rc ;
2020-03-06 22:41:18 +03:00
}
static int fsi_spi_write_reg ( struct fsi_spi * ctx , u32 offset , u64 value )
{
2021-10-26 22:33:27 +03:00
int rc = 0 ;
2020-03-06 22:41:18 +03:00
__be32 cmd_be ;
__be32 data_be ;
u32 cmd = offset + ctx - > base ;
2021-10-26 22:33:27 +03:00
struct fsi2spi * bridge = ctx - > bridge ;
2020-03-06 22:41:18 +03:00
if ( cmd & FSI2SPI_CMD_WRITE )
return - EINVAL ;
2021-10-26 22:33:27 +03:00
rc = mutex_lock_interruptible ( & bridge - > lock ) ;
if ( rc )
return rc ;
2020-03-06 22:41:18 +03:00
dev_dbg ( ctx - > dev , " Write %02x[%016llx]. \n " , offset , value ) ;
data_be = cpu_to_be32 ( upper_32_bits ( value ) ) ;
2021-10-26 22:33:27 +03:00
rc = fsi_device_write ( bridge - > fsi , FSI2SPI_DATA0 , & data_be ,
2020-03-06 22:41:18 +03:00
sizeof ( data_be ) ) ;
if ( rc )
2021-10-26 22:33:27 +03:00
goto unlock ;
2020-03-06 22:41:18 +03:00
data_be = cpu_to_be32 ( lower_32_bits ( value ) ) ;
2021-10-26 22:33:27 +03:00
rc = fsi_device_write ( bridge - > fsi , FSI2SPI_DATA1 , & data_be ,
2020-03-06 22:41:18 +03:00
sizeof ( data_be ) ) ;
if ( rc )
2021-10-26 22:33:27 +03:00
goto unlock ;
2020-03-06 22:41:18 +03:00
cmd_be = cpu_to_be32 ( cmd | FSI2SPI_CMD_WRITE ) ;
2021-10-26 22:33:27 +03:00
rc = fsi_device_write ( bridge - > fsi , FSI2SPI_CMD , & cmd_be ,
sizeof ( cmd_be ) ) ;
2020-03-06 22:41:18 +03:00
if ( rc )
2021-10-26 22:33:27 +03:00
goto unlock ;
rc = fsi_spi_check_status ( ctx ) ;
2020-03-06 22:41:18 +03:00
2021-10-26 22:33:27 +03:00
unlock :
mutex_unlock ( & bridge - > lock ) ;
return rc ;
2020-03-06 22:41:18 +03:00
}
static int fsi_spi_data_in ( u64 in , u8 * rx , int len )
{
int i ;
int num_bytes = min ( len , 8 ) ;
for ( i = 0 ; i < num_bytes ; + + i )
rx [ i ] = ( u8 ) ( in > > ( 8 * ( ( num_bytes - 1 ) - i ) ) ) ;
return num_bytes ;
}
static int fsi_spi_data_out ( u64 * out , const u8 * tx , int len )
{
int i ;
int num_bytes = min ( len , 8 ) ;
u8 * out_bytes = ( u8 * ) out ;
/* Unused bytes of the tx data should be 0. */
* out = 0ULL ;
for ( i = 0 ; i < num_bytes ; + + i )
out_bytes [ 8 - ( i + 1 ) ] = tx [ i ] ;
return num_bytes ;
}
static int fsi_spi_reset ( struct fsi_spi * ctx )
{
int rc ;
dev_dbg ( ctx - > dev , " Resetting SPI controller. \n " ) ;
rc = fsi_spi_write_reg ( ctx , SPI_FSI_CLOCK_CFG ,
SPI_FSI_CLOCK_CFG_RESET1 ) ;
if ( rc )
return rc ;
2020-09-10 01:28:56 +03:00
rc = fsi_spi_write_reg ( ctx , SPI_FSI_CLOCK_CFG ,
SPI_FSI_CLOCK_CFG_RESET2 ) ;
if ( rc )
return rc ;
return fsi_spi_write_reg ( ctx , SPI_FSI_STATUS , 0ULL ) ;
2020-03-06 22:41:18 +03:00
}
2021-10-04 22:51:49 +03:00
static int fsi_spi_status ( struct fsi_spi * ctx , u64 * status , const char * dir )
{
int rc = fsi_spi_read_reg ( ctx , SPI_FSI_STATUS , status ) ;
if ( rc )
return rc ;
if ( * status & SPI_FSI_STATUS_ANY_ERROR ) {
2021-10-26 22:33:27 +03:00
dev_err ( ctx - > dev , " %s error: %016llx \n " , dir , * status ) ;
2021-10-04 22:51:49 +03:00
rc = fsi_spi_reset ( ctx ) ;
if ( rc )
return rc ;
return - EREMOTEIO ;
}
return 0 ;
}
2021-07-16 16:39:14 +03:00
static void fsi_spi_sequence_add ( struct fsi_spi_sequence * seq , u8 val )
2020-03-06 22:41:18 +03:00
{
/*
* Add the next byte of instruction to the 8 - byte sequence register .
* Then decrement the counter so that the next instruction will go in
2020-09-10 01:28:56 +03:00
* the right place . Return the index of the slot we just filled in the
* sequence register .
2020-03-06 22:41:18 +03:00
*/
seq - > data | = ( u64 ) val < < seq - > bit ;
seq - > bit - = 8 ;
}
static void fsi_spi_sequence_init ( struct fsi_spi_sequence * seq )
{
seq - > bit = 56 ;
seq - > data = 0ULL ;
}
static int fsi_spi_transfer_data ( struct fsi_spi * ctx ,
struct spi_transfer * transfer )
{
2022-06-23 17:05:47 +03:00
int loops ;
2020-03-06 22:41:18 +03:00
int rc = 0 ;
2022-03-18 00:14:26 +03:00
unsigned long end ;
2020-03-06 22:41:18 +03:00
u64 status = 0ULL ;
if ( transfer - > tx_buf ) {
int nb ;
int sent = 0 ;
u64 out = 0ULL ;
const u8 * tx = transfer - > tx_buf ;
while ( transfer - > len > sent ) {
nb = fsi_spi_data_out ( & out , & tx [ sent ] ,
( int ) transfer - > len - sent ) ;
rc = fsi_spi_write_reg ( ctx , SPI_FSI_DATA_TX , out ) ;
if ( rc )
return rc ;
2022-06-23 17:05:47 +03:00
loops = 0 ;
end = jiffies + msecs_to_jiffies ( SPI_FSI_TIMEOUT_MS ) ;
2020-03-06 22:41:18 +03:00
do {
2022-06-23 17:05:47 +03:00
if ( loops + + & & time_after ( jiffies , end ) )
2022-05-25 19:58:51 +03:00
return - ETIMEDOUT ;
2021-10-04 22:51:49 +03:00
rc = fsi_spi_status ( ctx , & status , " TX " ) ;
2020-03-06 22:41:18 +03:00
if ( rc )
return rc ;
} while ( status & SPI_FSI_STATUS_TDR_FULL ) ;
sent + = nb ;
}
} else if ( transfer - > rx_buf ) {
int recv = 0 ;
u64 in = 0ULL ;
u8 * rx = transfer - > rx_buf ;
while ( transfer - > len > recv ) {
2022-06-23 17:05:47 +03:00
loops = 0 ;
end = jiffies + msecs_to_jiffies ( SPI_FSI_TIMEOUT_MS ) ;
2020-03-06 22:41:18 +03:00
do {
2022-06-23 17:05:47 +03:00
if ( loops + + & & time_after ( jiffies , end ) )
2022-05-25 19:58:51 +03:00
return - ETIMEDOUT ;
2021-10-04 22:51:49 +03:00
rc = fsi_spi_status ( ctx , & status , " RX " ) ;
2020-03-06 22:41:18 +03:00
if ( rc )
return rc ;
} while ( ! ( status & SPI_FSI_STATUS_RDR_FULL ) ) ;
rc = fsi_spi_read_reg ( ctx , SPI_FSI_DATA_RX , & in ) ;
if ( rc )
return rc ;
recv + = fsi_spi_data_in ( in , & rx [ recv ] ,
( int ) transfer - > len - recv ) ;
}
}
return 0 ;
}
static int fsi_spi_transfer_init ( struct fsi_spi * ctx )
{
2022-06-23 17:05:47 +03:00
int loops = 0 ;
2020-03-06 22:41:18 +03:00
int rc ;
bool reset = false ;
unsigned long end ;
u64 seq_state ;
u64 clock_cfg = 0ULL ;
u64 status = 0ULL ;
u64 wanted_clock_cfg = SPI_FSI_CLOCK_CFG_ECC_DISABLE |
SPI_FSI_CLOCK_CFG_SCK_NO_DEL |
2020-09-10 01:28:53 +03:00
FIELD_PREP ( SPI_FSI_CLOCK_CFG_SCK_DIV , 19 ) ;
2020-03-06 22:41:18 +03:00
2022-06-23 17:05:47 +03:00
end = jiffies + msecs_to_jiffies ( SPI_FSI_TIMEOUT_MS ) ;
2020-03-06 22:41:18 +03:00
do {
2022-06-23 17:05:47 +03:00
if ( loops + + & & time_after ( jiffies , end ) )
2020-03-06 22:41:18 +03:00
return - ETIMEDOUT ;
rc = fsi_spi_read_reg ( ctx , SPI_FSI_STATUS , & status ) ;
if ( rc )
return rc ;
seq_state = status & SPI_FSI_STATUS_SEQ_STATE ;
if ( status & ( SPI_FSI_STATUS_ANY_ERROR |
SPI_FSI_STATUS_TDR_FULL |
SPI_FSI_STATUS_RDR_FULL ) ) {
2021-10-04 22:51:49 +03:00
if ( reset ) {
dev_err ( ctx - > dev ,
" Initialization error: %08llx \n " ,
status ) ;
2020-03-06 22:41:18 +03:00
return - EIO ;
2021-10-04 22:51:49 +03:00
}
2020-03-06 22:41:18 +03:00
rc = fsi_spi_reset ( ctx ) ;
if ( rc )
return rc ;
reset = true ;
continue ;
}
} while ( seq_state & & ( seq_state ! = SPI_FSI_STATUS_SEQ_STATE_IDLE ) ) ;
2021-07-16 16:39:14 +03:00
rc = fsi_spi_write_reg ( ctx , SPI_FSI_COUNTER_CFG , 0ULL ) ;
if ( rc )
return rc ;
2020-03-06 22:41:18 +03:00
rc = fsi_spi_read_reg ( ctx , SPI_FSI_CLOCK_CFG , & clock_cfg ) ;
if ( rc )
return rc ;
if ( ( clock_cfg & ( SPI_FSI_CLOCK_CFG_MM_ENABLE |
SPI_FSI_CLOCK_CFG_ECC_DISABLE |
SPI_FSI_CLOCK_CFG_MODE |
SPI_FSI_CLOCK_CFG_SCK_RECV_DEL |
SPI_FSI_CLOCK_CFG_SCK_DIV ) ) ! = wanted_clock_cfg )
rc = fsi_spi_write_reg ( ctx , SPI_FSI_CLOCK_CFG ,
wanted_clock_cfg ) ;
return rc ;
}
static int fsi_spi_transfer_one_message ( struct spi_controller * ctlr ,
struct spi_message * mesg )
{
2020-09-10 01:28:57 +03:00
int rc ;
2020-03-06 22:41:18 +03:00
u8 seq_slave = SPI_FSI_SEQUENCE_SEL_SLAVE ( mesg - > spi - > chip_select + 1 ) ;
2021-07-16 16:39:14 +03:00
unsigned int len ;
2020-03-06 22:41:18 +03:00
struct spi_transfer * transfer ;
struct fsi_spi * ctx = spi_controller_get_devdata ( ctlr ) ;
2021-10-26 22:33:27 +03:00
rc = fsi_spi_check_mux ( ctx - > bridge - > fsi , ctx - > dev ) ;
2020-09-10 01:28:57 +03:00
if ( rc )
2020-11-11 00:47:36 +03:00
goto error ;
2020-09-10 01:28:57 +03:00
2020-03-06 22:41:18 +03:00
list_for_each_entry ( transfer , & mesg - > transfers , transfer_list ) {
struct fsi_spi_sequence seq ;
struct spi_transfer * next = NULL ;
/* Sequencer must do shift out (tx) first. */
2021-07-16 16:39:14 +03:00
if ( ! transfer - > tx_buf | | transfer - > len > SPI_FSI_MAX_TX_SIZE ) {
2020-03-06 22:41:18 +03:00
rc = - EINVAL ;
goto error ;
}
dev_dbg ( ctx - > dev , " Start tx of %d bytes. \n " , transfer - > len ) ;
rc = fsi_spi_transfer_init ( ctx ) ;
if ( rc < 0 )
goto error ;
fsi_spi_sequence_init ( & seq ) ;
fsi_spi_sequence_add ( & seq , seq_slave ) ;
2021-07-16 16:39:14 +03:00
len = transfer - > len ;
while ( len > 8 ) {
fsi_spi_sequence_add ( & seq ,
SPI_FSI_SEQUENCE_SHIFT_OUT ( 8 ) ) ;
len - = 8 ;
}
fsi_spi_sequence_add ( & seq , SPI_FSI_SEQUENCE_SHIFT_OUT ( len ) ) ;
2020-03-06 22:41:18 +03:00
if ( ! list_is_last ( & transfer - > transfer_list ,
& mesg - > transfers ) ) {
next = list_next_entry ( transfer , transfer_list ) ;
/* Sequencer can only do shift in (rx) after tx. */
if ( next - > rx_buf ) {
2021-07-16 16:39:14 +03:00
u8 shift ;
if ( next - > len > SPI_FSI_MAX_RX_SIZE ) {
2020-03-06 22:41:18 +03:00
rc = - EINVAL ;
goto error ;
}
dev_dbg ( ctx - > dev , " Sequence rx of %d bytes. \n " ,
next - > len ) ;
2021-07-16 16:39:14 +03:00
shift = SPI_FSI_SEQUENCE_SHIFT_IN ( next - > len ) ;
fsi_spi_sequence_add ( & seq , shift ) ;
2020-03-06 22:41:18 +03:00
} else {
next = NULL ;
}
}
fsi_spi_sequence_add ( & seq , SPI_FSI_SEQUENCE_SEL_SLAVE ( 0 ) ) ;
rc = fsi_spi_write_reg ( ctx , SPI_FSI_SEQUENCE , seq . data ) ;
if ( rc )
goto error ;
rc = fsi_spi_transfer_data ( ctx , transfer ) ;
if ( rc )
goto error ;
if ( next ) {
rc = fsi_spi_transfer_data ( ctx , next ) ;
if ( rc )
goto error ;
transfer = next ;
}
}
error :
mesg - > status = rc ;
spi_finalize_current_message ( ctlr ) ;
return rc ;
}
static size_t fsi_spi_max_transfer_size ( struct spi_device * spi )
{
2021-07-16 16:39:14 +03:00
return SPI_FSI_MAX_RX_SIZE ;
2020-03-06 22:41:18 +03:00
}
static int fsi_spi_probe ( struct device * dev )
{
int rc ;
struct device_node * np ;
int num_controllers_registered = 0 ;
2021-10-26 22:33:27 +03:00
struct fsi2spi * bridge ;
2020-03-06 22:41:18 +03:00
struct fsi_device * fsi = to_fsi_dev ( dev ) ;
2020-09-10 01:28:57 +03:00
rc = fsi_spi_check_mux ( fsi , dev ) ;
2020-03-06 22:41:18 +03:00
if ( rc )
return - ENODEV ;
2021-10-26 22:33:27 +03:00
bridge = devm_kzalloc ( dev , sizeof ( * bridge ) , GFP_KERNEL ) ;
if ( ! bridge )
return - ENOMEM ;
bridge - > fsi = fsi ;
mutex_init ( & bridge - > lock ) ;
2020-03-06 22:41:18 +03:00
for_each_available_child_of_node ( dev - > of_node , np ) {
u32 base ;
struct fsi_spi * ctx ;
struct spi_controller * ctlr ;
if ( of_property_read_u32 ( np , " reg " , & base ) )
continue ;
ctlr = spi_alloc_master ( dev , sizeof ( * ctx ) ) ;
2021-04-20 22:46:13 +03:00
if ( ! ctlr ) {
of_node_put ( np ) ;
2020-03-06 22:41:18 +03:00
break ;
2021-04-20 22:46:13 +03:00
}
2020-03-06 22:41:18 +03:00
ctlr - > dev . of_node = np ;
ctlr - > num_chipselect = of_get_available_child_count ( np ) ? : 1 ;
ctlr - > flags = SPI_CONTROLLER_HALF_DUPLEX ;
ctlr - > max_transfer_size = fsi_spi_max_transfer_size ;
ctlr - > transfer_one_message = fsi_spi_transfer_one_message ;
ctx = spi_controller_get_devdata ( ctlr ) ;
ctx - > dev = & ctlr - > dev ;
2021-10-26 22:33:27 +03:00
ctx - > bridge = bridge ;
2020-03-06 22:41:18 +03:00
ctx - > base = base + SPI_FSI_BASE ;
rc = devm_spi_register_controller ( dev , ctlr ) ;
if ( rc )
spi_controller_put ( ctlr ) ;
else
num_controllers_registered + + ;
}
if ( ! num_controllers_registered )
return - ENODEV ;
return 0 ;
}
static const struct fsi_device_id fsi_spi_ids [ ] = {
{ FSI_ENGID_SPI , FSI_VERSION_ANY } ,
{ }
} ;
MODULE_DEVICE_TABLE ( fsi , fsi_spi_ids ) ;
static struct fsi_driver fsi_spi_driver = {
. id_table = fsi_spi_ids ,
. drv = {
. name = " spi-fsi " ,
. bus = & fsi_bus_type ,
. probe = fsi_spi_probe ,
} ,
} ;
module_fsi_driver ( fsi_spi_driver ) ;
MODULE_AUTHOR ( " Eddie James <eajames@linux.ibm.com> " ) ;
MODULE_DESCRIPTION ( " FSI attached SPI controller " ) ;
MODULE_LICENSE ( " GPL " ) ;