2019-05-29 16:57:44 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2021-03-09 15:43:14 -08:00
/*
2015-04-27 18:34:00 +03:00
* Sensortek STK3310 / STK3311 Ambient Light and Proximity Sensor
*
* Copyright ( c ) 2015 , Intel Corporation .
*
* IIO driver for STK3310 / STK3311 . 7 - bit I2C address : 0x48 .
*/
# include <linux/acpi.h>
# include <linux/i2c.h>
2015-04-27 18:34:01 +03:00
# include <linux/interrupt.h>
2015-04-27 18:34:00 +03:00
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/regmap.h>
2015-04-27 18:34:01 +03:00
# include <linux/iio/events.h>
2015-04-27 18:34:00 +03:00
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# define STK3310_REG_STATE 0x00
# define STK3310_REG_PSCTRL 0x01
# define STK3310_REG_ALSCTRL 0x02
2015-04-27 18:34:01 +03:00
# define STK3310_REG_INT 0x04
# define STK3310_REG_THDH_PS 0x06
# define STK3310_REG_THDL_PS 0x08
# define STK3310_REG_FLAG 0x10
2015-04-27 18:34:00 +03:00
# define STK3310_REG_PS_DATA_MSB 0x11
# define STK3310_REG_PS_DATA_LSB 0x12
# define STK3310_REG_ALS_DATA_MSB 0x13
# define STK3310_REG_ALS_DATA_LSB 0x14
# define STK3310_REG_ID 0x3E
# define STK3310_MAX_REG 0x80
2015-07-09 23:51:32 +02:00
# define STK3310_STATE_EN_PS BIT(0)
# define STK3310_STATE_EN_ALS BIT(1)
2015-04-27 18:34:00 +03:00
# define STK3310_STATE_STANDBY 0x00
# define STK3310_CHIP_ID_VAL 0x13
# define STK3311_CHIP_ID_VAL 0x1D
2020-07-03 21:44:05 +02:00
# define STK3311X_CHIP_ID_VAL 0x12
2019-06-03 21:20:39 +02:00
# define STK3335_CHIP_ID_VAL 0x51
2015-04-27 18:34:01 +03:00
# define STK3310_PSINT_EN 0x01
2015-04-27 18:34:00 +03:00
# define STK3310_PS_MAX_VAL 0xFFFF
# define STK3310_DRIVER_NAME "stk3310"
# define STK3310_REGMAP_NAME "stk3310_regmap"
2015-04-27 18:34:01 +03:00
# define STK3310_EVENT "stk3310_event"
2015-04-27 18:34:00 +03:00
# define STK3310_SCALE_AVAILABLE "6.4 1.6 0.4 0.1"
# define STK3310_IT_AVAILABLE \
" 0.000185 0.000370 0.000741 0.001480 0.002960 0.005920 0.011840 " \
" 0.023680 0.047360 0.094720 0.189440 0.378880 0.757760 1.515520 " \
" 3.031040 6.062080 "
# define STK3310_REGFIELD(name) \
do { \
data - > reg_ # # name = \
devm_regmap_field_alloc ( & client - > dev , regmap , \
stk3310_reg_field_ # # name ) ; \
if ( IS_ERR ( data - > reg_ # # name ) ) { \
dev_err ( & client - > dev , " reg field alloc failed. \n " ) ; \
return PTR_ERR ( data - > reg_ # # name ) ; \
} \
} while ( 0 )
static const struct reg_field stk3310_reg_field_state =
REG_FIELD ( STK3310_REG_STATE , 0 , 2 ) ;
static const struct reg_field stk3310_reg_field_als_gain =
REG_FIELD ( STK3310_REG_ALSCTRL , 4 , 5 ) ;
static const struct reg_field stk3310_reg_field_ps_gain =
REG_FIELD ( STK3310_REG_PSCTRL , 4 , 5 ) ;
static const struct reg_field stk3310_reg_field_als_it =
REG_FIELD ( STK3310_REG_ALSCTRL , 0 , 3 ) ;
static const struct reg_field stk3310_reg_field_ps_it =
REG_FIELD ( STK3310_REG_PSCTRL , 0 , 3 ) ;
2015-04-27 18:34:01 +03:00
static const struct reg_field stk3310_reg_field_int_ps =
REG_FIELD ( STK3310_REG_INT , 0 , 2 ) ;
static const struct reg_field stk3310_reg_field_flag_psint =
REG_FIELD ( STK3310_REG_FLAG , 4 , 4 ) ;
static const struct reg_field stk3310_reg_field_flag_nf =
REG_FIELD ( STK3310_REG_FLAG , 0 , 0 ) ;
2015-07-01 15:32:00 +03:00
/* Estimate maximum proximity values with regard to measurement scale. */
2015-04-27 18:34:00 +03:00
static const int stk3310_ps_max [ 4 ] = {
2015-07-01 15:32:00 +03:00
STK3310_PS_MAX_VAL / 640 ,
STK3310_PS_MAX_VAL / 160 ,
STK3310_PS_MAX_VAL / 40 ,
STK3310_PS_MAX_VAL / 10
2015-04-27 18:34:00 +03:00
} ;
static const int stk3310_scale_table [ ] [ 2 ] = {
{ 6 , 400000 } , { 1 , 600000 } , { 0 , 400000 } , { 0 , 100000 }
} ;
/* Integration time in seconds, microseconds */
static const int stk3310_it_table [ ] [ 2 ] = {
{ 0 , 185 } , { 0 , 370 } , { 0 , 741 } , { 0 , 1480 } ,
{ 0 , 2960 } , { 0 , 5920 } , { 0 , 11840 } , { 0 , 23680 } ,
{ 0 , 47360 } , { 0 , 94720 } , { 0 , 189440 } , { 0 , 378880 } ,
{ 0 , 757760 } , { 1 , 515520 } , { 3 , 31040 } , { 6 , 62080 } ,
} ;
struct stk3310_data {
struct i2c_client * client ;
struct mutex lock ;
bool als_enabled ;
bool ps_enabled ;
2015-04-27 18:34:01 +03:00
u64 timestamp ;
2015-04-27 18:34:00 +03:00
struct regmap * regmap ;
struct regmap_field * reg_state ;
struct regmap_field * reg_als_gain ;
struct regmap_field * reg_ps_gain ;
struct regmap_field * reg_als_it ;
struct regmap_field * reg_ps_it ;
2015-04-27 18:34:01 +03:00
struct regmap_field * reg_int_ps ;
struct regmap_field * reg_flag_psint ;
struct regmap_field * reg_flag_nf ;
} ;
static const struct iio_event_spec stk3310_events [ ] = {
/* Proximity event */
{
. type = IIO_EV_TYPE_THRESH ,
2015-07-01 15:32:00 +03:00
. dir = IIO_EV_DIR_RISING ,
2015-04-27 18:34:01 +03:00
. mask_separate = BIT ( IIO_EV_INFO_VALUE ) |
BIT ( IIO_EV_INFO_ENABLE ) ,
} ,
/* Out-of-proximity event */
{
. type = IIO_EV_TYPE_THRESH ,
2015-07-01 15:32:00 +03:00
. dir = IIO_EV_DIR_FALLING ,
2015-04-27 18:34:01 +03:00
. mask_separate = BIT ( IIO_EV_INFO_VALUE ) |
BIT ( IIO_EV_INFO_ENABLE ) ,
} ,
2015-04-27 18:34:00 +03:00
} ;
static const struct iio_chan_spec stk3310_channels [ ] = {
{
. type = IIO_LIGHT ,
. info_mask_separate =
BIT ( IIO_CHAN_INFO_RAW ) |
BIT ( IIO_CHAN_INFO_SCALE ) |
BIT ( IIO_CHAN_INFO_INT_TIME ) ,
} ,
{
. type = IIO_PROXIMITY ,
. info_mask_separate =
BIT ( IIO_CHAN_INFO_RAW ) |
BIT ( IIO_CHAN_INFO_SCALE ) |
BIT ( IIO_CHAN_INFO_INT_TIME ) ,
2015-04-27 18:34:01 +03:00
. event_spec = stk3310_events ,
. num_event_specs = ARRAY_SIZE ( stk3310_events ) ,
2015-04-27 18:34:00 +03:00
}
} ;
static IIO_CONST_ATTR ( in_illuminance_scale_available , STK3310_SCALE_AVAILABLE ) ;
static IIO_CONST_ATTR ( in_proximity_scale_available , STK3310_SCALE_AVAILABLE ) ;
static IIO_CONST_ATTR ( in_illuminance_integration_time_available ,
STK3310_IT_AVAILABLE ) ;
static IIO_CONST_ATTR ( in_proximity_integration_time_available ,
STK3310_IT_AVAILABLE ) ;
static struct attribute * stk3310_attributes [ ] = {
& iio_const_attr_in_illuminance_scale_available . dev_attr . attr ,
& iio_const_attr_in_proximity_scale_available . dev_attr . attr ,
& iio_const_attr_in_illuminance_integration_time_available . dev_attr . attr ,
& iio_const_attr_in_proximity_integration_time_available . dev_attr . attr ,
NULL ,
} ;
static const struct attribute_group stk3310_attribute_group = {
. attrs = stk3310_attributes
} ;
static int stk3310_get_index ( const int table [ ] [ 2 ] , int table_size ,
int val , int val2 )
{
int i ;
for ( i = 0 ; i < table_size ; i + + ) {
if ( val = = table [ i ] [ 0 ] & & val2 = = table [ i ] [ 1 ] )
return i ;
}
return - EINVAL ;
}
2015-04-27 18:34:01 +03:00
static int stk3310_read_event ( struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan ,
enum iio_event_type type ,
enum iio_event_direction dir ,
enum iio_event_info info ,
int * val , int * val2 )
{
u8 reg ;
2015-07-09 23:51:30 +02:00
__be16 buf ;
2015-04-27 18:34:01 +03:00
int ret ;
struct stk3310_data * data = iio_priv ( indio_dev ) ;
if ( info ! = IIO_EV_INFO_VALUE )
return - EINVAL ;
2015-07-01 15:32:00 +03:00
/* Only proximity interrupts are implemented at the moment. */
2015-04-27 18:34:01 +03:00
if ( dir = = IIO_EV_DIR_RISING )
reg = STK3310_REG_THDH_PS ;
2015-07-01 15:32:00 +03:00
else if ( dir = = IIO_EV_DIR_FALLING )
reg = STK3310_REG_THDL_PS ;
2015-04-27 18:34:01 +03:00
else
return - EINVAL ;
mutex_lock ( & data - > lock ) ;
ret = regmap_bulk_read ( data - > regmap , reg , & buf , 2 ) ;
mutex_unlock ( & data - > lock ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " register read failed \n " ) ;
return ret ;
}
2015-07-09 23:51:30 +02:00
* val = be16_to_cpu ( buf ) ;
2015-04-27 18:34:01 +03:00
return IIO_VAL_INT ;
}
static int stk3310_write_event ( struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan ,
enum iio_event_type type ,
enum iio_event_direction dir ,
enum iio_event_info info ,
int val , int val2 )
{
u8 reg ;
2015-07-09 23:51:30 +02:00
__be16 buf ;
2015-04-27 18:34:01 +03:00
int ret ;
unsigned int index ;
struct stk3310_data * data = iio_priv ( indio_dev ) ;
struct i2c_client * client = data - > client ;
2015-07-09 23:51:31 +02:00
ret = regmap_field_read ( data - > reg_ps_gain , & index ) ;
if ( ret < 0 )
return ret ;
if ( val < 0 | | val > stk3310_ps_max [ index ] )
2015-04-27 18:34:01 +03:00
return - EINVAL ;
if ( dir = = IIO_EV_DIR_RISING )
reg = STK3310_REG_THDH_PS ;
2015-07-01 15:32:00 +03:00
else if ( dir = = IIO_EV_DIR_FALLING )
reg = STK3310_REG_THDL_PS ;
2015-04-27 18:34:01 +03:00
else
return - EINVAL ;
2015-07-09 23:51:30 +02:00
buf = cpu_to_be16 ( val ) ;
2015-04-27 18:34:01 +03:00
ret = regmap_bulk_write ( data - > regmap , reg , & buf , 2 ) ;
if ( ret < 0 )
dev_err ( & client - > dev , " failed to set PS threshold! \n " ) ;
return ret ;
}
static int stk3310_read_event_config ( struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan ,
enum iio_event_type type ,
enum iio_event_direction dir )
{
unsigned int event_val ;
2015-07-09 23:51:31 +02:00
int ret ;
2015-04-27 18:34:01 +03:00
struct stk3310_data * data = iio_priv ( indio_dev ) ;
2015-07-09 23:51:31 +02:00
ret = regmap_field_read ( data - > reg_int_ps , & event_val ) ;
if ( ret < 0 )
return ret ;
2015-04-27 18:34:01 +03:00
return event_val ;
}
static int stk3310_write_event_config ( struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan ,
enum iio_event_type type ,
enum iio_event_direction dir ,
int state )
{
int ret ;
struct stk3310_data * data = iio_priv ( indio_dev ) ;
struct i2c_client * client = data - > client ;
if ( state < 0 | | state > 7 )
return - EINVAL ;
/* Set INT_PS value */
mutex_lock ( & data - > lock ) ;
ret = regmap_field_write ( data - > reg_int_ps , state ) ;
if ( ret < 0 )
dev_err ( & client - > dev , " failed to set interrupt mode \n " ) ;
mutex_unlock ( & data - > lock ) ;
return ret ;
}
2015-04-27 18:34:00 +03:00
static int stk3310_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val , int * val2 , long mask )
{
u8 reg ;
2015-07-09 23:51:30 +02:00
__be16 buf ;
2015-04-27 18:34:00 +03:00
int ret ;
unsigned int index ;
struct stk3310_data * data = iio_priv ( indio_dev ) ;
struct i2c_client * client = data - > client ;
2015-07-09 23:51:31 +02:00
if ( chan - > type ! = IIO_LIGHT & & chan - > type ! = IIO_PROXIMITY )
return - EINVAL ;
2015-04-27 18:34:00 +03:00
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
if ( chan - > type = = IIO_LIGHT )
reg = STK3310_REG_ALS_DATA_MSB ;
else
2015-07-09 23:51:31 +02:00
reg = STK3310_REG_PS_DATA_MSB ;
2015-04-27 18:34:00 +03:00
mutex_lock ( & data - > lock ) ;
ret = regmap_bulk_read ( data - > regmap , reg , & buf , 2 ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " register read failed \n " ) ;
mutex_unlock ( & data - > lock ) ;
return ret ;
}
2015-07-09 23:51:30 +02:00
* val = be16_to_cpu ( buf ) ;
2015-04-27 18:34:00 +03:00
mutex_unlock ( & data - > lock ) ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_INT_TIME :
if ( chan - > type = = IIO_LIGHT )
2015-07-09 23:51:31 +02:00
ret = regmap_field_read ( data - > reg_als_it , & index ) ;
2015-04-27 18:34:00 +03:00
else
2015-07-09 23:51:31 +02:00
ret = regmap_field_read ( data - > reg_ps_it , & index ) ;
if ( ret < 0 )
return ret ;
2015-04-27 18:34:00 +03:00
* val = stk3310_it_table [ index ] [ 0 ] ;
* val2 = stk3310_it_table [ index ] [ 1 ] ;
return IIO_VAL_INT_PLUS_MICRO ;
case IIO_CHAN_INFO_SCALE :
if ( chan - > type = = IIO_LIGHT )
2015-07-09 23:51:31 +02:00
ret = regmap_field_read ( data - > reg_als_gain , & index ) ;
2015-04-27 18:34:00 +03:00
else
2015-07-09 23:51:31 +02:00
ret = regmap_field_read ( data - > reg_ps_gain , & index ) ;
if ( ret < 0 )
return ret ;
2015-04-27 18:34:00 +03:00
* val = stk3310_scale_table [ index ] [ 0 ] ;
* val2 = stk3310_scale_table [ index ] [ 1 ] ;
return IIO_VAL_INT_PLUS_MICRO ;
}
return - EINVAL ;
}
static int stk3310_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int val , int val2 , long mask )
{
int ret ;
2015-05-27 11:24:25 +03:00
int index ;
2015-04-27 18:34:00 +03:00
struct stk3310_data * data = iio_priv ( indio_dev ) ;
2015-07-09 23:51:31 +02:00
if ( chan - > type ! = IIO_LIGHT & & chan - > type ! = IIO_PROXIMITY )
return - EINVAL ;
2015-04-27 18:34:00 +03:00
switch ( mask ) {
case IIO_CHAN_INFO_INT_TIME :
index = stk3310_get_index ( stk3310_it_table ,
ARRAY_SIZE ( stk3310_it_table ) ,
val , val2 ) ;
if ( index < 0 )
return - EINVAL ;
mutex_lock ( & data - > lock ) ;
if ( chan - > type = = IIO_LIGHT )
ret = regmap_field_write ( data - > reg_als_it , index ) ;
else
ret = regmap_field_write ( data - > reg_ps_it , index ) ;
if ( ret < 0 )
dev_err ( & data - > client - > dev ,
2015-07-09 23:51:33 +02:00
" sensor configuration failed \n " ) ;
2015-04-27 18:34:00 +03:00
mutex_unlock ( & data - > lock ) ;
return ret ;
case IIO_CHAN_INFO_SCALE :
index = stk3310_get_index ( stk3310_scale_table ,
ARRAY_SIZE ( stk3310_scale_table ) ,
val , val2 ) ;
if ( index < 0 )
return - EINVAL ;
mutex_lock ( & data - > lock ) ;
if ( chan - > type = = IIO_LIGHT )
ret = regmap_field_write ( data - > reg_als_gain , index ) ;
else
ret = regmap_field_write ( data - > reg_ps_gain , index ) ;
if ( ret < 0 )
dev_err ( & data - > client - > dev ,
2015-07-09 23:51:33 +02:00
" sensor configuration failed \n " ) ;
2015-04-27 18:34:00 +03:00
mutex_unlock ( & data - > lock ) ;
return ret ;
}
return - EINVAL ;
}
static const struct iio_info stk3310_info = {
. read_raw = stk3310_read_raw ,
. write_raw = stk3310_write_raw ,
. attrs = & stk3310_attribute_group ,
2015-04-27 18:34:01 +03:00
. read_event_value = stk3310_read_event ,
. write_event_value = stk3310_write_event ,
. read_event_config = stk3310_read_event_config ,
. write_event_config = stk3310_write_event_config ,
2015-04-27 18:34:00 +03:00
} ;
static int stk3310_set_state ( struct stk3310_data * data , u8 state )
{
int ret ;
struct i2c_client * client = data - > client ;
/* 3-bit state; 0b100 is not supported. */
if ( state > 7 | | state = = 4 )
return - EINVAL ;
mutex_lock ( & data - > lock ) ;
ret = regmap_field_write ( data - > reg_state , state ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " failed to change sensor state \n " ) ;
} else if ( state ! = STK3310_STATE_STANDBY ) {
/* Don't reset the 'enabled' flags if we're going in standby */
2015-07-09 23:51:32 +02:00
data - > ps_enabled = ! ! ( state & STK3310_STATE_EN_PS ) ;
data - > als_enabled = ! ! ( state & STK3310_STATE_EN_ALS ) ;
2015-04-27 18:34:00 +03:00
}
mutex_unlock ( & data - > lock ) ;
return ret ;
}
static int stk3310_init ( struct iio_dev * indio_dev )
{
int ret ;
int chipid ;
u8 state ;
struct stk3310_data * data = iio_priv ( indio_dev ) ;
struct i2c_client * client = data - > client ;
2015-07-09 23:51:31 +02:00
ret = regmap_read ( data - > regmap , STK3310_REG_ID , & chipid ) ;
if ( ret < 0 )
return ret ;
2015-04-27 18:34:00 +03:00
if ( chipid ! = STK3310_CHIP_ID_VAL & &
2019-06-03 21:20:39 +02:00
chipid ! = STK3311_CHIP_ID_VAL & &
2020-07-03 21:44:05 +02:00
chipid ! = STK3311X_CHIP_ID_VAL & &
2019-06-03 21:20:39 +02:00
chipid ! = STK3335_CHIP_ID_VAL ) {
2015-04-27 18:34:00 +03:00
dev_err ( & client - > dev , " invalid chip id: 0x%x \n " , chipid ) ;
return - ENODEV ;
}
state = STK3310_STATE_EN_ALS | STK3310_STATE_EN_PS ;
ret = stk3310_set_state ( data , state ) ;
2015-04-27 18:34:01 +03:00
if ( ret < 0 ) {
2015-04-27 18:34:00 +03:00
dev_err ( & client - > dev , " failed to enable sensor " ) ;
2015-04-27 18:34:01 +03:00
return ret ;
}
/* Enable PS interrupts */
ret = regmap_field_write ( data - > reg_int_ps , STK3310_PSINT_EN ) ;
if ( ret < 0 )
dev_err ( & client - > dev , " failed to enable interrupts! \n " ) ;
return ret ;
}
2015-04-27 18:34:00 +03:00
static bool stk3310_is_volatile_reg ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case STK3310_REG_ALS_DATA_MSB :
case STK3310_REG_ALS_DATA_LSB :
case STK3310_REG_PS_DATA_LSB :
case STK3310_REG_PS_DATA_MSB :
2015-04-27 18:34:01 +03:00
case STK3310_REG_FLAG :
2015-04-27 18:34:00 +03:00
return true ;
default :
return false ;
}
}
2020-05-26 23:02:22 +02:00
static const struct regmap_config stk3310_regmap_config = {
2015-04-27 18:34:00 +03:00
. name = STK3310_REGMAP_NAME ,
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = STK3310_MAX_REG ,
. cache_type = REGCACHE_RBTREE ,
. volatile_reg = stk3310_is_volatile_reg ,
} ;
static int stk3310_regmap_init ( struct stk3310_data * data )
{
struct regmap * regmap ;
struct i2c_client * client ;
client = data - > client ;
regmap = devm_regmap_init_i2c ( client , & stk3310_regmap_config ) ;
if ( IS_ERR ( regmap ) ) {
dev_err ( & client - > dev , " regmap initialization failed. \n " ) ;
return PTR_ERR ( regmap ) ;
}
data - > regmap = regmap ;
STK3310_REGFIELD ( state ) ;
STK3310_REGFIELD ( als_gain ) ;
STK3310_REGFIELD ( ps_gain ) ;
STK3310_REGFIELD ( als_it ) ;
STK3310_REGFIELD ( ps_it ) ;
2015-04-27 18:34:01 +03:00
STK3310_REGFIELD ( int_ps ) ;
STK3310_REGFIELD ( flag_psint ) ;
STK3310_REGFIELD ( flag_nf ) ;
2015-04-27 18:34:00 +03:00
return 0 ;
}
2015-04-27 18:34:01 +03:00
static irqreturn_t stk3310_irq_handler ( int irq , void * private )
{
struct iio_dev * indio_dev = private ;
struct stk3310_data * data = iio_priv ( indio_dev ) ;
2016-03-09 19:05:49 +01:00
data - > timestamp = iio_get_time_ns ( indio_dev ) ;
2015-04-27 18:34:01 +03:00
return IRQ_WAKE_THREAD ;
}
static irqreturn_t stk3310_irq_event_handler ( int irq , void * private )
{
int ret ;
unsigned int dir ;
u64 event ;
struct iio_dev * indio_dev = private ;
struct stk3310_data * data = iio_priv ( indio_dev ) ;
/* Read FLAG_NF to figure out what threshold has been met. */
mutex_lock ( & data - > lock ) ;
ret = regmap_field_read ( data - > reg_flag_nf , & dir ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " register read failed \n " ) ;
mutex_unlock ( & data - > lock ) ;
return ret ;
}
event = IIO_UNMOD_EVENT_CODE ( IIO_PROXIMITY , 1 ,
IIO_EV_TYPE_THRESH ,
2015-07-01 15:32:00 +03:00
( dir ? IIO_EV_DIR_FALLING :
IIO_EV_DIR_RISING ) ) ;
2015-04-27 18:34:01 +03:00
iio_push_event ( indio_dev , event , data - > timestamp ) ;
/* Reset the interrupt flag */
ret = regmap_field_write ( data - > reg_flag_psint , 0 ) ;
if ( ret < 0 )
dev_err ( & data - > client - > dev , " failed to reset interrupts \n " ) ;
mutex_unlock ( & data - > lock ) ;
return IRQ_HANDLED ;
}
2015-04-27 18:34:00 +03:00
static int stk3310_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
int ret ;
struct iio_dev * indio_dev ;
struct stk3310_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 ;
i2c_set_clientdata ( client , indio_dev ) ;
mutex_init ( & data - > lock ) ;
ret = stk3310_regmap_init ( data ) ;
if ( ret < 0 )
return ret ;
indio_dev - > info = & stk3310_info ;
indio_dev - > name = STK3310_DRIVER_NAME ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > channels = stk3310_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( stk3310_channels ) ;
ret = stk3310_init ( indio_dev ) ;
if ( ret < 0 )
return ret ;
2015-09-23 12:02:00 +03:00
if ( client - > irq > 0 ) {
2015-04-27 18:34:01 +03:00
ret = devm_request_threaded_irq ( & client - > dev , client - > irq ,
stk3310_irq_handler ,
stk3310_irq_event_handler ,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT ,
STK3310_EVENT , indio_dev ) ;
2015-07-09 23:51:31 +02:00
if ( ret < 0 ) {
2015-04-27 18:34:01 +03:00
dev_err ( & client - > dev , " request irq %d failed \n " ,
2015-07-09 23:51:33 +02:00
client - > irq ) ;
2015-07-09 23:51:31 +02:00
goto err_standby ;
}
2015-04-27 18:34:01 +03:00
}
2015-07-09 23:51:29 +02:00
ret = iio_device_register ( indio_dev ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " device_register failed \n " ) ;
2015-07-09 23:51:31 +02:00
goto err_standby ;
2015-07-09 23:51:29 +02:00
}
2015-07-09 23:51:31 +02:00
return 0 ;
err_standby :
stk3310_set_state ( data , STK3310_STATE_STANDBY ) ;
2015-04-27 18:34:00 +03:00
return ret ;
}
static int stk3310_remove ( struct i2c_client * client )
{
struct iio_dev * indio_dev = i2c_get_clientdata ( client ) ;
iio_device_unregister ( indio_dev ) ;
return stk3310_set_state ( iio_priv ( indio_dev ) , STK3310_STATE_STANDBY ) ;
}
# ifdef CONFIG_PM_SLEEP
static int stk3310_suspend ( struct device * dev )
{
struct stk3310_data * data ;
data = iio_priv ( i2c_get_clientdata ( to_i2c_client ( dev ) ) ) ;
return stk3310_set_state ( data , STK3310_STATE_STANDBY ) ;
}
static int stk3310_resume ( struct device * dev )
{
2015-07-09 23:51:32 +02:00
u8 state = 0 ;
2015-04-27 18:34:00 +03:00
struct stk3310_data * data ;
data = iio_priv ( i2c_get_clientdata ( to_i2c_client ( dev ) ) ) ;
if ( data - > ps_enabled )
state | = STK3310_STATE_EN_PS ;
if ( data - > als_enabled )
state | = STK3310_STATE_EN_ALS ;
return stk3310_set_state ( data , state ) ;
}
static SIMPLE_DEV_PM_OPS ( stk3310_pm_ops , stk3310_suspend , stk3310_resume ) ;
# define STK3310_PM_OPS (&stk3310_pm_ops)
# else
# define STK3310_PM_OPS NULL
# endif
static const struct i2c_device_id stk3310_i2c_id [ ] = {
{ " STK3310 " , 0 } ,
{ " STK3311 " , 0 } ,
2019-06-03 21:20:39 +02:00
{ " STK3335 " , 0 } ,
2015-04-27 18:34:00 +03:00
{ }
} ;
2015-07-30 18:18:28 +02:00
MODULE_DEVICE_TABLE ( i2c , stk3310_i2c_id ) ;
2015-04-27 18:34:00 +03:00
static const struct acpi_device_id stk3310_acpi_id [ ] = {
{ " STK3310 " , 0 } ,
{ " STK3311 " , 0 } ,
2019-06-03 21:20:39 +02:00
{ " STK3335 " , 0 } ,
2015-04-27 18:34:00 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( acpi , stk3310_acpi_id ) ;
2019-07-03 20:05:59 +02:00
static const struct of_device_id stk3310_of_match [ ] = {
{ . compatible = " sensortek,stk3310 " , } ,
{ . compatible = " sensortek,stk3311 " , } ,
{ . compatible = " sensortek,stk3335 " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , stk3310_of_match ) ;
2015-04-27 18:34:00 +03:00
static struct i2c_driver stk3310_driver = {
. driver = {
. name = " stk3310 " ,
2019-07-03 20:05:59 +02:00
. of_match_table = stk3310_of_match ,
2015-04-27 18:34:00 +03:00
. pm = STK3310_PM_OPS ,
. acpi_match_table = ACPI_PTR ( stk3310_acpi_id ) ,
} ,
. probe = stk3310_probe ,
. remove = stk3310_remove ,
. id_table = stk3310_i2c_id ,
} ;
module_i2c_driver ( stk3310_driver ) ;
MODULE_AUTHOR ( " Tiberiu Breana <tiberiu.a.breana@intel.com> " ) ;
MODULE_DESCRIPTION ( " STK3310 Ambient Light and Proximity Sensor driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;