2021-01-07 07:37:13 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* DFL device driver for Nios private feature on Intel PAC ( Programmable
* Acceleration Card ) N3000
*
* Copyright ( C ) 2019 - 2020 Intel Corporation , Inc .
*
* Authors :
* Wu Hao < hao . wu @ intel . com >
* Xu Yilun < yilun . xu @ intel . com >
*/
# include <linux/bitfield.h>
# include <linux/dfl.h>
# include <linux/errno.h>
# include <linux/io.h>
# include <linux/io-64-nonatomic-lo-hi.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
# include <linux/stddef.h>
# include <linux/spi/altera.h>
# include <linux/spi/spi.h>
# include <linux/types.h>
/*
* N3000 Nios private feature registers , named as NIOS_SPI_XX on spec .
* NS is the abbreviation of NIOS_SPI .
*/
# define N3000_NS_PARAM 0x8
# define N3000_NS_PARAM_SHIFT_MODE_MSK BIT_ULL(1)
# define N3000_NS_PARAM_SHIFT_MODE_MSB 0
# define N3000_NS_PARAM_SHIFT_MODE_LSB 1
# define N3000_NS_PARAM_DATA_WIDTH GENMASK_ULL(7, 2)
# define N3000_NS_PARAM_NUM_CS GENMASK_ULL(13, 8)
# define N3000_NS_PARAM_CLK_POL BIT_ULL(14)
# define N3000_NS_PARAM_CLK_PHASE BIT_ULL(15)
# define N3000_NS_PARAM_PERIPHERAL_ID GENMASK_ULL(47, 32)
# define N3000_NS_CTRL 0x10
# define N3000_NS_CTRL_WR_DATA GENMASK_ULL(31, 0)
# define N3000_NS_CTRL_ADDR GENMASK_ULL(44, 32)
# define N3000_NS_CTRL_CMD_MSK GENMASK_ULL(63, 62)
# define N3000_NS_CTRL_CMD_NOP 0
# define N3000_NS_CTRL_CMD_RD 1
# define N3000_NS_CTRL_CMD_WR 2
# define N3000_NS_STAT 0x18
# define N3000_NS_STAT_RD_DATA GENMASK_ULL(31, 0)
# define N3000_NS_STAT_RW_VAL BIT_ULL(32)
/* Nios handshake registers, indirect access */
# define N3000_NIOS_INIT 0x1000
# define N3000_NIOS_INIT_DONE BIT(0)
# define N3000_NIOS_INIT_START BIT(1)
/* Mode for retimer A, link 0, the same below */
# define N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK GENMASK(9, 8)
# define N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK GENMASK(11, 10)
# define N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK GENMASK(13, 12)
# define N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK GENMASK(15, 14)
# define N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK GENMASK(17, 16)
# define N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK GENMASK(19, 18)
# define N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK GENMASK(21, 20)
# define N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK GENMASK(23, 22)
# define N3000_NIOS_INIT_REQ_FEC_MODE_NO 0x0
# define N3000_NIOS_INIT_REQ_FEC_MODE_KR 0x1
# define N3000_NIOS_INIT_REQ_FEC_MODE_RS 0x2
# define N3000_NIOS_FW_VERSION 0x1004
# define N3000_NIOS_FW_VERSION_PATCH GENMASK(23, 20)
# define N3000_NIOS_FW_VERSION_MINOR GENMASK(27, 24)
# define N3000_NIOS_FW_VERSION_MAJOR GENMASK(31, 28)
/* The retimers we use on Intel PAC N3000 is Parkvale, abbreviated to PKVL */
# define N3000_NIOS_PKVL_A_MODE_STS 0x1020
# define N3000_NIOS_PKVL_B_MODE_STS 0x1024
# define N3000_NIOS_PKVL_MODE_STS_GROUP_MSK GENMASK(15, 8)
# define N3000_NIOS_PKVL_MODE_STS_GROUP_OK 0x0
# define N3000_NIOS_PKVL_MODE_STS_ID_MSK GENMASK(7, 0)
/* When GROUP MASK field == GROUP_OK */
# define N3000_NIOS_PKVL_MODE_ID_RESET 0x0
# define N3000_NIOS_PKVL_MODE_ID_4X10G 0x1
# define N3000_NIOS_PKVL_MODE_ID_4X25G 0x2
# define N3000_NIOS_PKVL_MODE_ID_2X25G 0x3
# define N3000_NIOS_PKVL_MODE_ID_2X25G_2X10G 0x4
# define N3000_NIOS_PKVL_MODE_ID_1X25G 0x5
# define N3000_NIOS_REGBUS_RETRY_COUNT 10000 /* loop count */
# define N3000_NIOS_INIT_TIMEOUT 10000000 /* usec */
# define N3000_NIOS_INIT_TIME_INTV 100000 /* usec */
# define N3000_NIOS_INIT_REQ_FEC_MODE_MSK_ALL \
( N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK | \
N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK | \
N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK | \
N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK | \
N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK | \
N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK | \
N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK | \
N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK )
# define N3000_NIOS_INIT_REQ_FEC_MODE_NO_ALL \
( FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_NO ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_NO ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_NO ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_NO ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_NO ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_NO ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_NO ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_NO ) )
# define N3000_NIOS_INIT_REQ_FEC_MODE_KR_ALL \
( FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_KR ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_KR ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_KR ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_KR ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_KR ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_KR ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_KR ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_KR ) )
# define N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL \
( FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_RS ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_RS ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_RS ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_RS ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_RS ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_RS ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_RS ) | \
FIELD_PREP ( N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK , \
N3000_NIOS_INIT_REQ_FEC_MODE_RS ) )
struct n3000_nios {
void __iomem * base ;
struct regmap * regmap ;
struct device * dev ;
struct platform_device * altera_spi ;
} ;
static ssize_t nios_fw_version_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct n3000_nios * nn = dev_get_drvdata ( dev ) ;
unsigned int val ;
int ret ;
ret = regmap_read ( nn - > regmap , N3000_NIOS_FW_VERSION , & val ) ;
if ( ret )
return ret ;
return sysfs_emit ( buf , " %x.%x.%x \n " ,
( u8 ) FIELD_GET ( N3000_NIOS_FW_VERSION_MAJOR , val ) ,
( u8 ) FIELD_GET ( N3000_NIOS_FW_VERSION_MINOR , val ) ,
( u8 ) FIELD_GET ( N3000_NIOS_FW_VERSION_PATCH , val ) ) ;
}
static DEVICE_ATTR_RO ( nios_fw_version ) ;
# define IS_MODE_STATUS_OK(mode_stat) \
( FIELD_GET ( N3000_NIOS_PKVL_MODE_STS_GROUP_MSK , ( mode_stat ) ) = = \
N3000_NIOS_PKVL_MODE_STS_GROUP_OK )
# define IS_RETIMER_FEC_SUPPORTED(retimer_mode) \
( ( retimer_mode ) ! = N3000_NIOS_PKVL_MODE_ID_RESET & & \
( retimer_mode ) ! = N3000_NIOS_PKVL_MODE_ID_4X10G )
static int get_retimer_mode ( struct n3000_nios * nn , unsigned int mode_stat_reg ,
unsigned int * retimer_mode )
{
unsigned int val ;
int ret ;
ret = regmap_read ( nn - > regmap , mode_stat_reg , & val ) ;
if ( ret )
return ret ;
if ( ! IS_MODE_STATUS_OK ( val ) )
return - EFAULT ;
* retimer_mode = FIELD_GET ( N3000_NIOS_PKVL_MODE_STS_ID_MSK , val ) ;
return 0 ;
}
static ssize_t retimer_A_mode_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct n3000_nios * nn = dev_get_drvdata ( dev ) ;
unsigned int mode ;
int ret ;
ret = get_retimer_mode ( nn , N3000_NIOS_PKVL_A_MODE_STS , & mode ) ;
if ( ret )
return ret ;
return sysfs_emit ( buf , " 0x%x \n " , mode ) ;
}
static DEVICE_ATTR_RO ( retimer_A_mode ) ;
static ssize_t retimer_B_mode_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct n3000_nios * nn = dev_get_drvdata ( dev ) ;
unsigned int mode ;
int ret ;
ret = get_retimer_mode ( nn , N3000_NIOS_PKVL_B_MODE_STS , & mode ) ;
if ( ret )
return ret ;
return sysfs_emit ( buf , " 0x%x \n " , mode ) ;
}
static DEVICE_ATTR_RO ( retimer_B_mode ) ;
static ssize_t fec_mode_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned int val , retimer_a_mode , retimer_b_mode , fec_modes ;
struct n3000_nios * nn = dev_get_drvdata ( dev ) ;
int ret ;
/* FEC mode setting is not supported in early FW versions */
ret = regmap_read ( nn - > regmap , N3000_NIOS_FW_VERSION , & val ) ;
if ( ret )
return ret ;
if ( FIELD_GET ( N3000_NIOS_FW_VERSION_MAJOR , val ) < 3 )
return sysfs_emit ( buf , " not supported \n " ) ;
/* If no 25G links, FEC mode setting is not supported either */
ret = get_retimer_mode ( nn , N3000_NIOS_PKVL_A_MODE_STS , & retimer_a_mode ) ;
if ( ret )
return ret ;
ret = get_retimer_mode ( nn , N3000_NIOS_PKVL_B_MODE_STS , & retimer_b_mode ) ;
if ( ret )
return ret ;
if ( ! IS_RETIMER_FEC_SUPPORTED ( retimer_a_mode ) & &
! IS_RETIMER_FEC_SUPPORTED ( retimer_b_mode ) )
return sysfs_emit ( buf , " not supported \n " ) ;
/* get the valid FEC mode for 25G links */
ret = regmap_read ( nn - > regmap , N3000_NIOS_INIT , & val ) ;
if ( ret )
return ret ;
/*
* FEC mode should always be the same for all links , as we set them
* in this way .
*/
fec_modes = ( val & N3000_NIOS_INIT_REQ_FEC_MODE_MSK_ALL ) ;
if ( fec_modes = = N3000_NIOS_INIT_REQ_FEC_MODE_NO_ALL )
return sysfs_emit ( buf , " no \n " ) ;
else if ( fec_modes = = N3000_NIOS_INIT_REQ_FEC_MODE_KR_ALL )
return sysfs_emit ( buf , " kr \n " ) ;
else if ( fec_modes = = N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL )
return sysfs_emit ( buf , " rs \n " ) ;
return - EFAULT ;
}
static DEVICE_ATTR_RO ( fec_mode ) ;
static struct attribute * n3000_nios_attrs [ ] = {
& dev_attr_nios_fw_version . attr ,
& dev_attr_retimer_A_mode . attr ,
& dev_attr_retimer_B_mode . attr ,
& dev_attr_fec_mode . attr ,
NULL ,
} ;
ATTRIBUTE_GROUPS ( n3000_nios ) ;
static int n3000_nios_init_done_check ( struct n3000_nios * nn )
{
unsigned int val , state_a , state_b ;
struct device * dev = nn - > dev ;
int ret , ret2 ;
/*
* The SPI is shared by the Nios core inside the FPGA , Nios will use
* this SPI master to do some one time initialization after power up ,
* and then release the control to OS . The driver needs to poll on
* INIT_DONE to see when driver could take the control .
*
* Please note that after Nios firmware version 3.0 .0 , INIT_START is
* introduced , so driver needs to trigger START firstly and then check
* INIT_DONE .
*/
ret = regmap_read ( nn - > regmap , N3000_NIOS_FW_VERSION , & val ) ;
if ( ret )
return ret ;
/*
* If Nios version register is totally uninitialized ( = = 0x0 ) , then the
* Nios firmware is missing . So host could take control of SPI master
* safely , but initialization work for Nios is not done . To restore the
* card , we need to reprogram a new Nios firmware via the BMC chip on
* SPI bus . So the driver doesn ' t error out , it continues to create the
* spi controller device and spi_board_info for BMC .
*/
if ( val = = 0 ) {
dev_err ( dev , " Nios version reg = 0x%x, skip INIT_DONE check, but the retimer may be uninitialized \n " ,
val ) ;
return 0 ;
}
if ( FIELD_GET ( N3000_NIOS_FW_VERSION_MAJOR , val ) > = 3 ) {
/* read NIOS_INIT to check if retimer initialization is done */
ret = regmap_read ( nn - > regmap , N3000_NIOS_INIT , & val ) ;
if ( ret )
return ret ;
/* check if retimers are initialized already */
if ( val & ( N3000_NIOS_INIT_DONE | N3000_NIOS_INIT_START ) )
goto nios_init_done ;
/* configure FEC mode per module param */
val = N3000_NIOS_INIT_START ;
/*
* When the retimer is to be set to 10 G mode , there is no FEC
* mode setting , so the REQ_FEC_MODE field will be ignored by
* Nios firmware in this case . But we should still fill the FEC
* mode field cause host could not get the retimer working mode
* until the Nios init is done .
*
* For now the driver doesn ' t support the retimer FEC mode
* switching per user ' s request . It is always set to Reed
* Solomon FEC .
*
* The driver will set the same FEC mode for all links .
*/
val | = N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL ;
ret = regmap_write ( nn - > regmap , N3000_NIOS_INIT , val ) ;
if ( ret )
return ret ;
}
nios_init_done :
/* polls on NIOS_INIT_DONE */
ret = regmap_read_poll_timeout ( nn - > regmap , N3000_NIOS_INIT , val ,
val & N3000_NIOS_INIT_DONE ,
N3000_NIOS_INIT_TIME_INTV ,
N3000_NIOS_INIT_TIMEOUT ) ;
if ( ret )
dev_err ( dev , " NIOS_INIT_DONE %s \n " ,
( ret = = - ETIMEDOUT ) ? " timed out " : " check error " ) ;
ret2 = regmap_read ( nn - > regmap , N3000_NIOS_PKVL_A_MODE_STS , & state_a ) ;
if ( ret2 )
return ret2 ;
ret2 = regmap_read ( nn - > regmap , N3000_NIOS_PKVL_B_MODE_STS , & state_b ) ;
if ( ret2 )
return ret2 ;
if ( ! ret ) {
/*
* After INIT_DONE is detected , it still needs to check if the
* Nios firmware reports any error during the retimer
* configuration .
*/
if ( IS_MODE_STATUS_OK ( state_a ) & & IS_MODE_STATUS_OK ( state_b ) )
return 0 ;
/*
* If the retimer configuration is failed , the Nios firmware
* will still release the spi controller for host to
* communicate with the BMC . It makes possible for people to
* reprogram a new Nios firmware and restore the card . So the
* driver doesn ' t error out , it continues to create the spi
* controller device and spi_board_info for BMC .
*/
dev_err ( dev , " NIOS_INIT_DONE OK, but err on retimer init \n " ) ;
}
dev_err ( nn - > dev , " PKVL_A_MODE_STS 0x%x \n " , state_a ) ;
dev_err ( nn - > dev , " PKVL_B_MODE_STS 0x%x \n " , state_b ) ;
return ret ;
}
static struct spi_board_info m10_n3000_info = {
. modalias = " m10-n3000 " ,
. max_speed_hz = 12500000 ,
. bus_num = 0 ,
. chip_select = 0 ,
} ;
static int create_altera_spi_controller ( struct n3000_nios * nn )
{
struct altera_spi_platform_data pdata = { 0 } ;
struct platform_device_info pdevinfo = { 0 } ;
void __iomem * base = nn - > base ;
u64 v ;
v = readq ( base + N3000_NS_PARAM ) ;
pdata . mode_bits = SPI_CS_HIGH ;
if ( FIELD_GET ( N3000_NS_PARAM_CLK_POL , v ) )
pdata . mode_bits | = SPI_CPOL ;
if ( FIELD_GET ( N3000_NS_PARAM_CLK_PHASE , v ) )
pdata . mode_bits | = SPI_CPHA ;
pdata . num_chipselect = FIELD_GET ( N3000_NS_PARAM_NUM_CS , v ) ;
pdata . bits_per_word_mask =
SPI_BPW_RANGE_MASK ( 1 , FIELD_GET ( N3000_NS_PARAM_DATA_WIDTH , v ) ) ;
pdata . num_devices = 1 ;
pdata . devices = & m10_n3000_info ;
dev_dbg ( nn - > dev , " %s cs %u bpm 0x%x mode 0x%x \n " , __func__ ,
pdata . num_chipselect , pdata . bits_per_word_mask ,
pdata . mode_bits ) ;
pdevinfo . name = " subdev_spi_altera " ;
pdevinfo . id = PLATFORM_DEVID_AUTO ;
pdevinfo . parent = nn - > dev ;
pdevinfo . data = & pdata ;
pdevinfo . size_data = sizeof ( pdata ) ;
nn - > altera_spi = platform_device_register_full ( & pdevinfo ) ;
return PTR_ERR_OR_ZERO ( nn - > altera_spi ) ;
}
static void destroy_altera_spi_controller ( struct n3000_nios * nn )
{
platform_device_unregister ( nn - > altera_spi ) ;
}
static int n3000_nios_poll_stat_timeout ( void __iomem * base , u64 * v )
{
int loops ;
/*
* We don ' t use the time based timeout here for performance .
*
* The regbus read / write is on the critical path of Intel PAC N3000
2021-05-19 19:30:56 +03:00
* image programming . The time based timeout checking will add too much
2021-01-07 07:37:13 +03:00
* overhead on it . Usually the state changes in 1 or 2 loops on the
* test server , and we set 10000 times loop here for safety .
*/
for ( loops = N3000_NIOS_REGBUS_RETRY_COUNT ; loops > 0 ; loops - - ) {
* v = readq ( base + N3000_NS_STAT ) ;
if ( * v & N3000_NS_STAT_RW_VAL )
break ;
cpu_relax ( ) ;
}
return ( loops > 0 ) ? 0 : - ETIMEDOUT ;
}
static int n3000_nios_reg_write ( void * context , unsigned int reg , unsigned int val )
{
struct n3000_nios * nn = context ;
u64 v ;
int ret ;
v = FIELD_PREP ( N3000_NS_CTRL_CMD_MSK , N3000_NS_CTRL_CMD_WR ) |
FIELD_PREP ( N3000_NS_CTRL_ADDR , reg ) |
FIELD_PREP ( N3000_NS_CTRL_WR_DATA , val ) ;
writeq ( v , nn - > base + N3000_NS_CTRL ) ;
ret = n3000_nios_poll_stat_timeout ( nn - > base , & v ) ;
if ( ret )
dev_err ( nn - > dev , " fail to write reg 0x%x val 0x%x: %d \n " ,
reg , val , ret ) ;
return ret ;
}
static int n3000_nios_reg_read ( void * context , unsigned int reg , unsigned int * val )
{
struct n3000_nios * nn = context ;
u64 v ;
int ret ;
v = FIELD_PREP ( N3000_NS_CTRL_CMD_MSK , N3000_NS_CTRL_CMD_RD ) |
FIELD_PREP ( N3000_NS_CTRL_ADDR , reg ) ;
writeq ( v , nn - > base + N3000_NS_CTRL ) ;
ret = n3000_nios_poll_stat_timeout ( nn - > base , & v ) ;
if ( ret )
dev_err ( nn - > dev , " fail to read reg 0x%x: %d \n " , reg , ret ) ;
else
* val = FIELD_GET ( N3000_NS_STAT_RD_DATA , v ) ;
return ret ;
}
static const struct regmap_config n3000_nios_regbus_cfg = {
. reg_bits = 32 ,
. reg_stride = 4 ,
. val_bits = 32 ,
. fast_io = true ,
. reg_write = n3000_nios_reg_write ,
. reg_read = n3000_nios_reg_read ,
} ;
static int n3000_nios_probe ( struct dfl_device * ddev )
{
struct device * dev = & ddev - > dev ;
struct n3000_nios * nn ;
int ret ;
nn = devm_kzalloc ( dev , sizeof ( * nn ) , GFP_KERNEL ) ;
if ( ! nn )
return - ENOMEM ;
dev_set_drvdata ( & ddev - > dev , nn ) ;
nn - > dev = dev ;
nn - > base = devm_ioremap_resource ( & ddev - > dev , & ddev - > mmio_res ) ;
if ( IS_ERR ( nn - > base ) )
return PTR_ERR ( nn - > base ) ;
nn - > regmap = devm_regmap_init ( dev , NULL , nn , & n3000_nios_regbus_cfg ) ;
if ( IS_ERR ( nn - > regmap ) )
return PTR_ERR ( nn - > regmap ) ;
ret = n3000_nios_init_done_check ( nn ) ;
if ( ret )
return ret ;
ret = create_altera_spi_controller ( nn ) ;
if ( ret )
dev_err ( dev , " altera spi controller create failed: %d \n " , ret ) ;
return ret ;
}
static void n3000_nios_remove ( struct dfl_device * ddev )
{
struct n3000_nios * nn = dev_get_drvdata ( & ddev - > dev ) ;
destroy_altera_spi_controller ( nn ) ;
}
# define FME_FEATURE_ID_N3000_NIOS 0xd
static const struct dfl_device_id n3000_nios_ids [ ] = {
{ FME_ID , FME_FEATURE_ID_N3000_NIOS } ,
{ }
} ;
MODULE_DEVICE_TABLE ( dfl , n3000_nios_ids ) ;
static struct dfl_driver n3000_nios_driver = {
. drv = {
. name = " dfl-n3000-nios " ,
. dev_groups = n3000_nios_groups ,
} ,
. id_table = n3000_nios_ids ,
. probe = n3000_nios_probe ,
. remove = n3000_nios_remove ,
} ;
module_dfl_driver ( n3000_nios_driver ) ;
MODULE_DESCRIPTION ( " Driver for Nios private feature on Intel PAC N3000 " ) ;
MODULE_AUTHOR ( " Intel Corporation " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;