2013-01-26 03:44:00 +04:00
/*
* STMicroelectronics magnetometers driver
*
* Copyright 2012 - 2013 STMicroelectronics Inc .
*
* Denis Ciocca < denis . ciocca @ st . com >
*
* Licensed under the GPL - 2.
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/errno.h>
# include <linux/types.h>
# include <linux/mutex.h>
# include <linux/interrupt.h>
# include <linux/i2c.h>
# include <linux/gpio.h>
# include <linux/irq.h>
# include <linux/delay.h>
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# include <linux/iio/buffer.h>
# include <linux/iio/common/st_sensors.h>
# include "st_magn.h"
2013-06-03 18:58:00 +04:00
# define ST_MAGN_NUMBER_DATA_CHANNELS 3
2013-01-26 03:44:00 +04:00
/* DEFAULT VALUE FOR SENSORS */
2013-09-24 18:51:00 +04:00
# define ST_MAGN_DEFAULT_OUT_X_H_ADDR 0X03
# define ST_MAGN_DEFAULT_OUT_Y_H_ADDR 0X07
# define ST_MAGN_DEFAULT_OUT_Z_H_ADDR 0X05
2013-01-26 03:44:00 +04:00
/* FULLSCALE */
# define ST_MAGN_FS_AVL_1300MG 1300
# define ST_MAGN_FS_AVL_1900MG 1900
# define ST_MAGN_FS_AVL_2500MG 2500
# define ST_MAGN_FS_AVL_4000MG 4000
# define ST_MAGN_FS_AVL_4700MG 4700
# define ST_MAGN_FS_AVL_5600MG 5600
# define ST_MAGN_FS_AVL_8000MG 8000
# define ST_MAGN_FS_AVL_8100MG 8100
2014-10-09 16:55:00 +04:00
# define ST_MAGN_FS_AVL_12000MG 12000
# define ST_MAGN_FS_AVL_16000MG 16000
2013-01-26 03:44:00 +04:00
2015-04-30 16:15:50 +03:00
/* CUSTOM VALUES FOR SENSOR 0 */
# define ST_MAGN_0_ODR_ADDR 0x00
# define ST_MAGN_0_ODR_MASK 0x1c
# define ST_MAGN_0_ODR_AVL_1HZ_VAL 0x00
# define ST_MAGN_0_ODR_AVL_2HZ_VAL 0x01
# define ST_MAGN_0_ODR_AVL_3HZ_VAL 0x02
# define ST_MAGN_0_ODR_AVL_8HZ_VAL 0x03
# define ST_MAGN_0_ODR_AVL_15HZ_VAL 0x04
# define ST_MAGN_0_ODR_AVL_30HZ_VAL 0x05
# define ST_MAGN_0_ODR_AVL_75HZ_VAL 0x06
# define ST_MAGN_0_ODR_AVL_220HZ_VAL 0x07
# define ST_MAGN_0_PW_ADDR 0x02
# define ST_MAGN_0_PW_MASK 0x03
# define ST_MAGN_0_PW_ON 0x00
# define ST_MAGN_0_PW_OFF 0x03
# define ST_MAGN_0_FS_ADDR 0x01
# define ST_MAGN_0_FS_MASK 0xe0
# define ST_MAGN_0_FS_AVL_1300_VAL 0x01
# define ST_MAGN_0_FS_AVL_1900_VAL 0x02
# define ST_MAGN_0_FS_AVL_2500_VAL 0x03
# define ST_MAGN_0_FS_AVL_4000_VAL 0x04
# define ST_MAGN_0_FS_AVL_4700_VAL 0x05
# define ST_MAGN_0_FS_AVL_5600_VAL 0x06
# define ST_MAGN_0_FS_AVL_8100_VAL 0x07
# define ST_MAGN_0_FS_AVL_1300_GAIN_XY 1100
# define ST_MAGN_0_FS_AVL_1900_GAIN_XY 855
# define ST_MAGN_0_FS_AVL_2500_GAIN_XY 670
# define ST_MAGN_0_FS_AVL_4000_GAIN_XY 450
# define ST_MAGN_0_FS_AVL_4700_GAIN_XY 400
# define ST_MAGN_0_FS_AVL_5600_GAIN_XY 330
# define ST_MAGN_0_FS_AVL_8100_GAIN_XY 230
# define ST_MAGN_0_FS_AVL_1300_GAIN_Z 980
# define ST_MAGN_0_FS_AVL_1900_GAIN_Z 760
# define ST_MAGN_0_FS_AVL_2500_GAIN_Z 600
# define ST_MAGN_0_FS_AVL_4000_GAIN_Z 400
# define ST_MAGN_0_FS_AVL_4700_GAIN_Z 355
# define ST_MAGN_0_FS_AVL_5600_GAIN_Z 295
# define ST_MAGN_0_FS_AVL_8100_GAIN_Z 205
# define ST_MAGN_0_MULTIREAD_BIT false
2013-01-26 03:44:00 +04:00
/* CUSTOM VALUES FOR SENSOR 1 */
# define ST_MAGN_1_WAI_EXP 0x3c
# define ST_MAGN_1_ODR_ADDR 0x00
# define ST_MAGN_1_ODR_MASK 0x1c
# define ST_MAGN_1_ODR_AVL_1HZ_VAL 0x00
# define ST_MAGN_1_ODR_AVL_2HZ_VAL 0x01
# define ST_MAGN_1_ODR_AVL_3HZ_VAL 0x02
# define ST_MAGN_1_ODR_AVL_8HZ_VAL 0x03
# define ST_MAGN_1_ODR_AVL_15HZ_VAL 0x04
# define ST_MAGN_1_ODR_AVL_30HZ_VAL 0x05
# define ST_MAGN_1_ODR_AVL_75HZ_VAL 0x06
# define ST_MAGN_1_ODR_AVL_220HZ_VAL 0x07
# define ST_MAGN_1_PW_ADDR 0x02
# define ST_MAGN_1_PW_MASK 0x03
# define ST_MAGN_1_PW_ON 0x00
# define ST_MAGN_1_PW_OFF 0x03
# define ST_MAGN_1_FS_ADDR 0x01
# define ST_MAGN_1_FS_MASK 0xe0
# define ST_MAGN_1_FS_AVL_1300_VAL 0x01
# define ST_MAGN_1_FS_AVL_1900_VAL 0x02
# define ST_MAGN_1_FS_AVL_2500_VAL 0x03
# define ST_MAGN_1_FS_AVL_4000_VAL 0x04
# define ST_MAGN_1_FS_AVL_4700_VAL 0x05
# define ST_MAGN_1_FS_AVL_5600_VAL 0x06
# define ST_MAGN_1_FS_AVL_8100_VAL 0x07
2014-10-09 16:55:00 +04:00
# define ST_MAGN_1_FS_AVL_1300_GAIN_XY 909
# define ST_MAGN_1_FS_AVL_1900_GAIN_XY 1169
# define ST_MAGN_1_FS_AVL_2500_GAIN_XY 1492
# define ST_MAGN_1_FS_AVL_4000_GAIN_XY 2222
# define ST_MAGN_1_FS_AVL_4700_GAIN_XY 2500
# define ST_MAGN_1_FS_AVL_5600_GAIN_XY 3030
# define ST_MAGN_1_FS_AVL_8100_GAIN_XY 4347
# define ST_MAGN_1_FS_AVL_1300_GAIN_Z 1020
# define ST_MAGN_1_FS_AVL_1900_GAIN_Z 1315
# define ST_MAGN_1_FS_AVL_2500_GAIN_Z 1666
# define ST_MAGN_1_FS_AVL_4000_GAIN_Z 2500
# define ST_MAGN_1_FS_AVL_4700_GAIN_Z 2816
# define ST_MAGN_1_FS_AVL_5600_GAIN_Z 3389
# define ST_MAGN_1_FS_AVL_8100_GAIN_Z 4878
2013-01-26 03:44:00 +04:00
# define ST_MAGN_1_MULTIREAD_BIT false
/* CUSTOM VALUES FOR SENSOR 2 */
# define ST_MAGN_2_WAI_EXP 0x3d
# define ST_MAGN_2_ODR_ADDR 0x20
# define ST_MAGN_2_ODR_MASK 0x1c
# define ST_MAGN_2_ODR_AVL_1HZ_VAL 0x00
# define ST_MAGN_2_ODR_AVL_2HZ_VAL 0x01
# define ST_MAGN_2_ODR_AVL_3HZ_VAL 0x02
# define ST_MAGN_2_ODR_AVL_5HZ_VAL 0x03
# define ST_MAGN_2_ODR_AVL_10HZ_VAL 0x04
# define ST_MAGN_2_ODR_AVL_20HZ_VAL 0x05
# define ST_MAGN_2_ODR_AVL_40HZ_VAL 0x06
# define ST_MAGN_2_ODR_AVL_80HZ_VAL 0x07
# define ST_MAGN_2_PW_ADDR 0x22
# define ST_MAGN_2_PW_MASK 0x03
# define ST_MAGN_2_PW_ON 0x00
# define ST_MAGN_2_PW_OFF 0x03
# define ST_MAGN_2_FS_ADDR 0x21
# define ST_MAGN_2_FS_MASK 0x60
# define ST_MAGN_2_FS_AVL_4000_VAL 0x00
# define ST_MAGN_2_FS_AVL_8000_VAL 0x01
2014-10-09 16:55:00 +04:00
# define ST_MAGN_2_FS_AVL_12000_VAL 0x02
# define ST_MAGN_2_FS_AVL_16000_VAL 0x03
# define ST_MAGN_2_FS_AVL_4000_GAIN 146
# define ST_MAGN_2_FS_AVL_8000_GAIN 292
# define ST_MAGN_2_FS_AVL_12000_GAIN 438
# define ST_MAGN_2_FS_AVL_16000_GAIN 584
2013-01-26 03:44:00 +04:00
# define ST_MAGN_2_MULTIREAD_BIT false
# define ST_MAGN_2_OUT_X_L_ADDR 0x28
# define ST_MAGN_2_OUT_Y_L_ADDR 0x2a
# define ST_MAGN_2_OUT_Z_L_ADDR 0x2c
static const struct iio_chan_spec st_magn_16bit_channels [ ] = {
2013-06-03 18:58:00 +04:00
ST_SENSORS_LSM_CHANNELS ( IIO_MAGN ,
BIT ( IIO_CHAN_INFO_RAW ) | BIT ( IIO_CHAN_INFO_SCALE ) ,
2013-09-24 18:51:00 +04:00
ST_SENSORS_SCAN_X , 1 , IIO_MOD_X , ' s ' , IIO_BE , 16 , 16 ,
ST_MAGN_DEFAULT_OUT_X_H_ADDR ) ,
2013-06-03 18:58:00 +04:00
ST_SENSORS_LSM_CHANNELS ( IIO_MAGN ,
BIT ( IIO_CHAN_INFO_RAW ) | BIT ( IIO_CHAN_INFO_SCALE ) ,
2013-09-24 18:51:00 +04:00
ST_SENSORS_SCAN_Y , 1 , IIO_MOD_Y , ' s ' , IIO_BE , 16 , 16 ,
ST_MAGN_DEFAULT_OUT_Y_H_ADDR ) ,
2013-06-03 18:58:00 +04:00
ST_SENSORS_LSM_CHANNELS ( IIO_MAGN ,
BIT ( IIO_CHAN_INFO_RAW ) | BIT ( IIO_CHAN_INFO_SCALE ) ,
2013-09-24 18:51:00 +04:00
ST_SENSORS_SCAN_Z , 1 , IIO_MOD_Z , ' s ' , IIO_BE , 16 , 16 ,
ST_MAGN_DEFAULT_OUT_Z_H_ADDR ) ,
2013-01-26 03:44:00 +04:00
IIO_CHAN_SOFT_TIMESTAMP ( 3 )
} ;
static const struct iio_chan_spec st_magn_2_16bit_channels [ ] = {
2013-06-03 18:58:00 +04:00
ST_SENSORS_LSM_CHANNELS ( IIO_MAGN ,
BIT ( IIO_CHAN_INFO_RAW ) | BIT ( IIO_CHAN_INFO_SCALE ) ,
ST_SENSORS_SCAN_X , 1 , IIO_MOD_X , ' s ' , IIO_LE , 16 , 16 ,
ST_MAGN_2_OUT_X_L_ADDR ) ,
ST_SENSORS_LSM_CHANNELS ( IIO_MAGN ,
BIT ( IIO_CHAN_INFO_RAW ) | BIT ( IIO_CHAN_INFO_SCALE ) ,
ST_SENSORS_SCAN_Y , 1 , IIO_MOD_Y , ' s ' , IIO_LE , 16 , 16 ,
ST_MAGN_2_OUT_Y_L_ADDR ) ,
ST_SENSORS_LSM_CHANNELS ( IIO_MAGN ,
BIT ( IIO_CHAN_INFO_RAW ) | BIT ( IIO_CHAN_INFO_SCALE ) ,
ST_SENSORS_SCAN_Z , 1 , IIO_MOD_Z , ' s ' , IIO_LE , 16 , 16 ,
ST_MAGN_2_OUT_Z_L_ADDR ) ,
2013-01-26 03:44:00 +04:00
IIO_CHAN_SOFT_TIMESTAMP ( 3 )
} ;
2014-10-03 19:35:35 +04:00
static const struct st_sensor_settings st_magn_sensors_settings [ ] = {
2015-04-30 16:15:50 +03:00
{
. wai = 0 , /* This sensor has no valid WhoAmI report 0 */
2015-07-21 11:35:41 +03:00
. wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS ,
2015-04-30 16:15:50 +03:00
. sensors_supported = {
[ 0 ] = LSM303DLH_MAGN_DEV_NAME ,
} ,
. ch = ( struct iio_chan_spec * ) st_magn_16bit_channels ,
. odr = {
. addr = ST_MAGN_0_ODR_ADDR ,
. mask = ST_MAGN_0_ODR_MASK ,
. odr_avl = {
{ 1 , ST_MAGN_0_ODR_AVL_1HZ_VAL , } ,
{ 2 , ST_MAGN_0_ODR_AVL_2HZ_VAL , } ,
{ 3 , ST_MAGN_0_ODR_AVL_3HZ_VAL , } ,
{ 8 , ST_MAGN_0_ODR_AVL_8HZ_VAL , } ,
{ 15 , ST_MAGN_0_ODR_AVL_15HZ_VAL , } ,
{ 30 , ST_MAGN_0_ODR_AVL_30HZ_VAL , } ,
{ 75 , ST_MAGN_0_ODR_AVL_75HZ_VAL , } ,
} ,
} ,
. pw = {
. addr = ST_MAGN_0_PW_ADDR ,
. mask = ST_MAGN_0_PW_MASK ,
. value_on = ST_MAGN_0_PW_ON ,
. value_off = ST_MAGN_0_PW_OFF ,
} ,
. fs = {
. addr = ST_MAGN_0_FS_ADDR ,
. mask = ST_MAGN_0_FS_MASK ,
. fs_avl = {
[ 0 ] = {
. num = ST_MAGN_FS_AVL_1300MG ,
. value = ST_MAGN_0_FS_AVL_1300_VAL ,
. gain = ST_MAGN_0_FS_AVL_1300_GAIN_XY ,
. gain2 = ST_MAGN_0_FS_AVL_1300_GAIN_Z ,
} ,
[ 1 ] = {
. num = ST_MAGN_FS_AVL_1900MG ,
. value = ST_MAGN_0_FS_AVL_1900_VAL ,
. gain = ST_MAGN_0_FS_AVL_1900_GAIN_XY ,
. gain2 = ST_MAGN_0_FS_AVL_1900_GAIN_Z ,
} ,
[ 2 ] = {
. num = ST_MAGN_FS_AVL_2500MG ,
. value = ST_MAGN_0_FS_AVL_2500_VAL ,
. gain = ST_MAGN_0_FS_AVL_2500_GAIN_XY ,
. gain2 = ST_MAGN_0_FS_AVL_2500_GAIN_Z ,
} ,
[ 3 ] = {
. num = ST_MAGN_FS_AVL_4000MG ,
. value = ST_MAGN_0_FS_AVL_4000_VAL ,
. gain = ST_MAGN_0_FS_AVL_4000_GAIN_XY ,
. gain2 = ST_MAGN_0_FS_AVL_4000_GAIN_Z ,
} ,
[ 4 ] = {
. num = ST_MAGN_FS_AVL_4700MG ,
. value = ST_MAGN_0_FS_AVL_4700_VAL ,
. gain = ST_MAGN_0_FS_AVL_4700_GAIN_XY ,
. gain2 = ST_MAGN_0_FS_AVL_4700_GAIN_Z ,
} ,
[ 5 ] = {
. num = ST_MAGN_FS_AVL_5600MG ,
. value = ST_MAGN_0_FS_AVL_5600_VAL ,
. gain = ST_MAGN_0_FS_AVL_5600_GAIN_XY ,
. gain2 = ST_MAGN_0_FS_AVL_5600_GAIN_Z ,
} ,
[ 6 ] = {
. num = ST_MAGN_FS_AVL_8100MG ,
. value = ST_MAGN_0_FS_AVL_8100_VAL ,
. gain = ST_MAGN_0_FS_AVL_8100_GAIN_XY ,
. gain2 = ST_MAGN_0_FS_AVL_8100_GAIN_Z ,
} ,
} ,
} ,
. multi_read_bit = ST_MAGN_0_MULTIREAD_BIT ,
. bootime = 2 ,
} ,
2013-01-26 03:44:00 +04:00
{
. wai = ST_MAGN_1_WAI_EXP ,
2015-07-21 11:35:41 +03:00
. wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS ,
2013-01-26 03:44:00 +04:00
. sensors_supported = {
[ 0 ] = LSM303DLHC_MAGN_DEV_NAME ,
[ 1 ] = LSM303DLM_MAGN_DEV_NAME ,
} ,
. ch = ( struct iio_chan_spec * ) st_magn_16bit_channels ,
. odr = {
. addr = ST_MAGN_1_ODR_ADDR ,
. mask = ST_MAGN_1_ODR_MASK ,
. odr_avl = {
{ 1 , ST_MAGN_1_ODR_AVL_1HZ_VAL , } ,
{ 2 , ST_MAGN_1_ODR_AVL_2HZ_VAL , } ,
{ 3 , ST_MAGN_1_ODR_AVL_3HZ_VAL , } ,
{ 8 , ST_MAGN_1_ODR_AVL_8HZ_VAL , } ,
{ 15 , ST_MAGN_1_ODR_AVL_15HZ_VAL , } ,
{ 30 , ST_MAGN_1_ODR_AVL_30HZ_VAL , } ,
{ 75 , ST_MAGN_1_ODR_AVL_75HZ_VAL , } ,
{ 220 , ST_MAGN_1_ODR_AVL_220HZ_VAL , } ,
} ,
} ,
. pw = {
. addr = ST_MAGN_1_PW_ADDR ,
. mask = ST_MAGN_1_PW_MASK ,
. value_on = ST_MAGN_1_PW_ON ,
. value_off = ST_MAGN_1_PW_OFF ,
} ,
. fs = {
. addr = ST_MAGN_1_FS_ADDR ,
. mask = ST_MAGN_1_FS_MASK ,
. fs_avl = {
[ 0 ] = {
. num = ST_MAGN_FS_AVL_1300MG ,
. value = ST_MAGN_1_FS_AVL_1300_VAL ,
. gain = ST_MAGN_1_FS_AVL_1300_GAIN_XY ,
. gain2 = ST_MAGN_1_FS_AVL_1300_GAIN_Z ,
} ,
[ 1 ] = {
. num = ST_MAGN_FS_AVL_1900MG ,
. value = ST_MAGN_1_FS_AVL_1900_VAL ,
. gain = ST_MAGN_1_FS_AVL_1900_GAIN_XY ,
. gain2 = ST_MAGN_1_FS_AVL_1900_GAIN_Z ,
} ,
[ 2 ] = {
. num = ST_MAGN_FS_AVL_2500MG ,
. value = ST_MAGN_1_FS_AVL_2500_VAL ,
. gain = ST_MAGN_1_FS_AVL_2500_GAIN_XY ,
. gain2 = ST_MAGN_1_FS_AVL_2500_GAIN_Z ,
} ,
[ 3 ] = {
. num = ST_MAGN_FS_AVL_4000MG ,
. value = ST_MAGN_1_FS_AVL_4000_VAL ,
. gain = ST_MAGN_1_FS_AVL_4000_GAIN_XY ,
. gain2 = ST_MAGN_1_FS_AVL_4000_GAIN_Z ,
} ,
[ 4 ] = {
. num = ST_MAGN_FS_AVL_4700MG ,
. value = ST_MAGN_1_FS_AVL_4700_VAL ,
. gain = ST_MAGN_1_FS_AVL_4700_GAIN_XY ,
. gain2 = ST_MAGN_1_FS_AVL_4700_GAIN_Z ,
} ,
[ 5 ] = {
. num = ST_MAGN_FS_AVL_5600MG ,
. value = ST_MAGN_1_FS_AVL_5600_VAL ,
. gain = ST_MAGN_1_FS_AVL_5600_GAIN_XY ,
. gain2 = ST_MAGN_1_FS_AVL_5600_GAIN_Z ,
} ,
[ 6 ] = {
. num = ST_MAGN_FS_AVL_8100MG ,
. value = ST_MAGN_1_FS_AVL_8100_VAL ,
. gain = ST_MAGN_1_FS_AVL_8100_GAIN_XY ,
. gain2 = ST_MAGN_1_FS_AVL_8100_GAIN_Z ,
} ,
} ,
} ,
. multi_read_bit = ST_MAGN_1_MULTIREAD_BIT ,
. bootime = 2 ,
} ,
{
. wai = ST_MAGN_2_WAI_EXP ,
2015-07-21 11:35:41 +03:00
. wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS ,
2013-01-26 03:44:00 +04:00
. sensors_supported = {
[ 0 ] = LIS3MDL_MAGN_DEV_NAME ,
} ,
. ch = ( struct iio_chan_spec * ) st_magn_2_16bit_channels ,
. odr = {
. addr = ST_MAGN_2_ODR_ADDR ,
. mask = ST_MAGN_2_ODR_MASK ,
. odr_avl = {
{ 1 , ST_MAGN_2_ODR_AVL_1HZ_VAL , } ,
{ 2 , ST_MAGN_2_ODR_AVL_2HZ_VAL , } ,
{ 3 , ST_MAGN_2_ODR_AVL_3HZ_VAL , } ,
{ 5 , ST_MAGN_2_ODR_AVL_5HZ_VAL , } ,
{ 10 , ST_MAGN_2_ODR_AVL_10HZ_VAL , } ,
{ 20 , ST_MAGN_2_ODR_AVL_20HZ_VAL , } ,
{ 40 , ST_MAGN_2_ODR_AVL_40HZ_VAL , } ,
{ 80 , ST_MAGN_2_ODR_AVL_80HZ_VAL , } ,
} ,
} ,
. pw = {
. addr = ST_MAGN_2_PW_ADDR ,
. mask = ST_MAGN_2_PW_MASK ,
. value_on = ST_MAGN_2_PW_ON ,
. value_off = ST_MAGN_2_PW_OFF ,
} ,
. fs = {
. addr = ST_MAGN_2_FS_ADDR ,
. mask = ST_MAGN_2_FS_MASK ,
. fs_avl = {
[ 0 ] = {
. num = ST_MAGN_FS_AVL_4000MG ,
. value = ST_MAGN_2_FS_AVL_4000_VAL ,
. gain = ST_MAGN_2_FS_AVL_4000_GAIN ,
} ,
[ 1 ] = {
. num = ST_MAGN_FS_AVL_8000MG ,
. value = ST_MAGN_2_FS_AVL_8000_VAL ,
. gain = ST_MAGN_2_FS_AVL_8000_GAIN ,
} ,
[ 2 ] = {
2014-10-09 16:55:00 +04:00
. num = ST_MAGN_FS_AVL_12000MG ,
. value = ST_MAGN_2_FS_AVL_12000_VAL ,
. gain = ST_MAGN_2_FS_AVL_12000_GAIN ,
} ,
[ 3 ] = {
. num = ST_MAGN_FS_AVL_16000MG ,
. value = ST_MAGN_2_FS_AVL_16000_VAL ,
. gain = ST_MAGN_2_FS_AVL_16000_GAIN ,
2013-01-26 03:44:00 +04:00
} ,
} ,
} ,
. multi_read_bit = ST_MAGN_2_MULTIREAD_BIT ,
. bootime = 2 ,
} ,
} ;
static int st_magn_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * ch , int * val ,
int * val2 , long mask )
{
int err ;
struct st_sensor_data * mdata = iio_priv ( indio_dev ) ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
err = st_sensors_read_info_raw ( indio_dev , ch , val ) ;
if ( err < 0 )
goto read_error ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
* val = 0 ;
if ( ( ch - > scan_index = = ST_SENSORS_SCAN_Z ) & &
( mdata - > current_fullscale - > gain2 ! = 0 ) )
* val2 = mdata - > current_fullscale - > gain2 ;
else
* val2 = mdata - > current_fullscale - > gain ;
return IIO_VAL_INT_PLUS_MICRO ;
2014-06-22 23:59:00 +04:00
case IIO_CHAN_INFO_SAMP_FREQ :
* val = mdata - > odr ;
return IIO_VAL_INT ;
2013-01-26 03:44:00 +04:00
default :
return - EINVAL ;
}
read_error :
return err ;
}
static int st_magn_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan , int val , int val2 , long mask )
{
int err ;
switch ( mask ) {
case IIO_CHAN_INFO_SCALE :
err = st_sensors_set_fullscale_by_gain ( indio_dev , val2 ) ;
break ;
2014-06-22 23:59:00 +04:00
case IIO_CHAN_INFO_SAMP_FREQ :
if ( val2 )
return - EINVAL ;
mutex_lock ( & indio_dev - > mlock ) ;
err = st_sensors_set_odr ( indio_dev , val ) ;
mutex_unlock ( & indio_dev - > mlock ) ;
return err ;
2013-01-26 03:44:00 +04:00
default :
err = - EINVAL ;
}
return err ;
}
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL ( ) ;
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL ( in_magn_scale_available ) ;
static struct attribute * st_magn_attributes [ ] = {
& iio_dev_attr_sampling_frequency_available . dev_attr . attr ,
& iio_dev_attr_in_magn_scale_available . dev_attr . attr ,
NULL ,
} ;
static const struct attribute_group st_magn_attribute_group = {
. attrs = st_magn_attributes ,
} ;
static const struct iio_info magn_info = {
. driver_module = THIS_MODULE ,
. attrs = & st_magn_attribute_group ,
. read_raw = & st_magn_read_raw ,
. write_raw = & st_magn_write_raw ,
} ;
2015-07-21 11:35:43 +03:00
# ifdef CONFIG_IIO_TRIGGER
static const struct iio_trigger_ops st_magn_trigger_ops = {
. owner = THIS_MODULE ,
. set_trigger_state = ST_MAGN_TRIGGER_SET_STATE ,
} ;
# define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)
# else
# define ST_MAGN_TRIGGER_OPS NULL
# endif
2014-10-03 19:35:38 +04:00
int st_magn_common_probe ( struct iio_dev * indio_dev )
2013-01-26 03:44:00 +04:00
{
struct st_sensor_data * mdata = iio_priv ( indio_dev ) ;
2013-09-16 20:02:00 +04:00
int irq = mdata - > get_irq_data_ready ( indio_dev ) ;
int err ;
2013-01-26 03:44:00 +04:00
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > info = & magn_info ;
2015-04-20 14:57:18 +03:00
mutex_init ( & mdata - > tb . buf_lock ) ;
2013-01-26 03:44:00 +04:00
2014-04-13 23:08:00 +04:00
st_sensors_power_enable ( indio_dev ) ;
2013-01-26 03:44:00 +04:00
err = st_sensors_check_device_support ( indio_dev ,
2014-10-03 19:35:35 +04:00
ARRAY_SIZE ( st_magn_sensors_settings ) ,
st_magn_sensors_settings ) ;
2013-01-26 03:44:00 +04:00
if ( err < 0 )
2013-09-16 20:02:00 +04:00
return err ;
2013-01-26 03:44:00 +04:00
2013-06-03 18:58:00 +04:00
mdata - > num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS ;
2014-10-03 19:35:35 +04:00
mdata - > multiread_bit = mdata - > sensor_settings - > multi_read_bit ;
indio_dev - > channels = mdata - > sensor_settings - > ch ;
2013-01-26 03:44:00 +04:00
indio_dev - > num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS ;
mdata - > current_fullscale = ( struct st_sensor_fullscale_avl * )
2014-10-03 19:35:35 +04:00
& mdata - > sensor_settings - > fs . fs_avl [ 0 ] ;
mdata - > odr = mdata - > sensor_settings - > odr . odr_avl [ 0 ] . hz ;
2013-01-26 03:44:00 +04:00
2014-10-03 19:35:38 +04:00
err = st_sensors_init_sensor ( indio_dev , NULL ) ;
2013-01-26 03:44:00 +04:00
if ( err < 0 )
2013-09-16 20:02:00 +04:00
return err ;
2013-01-26 03:44:00 +04:00
2013-09-18 13:00:00 +04:00
err = st_magn_allocate_ring ( indio_dev ) ;
if ( err < 0 )
return err ;
2013-09-16 20:02:00 +04:00
if ( irq > 0 ) {
2015-07-21 11:35:43 +03:00
err = st_sensors_allocate_trigger ( indio_dev ,
ST_MAGN_TRIGGER_OPS ) ;
2013-01-26 03:44:00 +04:00
if ( err < 0 )
goto st_magn_probe_trigger_error ;
}
err = iio_device_register ( indio_dev ) ;
if ( err )
goto st_magn_device_register_error ;
2014-04-13 23:08:00 +04:00
dev_info ( & indio_dev - > dev , " registered magnetometer %s \n " ,
indio_dev - > name ) ;
2013-09-16 20:02:00 +04:00
return 0 ;
2013-01-26 03:44:00 +04:00
st_magn_device_register_error :
2013-09-16 20:02:00 +04:00
if ( irq > 0 )
2013-01-26 03:44:00 +04:00
st_sensors_deallocate_trigger ( indio_dev ) ;
st_magn_probe_trigger_error :
2013-09-18 13:00:00 +04:00
st_magn_deallocate_ring ( indio_dev ) ;
2013-09-16 20:02:00 +04:00
2013-01-26 03:44:00 +04:00
return err ;
}
EXPORT_SYMBOL ( st_magn_common_probe ) ;
void st_magn_common_remove ( struct iio_dev * indio_dev )
{
struct st_sensor_data * mdata = iio_priv ( indio_dev ) ;
2014-04-13 23:08:00 +04:00
st_sensors_power_disable ( indio_dev ) ;
2013-01-26 03:44:00 +04:00
iio_device_unregister ( indio_dev ) ;
2013-09-18 13:00:00 +04:00
if ( mdata - > get_irq_data_ready ( indio_dev ) > 0 )
2013-01-26 03:44:00 +04:00
st_sensors_deallocate_trigger ( indio_dev ) ;
2013-09-18 13:00:00 +04:00
st_magn_deallocate_ring ( indio_dev ) ;
2013-01-26 03:44:00 +04:00
}
EXPORT_SYMBOL ( st_magn_common_remove ) ;
MODULE_AUTHOR ( " Denis Ciocca <denis.ciocca@st.com> " ) ;
MODULE_DESCRIPTION ( " STMicroelectronics magnetometers driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;