2019-05-29 17:18:02 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-07-27 00:23:48 +03:00
/*
* IIO driver for the 3 - axis accelerometer Domintech DMARD09 .
*
* Copyright ( c ) 2016 , Jelle van der Waa < jelle @ vdwaa . nl >
*/
# include <asm/unaligned.h>
# include <linux/module.h>
# include <linux/i2c.h>
# include <linux/iio/iio.h>
# define DMARD09_DRV_NAME "dmard09"
# define DMARD09_REG_CHIPID 0x18
# define DMARD09_REG_STAT 0x0A
# define DMARD09_REG_X 0x0C
# define DMARD09_REG_Y 0x0E
# define DMARD09_REG_Z 0x10
# define DMARD09_CHIPID 0x95
# define DMARD09_BUF_LEN 8
# define DMARD09_AXIS_X 0
# define DMARD09_AXIS_Y 1
# define DMARD09_AXIS_Z 2
# define DMARD09_AXIS_X_OFFSET ((DMARD09_AXIS_X + 1) * 2)
2022-03-29 00:48:16 +03:00
# define DMARD09_AXIS_Y_OFFSET ((DMARD09_AXIS_Y + 1) * 2)
2016-07-27 00:23:48 +03:00
# define DMARD09_AXIS_Z_OFFSET ((DMARD09_AXIS_Z + 1) * 2)
struct dmard09_data {
struct i2c_client * client ;
} ;
# define DMARD09_CHANNEL(_axis, offset) { \
. type = IIO_ACCEL , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) , \
. modified = 1 , \
. address = offset , \
. channel2 = IIO_MOD_ # # _axis , \
}
static const struct iio_chan_spec dmard09_channels [ ] = {
DMARD09_CHANNEL ( X , DMARD09_AXIS_X_OFFSET ) ,
DMARD09_CHANNEL ( Y , DMARD09_AXIS_Y_OFFSET ) ,
DMARD09_CHANNEL ( Z , DMARD09_AXIS_Z_OFFSET ) ,
} ;
static int dmard09_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val , int * val2 , long mask )
{
struct dmard09_data * data = iio_priv ( indio_dev ) ;
u8 buf [ DMARD09_BUF_LEN ] ;
int ret ;
s16 accel ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
/*
* Read from the DMAR09_REG_STAT register , since the chip
* caches reads from the individual X , Y , Z registers .
*/
ret = i2c_smbus_read_i2c_block_data ( data - > client ,
DMARD09_REG_STAT ,
DMARD09_BUF_LEN , buf ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg %d \n " ,
DMARD09_REG_STAT ) ;
return ret ;
}
accel = get_unaligned_le16 ( & buf [ chan - > address ] ) ;
/* Remove lower 3 bits and sign extend */
accel < < = 4 ;
accel > > = 7 ;
* val = accel ;
return IIO_VAL_INT ;
default :
return - EINVAL ;
}
}
static const struct iio_info dmard09_info = {
. read_raw = dmard09_read_raw ,
} ;
2022-10-23 16:22:47 +03:00
static int dmard09_probe ( struct i2c_client * client )
2016-07-27 00:23:48 +03:00
{
int ret ;
struct iio_dev * indio_dev ;
struct dmard09_data * data ;
indio_dev = devm_iio_device_alloc ( & client - > dev , sizeof ( * data ) ) ;
if ( ! indio_dev ) {
dev_err ( & client - > dev , " iio allocation failed \n " ) ;
return - ENOMEM ;
}
data = iio_priv ( indio_dev ) ;
data - > client = client ;
ret = i2c_smbus_read_byte_data ( data - > client , DMARD09_REG_CHIPID ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " Error reading chip id %d \n " , ret ) ;
return ret ;
}
if ( ret ! = DMARD09_CHIPID ) {
dev_err ( & client - > dev , " Invalid chip id %d \n " , ret ) ;
return - ENODEV ;
}
i2c_set_clientdata ( client , indio_dev ) ;
indio_dev - > name = DMARD09_DRV_NAME ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > channels = dmard09_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( dmard09_channels ) ;
indio_dev - > info = & dmard09_info ;
return devm_iio_device_register ( & client - > dev , indio_dev ) ;
}
static const struct i2c_device_id dmard09_id [ ] = {
2021-12-30 20:49:11 +03:00
{ " dmard09 " , 0 } ,
2016-07-27 00:23:48 +03:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , dmard09_id ) ;
static struct i2c_driver dmard09_driver = {
. driver = {
. name = DMARD09_DRV_NAME
} ,
2022-10-23 16:22:47 +03:00
. probe_new = dmard09_probe ,
2016-07-27 00:23:48 +03:00
. id_table = dmard09_id ,
} ;
module_i2c_driver ( dmard09_driver ) ;
MODULE_AUTHOR ( " Jelle van der Waa <jelle@vdwaa.nl> " ) ;
MODULE_DESCRIPTION ( " DMARD09 3-axis accelerometer driver " ) ;
MODULE_LICENSE ( " GPL " ) ;