2019-05-28 09:57:06 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2016-10-13 22:06:04 +02:00
/*
* STMicroelectronics hts221 sensor driver
*
* Copyright 2016 STMicroelectronics Inc .
*
* Lorenzo Bianconi < lorenzo . bianconi @ st . com >
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/device.h>
# include <linux/iio/sysfs.h>
# include <linux/delay.h>
2017-05-14 17:45:44 +02:00
# include <linux/pm.h>
2018-01-08 23:12:30 +01:00
# include <linux/regmap.h>
# include <linux/bitfield.h>
2016-10-13 22:06:04 +02:00
# include "hts221.h"
# define HTS221_REG_WHOAMI_ADDR 0x0f
# define HTS221_REG_WHOAMI_VAL 0xbc
# define HTS221_REG_CNTRL1_ADDR 0x20
# define HTS221_REG_CNTRL2_ADDR 0x21
# define HTS221_REG_AVG_ADDR 0x10
# define HTS221_REG_H_OUT_L 0x28
# define HTS221_REG_T_OUT_L 0x2a
# define HTS221_HUMIDITY_AVG_MASK 0x07
# define HTS221_TEMP_AVG_MASK 0x38
2017-07-17 19:38:56 +02:00
# define HTS221_ODR_MASK 0x03
2016-10-13 22:06:04 +02:00
# define HTS221_BDU_MASK BIT(2)
2017-07-17 19:38:56 +02:00
# define HTS221_ENABLE_MASK BIT(7)
2016-10-13 22:06:04 +02:00
/* calibration registers */
# define HTS221_REG_0RH_CAL_X_H 0x36
# define HTS221_REG_1RH_CAL_X_H 0x3a
# define HTS221_REG_0RH_CAL_Y_H 0x30
# define HTS221_REG_1RH_CAL_Y_H 0x31
# define HTS221_REG_0T_CAL_X_L 0x3c
# define HTS221_REG_1T_CAL_X_L 0x3e
# define HTS221_REG_0T_CAL_Y_H 0x32
# define HTS221_REG_1T_CAL_Y_H 0x33
# define HTS221_REG_T1_T0_CAL_Y_H 0x35
struct hts221_odr {
u8 hz ;
u8 val ;
} ;
2017-07-17 19:38:56 +02:00
# define HTS221_AVG_DEPTH 8
2016-10-13 22:06:04 +02:00
struct hts221_avg {
u8 addr ;
u8 mask ;
2017-07-17 19:38:56 +02:00
u16 avg_avl [ HTS221_AVG_DEPTH ] ;
2016-10-13 22:06:04 +02:00
} ;
static const struct hts221_odr hts221_odr_table [ ] = {
{ 1 , 0x01 } , /* 1Hz */
{ 7 , 0x02 } , /* 7Hz */
{ 13 , 0x03 } , /* 12.5Hz */
} ;
static const struct hts221_avg hts221_avg_list [ ] = {
{
. addr = HTS221_REG_AVG_ADDR ,
. mask = HTS221_HUMIDITY_AVG_MASK ,
. avg_avl = {
2017-07-17 19:38:56 +02:00
4 , /* 0.4 %RH */
8 , /* 0.3 %RH */
16 , /* 0.2 %RH */
32 , /* 0.15 %RH */
64 , /* 0.1 %RH */
128 , /* 0.07 %RH */
256 , /* 0.05 %RH */
512 , /* 0.03 %RH */
2016-10-13 22:06:04 +02:00
} ,
} ,
{
. addr = HTS221_REG_AVG_ADDR ,
. mask = HTS221_TEMP_AVG_MASK ,
. avg_avl = {
2017-07-17 19:38:56 +02:00
2 , /* 0.08 degC */
4 , /* 0.05 degC */
8 , /* 0.04 degC */
16 , /* 0.03 degC */
32 , /* 0.02 degC */
64 , /* 0.015 degC */
128 , /* 0.01 degC */
256 , /* 0.007 degC */
2016-10-13 22:06:04 +02:00
} ,
} ,
} ;
static const struct iio_chan_spec hts221_channels [ ] = {
{
. type = IIO_HUMIDITYRELATIVE ,
. address = HTS221_REG_H_OUT_L ,
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) |
BIT ( IIO_CHAN_INFO_OFFSET ) |
BIT ( IIO_CHAN_INFO_SCALE ) |
BIT ( IIO_CHAN_INFO_OVERSAMPLING_RATIO ) ,
. info_mask_shared_by_all = BIT ( IIO_CHAN_INFO_SAMP_FREQ ) ,
. scan_index = 0 ,
. scan_type = {
. sign = ' s ' ,
. realbits = 16 ,
. storagebits = 16 ,
. endianness = IIO_LE ,
} ,
} ,
{
. type = IIO_TEMP ,
. address = HTS221_REG_T_OUT_L ,
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) |
BIT ( IIO_CHAN_INFO_OFFSET ) |
BIT ( IIO_CHAN_INFO_SCALE ) |
BIT ( IIO_CHAN_INFO_OVERSAMPLING_RATIO ) ,
. info_mask_shared_by_all = BIT ( IIO_CHAN_INFO_SAMP_FREQ ) ,
. scan_index = 1 ,
. scan_type = {
. sign = ' s ' ,
. realbits = 16 ,
. storagebits = 16 ,
. endianness = IIO_LE ,
} ,
} ,
IIO_CHAN_SOFT_TIMESTAMP ( 2 ) ,
} ;
static int hts221_check_whoami ( struct hts221_hw * hw )
{
2018-01-08 23:12:30 +01:00
int err , data ;
2016-10-13 22:06:04 +02:00
2018-01-08 23:12:30 +01:00
err = regmap_read ( hw - > regmap , HTS221_REG_WHOAMI_ADDR , & data ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 ) {
dev_err ( hw - > dev , " failed to read whoami register \n " ) ;
return err ;
}
if ( data ! = HTS221_REG_WHOAMI_VAL ) {
dev_err ( hw - > dev , " wrong whoami {%02x vs %02x} \n " ,
data , HTS221_REG_WHOAMI_VAL ) ;
return - ENODEV ;
}
return 0 ;
}
static int hts221_update_odr ( struct hts221_hw * hw , u8 odr )
{
int i , err ;
for ( i = 0 ; i < ARRAY_SIZE ( hts221_odr_table ) ; i + + )
if ( hts221_odr_table [ i ] . hz = = odr )
break ;
if ( i = = ARRAY_SIZE ( hts221_odr_table ) )
return - EINVAL ;
2018-01-08 23:12:30 +01:00
err = regmap_update_bits ( hw - > regmap , HTS221_REG_CNTRL1_ADDR ,
HTS221_ODR_MASK ,
FIELD_PREP ( HTS221_ODR_MASK ,
hts221_odr_table [ i ] . val ) ) ;
2017-07-17 19:38:56 +02:00
if ( err < 0 )
return err ;
2016-10-13 22:06:04 +02:00
hw - > odr = odr ;
return 0 ;
}
static int hts221_update_avg ( struct hts221_hw * hw ,
enum hts221_sensor_type type ,
u16 val )
{
const struct hts221_avg * avg = & hts221_avg_list [ type ] ;
2018-01-08 23:12:30 +01:00
int i , err , data ;
2016-10-13 22:06:04 +02:00
for ( i = 0 ; i < HTS221_AVG_DEPTH ; i + + )
2017-07-17 19:38:56 +02:00
if ( avg - > avg_avl [ i ] = = val )
2016-10-13 22:06:04 +02:00
break ;
if ( i = = HTS221_AVG_DEPTH )
return - EINVAL ;
2018-01-08 23:12:30 +01:00
data = ( ( i < < __ffs ( avg - > mask ) ) & avg - > mask ) ;
err = regmap_update_bits ( hw - > regmap , avg - > addr ,
avg - > mask , data ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
hw - > sensors [ type ] . cur_avg_idx = i ;
return 0 ;
}
static ssize_t hts221_sysfs_sampling_freq ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
int i ;
ssize_t len = 0 ;
for ( i = 0 ; i < ARRAY_SIZE ( hts221_odr_table ) ; i + + )
len + = scnprintf ( buf + len , PAGE_SIZE - len , " %d " ,
hts221_odr_table [ i ] . hz ) ;
buf [ len - 1 ] = ' \n ' ;
return len ;
}
static ssize_t
hts221_sysfs_rh_oversampling_avail ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
const struct hts221_avg * avg = & hts221_avg_list [ HTS221_SENSOR_H ] ;
ssize_t len = 0 ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( avg - > avg_avl ) ; i + + )
len + = scnprintf ( buf + len , PAGE_SIZE - len , " %d " ,
2017-07-17 19:38:56 +02:00
avg - > avg_avl [ i ] ) ;
2016-10-13 22:06:04 +02:00
buf [ len - 1 ] = ' \n ' ;
return len ;
}
static ssize_t
hts221_sysfs_temp_oversampling_avail ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
const struct hts221_avg * avg = & hts221_avg_list [ HTS221_SENSOR_T ] ;
ssize_t len = 0 ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( avg - > avg_avl ) ; i + + )
len + = scnprintf ( buf + len , PAGE_SIZE - len , " %d " ,
2017-07-17 19:38:56 +02:00
avg - > avg_avl [ i ] ) ;
2016-10-13 22:06:04 +02:00
buf [ len - 1 ] = ' \n ' ;
return len ;
}
2017-07-17 19:39:00 +02:00
int hts221_set_enable ( struct hts221_hw * hw , bool enable )
2016-10-13 22:06:04 +02:00
{
2017-05-14 17:45:44 +02:00
int err ;
2018-01-08 23:12:30 +01:00
err = regmap_update_bits ( hw - > regmap , HTS221_REG_CNTRL1_ADDR ,
HTS221_ENABLE_MASK ,
FIELD_PREP ( HTS221_ENABLE_MASK , enable ) ) ;
2017-05-14 17:45:44 +02:00
if ( err < 0 )
return err ;
2017-07-17 19:39:00 +02:00
hw - > enabled = enable ;
2017-05-14 17:45:44 +02:00
return 0 ;
2016-10-13 22:06:04 +02:00
}
static int hts221_parse_temp_caldata ( struct hts221_hw * hw )
{
2018-01-08 23:12:30 +01:00
int err , * slope , * b_gen , cal0 , cal1 ;
2016-10-13 22:06:04 +02:00
s16 cal_x0 , cal_x1 , cal_y0 , cal_y1 ;
2018-01-08 23:12:28 +01:00
__le16 val ;
2016-10-13 22:06:04 +02:00
2018-01-08 23:12:30 +01:00
err = regmap_read ( hw - > regmap , HTS221_REG_0T_CAL_Y_H , & cal0 ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
2018-01-08 23:12:30 +01:00
err = regmap_read ( hw - > regmap , HTS221_REG_T1_T0_CAL_Y_H , & cal1 ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
2018-01-08 23:12:28 +01:00
cal_y0 = ( ( cal1 & 0x3 ) < < 8 ) | cal0 ;
2016-10-13 22:06:04 +02:00
2018-01-08 23:12:30 +01:00
err = regmap_read ( hw - > regmap , HTS221_REG_1T_CAL_Y_H , & cal0 ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
cal_y1 = ( ( ( cal1 & 0xc ) > > 2 ) < < 8 ) | cal0 ;
2018-01-08 23:12:30 +01:00
err = regmap_bulk_read ( hw - > regmap , HTS221_REG_0T_CAL_X_L ,
& val , sizeof ( val ) ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
2018-01-08 23:12:28 +01:00
cal_x0 = le16_to_cpu ( val ) ;
2016-10-13 22:06:04 +02:00
2018-01-08 23:12:30 +01:00
err = regmap_bulk_read ( hw - > regmap , HTS221_REG_1T_CAL_X_L ,
& val , sizeof ( val ) ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
2018-01-08 23:12:28 +01:00
cal_x1 = le16_to_cpu ( val ) ;
2016-10-13 22:06:04 +02:00
slope = & hw - > sensors [ HTS221_SENSOR_T ] . slope ;
b_gen = & hw - > sensors [ HTS221_SENSOR_T ] . b_gen ;
* slope = ( ( cal_y1 - cal_y0 ) * 8000 ) / ( cal_x1 - cal_x0 ) ;
* b_gen = ( ( ( s32 ) cal_x1 * cal_y0 - ( s32 ) cal_x0 * cal_y1 ) * 1000 ) /
( cal_x1 - cal_x0 ) ;
* b_gen * = 8 ;
return 0 ;
}
static int hts221_parse_rh_caldata ( struct hts221_hw * hw )
{
2018-01-08 23:12:30 +01:00
int err , * slope , * b_gen , data ;
2016-10-13 22:06:04 +02:00
s16 cal_x0 , cal_x1 , cal_y0 , cal_y1 ;
2018-01-08 23:12:28 +01:00
__le16 val ;
2016-10-13 22:06:04 +02:00
2018-01-08 23:12:30 +01:00
err = regmap_read ( hw - > regmap , HTS221_REG_0RH_CAL_Y_H , & data ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
cal_y0 = data ;
2018-01-08 23:12:30 +01:00
err = regmap_read ( hw - > regmap , HTS221_REG_1RH_CAL_Y_H , & data ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
cal_y1 = data ;
2018-01-08 23:12:30 +01:00
err = regmap_bulk_read ( hw - > regmap , HTS221_REG_0RH_CAL_X_H ,
& val , sizeof ( val ) ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
2018-01-08 23:12:28 +01:00
cal_x0 = le16_to_cpu ( val ) ;
2016-10-13 22:06:04 +02:00
2018-01-08 23:12:30 +01:00
err = regmap_bulk_read ( hw - > regmap , HTS221_REG_1RH_CAL_X_H ,
& val , sizeof ( val ) ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
2018-01-08 23:12:28 +01:00
cal_x1 = le16_to_cpu ( val ) ;
2016-10-13 22:06:04 +02:00
slope = & hw - > sensors [ HTS221_SENSOR_H ] . slope ;
b_gen = & hw - > sensors [ HTS221_SENSOR_H ] . b_gen ;
* slope = ( ( cal_y1 - cal_y0 ) * 8000 ) / ( cal_x1 - cal_x0 ) ;
* b_gen = ( ( ( s32 ) cal_x1 * cal_y0 - ( s32 ) cal_x0 * cal_y1 ) * 1000 ) /
( cal_x1 - cal_x0 ) ;
* b_gen * = 8 ;
return 0 ;
}
static int hts221_get_sensor_scale ( struct hts221_hw * hw ,
enum iio_chan_type ch_type ,
int * val , int * val2 )
{
s64 tmp ;
s32 rem , div , data ;
switch ( ch_type ) {
case IIO_HUMIDITYRELATIVE :
data = hw - > sensors [ HTS221_SENSOR_H ] . slope ;
div = ( 1 < < 4 ) * 1000 ;
break ;
case IIO_TEMP :
data = hw - > sensors [ HTS221_SENSOR_T ] . slope ;
div = ( 1 < < 6 ) * 1000 ;
break ;
default :
return - EINVAL ;
}
tmp = div_s64 ( data * 1000000000LL , div ) ;
tmp = div_s64_rem ( tmp , 1000000000LL , & rem ) ;
* val = tmp ;
* val2 = rem ;
return IIO_VAL_INT_PLUS_NANO ;
}
static int hts221_get_sensor_offset ( struct hts221_hw * hw ,
enum iio_chan_type ch_type ,
int * val , int * val2 )
{
s64 tmp ;
s32 rem , div , data ;
switch ( ch_type ) {
case IIO_HUMIDITYRELATIVE :
data = hw - > sensors [ HTS221_SENSOR_H ] . b_gen ;
div = hw - > sensors [ HTS221_SENSOR_H ] . slope ;
break ;
case IIO_TEMP :
data = hw - > sensors [ HTS221_SENSOR_T ] . b_gen ;
div = hw - > sensors [ HTS221_SENSOR_T ] . slope ;
break ;
default :
return - EINVAL ;
}
tmp = div_s64 ( data * 1000000000LL , div ) ;
tmp = div_s64_rem ( tmp , 1000000000LL , & rem ) ;
* val = tmp ;
* val2 = rem ;
return IIO_VAL_INT_PLUS_NANO ;
}
static int hts221_read_oneshot ( struct hts221_hw * hw , u8 addr , int * val )
{
2018-01-08 23:12:31 +01:00
__le16 data ;
2016-10-13 22:06:04 +02:00
int err ;
2017-07-17 19:39:00 +02:00
err = hts221_set_enable ( hw , true ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
msleep ( 50 ) ;
2018-01-08 23:12:31 +01:00
err = regmap_bulk_read ( hw - > regmap , addr , & data , sizeof ( data ) ) ;
2016-10-13 22:06:04 +02:00
if ( err < 0 )
return err ;
2017-07-17 19:39:00 +02:00
hts221_set_enable ( hw , false ) ;
2016-10-13 22:06:04 +02:00
2018-01-08 23:12:31 +01:00
* val = ( s16 ) le16_to_cpu ( data ) ;
2016-10-13 22:06:04 +02:00
return IIO_VAL_INT ;
}
static int hts221_read_raw ( struct iio_dev * iio_dev ,
struct iio_chan_spec const * ch ,
int * val , int * val2 , long mask )
{
struct hts221_hw * hw = iio_priv ( iio_dev ) ;
int ret ;
ret = iio_device_claim_direct_mode ( iio_dev ) ;
if ( ret )
return ret ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
ret = hts221_read_oneshot ( hw , ch - > address , val ) ;
break ;
case IIO_CHAN_INFO_SCALE :
ret = hts221_get_sensor_scale ( hw , ch - > type , val , val2 ) ;
break ;
case IIO_CHAN_INFO_OFFSET :
ret = hts221_get_sensor_offset ( hw , ch - > type , val , val2 ) ;
break ;
case IIO_CHAN_INFO_SAMP_FREQ :
* val = hw - > odr ;
ret = IIO_VAL_INT ;
break ;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO : {
u8 idx ;
const struct hts221_avg * avg ;
switch ( ch - > type ) {
case IIO_HUMIDITYRELATIVE :
avg = & hts221_avg_list [ HTS221_SENSOR_H ] ;
idx = hw - > sensors [ HTS221_SENSOR_H ] . cur_avg_idx ;
2017-07-17 19:38:56 +02:00
* val = avg - > avg_avl [ idx ] ;
2016-10-13 22:06:04 +02:00
ret = IIO_VAL_INT ;
break ;
case IIO_TEMP :
avg = & hts221_avg_list [ HTS221_SENSOR_T ] ;
idx = hw - > sensors [ HTS221_SENSOR_T ] . cur_avg_idx ;
2017-07-17 19:38:56 +02:00
* val = avg - > avg_avl [ idx ] ;
2016-10-13 22:06:04 +02:00
ret = IIO_VAL_INT ;
break ;
default :
ret = - EINVAL ;
break ;
}
break ;
}
default :
ret = - EINVAL ;
break ;
}
iio_device_release_direct_mode ( iio_dev ) ;
return ret ;
}
static int hts221_write_raw ( struct iio_dev * iio_dev ,
struct iio_chan_spec const * chan ,
int val , int val2 , long mask )
{
struct hts221_hw * hw = iio_priv ( iio_dev ) ;
int ret ;
ret = iio_device_claim_direct_mode ( iio_dev ) ;
if ( ret )
return ret ;
switch ( mask ) {
case IIO_CHAN_INFO_SAMP_FREQ :
ret = hts221_update_odr ( hw , val ) ;
break ;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO :
switch ( chan - > type ) {
case IIO_HUMIDITYRELATIVE :
ret = hts221_update_avg ( hw , HTS221_SENSOR_H , val ) ;
break ;
case IIO_TEMP :
ret = hts221_update_avg ( hw , HTS221_SENSOR_T , val ) ;
break ;
default :
ret = - EINVAL ;
break ;
}
break ;
default :
ret = - EINVAL ;
break ;
}
iio_device_release_direct_mode ( iio_dev ) ;
return ret ;
}
static int hts221_validate_trigger ( struct iio_dev * iio_dev ,
struct iio_trigger * trig )
{
struct hts221_hw * hw = iio_priv ( iio_dev ) ;
return hw - > trig = = trig ? 0 : - EINVAL ;
}
static IIO_DEVICE_ATTR ( in_humidity_oversampling_ratio_available , S_IRUGO ,
hts221_sysfs_rh_oversampling_avail , NULL , 0 ) ;
static IIO_DEVICE_ATTR ( in_temp_oversampling_ratio_available , S_IRUGO ,
hts221_sysfs_temp_oversampling_avail , NULL , 0 ) ;
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL ( hts221_sysfs_sampling_freq ) ;
static struct attribute * hts221_attributes [ ] = {
& iio_dev_attr_sampling_frequency_available . dev_attr . attr ,
& iio_dev_attr_in_humidity_oversampling_ratio_available . dev_attr . attr ,
& iio_dev_attr_in_temp_oversampling_ratio_available . dev_attr . attr ,
NULL ,
} ;
static const struct attribute_group hts221_attribute_group = {
. attrs = hts221_attributes ,
} ;
static const struct iio_info hts221_info = {
. attrs = & hts221_attribute_group ,
. read_raw = hts221_read_raw ,
. write_raw = hts221_write_raw ,
. validate_trigger = hts221_validate_trigger ,
} ;
static const unsigned long hts221_scan_masks [ ] = { 0x3 , 0x0 } ;
2017-12-30 00:33:04 +01:00
int hts221_probe ( struct device * dev , int irq , const char * name ,
2018-01-08 23:12:30 +01:00
struct regmap * regmap )
2016-10-13 22:06:04 +02:00
{
2017-12-30 00:33:04 +01:00
struct iio_dev * iio_dev ;
struct hts221_hw * hw ;
2016-10-13 22:06:04 +02:00
int err ;
u8 data ;
2017-12-30 00:33:04 +01:00
iio_dev = devm_iio_device_alloc ( dev , sizeof ( * hw ) ) ;
if ( ! iio_dev )
return - ENOMEM ;
dev_set_drvdata ( dev , ( void * ) iio_dev ) ;
hw = iio_priv ( iio_dev ) ;
hw - > name = name ;
hw - > dev = dev ;
hw - > irq = irq ;
2018-01-08 23:12:30 +01:00
hw - > regmap = regmap ;
2016-10-13 22:06:04 +02:00
err = hts221_check_whoami ( hw ) ;
if ( err < 0 )
return err ;
iio_dev - > modes = INDIO_DIRECT_MODE ;
iio_dev - > dev . parent = hw - > dev ;
iio_dev - > available_scan_masks = hts221_scan_masks ;
iio_dev - > channels = hts221_channels ;
iio_dev - > num_channels = ARRAY_SIZE ( hts221_channels ) ;
iio_dev - > name = HTS221_DEV_NAME ;
iio_dev - > info = & hts221_info ;
2017-07-17 19:38:57 +02:00
/* enable Block Data Update */
2018-01-08 23:12:30 +01:00
err = regmap_update_bits ( hw - > regmap , HTS221_REG_CNTRL1_ADDR ,
HTS221_BDU_MASK ,
FIELD_PREP ( HTS221_BDU_MASK , 1 ) ) ;
2017-07-17 19:38:57 +02:00
if ( err < 0 )
return err ;
2017-07-17 19:38:59 +02:00
err = hts221_update_odr ( hw , hts221_odr_table [ 0 ] . hz ) ;
if ( err < 0 )
return err ;
2016-10-13 22:06:04 +02:00
/* configure humidity sensor */
err = hts221_parse_rh_caldata ( hw ) ;
if ( err < 0 ) {
dev_err ( hw - > dev , " failed to get rh calibration data \n " ) ;
return err ;
}
2017-07-17 19:38:56 +02:00
data = hts221_avg_list [ HTS221_SENSOR_H ] . avg_avl [ 3 ] ;
2016-10-13 22:06:04 +02:00
err = hts221_update_avg ( hw , HTS221_SENSOR_H , data ) ;
if ( err < 0 ) {
dev_err ( hw - > dev , " failed to set rh oversampling ratio \n " ) ;
return err ;
}
/* configure temperature sensor */
err = hts221_parse_temp_caldata ( hw ) ;
if ( err < 0 ) {
dev_err ( hw - > dev ,
" failed to get temperature calibration data \n " ) ;
return err ;
}
2017-07-17 19:38:56 +02:00
data = hts221_avg_list [ HTS221_SENSOR_T ] . avg_avl [ 3 ] ;
2016-10-13 22:06:04 +02:00
err = hts221_update_avg ( hw , HTS221_SENSOR_T , data ) ;
if ( err < 0 ) {
dev_err ( hw - > dev ,
" failed to set temperature oversampling ratio \n " ) ;
return err ;
}
if ( hw - > irq > 0 ) {
err = hts221_allocate_buffers ( hw ) ;
if ( err < 0 )
return err ;
err = hts221_allocate_trigger ( hw ) ;
if ( err )
return err ;
}
return devm_iio_device_register ( hw - > dev , iio_dev ) ;
}
EXPORT_SYMBOL ( hts221_probe ) ;
2017-05-14 17:45:44 +02:00
static int __maybe_unused hts221_suspend ( struct device * dev )
{
struct iio_dev * iio_dev = dev_get_drvdata ( dev ) ;
struct hts221_hw * hw = iio_priv ( iio_dev ) ;
2018-01-08 23:12:30 +01:00
return regmap_update_bits ( hw - > regmap , HTS221_REG_CNTRL1_ADDR ,
HTS221_ENABLE_MASK ,
FIELD_PREP ( HTS221_ENABLE_MASK , false ) ) ;
2017-05-14 17:45:44 +02:00
}
static int __maybe_unused hts221_resume ( struct device * dev )
{
struct iio_dev * iio_dev = dev_get_drvdata ( dev ) ;
struct hts221_hw * hw = iio_priv ( iio_dev ) ;
int err = 0 ;
if ( hw - > enabled )
2018-01-08 23:12:30 +01:00
err = regmap_update_bits ( hw - > regmap , HTS221_REG_CNTRL1_ADDR ,
HTS221_ENABLE_MASK ,
FIELD_PREP ( HTS221_ENABLE_MASK ,
true ) ) ;
2017-05-14 17:45:44 +02:00
return err ;
}
const struct dev_pm_ops hts221_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS ( hts221_suspend , hts221_resume )
} ;
EXPORT_SYMBOL ( hts221_pm_ops ) ;
2016-10-13 22:06:04 +02:00
MODULE_AUTHOR ( " Lorenzo Bianconi <lorenzo.bianconi@st.com> " ) ;
MODULE_DESCRIPTION ( " STMicroelectronics hts221 sensor driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;