2019-10-14 11:49:21 -07:00
// SPDX-License-Identifier: GPL-2.0
/*
* FXOS8700 - NXP IMU ( accelerometer plus magnetometer )
*
* IIO core driver for FXOS8700 , with support for I2C / SPI busses
*
* TODO : Buffer , trigger , and IRQ support
*/
# include <linux/module.h>
# include <linux/regmap.h>
# include <linux/acpi.h>
# include <linux/bitops.h>
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# include "fxos8700.h"
/* Register Definitions */
# define FXOS8700_STATUS 0x00
# define FXOS8700_OUT_X_MSB 0x01
# define FXOS8700_OUT_X_LSB 0x02
# define FXOS8700_OUT_Y_MSB 0x03
# define FXOS8700_OUT_Y_LSB 0x04
# define FXOS8700_OUT_Z_MSB 0x05
# define FXOS8700_OUT_Z_LSB 0x06
# define FXOS8700_F_SETUP 0x09
# define FXOS8700_TRIG_CFG 0x0a
# define FXOS8700_SYSMOD 0x0b
# define FXOS8700_INT_SOURCE 0x0c
# define FXOS8700_WHO_AM_I 0x0d
# define FXOS8700_XYZ_DATA_CFG 0x0e
# define FXOS8700_HP_FILTER_CUTOFF 0x0f
# define FXOS8700_PL_STATUS 0x10
# define FXOS8700_PL_CFG 0x11
# define FXOS8700_PL_COUNT 0x12
# define FXOS8700_PL_BF_ZCOMP 0x13
# define FXOS8700_PL_THS_REG 0x14
# define FXOS8700_A_FFMT_CFG 0x15
# define FXOS8700_A_FFMT_SRC 0x16
# define FXOS8700_A_FFMT_THS 0x17
# define FXOS8700_A_FFMT_COUNT 0x18
# define FXOS8700_TRANSIENT_CFG 0x1d
# define FXOS8700_TRANSIENT_SRC 0x1e
# define FXOS8700_TRANSIENT_THS 0x1f
# define FXOS8700_TRANSIENT_COUNT 0x20
# define FXOS8700_PULSE_CFG 0x21
# define FXOS8700_PULSE_SRC 0x22
# define FXOS8700_PULSE_THSX 0x23
# define FXOS8700_PULSE_THSY 0x24
# define FXOS8700_PULSE_THSZ 0x25
# define FXOS8700_PULSE_TMLT 0x26
# define FXOS8700_PULSE_LTCY 0x27
# define FXOS8700_PULSE_WIND 0x28
# define FXOS8700_ASLP_COUNT 0x29
# define FXOS8700_CTRL_REG1 0x2a
# define FXOS8700_CTRL_REG2 0x2b
# define FXOS8700_CTRL_REG3 0x2c
# define FXOS8700_CTRL_REG4 0x2d
# define FXOS8700_CTRL_REG5 0x2e
# define FXOS8700_OFF_X 0x2f
# define FXOS8700_OFF_Y 0x30
# define FXOS8700_OFF_Z 0x31
# define FXOS8700_M_DR_STATUS 0x32
# define FXOS8700_M_OUT_X_MSB 0x33
# define FXOS8700_M_OUT_X_LSB 0x34
# define FXOS8700_M_OUT_Y_MSB 0x35
# define FXOS8700_M_OUT_Y_LSB 0x36
# define FXOS8700_M_OUT_Z_MSB 0x37
# define FXOS8700_M_OUT_Z_LSB 0x38
# define FXOS8700_CMP_X_MSB 0x39
# define FXOS8700_CMP_X_LSB 0x3a
# define FXOS8700_CMP_Y_MSB 0x3b
# define FXOS8700_CMP_Y_LSB 0x3c
# define FXOS8700_CMP_Z_MSB 0x3d
# define FXOS8700_CMP_Z_LSB 0x3e
# define FXOS8700_M_OFF_X_MSB 0x3f
# define FXOS8700_M_OFF_X_LSB 0x40
# define FXOS8700_M_OFF_Y_MSB 0x41
# define FXOS8700_M_OFF_Y_LSB 0x42
# define FXOS8700_M_OFF_Z_MSB 0x43
# define FXOS8700_M_OFF_Z_LSB 0x44
# define FXOS8700_MAX_X_MSB 0x45
# define FXOS8700_MAX_X_LSB 0x46
# define FXOS8700_MAX_Y_MSB 0x47
# define FXOS8700_MAX_Y_LSB 0x48
# define FXOS8700_MAX_Z_MSB 0x49
# define FXOS8700_MAX_Z_LSB 0x4a
# define FXOS8700_MIN_X_MSB 0x4b
# define FXOS8700_MIN_X_LSB 0x4c
# define FXOS8700_MIN_Y_MSB 0x4d
# define FXOS8700_MIN_Y_LSB 0x4e
# define FXOS8700_MIN_Z_MSB 0x4f
# define FXOS8700_MIN_Z_LSB 0x50
# define FXOS8700_TEMP 0x51
# define FXOS8700_M_THS_CFG 0x52
# define FXOS8700_M_THS_SRC 0x53
# define FXOS8700_M_THS_X_MSB 0x54
# define FXOS8700_M_THS_X_LSB 0x55
# define FXOS8700_M_THS_Y_MSB 0x56
# define FXOS8700_M_THS_Y_LSB 0x57
# define FXOS8700_M_THS_Z_MSB 0x58
# define FXOS8700_M_THS_Z_LSB 0x59
# define FXOS8700_M_THS_COUNT 0x5a
# define FXOS8700_M_CTRL_REG1 0x5b
# define FXOS8700_M_CTRL_REG2 0x5c
# define FXOS8700_M_CTRL_REG3 0x5d
# define FXOS8700_M_INT_SRC 0x5e
# define FXOS8700_A_VECM_CFG 0x5f
# define FXOS8700_A_VECM_THS_MSB 0x60
# define FXOS8700_A_VECM_THS_LSB 0x61
# define FXOS8700_A_VECM_CNT 0x62
# define FXOS8700_A_VECM_INITX_MSB 0x63
# define FXOS8700_A_VECM_INITX_LSB 0x64
# define FXOS8700_A_VECM_INITY_MSB 0x65
# define FXOS8700_A_VECM_INITY_LSB 0x66
# define FXOS8700_A_VECM_INITZ_MSB 0x67
# define FXOS8700_A_VECM_INITZ_LSB 0x68
# define FXOS8700_M_VECM_CFG 0x69
# define FXOS8700_M_VECM_THS_MSB 0x6a
# define FXOS8700_M_VECM_THS_LSB 0x6b
# define FXOS8700_M_VECM_CNT 0x6c
# define FXOS8700_M_VECM_INITX_MSB 0x6d
# define FXOS8700_M_VECM_INITX_LSB 0x6e
# define FXOS8700_M_VECM_INITY_MSB 0x6f
# define FXOS8700_M_VECM_INITY_LSB 0x70
# define FXOS8700_M_VECM_INITZ_MSB 0x71
# define FXOS8700_M_VECM_INITZ_LSB 0x72
# define FXOS8700_A_FFMT_THS_X_MSB 0x73
# define FXOS8700_A_FFMT_THS_X_LSB 0x74
# define FXOS8700_A_FFMT_THS_Y_MSB 0x75
# define FXOS8700_A_FFMT_THS_Y_LSB 0x76
# define FXOS8700_A_FFMT_THS_Z_MSB 0x77
# define FXOS8700_A_FFMT_THS_Z_LSB 0x78
# define FXOS8700_A_TRAN_INIT_MSB 0x79
# define FXOS8700_A_TRAN_INIT_LSB_X 0x7a
# define FXOS8700_A_TRAN_INIT_LSB_Y 0x7b
# define FXOS8700_A_TRAN_INIT_LSB_Z 0x7d
# define FXOS8700_TM_NVM_LOCK 0x7e
# define FXOS8700_NVM_DATA0_35 0x80
# define FXOS8700_NVM_DATA_BNK3 0xa4
# define FXOS8700_NVM_DATA_BNK2 0xa5
# define FXOS8700_NVM_DATA_BNK1 0xa6
# define FXOS8700_NVM_DATA_BNK0 0xa7
/* Bit definitions for FXOS8700_CTRL_REG1 */
# define FXOS8700_CTRL_ODR_MSK 0x38
# define FXOS8700_CTRL_ODR_MAX 0x00
# define FXOS8700_CTRL_ODR_MIN GENMASK(4, 3)
/* Bit definitions for FXOS8700_M_CTRL_REG1 */
# define FXOS8700_HMS_MASK GENMASK(1, 0)
# define FXOS8700_OS_MASK GENMASK(4, 2)
/* Bit definitions for FXOS8700_M_CTRL_REG2 */
# define FXOS8700_MAXMIN_RST BIT(2)
# define FXOS8700_MAXMIN_DIS_THS BIT(3)
# define FXOS8700_MAXMIN_DIS BIT(4)
# define FXOS8700_ACTIVE 0x01
# define FXOS8700_ACTIVE_MIN_USLEEP 4000 /* from table 6 in datasheet */
# define FXOS8700_DEVICE_ID 0xC7
# define FXOS8700_PRE_DEVICE_ID 0xC4
# define FXOS8700_DATA_BUF_SIZE 3
struct fxos8700_data {
struct regmap * regmap ;
struct iio_trigger * trig ;
2022-05-08 18:56:56 +01:00
__be16 buf [ FXOS8700_DATA_BUF_SIZE ] __aligned ( IIO_DMA_MINALIGN ) ;
2019-10-14 11:49:21 -07:00
} ;
/* Regmap info */
static const struct regmap_range read_range [ ] = {
{
. range_min = FXOS8700_STATUS ,
. range_max = FXOS8700_A_FFMT_COUNT ,
} , {
. range_min = FXOS8700_TRANSIENT_CFG ,
. range_max = FXOS8700_A_FFMT_THS_Z_LSB ,
} ,
} ;
static const struct regmap_range write_range [ ] = {
{
. range_min = FXOS8700_F_SETUP ,
. range_max = FXOS8700_TRIG_CFG ,
} , {
. range_min = FXOS8700_XYZ_DATA_CFG ,
. range_max = FXOS8700_HP_FILTER_CUTOFF ,
} , {
. range_min = FXOS8700_PL_CFG ,
. range_max = FXOS8700_A_FFMT_CFG ,
} , {
. range_min = FXOS8700_A_FFMT_THS ,
. range_max = FXOS8700_TRANSIENT_CFG ,
} , {
. range_min = FXOS8700_TRANSIENT_THS ,
. range_max = FXOS8700_PULSE_CFG ,
} , {
. range_min = FXOS8700_PULSE_THSX ,
. range_max = FXOS8700_OFF_Z ,
} , {
. range_min = FXOS8700_M_OFF_X_MSB ,
. range_max = FXOS8700_M_OFF_Z_LSB ,
} , {
. range_min = FXOS8700_M_THS_CFG ,
. range_max = FXOS8700_M_THS_CFG ,
} , {
. range_min = FXOS8700_M_THS_X_MSB ,
. range_max = FXOS8700_M_CTRL_REG3 ,
} , {
. range_min = FXOS8700_A_VECM_CFG ,
. range_max = FXOS8700_A_FFMT_THS_Z_LSB ,
} ,
} ;
static const struct regmap_access_table driver_read_table = {
. yes_ranges = read_range ,
. n_yes_ranges = ARRAY_SIZE ( read_range ) ,
} ;
static const struct regmap_access_table driver_write_table = {
. yes_ranges = write_range ,
. n_yes_ranges = ARRAY_SIZE ( write_range ) ,
} ;
const struct regmap_config fxos8700_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = FXOS8700_NVM_DATA_BNK0 ,
. rd_table = & driver_read_table ,
. wr_table = & driver_write_table ,
} ;
EXPORT_SYMBOL ( fxos8700_regmap_config ) ;
# define FXOS8700_CHANNEL(_type, _axis) { \
. type = _type , \
. modified = 1 , \
. channel2 = IIO_MOD_ # # _axis , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) | \
BIT ( IIO_CHAN_INFO_SAMP_FREQ ) , \
}
enum fxos8700_accel_scale_bits {
MODE_2G = 0 ,
MODE_4G ,
MODE_8G ,
} ;
/* scan indexes follow DATA register order */
enum fxos8700_scan_axis {
FXOS8700_SCAN_ACCEL_X = 0 ,
FXOS8700_SCAN_ACCEL_Y ,
FXOS8700_SCAN_ACCEL_Z ,
FXOS8700_SCAN_MAGN_X ,
FXOS8700_SCAN_MAGN_Y ,
FXOS8700_SCAN_MAGN_Z ,
FXOS8700_SCAN_RHALL ,
FXOS8700_SCAN_TIMESTAMP ,
} ;
enum fxos8700_sensor {
FXOS8700_ACCEL = 0 ,
FXOS8700_MAGN ,
FXOS8700_NUM_SENSORS /* must be last */
} ;
enum fxos8700_int_pin {
FXOS8700_PIN_INT1 ,
FXOS8700_PIN_INT2
} ;
struct fxos8700_scale {
u8 bits ;
int uscale ;
} ;
struct fxos8700_odr {
u8 bits ;
int odr ;
int uodr ;
} ;
static const struct fxos8700_scale fxos8700_accel_scale [ ] = {
{ MODE_2G , 244 } ,
{ MODE_4G , 488 } ,
{ MODE_8G , 976 } ,
} ;
/*
* Accellerometer and magnetometer have the same ODR options , set in the
* CTRL_REG1 register . ODR is halved when using both sensors at once in
* hybrid mode .
*/
static const struct fxos8700_odr fxos8700_odr [ ] = {
{ 0x00 , 800 , 0 } ,
{ 0x01 , 400 , 0 } ,
{ 0x02 , 200 , 0 } ,
{ 0x03 , 100 , 0 } ,
{ 0x04 , 50 , 0 } ,
{ 0x05 , 12 , 500000 } ,
{ 0x06 , 6 , 250000 } ,
{ 0x07 , 1 , 562500 } ,
} ;
static const struct iio_chan_spec fxos8700_channels [ ] = {
FXOS8700_CHANNEL ( IIO_ACCEL , X ) ,
FXOS8700_CHANNEL ( IIO_ACCEL , Y ) ,
FXOS8700_CHANNEL ( IIO_ACCEL , Z ) ,
FXOS8700_CHANNEL ( IIO_MAGN , X ) ,
FXOS8700_CHANNEL ( IIO_MAGN , Y ) ,
FXOS8700_CHANNEL ( IIO_MAGN , Z ) ,
IIO_CHAN_SOFT_TIMESTAMP ( FXOS8700_SCAN_TIMESTAMP ) ,
} ;
static enum fxos8700_sensor fxos8700_to_sensor ( enum iio_chan_type iio_type )
{
switch ( iio_type ) {
case IIO_ACCEL :
return FXOS8700_ACCEL ;
case IIO_ANGL_VEL :
return FXOS8700_MAGN ;
default :
return - EINVAL ;
}
}
static int fxos8700_set_active_mode ( struct fxos8700_data * data ,
enum fxos8700_sensor t , bool mode )
{
int ret ;
ret = regmap_write ( data - > regmap , FXOS8700_CTRL_REG1 , mode ) ;
if ( ret )
return ret ;
usleep_range ( FXOS8700_ACTIVE_MIN_USLEEP ,
FXOS8700_ACTIVE_MIN_USLEEP + 1000 ) ;
return 0 ;
}
static int fxos8700_set_scale ( struct fxos8700_data * data ,
enum fxos8700_sensor t , int uscale )
{
int i ;
static const int scale_num = ARRAY_SIZE ( fxos8700_accel_scale ) ;
struct device * dev = regmap_get_device ( data - > regmap ) ;
if ( t = = FXOS8700_MAGN ) {
dev_err ( dev , " Magnetometer scale is locked at 1200uT \n " ) ;
return - EINVAL ;
}
for ( i = 0 ; i < scale_num ; i + + )
if ( fxos8700_accel_scale [ i ] . uscale = = uscale )
break ;
if ( i = = scale_num )
return - EINVAL ;
return regmap_write ( data - > regmap , FXOS8700_XYZ_DATA_CFG ,
fxos8700_accel_scale [ i ] . bits ) ;
}
static int fxos8700_get_scale ( struct fxos8700_data * data ,
enum fxos8700_sensor t , int * uscale )
{
int i , ret , val ;
static const int scale_num = ARRAY_SIZE ( fxos8700_accel_scale ) ;
if ( t = = FXOS8700_MAGN ) {
* uscale = 1200 ; /* Magnetometer is locked at 1200uT */
return 0 ;
}
ret = regmap_read ( data - > regmap , FXOS8700_XYZ_DATA_CFG , & val ) ;
if ( ret )
return ret ;
for ( i = 0 ; i < scale_num ; i + + ) {
if ( fxos8700_accel_scale [ i ] . bits = = ( val & 0x3 ) ) {
* uscale = fxos8700_accel_scale [ i ] . uscale ;
return 0 ;
}
}
return - EINVAL ;
}
static int fxos8700_get_data ( struct fxos8700_data * data , int chan_type ,
int axis , int * val )
{
u8 base , reg ;
int ret ;
enum fxos8700_sensor type = fxos8700_to_sensor ( chan_type ) ;
base = type ? FXOS8700_OUT_X_MSB : FXOS8700_M_OUT_X_MSB ;
/* Block read 6 bytes of device output registers to avoid data loss */
ret = regmap_bulk_read ( data - > regmap , base , data - > buf ,
FXOS8700_DATA_BUF_SIZE ) ;
if ( ret )
return ret ;
/* Convert axis to buffer index */
reg = axis - IIO_MOD_X ;
/* Convert to native endianness */
* val = sign_extend32 ( be16_to_cpu ( data - > buf [ reg ] ) , 15 ) ;
return 0 ;
}
static int fxos8700_set_odr ( struct fxos8700_data * data , enum fxos8700_sensor t ,
int odr , int uodr )
{
int i , ret , val ;
bool active_mode ;
static const int odr_num = ARRAY_SIZE ( fxos8700_odr ) ;
ret = regmap_read ( data - > regmap , FXOS8700_CTRL_REG1 , & val ) ;
if ( ret )
return ret ;
active_mode = val & FXOS8700_ACTIVE ;
if ( active_mode ) {
/*
* The device must be in standby mode to change any of the
* other fields within CTRL_REG1
*/
ret = regmap_write ( data - > regmap , FXOS8700_CTRL_REG1 ,
val & ~ FXOS8700_ACTIVE ) ;
if ( ret )
return ret ;
}
for ( i = 0 ; i < odr_num ; i + + )
if ( fxos8700_odr [ i ] . odr = = odr & & fxos8700_odr [ i ] . uodr = = uodr )
break ;
if ( i > = odr_num )
return - EINVAL ;
return regmap_update_bits ( data - > regmap ,
FXOS8700_CTRL_REG1 ,
FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE ,
fxos8700_odr [ i ] . bits < < 3 | active_mode ) ;
}
static int fxos8700_get_odr ( struct fxos8700_data * data , enum fxos8700_sensor t ,
int * odr , int * uodr )
{
int i , val , ret ;
static const int odr_num = ARRAY_SIZE ( fxos8700_odr ) ;
ret = regmap_read ( data - > regmap , FXOS8700_CTRL_REG1 , & val ) ;
if ( ret )
return ret ;
val & = FXOS8700_CTRL_ODR_MSK ;
for ( i = 0 ; i < odr_num ; i + + )
if ( val = = fxos8700_odr [ i ] . bits )
break ;
if ( i > = odr_num )
return - EINVAL ;
* odr = fxos8700_odr [ i ] . odr ;
* uodr = fxos8700_odr [ i ] . uodr ;
return 0 ;
}
static int fxos8700_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val , int * val2 , long mask )
{
int ret ;
struct fxos8700_data * data = iio_priv ( indio_dev ) ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
ret = fxos8700_get_data ( data , chan - > type , chan - > channel2 , val ) ;
if ( ret )
return ret ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
* val = 0 ;
ret = fxos8700_get_scale ( data , fxos8700_to_sensor ( chan - > type ) ,
val2 ) ;
return ret ? ret : IIO_VAL_INT_PLUS_MICRO ;
case IIO_CHAN_INFO_SAMP_FREQ :
ret = fxos8700_get_odr ( data , fxos8700_to_sensor ( chan - > type ) ,
val , val2 ) ;
return ret ? ret : IIO_VAL_INT_PLUS_MICRO ;
default :
return - EINVAL ;
}
}
static int fxos8700_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int val , int val2 , long mask )
{
struct fxos8700_data * data = iio_priv ( indio_dev ) ;
switch ( mask ) {
case IIO_CHAN_INFO_SCALE :
return fxos8700_set_scale ( data , fxos8700_to_sensor ( chan - > type ) ,
val2 ) ;
case IIO_CHAN_INFO_SAMP_FREQ :
return fxos8700_set_odr ( data , fxos8700_to_sensor ( chan - > type ) ,
val , val2 ) ;
default :
return - EINVAL ;
}
}
static IIO_CONST_ATTR ( in_accel_sampling_frequency_available ,
" 1.5625 6.25 12.5 50 100 200 400 800 " ) ;
static IIO_CONST_ATTR ( in_magn_sampling_frequency_available ,
" 1.5625 6.25 12.5 50 100 200 400 800 " ) ;
static IIO_CONST_ATTR ( in_accel_scale_available , " 0.000244 0.000488 0.000976 " ) ;
static IIO_CONST_ATTR ( in_magn_scale_available , " 0.000001200 " ) ;
static struct attribute * fxos8700_attrs [ ] = {
& iio_const_attr_in_accel_sampling_frequency_available . dev_attr . attr ,
& iio_const_attr_in_magn_sampling_frequency_available . dev_attr . attr ,
& iio_const_attr_in_accel_scale_available . dev_attr . attr ,
& iio_const_attr_in_magn_scale_available . dev_attr . attr ,
NULL ,
} ;
static const struct attribute_group fxos8700_attrs_group = {
. attrs = fxos8700_attrs ,
} ;
static const struct iio_info fxos8700_info = {
. read_raw = fxos8700_read_raw ,
. write_raw = fxos8700_write_raw ,
. attrs = & fxos8700_attrs_group ,
} ;
static int fxos8700_chip_init ( struct fxos8700_data * data , bool use_spi )
{
int ret ;
unsigned int val ;
struct device * dev = regmap_get_device ( data - > regmap ) ;
ret = regmap_read ( data - > regmap , FXOS8700_WHO_AM_I , & val ) ;
if ( ret ) {
dev_err ( dev , " Error reading chip id \n " ) ;
return ret ;
}
if ( val ! = FXOS8700_DEVICE_ID & & val ! = FXOS8700_PRE_DEVICE_ID ) {
dev_err ( dev , " Wrong chip id, got %x expected %x or %x \n " ,
val , FXOS8700_DEVICE_ID , FXOS8700_PRE_DEVICE_ID ) ;
return - ENODEV ;
}
ret = fxos8700_set_active_mode ( data , FXOS8700_ACCEL , true ) ;
if ( ret )
return ret ;
ret = fxos8700_set_active_mode ( data , FXOS8700_MAGN , true ) ;
if ( ret )
return ret ;
/*
* The device must be in standby mode to change any of the other fields
* within CTRL_REG1
*/
ret = regmap_write ( data - > regmap , FXOS8700_CTRL_REG1 , 0x00 ) ;
if ( ret )
return ret ;
/* Set max oversample ratio (OSR) and both devices active */
ret = regmap_write ( data - > regmap , FXOS8700_M_CTRL_REG1 ,
FXOS8700_HMS_MASK | FXOS8700_OS_MASK ) ;
if ( ret )
return ret ;
/* Disable and rst min/max measurements & threshold */
ret = regmap_write ( data - > regmap , FXOS8700_M_CTRL_REG2 ,
FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |
FXOS8700_MAXMIN_DIS ) ;
if ( ret )
return ret ;
/* Max ODR (800Hz individual or 400Hz hybrid), active mode */
ret = regmap_write ( data - > regmap , FXOS8700_CTRL_REG1 ,
FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE ) ;
if ( ret )
return ret ;
/* Set for max full-scale range (+/-8G) */
return regmap_write ( data - > regmap , FXOS8700_XYZ_DATA_CFG , MODE_8G ) ;
}
static void fxos8700_chip_uninit ( void * data )
{
struct fxos8700_data * fxos8700_data = data ;
fxos8700_set_active_mode ( fxos8700_data , FXOS8700_ACCEL , false ) ;
fxos8700_set_active_mode ( fxos8700_data , FXOS8700_MAGN , false ) ;
}
int fxos8700_core_probe ( struct device * dev , struct regmap * regmap ,
const char * name , bool use_spi )
{
struct iio_dev * indio_dev ;
struct fxos8700_data * data ;
int ret ;
indio_dev = devm_iio_device_alloc ( dev , sizeof ( * data ) ) ;
if ( ! indio_dev )
return - ENOMEM ;
data = iio_priv ( indio_dev ) ;
dev_set_drvdata ( dev , indio_dev ) ;
data - > regmap = regmap ;
ret = fxos8700_chip_init ( data , use_spi ) ;
if ( ret )
return ret ;
ret = devm_add_action_or_reset ( dev , fxos8700_chip_uninit , data ) ;
if ( ret )
return ret ;
indio_dev - > channels = fxos8700_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( fxos8700_channels ) ;
indio_dev - > name = name ? name : " fxos8700 " ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > info = & fxos8700_info ;
return devm_iio_device_register ( dev , indio_dev ) ;
}
EXPORT_SYMBOL_GPL ( fxos8700_core_probe ) ;
MODULE_AUTHOR ( " Robert Jones <rjones@gateworks.com> " ) ;
MODULE_DESCRIPTION ( " FXOS8700 6-Axis Acc and Mag Combo Sensor driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;