2019-05-29 07:18:02 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2014-11-06 23:07:00 +00:00
/*
* KXCJK - 1013 3 - axis accelerometer driver
* Copyright ( c ) 2014 , Intel Corporation .
*/
# include <linux/module.h>
# include <linux/i2c.h>
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/bitops.h>
# include <linux/slab.h>
# include <linux/string.h>
# include <linux/acpi.h>
2014-05-08 22:58:00 +01:00
# include <linux/pm.h>
# include <linux/pm_runtime.h>
2020-12-13 22:54:36 +05:30
# include <linux/regulator/consumer.h>
2014-11-06 23:07:00 +00:00
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# include <linux/iio/buffer.h>
# include <linux/iio/trigger.h>
2014-08-22 20:01:00 +01:00
# include <linux/iio/events.h>
2014-11-06 23:07:00 +00:00
# include <linux/iio/trigger_consumer.h>
# include <linux/iio/triggered_buffer.h>
# include <linux/iio/accel/kxcjk_1013.h>
# define KXCJK1013_DRV_NAME "kxcjk1013"
# define KXCJK1013_IRQ_NAME "kxcjk1013_event"
2017-09-17 17:01:04 +02:00
# define KXTF9_REG_HP_XOUT_L 0x00
# define KXTF9_REG_HP_XOUT_H 0x01
# define KXTF9_REG_HP_YOUT_L 0x02
# define KXTF9_REG_HP_YOUT_H 0x03
# define KXTF9_REG_HP_ZOUT_L 0x04
# define KXTF9_REG_HP_ZOUT_H 0x05
2014-11-06 23:07:00 +00:00
# define KXCJK1013_REG_XOUT_L 0x06
/*
* From low byte X axis register , all the other addresses of Y and Z can be
* obtained by just applying axis offset . The following axis defines are just
* provide clarity , but not used .
*/
# define KXCJK1013_REG_XOUT_H 0x07
# define KXCJK1013_REG_YOUT_L 0x08
# define KXCJK1013_REG_YOUT_H 0x09
# define KXCJK1013_REG_ZOUT_L 0x0A
# define KXCJK1013_REG_ZOUT_H 0x0B
# define KXCJK1013_REG_DCST_RESP 0x0C
# define KXCJK1013_REG_WHO_AM_I 0x0F
2017-09-17 17:01:04 +02:00
# define KXTF9_REG_TILT_POS_CUR 0x10
# define KXTF9_REG_TILT_POS_PREV 0x11
# define KXTF9_REG_INT_SRC1 0x15
2021-05-11 16:24:01 +02:00
# define KXTF9_REG_INT_SRC2 0x16
# define KXCJK1013_REG_INT_SRC1 0x16
2014-11-06 23:07:00 +00:00
# define KXCJK1013_REG_INT_SRC2 0x17
# define KXCJK1013_REG_STATUS_REG 0x18
# define KXCJK1013_REG_INT_REL 0x1A
# define KXCJK1013_REG_CTRL1 0x1B
2017-09-17 17:01:04 +02:00
# define KXTF9_REG_CTRL2 0x1C
2021-05-11 16:24:01 +02:00
# define KXTF9_REG_CTRL3 0x1D
# define KXCJK1013_REG_CTRL2 0x1D
2014-11-06 23:07:00 +00:00
# define KXCJK1013_REG_INT_CTRL1 0x1E
# define KXCJK1013_REG_INT_CTRL2 0x1F
2017-09-17 17:01:04 +02:00
# define KXTF9_REG_INT_CTRL3 0x20
2014-11-06 23:07:00 +00:00
# define KXCJK1013_REG_DATA_CTRL 0x21
2017-09-17 17:01:04 +02:00
# define KXTF9_REG_TILT_TIMER 0x28
2014-11-06 23:07:00 +00:00
# define KXCJK1013_REG_WAKE_TIMER 0x29
2017-09-17 17:01:04 +02:00
# define KXTF9_REG_TDT_TIMER 0x2B
# define KXTF9_REG_TDT_THRESH_H 0x2C
# define KXTF9_REG_TDT_THRESH_L 0x2D
# define KXTF9_REG_TDT_TAP_TIMER 0x2E
# define KXTF9_REG_TDT_TOTAL_TIMER 0x2F
# define KXTF9_REG_TDT_LATENCY_TIMER 0x30
# define KXTF9_REG_TDT_WINDOW_TIMER 0x31
2014-11-06 23:07:00 +00:00
# define KXCJK1013_REG_SELF_TEST 0x3A
2017-09-17 17:01:04 +02:00
# define KXTF9_REG_WAKE_THRESH 0x5A
# define KXTF9_REG_TILT_ANGLE 0x5C
# define KXTF9_REG_HYST_SET 0x5F
2014-11-06 23:07:00 +00:00
# define KXCJK1013_REG_WAKE_THRES 0x6A
2021-05-11 16:24:02 +02:00
/* Everything up to 0x11 is equal to KXCJK1013/KXTF9 above */
# define KX023_REG_INS1 0x12
# define KX023_REG_INS2 0x13
# define KX023_REG_INS3 0x14
# define KX023_REG_STAT 0x15
# define KX023_REG_INT_REL 0x17
# define KX023_REG_CNTL1 0x18
# define KX023_REG_CNTL2 0x19
# define KX023_REG_CNTL3 0x1A
# define KX023_REG_ODCNTL 0x1B
# define KX023_REG_INC1 0x1C
# define KX023_REG_INC2 0x1D
# define KX023_REG_INC3 0x1E
# define KX023_REG_INC4 0x1F
# define KX023_REG_INC5 0x20
# define KX023_REG_INC6 0x21
# define KX023_REG_TILT_TIMER 0x22
# define KX023_REG_WUFC 0x23
# define KX023_REG_TDTRC 0x24
# define KX023_REG_TDTC 0x25
# define KX023_REG_TTH 0x26
# define KX023_REG_TTL 0x27
# define KX023_REG_FTD 0x28
# define KX023_REG_STD 0x29
# define KX023_REG_TLT 0x2A
# define KX023_REG_TWS 0x2B
# define KX023_REG_ATH 0x30
# define KX023_REG_TILT_ANGLE_LL 0x32
# define KX023_REG_TILT_ANGLE_HL 0x33
# define KX023_REG_HYST_SET 0x34
# define KX023_REG_LP_CNTL 0x35
# define KX023_REG_BUF_CNTL1 0x3A
# define KX023_REG_BUF_CNTL2 0x3B
# define KX023_REG_BUF_STATUS_1 0x3C
# define KX023_REG_BUF_STATUS_2 0x3D
# define KX023_REG_BUF_CLEAR 0x3E
# define KX023_REG_BUF_READ 0x3F
# define KX023_REG_SELF_TEST 0x60
2014-11-06 23:07:00 +00:00
# define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7)
# define KXCJK1013_REG_CTRL1_BIT_RES BIT(6)
# define KXCJK1013_REG_CTRL1_BIT_DRDY BIT(5)
# define KXCJK1013_REG_CTRL1_BIT_GSEL1 BIT(4)
# define KXCJK1013_REG_CTRL1_BIT_GSEL0 BIT(3)
# define KXCJK1013_REG_CTRL1_BIT_WUFE BIT(1)
2017-09-17 17:01:02 +02:00
2017-09-17 17:01:04 +02:00
# define KXCJK1013_REG_INT_CTRL1_BIT_IEU BIT(2) /* KXTF9 */
2017-09-17 17:01:02 +02:00
# define KXCJK1013_REG_INT_CTRL1_BIT_IEL BIT(3)
# define KXCJK1013_REG_INT_CTRL1_BIT_IEA BIT(4)
# define KXCJK1013_REG_INT_CTRL1_BIT_IEN BIT(5)
2014-11-06 23:07:00 +00:00
2017-09-17 17:01:04 +02:00
# define KXTF9_REG_TILT_BIT_LEFT_EDGE BIT(5)
# define KXTF9_REG_TILT_BIT_RIGHT_EDGE BIT(4)
# define KXTF9_REG_TILT_BIT_LOWER_EDGE BIT(3)
# define KXTF9_REG_TILT_BIT_UPPER_EDGE BIT(2)
# define KXTF9_REG_TILT_BIT_FACE_DOWN BIT(1)
# define KXTF9_REG_TILT_BIT_FACE_UP BIT(0)
2014-11-06 23:07:00 +00:00
# define KXCJK1013_DATA_MASK_12_BIT 0x0FFF
# define KXCJK1013_MAX_STARTUP_TIME_US 100000
2014-05-08 22:58:00 +01:00
# define KXCJK1013_SLEEP_DELAY_MS 2000
2017-09-17 17:01:04 +02:00
# define KXCJK1013_REG_INT_SRC1_BIT_TPS BIT(0) /* KXTF9 */
2017-09-17 17:01:02 +02:00
# define KXCJK1013_REG_INT_SRC1_BIT_WUFS BIT(1)
2017-09-17 17:01:04 +02:00
# define KXCJK1013_REG_INT_SRC1_MASK_TDTS (BIT(2) | BIT(3)) /* KXTF9 */
# define KXCJK1013_REG_INT_SRC1_TAP_NONE 0
# define KXCJK1013_REG_INT_SRC1_TAP_SINGLE BIT(2)
# define KXCJK1013_REG_INT_SRC1_TAP_DOUBLE BIT(3)
2017-09-17 17:01:02 +02:00
# define KXCJK1013_REG_INT_SRC1_BIT_DRDY BIT(4)
2017-09-17 17:01:04 +02:00
/* KXCJK: INT_SOURCE2: motion detect, KXTF9: INT_SRC_REG1: tap detect */
2014-08-22 20:01:00 +01:00
# define KXCJK1013_REG_INT_SRC2_BIT_ZP BIT(0)
# define KXCJK1013_REG_INT_SRC2_BIT_ZN BIT(1)
# define KXCJK1013_REG_INT_SRC2_BIT_YP BIT(2)
# define KXCJK1013_REG_INT_SRC2_BIT_YN BIT(3)
# define KXCJK1013_REG_INT_SRC2_BIT_XP BIT(4)
# define KXCJK1013_REG_INT_SRC2_BIT_XN BIT(5)
2021-05-11 16:24:02 +02:00
/* KX023 interrupt routing to INT1. INT2 can be configured with INC6 */
# define KX023_REG_INC4_BFI1 BIT(6)
# define KX023_REG_INC4_WMI1 BIT(5)
# define KX023_REG_INC4_DRDY1 BIT(4)
# define KX023_REG_INC4_TDTI1 BIT(2)
# define KX023_REG_INC4_WUFI1 BIT(1)
# define KX023_REG_INC4_TPI1 BIT(0)
2014-08-22 20:01:00 +01:00
# define KXCJK1013_DEFAULT_WAKE_THRES 1
2014-03-09 08:33:00 +00:00
enum kx_chipset {
KXCJK1013 ,
KXCJ91008 ,
KXTJ21009 ,
2017-09-17 17:01:04 +02:00
KXTF9 ,
2021-05-11 16:24:02 +02:00
KX0231025 ,
2014-03-09 08:33:00 +00:00
KX_MAX_CHIPS /* this must be last */
} ;
2020-11-10 14:38:34 +01:00
enum kx_acpi_type {
ACPI_GENERIC ,
ACPI_SMO8500 ,
2020-11-10 14:38:35 +01:00
ACPI_KIOX010A ,
2020-11-10 14:38:34 +01:00
} ;
2021-05-11 16:24:01 +02:00
struct kx_chipset_regs {
u8 int_src1 ;
u8 int_src2 ;
u8 int_rel ;
u8 ctrl1 ;
u8 wuf_ctrl ;
u8 int_ctrl1 ;
u8 data_ctrl ;
u8 wake_timer ;
u8 wake_thres ;
} ;
static const struct kx_chipset_regs kxcjk1013_regs = {
. int_src1 = KXCJK1013_REG_INT_SRC1 ,
. int_src2 = KXCJK1013_REG_INT_SRC2 ,
. int_rel = KXCJK1013_REG_INT_REL ,
. ctrl1 = KXCJK1013_REG_CTRL1 ,
. wuf_ctrl = KXCJK1013_REG_CTRL2 ,
. int_ctrl1 = KXCJK1013_REG_INT_CTRL1 ,
. data_ctrl = KXCJK1013_REG_DATA_CTRL ,
. wake_timer = KXCJK1013_REG_WAKE_TIMER ,
. wake_thres = KXCJK1013_REG_WAKE_THRES ,
} ;
static const struct kx_chipset_regs kxtf9_regs = {
/* .int_src1 was moved to INT_SRC2 on KXTF9 */
. int_src1 = KXTF9_REG_INT_SRC2 ,
/* .int_src2 is not available */
. int_rel = KXCJK1013_REG_INT_REL ,
. ctrl1 = KXCJK1013_REG_CTRL1 ,
. wuf_ctrl = KXTF9_REG_CTRL3 ,
. int_ctrl1 = KXCJK1013_REG_INT_CTRL1 ,
. data_ctrl = KXCJK1013_REG_DATA_CTRL ,
. wake_timer = KXCJK1013_REG_WAKE_TIMER ,
. wake_thres = KXTF9_REG_WAKE_THRESH ,
} ;
2021-05-11 16:24:02 +02:00
/* The registers have totally different names but the bits are compatible */
static const struct kx_chipset_regs kx0231025_regs = {
. int_src1 = KX023_REG_INS2 ,
. int_src2 = KX023_REG_INS3 ,
. int_rel = KX023_REG_INT_REL ,
. ctrl1 = KX023_REG_CNTL1 ,
. wuf_ctrl = KX023_REG_CNTL3 ,
. int_ctrl1 = KX023_REG_INC1 ,
. data_ctrl = KX023_REG_ODCNTL ,
. wake_timer = KX023_REG_WUFC ,
. wake_thres = KX023_REG_ATH ,
} ;
2021-05-01 18:01:06 +01:00
enum kxcjk1013_axis {
AXIS_X ,
AXIS_Y ,
AXIS_Z ,
AXIS_MAX
} ;
2014-11-06 23:07:00 +00:00
struct kxcjk1013_data {
2020-12-13 22:54:36 +05:30
struct regulator_bulk_data regulators [ 2 ] ;
2014-11-06 23:07:00 +00:00
struct i2c_client * client ;
2014-08-22 20:01:00 +01:00
struct iio_trigger * dready_trig ;
struct iio_trigger * motion_trig ;
2020-01-12 23:33:00 +03:00
struct iio_mount_matrix orientation ;
2014-11-06 23:07:00 +00:00
struct mutex mutex ;
2021-05-01 18:01:06 +01:00
/* Ensure timestamp naturally aligned */
struct {
s16 chans [ AXIS_MAX ] ;
s64 timestamp __aligned ( 8 ) ;
} scan ;
2014-11-06 23:07:00 +00:00
u8 odr_bits ;
2014-05-08 22:58:00 +01:00
u8 range ;
2014-08-22 20:01:00 +01:00
int wake_thres ;
int wake_dur ;
2014-11-06 23:07:00 +00:00
bool active_high_intr ;
2014-08-22 20:01:00 +01:00
bool dready_trigger_on ;
int ev_enable_state ;
bool motion_trigger_on ;
int64_t timestamp ;
2014-03-09 08:33:00 +00:00
enum kx_chipset chipset ;
2020-11-10 14:38:34 +01:00
enum kx_acpi_type acpi_type ;
2021-05-11 16:24:01 +02:00
const struct kx_chipset_regs * regs ;
2014-11-06 23:07:00 +00:00
} ;
enum kxcjk1013_mode {
STANDBY ,
OPERATION ,
} ;
2014-05-08 22:58:00 +01:00
enum kxcjk1013_range {
KXCJK1013_RANGE_2G ,
KXCJK1013_RANGE_4G ,
KXCJK1013_RANGE_8G ,
} ;
2017-09-17 17:01:01 +02:00
struct kx_odr_map {
2014-11-06 23:07:00 +00:00
int val ;
int val2 ;
int odr_bits ;
2017-09-17 17:01:01 +02:00
int wuf_bits ;
} ;
static const struct kx_odr_map samp_freq_table [ ] = {
{ 0 , 781000 , 0x08 , 0x00 } ,
{ 1 , 563000 , 0x09 , 0x01 } ,
{ 3 , 125000 , 0x0A , 0x02 } ,
{ 6 , 250000 , 0x0B , 0x03 } ,
{ 12 , 500000 , 0x00 , 0x04 } ,
{ 25 , 0 , 0x01 , 0x05 } ,
{ 50 , 0 , 0x02 , 0x06 } ,
{ 100 , 0 , 0x03 , 0x06 } ,
{ 200 , 0 , 0x04 , 0x06 } ,
{ 400 , 0 , 0x05 , 0x06 } ,
{ 800 , 0 , 0x06 , 0x06 } ,
{ 1600 , 0 , 0x07 , 0x06 } ,
} ;
2014-11-06 23:07:00 +00:00
2017-09-17 17:01:03 +02:00
static const char * const kxcjk1013_samp_freq_avail =
" 0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600 " ;
2017-09-17 17:01:04 +02:00
static const struct kx_odr_map kxtf9_samp_freq_table [ ] = {
{ 25 , 0 , 0x01 , 0x00 } ,
{ 50 , 0 , 0x02 , 0x01 } ,
{ 100 , 0 , 0x03 , 0x01 } ,
{ 200 , 0 , 0x04 , 0x01 } ,
{ 400 , 0 , 0x05 , 0x01 } ,
{ 800 , 0 , 0x06 , 0x01 } ,
} ;
static const char * const kxtf9_samp_freq_avail =
" 25 50 100 200 400 800 " ;
2014-11-06 23:07:00 +00:00
/* Refer to section 4 of the specification */
static const struct {
int odr_bits ;
int usec ;
2014-03-09 08:33:00 +00:00
} odr_start_up_times [ KX_MAX_CHIPS ] [ 12 ] = {
/* KXCJK-1013 */
{
{ 0x08 , 100000 } ,
{ 0x09 , 100000 } ,
{ 0x0A , 100000 } ,
{ 0x0B , 100000 } ,
{ 0 , 80000 } ,
{ 0x01 , 41000 } ,
{ 0x02 , 21000 } ,
{ 0x03 , 11000 } ,
{ 0x04 , 6400 } ,
{ 0x05 , 3900 } ,
{ 0x06 , 2700 } ,
{ 0x07 , 2100 } ,
} ,
/* KXCJ9-1008 */
{
{ 0x08 , 100000 } ,
{ 0x09 , 100000 } ,
{ 0x0A , 100000 } ,
{ 0x0B , 100000 } ,
{ 0 , 80000 } ,
{ 0x01 , 41000 } ,
{ 0x02 , 21000 } ,
{ 0x03 , 11000 } ,
{ 0x04 , 6400 } ,
{ 0x05 , 3900 } ,
{ 0x06 , 2700 } ,
{ 0x07 , 2100 } ,
} ,
/* KXCTJ2-1009 */
{
{ 0x08 , 1240000 } ,
{ 0x09 , 621000 } ,
{ 0x0A , 309000 } ,
{ 0x0B , 151000 } ,
{ 0 , 80000 } ,
{ 0x01 , 41000 } ,
{ 0x02 , 21000 } ,
{ 0x03 , 11000 } ,
{ 0x04 , 6000 } ,
{ 0x05 , 4000 } ,
{ 0x06 , 3000 } ,
{ 0x07 , 2000 } ,
} ,
2017-09-17 17:01:04 +02:00
/* KXTF9 */
{
{ 0x01 , 81000 } ,
{ 0x02 , 41000 } ,
{ 0x03 , 21000 } ,
{ 0x04 , 11000 } ,
{ 0x05 , 5100 } ,
{ 0x06 , 2700 } ,
} ,
2021-05-11 16:24:02 +02:00
/* KX023-1025 */
{
/* First 4 are not in datasheet, taken from KXCTJ2-1009 */
{ 0x08 , 1240000 } ,
{ 0x09 , 621000 } ,
{ 0x0A , 309000 } ,
{ 0x0B , 151000 } ,
{ 0 , 81000 } ,
{ 0x01 , 40000 } ,
{ 0x02 , 22000 } ,
{ 0x03 , 12000 } ,
{ 0x04 , 7000 } ,
{ 0x05 , 4400 } ,
{ 0x06 , 3000 } ,
{ 0x07 , 3000 } ,
} ,
2014-03-09 08:33:00 +00:00
} ;
2014-11-06 23:07:00 +00:00
2014-05-08 22:58:00 +01:00
static const struct {
u16 scale ;
u8 gsel_0 ;
u8 gsel_1 ;
} KXCJK1013_scale_table [ ] = { { 9582 , 0 , 0 } ,
{ 19163 , 1 , 0 } ,
{ 38326 , 0 , 1 } } ;
2020-11-10 14:38:35 +01:00
# ifdef CONFIG_ACPI
enum kiox010a_fn_index {
KIOX010A_SET_LAPTOP_MODE = 1 ,
KIOX010A_SET_TABLET_MODE = 2 ,
} ;
static int kiox010a_dsm ( struct device * dev , int fn_index )
{
acpi_handle handle = ACPI_HANDLE ( dev ) ;
guid_t kiox010a_dsm_guid ;
union acpi_object * obj ;
if ( ! handle )
return - ENODEV ;
guid_parse ( " 1f339696-d475-4e26-8cad-2e9f8e6d7a91 " , & kiox010a_dsm_guid ) ;
obj = acpi_evaluate_dsm ( handle , & kiox010a_dsm_guid , 1 , fn_index , NULL ) ;
if ( ! obj )
return - EIO ;
ACPI_FREE ( obj ) ;
return 0 ;
}
# endif
2014-11-06 23:07:00 +00:00
static int kxcjk1013_set_mode ( struct kxcjk1013_data * data ,
enum kxcjk1013_mode mode )
{
int ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > ctrl1 ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_ctrl1 \n " ) ;
return ret ;
}
if ( mode = = STANDBY )
ret & = ~ KXCJK1013_REG_CTRL1_BIT_PC1 ;
else
ret | = KXCJK1013_REG_CTRL1_BIT_PC1 ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > ctrl1 , ret ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_ctrl1 \n " ) ;
return ret ;
}
return 0 ;
}
2014-05-08 22:58:00 +01:00
static int kxcjk1013_get_mode ( struct kxcjk1013_data * data ,
enum kxcjk1013_mode * mode )
{
int ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > ctrl1 ) ;
2014-05-08 22:58:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_ctrl1 \n " ) ;
return ret ;
}
if ( ret & KXCJK1013_REG_CTRL1_BIT_PC1 )
* mode = OPERATION ;
else
* mode = STANDBY ;
return 0 ;
}
2014-05-08 22:58:00 +01:00
static int kxcjk1013_set_range ( struct kxcjk1013_data * data , int range_index )
{
int ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > ctrl1 ) ;
2014-05-08 22:58:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_ctrl1 \n " ) ;
return ret ;
}
2014-11-10 10:20:16 +02:00
ret & = ~ ( KXCJK1013_REG_CTRL1_BIT_GSEL0 |
KXCJK1013_REG_CTRL1_BIT_GSEL1 ) ;
2014-05-08 22:58:00 +01:00
ret | = ( KXCJK1013_scale_table [ range_index ] . gsel_0 < < 3 ) ;
ret | = ( KXCJK1013_scale_table [ range_index ] . gsel_1 < < 4 ) ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > ctrl1 , ret ) ;
2014-05-08 22:58:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_ctrl1 \n " ) ;
return ret ;
}
data - > range = range_index ;
return 0 ;
}
2014-11-06 23:07:00 +00:00
static int kxcjk1013_chip_init ( struct kxcjk1013_data * data )
{
int ret ;
2020-11-10 14:38:35 +01:00
# ifdef CONFIG_ACPI
if ( data - > acpi_type = = ACPI_KIOX010A ) {
/* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */
kiox010a_dsm ( & data - > client - > dev , KIOX010A_SET_LAPTOP_MODE ) ;
}
# endif
2014-11-06 23:07:00 +00:00
ret = i2c_smbus_read_byte_data ( data - > client , KXCJK1013_REG_WHO_AM_I ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading who_am_i \n " ) ;
return ret ;
}
dev_dbg ( & data - > client - > dev , " KXCJK1013 Chip Id %x \n " , ret ) ;
ret = kxcjk1013_set_mode ( data , STANDBY ) ;
if ( ret < 0 )
return ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > ctrl1 ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_ctrl1 \n " ) ;
return ret ;
}
/* Set 12 bit mode */
ret | = KXCJK1013_REG_CTRL1_BIT_RES ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > ctrl1 , ret ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_ctrl \n " ) ;
return ret ;
}
2014-05-08 22:58:00 +01:00
/* Setting range to 4G */
ret = kxcjk1013_set_range ( data , KXCJK1013_RANGE_4G ) ;
if ( ret < 0 )
return ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > data_ctrl ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_data_ctrl \n " ) ;
return ret ;
}
data - > odr_bits = ret ;
/* Set up INT polarity */
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > int_ctrl1 ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_int_ctrl1 \n " ) ;
return ret ;
}
if ( data - > active_high_intr )
2017-09-17 17:01:02 +02:00
ret | = KXCJK1013_REG_INT_CTRL1_BIT_IEA ;
2014-11-06 23:07:00 +00:00
else
2017-09-17 17:01:02 +02:00
ret & = ~ KXCJK1013_REG_INT_CTRL1_BIT_IEA ;
2014-11-06 23:07:00 +00:00
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > int_ctrl1 , ret ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_int_ctrl1 \n " ) ;
return ret ;
}
2021-05-11 16:24:02 +02:00
/* On KX023, route all used interrupts to INT1 for now */
if ( data - > chipset = = KX0231025 & & data - > client - > irq > 0 ) {
ret = i2c_smbus_write_byte_data ( data - > client , KX023_REG_INC4 ,
KX023_REG_INC4_DRDY1 |
KX023_REG_INC4_WUFI1 ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_inc4 \n " ) ;
return ret ;
}
}
2014-05-08 22:58:00 +01:00
ret = kxcjk1013_set_mode ( data , OPERATION ) ;
if ( ret < 0 )
return ret ;
2014-08-22 20:01:00 +01:00
data - > wake_thres = KXCJK1013_DEFAULT_WAKE_THRES ;
2014-05-08 22:58:00 +01:00
return 0 ;
}
2014-12-04 01:08:13 +01:00
# ifdef CONFIG_PM
2014-05-08 22:58:00 +01:00
static int kxcjk1013_get_startup_times ( struct kxcjk1013_data * data )
{
int i ;
2014-03-09 08:33:00 +00:00
int idx = data - > chipset ;
2014-05-08 22:58:00 +01:00
2014-03-09 08:33:00 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( odr_start_up_times [ idx ] ) ; + + i ) {
if ( odr_start_up_times [ idx ] [ i ] . odr_bits = = data - > odr_bits )
return odr_start_up_times [ idx ] [ i ] . usec ;
2014-05-08 22:58:00 +01:00
}
return KXCJK1013_MAX_STARTUP_TIME_US ;
}
2014-03-09 16:13:00 +00:00
# endif
2014-05-08 22:58:00 +01:00
static int kxcjk1013_set_power_state ( struct kxcjk1013_data * data , bool on )
{
2014-12-06 00:18:08 +02:00
# ifdef CONFIG_PM
2014-05-08 22:58:00 +01:00
int ret ;
if ( on )
2021-05-09 12:33:33 +01:00
ret = pm_runtime_resume_and_get ( & data - > client - > dev ) ;
2014-05-08 22:58:00 +01:00
else {
pm_runtime_mark_last_busy ( & data - > client - > dev ) ;
ret = pm_runtime_put_autosuspend ( & data - > client - > dev ) ;
}
if ( ret < 0 ) {
dev_err ( & data - > client - > dev ,
2019-04-19 11:36:51 +03:00
" Failed: %s for %d \n " , __func__ , on ) ;
2014-05-08 22:58:00 +01:00
return ret ;
}
2014-12-06 00:18:08 +02:00
# endif
2014-05-08 22:58:00 +01:00
2014-11-06 23:07:00 +00:00
return 0 ;
}
2014-08-22 20:01:00 +01:00
static int kxcjk1013_chip_update_thresholds ( struct kxcjk1013_data * data )
{
2021-05-11 16:24:01 +02:00
int ret ;
2014-08-22 20:01:00 +01:00
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > wake_timer ,
2014-08-22 20:01:00 +01:00
data - > wake_dur ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev ,
" Error writing reg_wake_timer \n " ) ;
return ret ;
}
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > wake_thres ,
2014-08-22 20:01:00 +01:00
data - > wake_thres ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_wake_thres \n " ) ;
return ret ;
}
return 0 ;
}
static int kxcjk1013_setup_any_motion_interrupt ( struct kxcjk1013_data * data ,
bool status )
{
int ret ;
enum kxcjk1013_mode store_mode ;
ret = kxcjk1013_get_mode ( data , & store_mode ) ;
if ( ret < 0 )
return ret ;
/* This is requirement by spec to change state to STANDBY */
ret = kxcjk1013_set_mode ( data , STANDBY ) ;
if ( ret < 0 )
return ret ;
ret = kxcjk1013_chip_update_thresholds ( data ) ;
if ( ret < 0 )
return ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > int_ctrl1 ) ;
2014-08-22 20:01:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_int_ctrl1 \n " ) ;
return ret ;
}
if ( status )
2017-09-17 17:01:02 +02:00
ret | = KXCJK1013_REG_INT_CTRL1_BIT_IEN ;
2014-08-22 20:01:00 +01:00
else
2017-09-17 17:01:02 +02:00
ret & = ~ KXCJK1013_REG_INT_CTRL1_BIT_IEN ;
2014-08-22 20:01:00 +01:00
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > int_ctrl1 , ret ) ;
2014-08-22 20:01:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_int_ctrl1 \n " ) ;
return ret ;
}
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > ctrl1 ) ;
2014-08-22 20:01:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_ctrl1 \n " ) ;
return ret ;
}
if ( status )
ret | = KXCJK1013_REG_CTRL1_BIT_WUFE ;
else
ret & = ~ KXCJK1013_REG_CTRL1_BIT_WUFE ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > ctrl1 , ret ) ;
2014-08-22 20:01:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_ctrl1 \n " ) ;
return ret ;
}
if ( store_mode = = OPERATION ) {
ret = kxcjk1013_set_mode ( data , OPERATION ) ;
if ( ret < 0 )
return ret ;
}
return 0 ;
}
static int kxcjk1013_setup_new_data_interrupt ( struct kxcjk1013_data * data ,
bool status )
2014-11-06 23:07:00 +00:00
{
int ret ;
2014-05-08 22:58:00 +01:00
enum kxcjk1013_mode store_mode ;
ret = kxcjk1013_get_mode ( data , & store_mode ) ;
if ( ret < 0 )
return ret ;
2014-11-06 23:07:00 +00:00
/* This is requirement by spec to change state to STANDBY */
ret = kxcjk1013_set_mode ( data , STANDBY ) ;
if ( ret < 0 )
return ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > int_ctrl1 ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_int_ctrl1 \n " ) ;
return ret ;
}
if ( status )
2017-09-17 17:01:02 +02:00
ret | = KXCJK1013_REG_INT_CTRL1_BIT_IEN ;
2014-11-06 23:07:00 +00:00
else
2017-09-17 17:01:02 +02:00
ret & = ~ KXCJK1013_REG_INT_CTRL1_BIT_IEN ;
2014-11-06 23:07:00 +00:00
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > int_ctrl1 , ret ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_int_ctrl1 \n " ) ;
return ret ;
}
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > ctrl1 ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_ctrl1 \n " ) ;
return ret ;
}
if ( status )
ret | = KXCJK1013_REG_CTRL1_BIT_DRDY ;
else
ret & = ~ KXCJK1013_REG_CTRL1_BIT_DRDY ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > ctrl1 , ret ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_ctrl1 \n " ) ;
return ret ;
}
2014-05-08 22:58:00 +01:00
if ( store_mode = = OPERATION ) {
ret = kxcjk1013_set_mode ( data , OPERATION ) ;
if ( ret < 0 )
return ret ;
}
return 0 ;
2014-11-06 23:07:00 +00:00
}
2017-09-17 17:01:01 +02:00
static const struct kx_odr_map * kxcjk1013_find_odr_value (
const struct kx_odr_map * map , size_t map_size , int val , int val2 )
2014-11-06 23:07:00 +00:00
{
int i ;
2017-09-17 17:01:01 +02:00
for ( i = 0 ; i < map_size ; + + i ) {
if ( map [ i ] . val = = val & & map [ i ] . val2 = = val2 )
return & map [ i ] ;
2014-11-06 23:07:00 +00:00
}
2017-09-17 17:01:01 +02:00
return ERR_PTR ( - EINVAL ) ;
2014-11-06 23:07:00 +00:00
}
2017-09-17 17:01:01 +02:00
static int kxcjk1013_convert_odr_value ( const struct kx_odr_map * map ,
size_t map_size , int odr_bits ,
int * val , int * val2 )
2014-08-22 20:01:00 +01:00
{
int i ;
2017-09-17 17:01:01 +02:00
for ( i = 0 ; i < map_size ; + + i ) {
if ( map [ i ] . odr_bits = = odr_bits ) {
* val = map [ i ] . val ;
* val2 = map [ i ] . val2 ;
return IIO_VAL_INT_PLUS_MICRO ;
2014-08-22 20:01:00 +01:00
}
}
return - EINVAL ;
}
2014-11-06 23:07:00 +00:00
static int kxcjk1013_set_odr ( struct kxcjk1013_data * data , int val , int val2 )
{
int ret ;
2014-05-08 22:58:00 +01:00
enum kxcjk1013_mode store_mode ;
2017-09-17 17:01:01 +02:00
const struct kx_odr_map * odr_setting ;
2014-05-08 22:58:00 +01:00
ret = kxcjk1013_get_mode ( data , & store_mode ) ;
if ( ret < 0 )
return ret ;
2014-11-06 23:07:00 +00:00
2017-09-17 17:01:04 +02:00
if ( data - > chipset = = KXTF9 )
odr_setting = kxcjk1013_find_odr_value ( kxtf9_samp_freq_table ,
ARRAY_SIZE ( kxtf9_samp_freq_table ) ,
val , val2 ) ;
else
odr_setting = kxcjk1013_find_odr_value ( samp_freq_table ,
ARRAY_SIZE ( samp_freq_table ) ,
val , val2 ) ;
2017-09-17 17:01:01 +02:00
if ( IS_ERR ( odr_setting ) )
return PTR_ERR ( odr_setting ) ;
2014-11-06 23:07:00 +00:00
/* To change ODR, the chip must be set to STANDBY as per spec */
ret = kxcjk1013_set_mode ( data , STANDBY ) ;
if ( ret < 0 )
return ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > data_ctrl ,
2017-09-17 17:01:01 +02:00
odr_setting - > odr_bits ) ;
2014-11-06 23:07:00 +00:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing data_ctrl \n " ) ;
return ret ;
}
2017-09-17 17:01:01 +02:00
data - > odr_bits = odr_setting - > odr_bits ;
2014-08-22 20:01:00 +01:00
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_write_byte_data ( data - > client , data - > regs - > wuf_ctrl ,
2017-09-17 17:01:01 +02:00
odr_setting - > wuf_bits ) ;
2014-08-22 20:01:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error writing reg_ctrl2 \n " ) ;
return ret ;
}
2014-05-08 22:58:00 +01:00
if ( store_mode = = OPERATION ) {
2014-11-06 23:07:00 +00:00
ret = kxcjk1013_set_mode ( data , OPERATION ) ;
if ( ret < 0 )
return ret ;
}
return 0 ;
}
static int kxcjk1013_get_odr ( struct kxcjk1013_data * data , int * val , int * val2 )
{
2017-09-17 17:01:04 +02:00
if ( data - > chipset = = KXTF9 )
return kxcjk1013_convert_odr_value ( kxtf9_samp_freq_table ,
ARRAY_SIZE ( kxtf9_samp_freq_table ) ,
data - > odr_bits , val , val2 ) ;
else
return kxcjk1013_convert_odr_value ( samp_freq_table ,
ARRAY_SIZE ( samp_freq_table ) ,
data - > odr_bits , val , val2 ) ;
2014-11-06 23:07:00 +00:00
}
static int kxcjk1013_get_acc_reg ( struct kxcjk1013_data * data , int axis )
{
u8 reg = KXCJK1013_REG_XOUT_L + axis * 2 ;
int ret ;
ret = i2c_smbus_read_word_data ( data - > client , reg ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev ,
" failed to read accel_%c registers \n " , ' x ' + axis ) ;
return ret ;
}
return ret ;
}
2014-05-08 22:58:00 +01:00
static int kxcjk1013_set_scale ( struct kxcjk1013_data * data , int val )
{
int ret , i ;
enum kxcjk1013_mode store_mode ;
for ( i = 0 ; i < ARRAY_SIZE ( KXCJK1013_scale_table ) ; + + i ) {
if ( KXCJK1013_scale_table [ i ] . scale = = val ) {
ret = kxcjk1013_get_mode ( data , & store_mode ) ;
if ( ret < 0 )
return ret ;
ret = kxcjk1013_set_mode ( data , STANDBY ) ;
if ( ret < 0 )
return ret ;
ret = kxcjk1013_set_range ( data , i ) ;
if ( ret < 0 )
return ret ;
if ( store_mode = = OPERATION ) {
ret = kxcjk1013_set_mode ( data , OPERATION ) ;
if ( ret )
return ret ;
}
return 0 ;
}
}
return - EINVAL ;
}
2014-11-06 23:07:00 +00:00
static int kxcjk1013_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan , int * val ,
int * val2 , long mask )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
int ret ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
mutex_lock ( & data - > mutex ) ;
if ( iio_buffer_enabled ( indio_dev ) )
ret = - EBUSY ;
else {
2014-05-08 22:58:00 +01:00
ret = kxcjk1013_set_power_state ( data , true ) ;
2014-06-16 20:00:00 +01:00
if ( ret < 0 ) {
mutex_unlock ( & data - > mutex ) ;
2014-11-06 23:07:00 +00:00
return ret ;
2014-06-16 20:00:00 +01:00
}
2014-11-06 23:07:00 +00:00
ret = kxcjk1013_get_acc_reg ( data , chan - > scan_index ) ;
2014-05-08 22:58:00 +01:00
if ( ret < 0 ) {
kxcjk1013_set_power_state ( data , false ) ;
mutex_unlock ( & data - > mutex ) ;
return ret ;
}
* val = sign_extend32 ( ret > > 4 , 11 ) ;
ret = kxcjk1013_set_power_state ( data , false ) ;
2014-11-06 23:07:00 +00:00
}
mutex_unlock ( & data - > mutex ) ;
if ( ret < 0 )
return ret ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
* val = 0 ;
2014-05-08 22:58:00 +01:00
* val2 = KXCJK1013_scale_table [ data - > range ] . scale ;
2014-11-06 23:07:00 +00:00
return IIO_VAL_INT_PLUS_MICRO ;
case IIO_CHAN_INFO_SAMP_FREQ :
mutex_lock ( & data - > mutex ) ;
ret = kxcjk1013_get_odr ( data , val , val2 ) ;
mutex_unlock ( & data - > mutex ) ;
return ret ;
default :
return - EINVAL ;
}
}
static int kxcjk1013_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan , int val ,
int val2 , long mask )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
int ret ;
switch ( mask ) {
case IIO_CHAN_INFO_SAMP_FREQ :
mutex_lock ( & data - > mutex ) ;
ret = kxcjk1013_set_odr ( data , val , val2 ) ;
mutex_unlock ( & data - > mutex ) ;
break ;
2014-05-08 22:58:00 +01:00
case IIO_CHAN_INFO_SCALE :
if ( val )
return - EINVAL ;
mutex_lock ( & data - > mutex ) ;
ret = kxcjk1013_set_scale ( data , val2 ) ;
mutex_unlock ( & data - > mutex ) ;
break ;
2014-11-06 23:07:00 +00:00
default :
ret = - EINVAL ;
}
return ret ;
}
2014-08-22 20:01:00 +01:00
static int kxcjk1013_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 )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
* val2 = 0 ;
switch ( info ) {
case IIO_EV_INFO_VALUE :
* val = data - > wake_thres ;
break ;
case IIO_EV_INFO_PERIOD :
* val = data - > wake_dur ;
break ;
default :
return - EINVAL ;
}
return IIO_VAL_INT ;
}
static int kxcjk1013_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 )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
if ( data - > ev_enable_state )
return - EBUSY ;
switch ( info ) {
case IIO_EV_INFO_VALUE :
data - > wake_thres = val ;
break ;
case IIO_EV_INFO_PERIOD :
data - > wake_dur = val ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
static int kxcjk1013_read_event_config ( struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan ,
enum iio_event_type type ,
enum iio_event_direction dir )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
return data - > ev_enable_state ;
}
static int kxcjk1013_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 )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
int ret ;
if ( state & & data - > ev_enable_state )
return 0 ;
mutex_lock ( & data - > mutex ) ;
if ( ! state & & data - > motion_trigger_on ) {
data - > ev_enable_state = 0 ;
mutex_unlock ( & data - > mutex ) ;
return 0 ;
}
/*
* We will expect the enable and disable to do operation in
* in reverse order . This will happen here anyway as our
* resume operation uses sync mode runtime pm calls , the
* suspend operation will be delayed by autosuspend delay
* So the disable operation will still happen in reverse of
* enable operation . When runtime pm is disabled the mode
* is always on so sequence doesn ' t matter
*/
ret = kxcjk1013_set_power_state ( data , state ) ;
if ( ret < 0 ) {
mutex_unlock ( & data - > mutex ) ;
return ret ;
}
ret = kxcjk1013_setup_any_motion_interrupt ( data , state ) ;
if ( ret < 0 ) {
2014-12-10 18:23:53 +02:00
kxcjk1013_set_power_state ( data , false ) ;
data - > ev_enable_state = 0 ;
2014-08-22 20:01:00 +01:00
mutex_unlock ( & data - > mutex ) ;
return ret ;
}
data - > ev_enable_state = state ;
mutex_unlock ( & data - > mutex ) ;
return 0 ;
}
2015-04-03 15:03:02 +03:00
static int kxcjk1013_buffer_preenable ( struct iio_dev * indio_dev )
2014-11-06 23:07:00 +00:00
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2015-04-03 15:03:02 +03:00
return kxcjk1013_set_power_state ( data , true ) ;
}
2014-11-06 23:07:00 +00:00
2015-04-03 15:03:02 +03:00
static int kxcjk1013_buffer_postdisable ( struct iio_dev * indio_dev )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
return kxcjk1013_set_power_state ( data , false ) ;
2014-11-06 23:07:00 +00:00
}
2017-09-17 17:01:03 +02:00
static ssize_t kxcjk1013_get_samp_freq_avail ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
2017-09-17 17:01:04 +02:00
struct iio_dev * indio_dev = dev_to_iio_dev ( dev ) ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
const char * str ;
if ( data - > chipset = = KXTF9 )
str = kxtf9_samp_freq_avail ;
else
str = kxcjk1013_samp_freq_avail ;
return sprintf ( buf , " %s \n " , str ) ;
2017-09-17 17:01:03 +02:00
}
2017-09-17 17:01:03 +02:00
static IIO_DEVICE_ATTR ( in_accel_sampling_frequency_available , S_IRUGO ,
kxcjk1013_get_samp_freq_avail , NULL , 0 ) ;
2014-11-06 23:07:00 +00:00
2014-05-08 22:58:00 +01:00
static IIO_CONST_ATTR ( in_accel_scale_available , " 0.009582 0.019163 0.038326 " ) ;
2014-11-06 23:07:00 +00:00
static struct attribute * kxcjk1013_attributes [ ] = {
2017-09-17 17:01:03 +02:00
& iio_dev_attr_in_accel_sampling_frequency_available . dev_attr . attr ,
2014-05-08 22:58:00 +01:00
& iio_const_attr_in_accel_scale_available . dev_attr . attr ,
2014-11-06 23:07:00 +00:00
NULL ,
} ;
static const struct attribute_group kxcjk1013_attrs_group = {
. attrs = kxcjk1013_attributes ,
} ;
2014-08-22 20:01:00 +01:00
static const struct iio_event_spec kxcjk1013_event = {
. type = IIO_EV_TYPE_THRESH ,
2014-10-10 15:53:00 +01:00
. dir = IIO_EV_DIR_EITHER ,
2014-08-22 20:01:00 +01:00
. mask_separate = BIT ( IIO_EV_INFO_VALUE ) |
BIT ( IIO_EV_INFO_ENABLE ) |
BIT ( IIO_EV_INFO_PERIOD )
} ;
2020-01-12 23:33:00 +03:00
static const struct iio_mount_matrix *
kxcjk1013_get_mount_matrix ( const struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
return & data - > orientation ;
}
static const struct iio_chan_spec_ext_info kxcjk1013_ext_info [ ] = {
IIO_MOUNT_MATRIX ( IIO_SHARED_BY_TYPE , kxcjk1013_get_mount_matrix ) ,
{ }
} ;
2014-11-06 23:07:00 +00:00
# define KXCJK1013_CHANNEL(_axis) { \
. type = IIO_ACCEL , \
. 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 ) , \
. scan_index = AXIS_ # # _axis , \
. scan_type = { \
. sign = ' s ' , \
. realbits = 12 , \
. storagebits = 16 , \
. shift = 4 , \
2016-03-24 11:29:31 +02:00
. endianness = IIO_LE , \
2014-11-06 23:07:00 +00:00
} , \
2014-08-22 20:01:00 +01:00
. event_spec = & kxcjk1013_event , \
2020-01-12 23:33:00 +03:00
. ext_info = kxcjk1013_ext_info , \
2014-08-22 20:01:00 +01:00
. num_event_specs = 1 \
2014-11-06 23:07:00 +00:00
}
static const struct iio_chan_spec kxcjk1013_channels [ ] = {
KXCJK1013_CHANNEL ( X ) ,
KXCJK1013_CHANNEL ( Y ) ,
KXCJK1013_CHANNEL ( Z ) ,
IIO_CHAN_SOFT_TIMESTAMP ( 3 ) ,
} ;
2015-04-03 15:03:02 +03:00
static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = {
. preenable = kxcjk1013_buffer_preenable ,
. postdisable = kxcjk1013_buffer_postdisable ,
} ;
2014-11-06 23:07:00 +00:00
static const struct iio_info kxcjk1013_info = {
. attrs = & kxcjk1013_attrs_group ,
. read_raw = kxcjk1013_read_raw ,
. write_raw = kxcjk1013_write_raw ,
2014-08-22 20:01:00 +01:00
. read_event_value = kxcjk1013_read_event ,
. write_event_value = kxcjk1013_write_event ,
. write_event_config = kxcjk1013_write_event_config ,
. read_event_config = kxcjk1013_read_event_config ,
2014-11-06 23:07:00 +00:00
} ;
2016-03-24 11:29:30 +02:00
static const unsigned long kxcjk1013_scan_masks [ ] = { 0x7 , 0 } ;
2014-11-06 23:07:00 +00:00
static irqreturn_t kxcjk1013_trigger_handler ( int irq , void * p )
{
struct iio_poll_func * pf = p ;
struct iio_dev * indio_dev = pf - > indio_dev ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2016-03-24 11:29:31 +02:00
int ret ;
2014-11-06 23:07:00 +00:00
mutex_lock ( & data - > mutex ) ;
2016-03-24 11:29:31 +02:00
ret = i2c_smbus_read_i2c_block_data_or_emulated ( data - > client ,
KXCJK1013_REG_XOUT_L ,
AXIS_MAX * 2 ,
2021-05-01 18:01:06 +01:00
( u8 * ) data - > scan . chans ) ;
2014-11-06 23:07:00 +00:00
mutex_unlock ( & data - > mutex ) ;
2016-03-24 11:29:31 +02:00
if ( ret < 0 )
goto err ;
2014-11-06 23:07:00 +00:00
2021-05-01 18:01:06 +01:00
iio_push_to_buffers_with_timestamp ( indio_dev , & data - > scan ,
2014-08-22 20:01:00 +01:00
data - > timestamp ) ;
2014-11-06 23:07:00 +00:00
err :
iio_trigger_notify_done ( indio_dev - > trig ) ;
return IRQ_HANDLED ;
}
2020-09-20 14:25:48 +01:00
static void kxcjk1013_trig_reen ( struct iio_trigger * trig )
2014-07-17 01:42:00 +01:00
{
struct iio_dev * indio_dev = iio_trigger_get_drvdata ( trig ) ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
int ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > int_rel ) ;
2020-09-20 14:25:48 +01:00
if ( ret < 0 )
2014-07-17 01:42:00 +01:00
dev_err ( & data - > client - > dev , " Error reading reg_int_rel \n " ) ;
}
2014-11-06 23:07:00 +00:00
static int kxcjk1013_data_rdy_trigger_set_state ( struct iio_trigger * trig ,
bool state )
{
struct iio_dev * indio_dev = iio_trigger_get_drvdata ( trig ) ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2014-05-08 22:58:00 +01:00
int ret ;
2014-08-22 20:01:00 +01:00
mutex_lock ( & data - > mutex ) ;
if ( ! state & & data - > ev_enable_state & & data - > motion_trigger_on ) {
data - > motion_trigger_on = false ;
mutex_unlock ( & data - > mutex ) ;
2014-05-08 22:58:00 +01:00
return 0 ;
2014-08-22 20:01:00 +01:00
}
2014-11-06 23:07:00 +00:00
2014-08-22 20:01:00 +01:00
ret = kxcjk1013_set_power_state ( data , state ) ;
if ( ret < 0 ) {
mutex_unlock ( & data - > mutex ) ;
return ret ;
2014-11-06 23:07:00 +00:00
}
2014-08-22 20:01:00 +01:00
if ( data - > motion_trig = = trig )
ret = kxcjk1013_setup_any_motion_interrupt ( data , state ) ;
else
ret = kxcjk1013_setup_new_data_interrupt ( data , state ) ;
if ( ret < 0 ) {
2014-12-10 18:23:53 +02:00
kxcjk1013_set_power_state ( data , false ) ;
2014-08-22 20:01:00 +01:00
mutex_unlock ( & data - > mutex ) ;
return ret ;
}
if ( data - > motion_trig = = trig )
data - > motion_trigger_on = state ;
else
data - > dready_trigger_on = state ;
2014-11-06 23:07:00 +00:00
mutex_unlock ( & data - > mutex ) ;
return 0 ;
}
static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
. set_trigger_state = kxcjk1013_data_rdy_trigger_set_state ,
2020-09-20 14:25:48 +01:00
. reenable = kxcjk1013_trig_reen ,
2014-11-06 23:07:00 +00:00
} ;
2017-09-17 17:01:02 +02:00
static void kxcjk1013_report_motion_event ( struct iio_dev * indio_dev )
{
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2021-05-11 16:24:01 +02:00
int ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > int_src2 ) ;
2017-09-17 17:01:02 +02:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_int_src2 \n " ) ;
return ;
}
if ( ret & KXCJK1013_REG_INT_SRC2_BIT_XN )
iio_push_event ( indio_dev ,
IIO_MOD_EVENT_CODE ( IIO_ACCEL ,
0 ,
IIO_MOD_X ,
IIO_EV_TYPE_THRESH ,
IIO_EV_DIR_FALLING ) ,
data - > timestamp ) ;
if ( ret & KXCJK1013_REG_INT_SRC2_BIT_XP )
iio_push_event ( indio_dev ,
IIO_MOD_EVENT_CODE ( IIO_ACCEL ,
0 ,
IIO_MOD_X ,
IIO_EV_TYPE_THRESH ,
IIO_EV_DIR_RISING ) ,
data - > timestamp ) ;
if ( ret & KXCJK1013_REG_INT_SRC2_BIT_YN )
iio_push_event ( indio_dev ,
IIO_MOD_EVENT_CODE ( IIO_ACCEL ,
0 ,
IIO_MOD_Y ,
IIO_EV_TYPE_THRESH ,
IIO_EV_DIR_FALLING ) ,
data - > timestamp ) ;
if ( ret & KXCJK1013_REG_INT_SRC2_BIT_YP )
iio_push_event ( indio_dev ,
IIO_MOD_EVENT_CODE ( IIO_ACCEL ,
0 ,
IIO_MOD_Y ,
IIO_EV_TYPE_THRESH ,
IIO_EV_DIR_RISING ) ,
data - > timestamp ) ;
if ( ret & KXCJK1013_REG_INT_SRC2_BIT_ZN )
iio_push_event ( indio_dev ,
IIO_MOD_EVENT_CODE ( IIO_ACCEL ,
0 ,
IIO_MOD_Z ,
IIO_EV_TYPE_THRESH ,
IIO_EV_DIR_FALLING ) ,
data - > timestamp ) ;
if ( ret & KXCJK1013_REG_INT_SRC2_BIT_ZP )
iio_push_event ( indio_dev ,
IIO_MOD_EVENT_CODE ( IIO_ACCEL ,
0 ,
IIO_MOD_Z ,
IIO_EV_TYPE_THRESH ,
IIO_EV_DIR_RISING ) ,
data - > timestamp ) ;
}
2014-08-22 20:01:00 +01:00
static irqreturn_t kxcjk1013_event_handler ( int irq , void * private )
{
struct iio_dev * indio_dev = private ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
int ret ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > int_src1 ) ;
2014-08-22 20:01:00 +01:00
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " Error reading reg_int_src1 \n " ) ;
goto ack_intr ;
}
2017-09-17 17:01:02 +02:00
if ( ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS ) {
2017-09-17 17:01:04 +02:00
if ( data - > chipset = = KXTF9 )
iio_push_event ( indio_dev ,
IIO_MOD_EVENT_CODE ( IIO_ACCEL ,
0 ,
IIO_MOD_X_AND_Y_AND_Z ,
IIO_EV_TYPE_THRESH ,
IIO_EV_DIR_RISING ) ,
data - > timestamp ) ;
else
kxcjk1013_report_motion_event ( indio_dev ) ;
2014-08-22 20:01:00 +01:00
}
ack_intr :
if ( data - > dready_trigger_on )
return IRQ_HANDLED ;
2021-05-11 16:24:01 +02:00
ret = i2c_smbus_read_byte_data ( data - > client , data - > regs - > int_rel ) ;
2014-08-22 20:01:00 +01:00
if ( ret < 0 )
dev_err ( & data - > client - > dev , " Error reading reg_int_rel \n " ) ;
return IRQ_HANDLED ;
}
static irqreturn_t kxcjk1013_data_rdy_trig_poll ( int irq , void * private )
{
struct iio_dev * indio_dev = private ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2016-03-09 19:05:49 +01:00
data - > timestamp = iio_get_time_ns ( indio_dev ) ;
2014-08-22 20:01:00 +01:00
if ( data - > dready_trigger_on )
iio_trigger_poll ( data - > dready_trig ) ;
else if ( data - > motion_trigger_on )
iio_trigger_poll ( data - > motion_trig ) ;
if ( data - > ev_enable_state )
return IRQ_WAKE_THREAD ;
else
return IRQ_HANDLED ;
}
2014-03-09 08:33:00 +00:00
static const char * kxcjk1013_match_acpi_device ( struct device * dev ,
2014-05-11 22:09:00 +01:00
enum kx_chipset * chipset ,
2021-02-07 17:09:01 +01:00
enum kx_acpi_type * acpi_type ,
const char * * label )
2014-11-06 23:07:00 +00:00
{
const struct acpi_device_id * id ;
2014-12-30 20:57:53 +02:00
2014-03-09 08:33:00 +00:00
id = acpi_match_device ( dev - > driver - > acpi_match_table , dev ) ;
if ( ! id )
return NULL ;
2015-05-04 11:13:04 +02:00
2021-02-07 17:09:01 +01:00
if ( strcmp ( id - > id , " SMO8500 " ) = = 0 ) {
2020-11-10 14:38:34 +01:00
* acpi_type = ACPI_SMO8500 ;
2021-02-07 17:09:01 +01:00
} else if ( strcmp ( id - > id , " KIOX010A " ) = = 0 ) {
2020-11-10 14:38:35 +01:00
* acpi_type = ACPI_KIOX010A ;
2021-02-07 17:09:01 +01:00
* label = " accel-display " ;
} else if ( strcmp ( id - > id , " KIOX020A " ) = = 0 ) {
* label = " accel-base " ;
}
2015-05-04 11:13:04 +02:00
2014-03-09 08:33:00 +00:00
* chipset = ( enum kx_chipset ) id - > driver_data ;
return dev_name ( dev ) ;
}
2020-12-13 22:54:36 +05:30
static void kxcjk1013_disable_regulators ( void * d )
{
struct kxcjk1013_data * data = d ;
regulator_bulk_disable ( ARRAY_SIZE ( data - > regulators ) , data - > regulators ) ;
}
2014-11-06 23:07:00 +00:00
static int kxcjk1013_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
struct kxcjk1013_data * data ;
struct iio_dev * indio_dev ;
struct kxcjk_1013_platform_data * pdata ;
2014-03-09 08:33:00 +00:00
const char * name ;
2014-11-06 23:07:00 +00:00
int ret ;
indio_dev = devm_iio_device_alloc ( & client - > dev , sizeof ( * data ) ) ;
if ( ! indio_dev )
return - ENOMEM ;
data = iio_priv ( indio_dev ) ;
i2c_set_clientdata ( client , indio_dev ) ;
data - > client = client ;
pdata = dev_get_platdata ( & client - > dev ) ;
2020-01-12 23:33:00 +03:00
if ( pdata ) {
2014-11-06 23:07:00 +00:00
data - > active_high_intr = pdata - > active_high_intr ;
2020-01-12 23:33:00 +03:00
data - > orientation = pdata - > orientation ;
} else {
2014-11-06 23:07:00 +00:00
data - > active_high_intr = true ; /* default polarity */
2021-05-18 14:25:46 +03:00
ret = iio_read_mount_matrix ( & client - > dev , & data - > orientation ) ;
2020-01-12 23:33:00 +03:00
if ( ret )
return ret ;
}
2020-12-13 22:54:36 +05:30
data - > regulators [ 0 ] . supply = " vdd " ;
data - > regulators [ 1 ] . supply = " vddio " ;
ret = devm_regulator_bulk_get ( & client - > dev , ARRAY_SIZE ( data - > regulators ) ,
data - > regulators ) ;
if ( ret )
return dev_err_probe ( & client - > dev , ret , " Failed to get regulators \n " ) ;
ret = regulator_bulk_enable ( ARRAY_SIZE ( data - > regulators ) ,
data - > regulators ) ;
if ( ret )
return ret ;
ret = devm_add_action_or_reset ( & client - > dev , kxcjk1013_disable_regulators , data ) ;
if ( ret )
return ret ;
/*
* A typical delay of 10 ms is required for powering up
* according to the data sheets of supported chips .
* Hence double that to play safe .
*/
msleep ( 20 ) ;
2014-03-09 08:33:00 +00:00
if ( id ) {
data - > chipset = ( enum kx_chipset ) ( id - > driver_data ) ;
name = id - > name ;
} else if ( ACPI_HANDLE ( & client - > dev ) ) {
name = kxcjk1013_match_acpi_device ( & client - > dev ,
2014-05-11 22:09:00 +01:00
& data - > chipset ,
2021-02-07 17:09:01 +01:00
& data - > acpi_type ,
& indio_dev - > label ) ;
2014-03-09 08:33:00 +00:00
} else
return - ENODEV ;
2021-05-11 16:24:01 +02:00
switch ( data - > chipset ) {
case KXCJK1013 :
case KXCJ91008 :
case KXTJ21009 :
data - > regs = & kxcjk1013_regs ;
break ;
case KXTF9 :
data - > regs = & kxtf9_regs ;
break ;
2021-05-11 16:24:02 +02:00
case KX0231025 :
data - > regs = & kx0231025_regs ;
break ;
2021-05-11 16:24:01 +02:00
default :
return - EINVAL ;
}
2014-11-06 23:07:00 +00:00
ret = kxcjk1013_chip_init ( data ) ;
if ( ret < 0 )
return ret ;
mutex_init ( & data - > mutex ) ;
indio_dev - > channels = kxcjk1013_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( kxcjk1013_channels ) ;
2016-03-24 11:29:30 +02:00
indio_dev - > available_scan_masks = kxcjk1013_scan_masks ;
2014-03-09 08:33:00 +00:00
indio_dev - > name = name ;
2014-11-06 23:07:00 +00:00
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > info = & kxcjk1013_info ;
2020-11-10 14:38:34 +01:00
if ( client - > irq > 0 & & data - > acpi_type ! = ACPI_SMO8500 ) {
2014-08-22 20:01:00 +01:00
ret = devm_request_threaded_irq ( & client - > dev , client - > irq ,
kxcjk1013_data_rdy_trig_poll ,
kxcjk1013_event_handler ,
IRQF_TRIGGER_RISING ,
KXCJK1013_IRQ_NAME ,
indio_dev ) ;
if ( ret )
2014-12-10 18:23:54 +02:00
goto err_poweroff ;
2014-11-06 23:07:00 +00:00
2014-08-22 20:01:00 +01:00
data - > dready_trig = devm_iio_trigger_alloc ( & client - > dev ,
" %s-dev%d " ,
indio_dev - > name ,
2021-04-26 18:49:03 +01:00
iio_device_id ( indio_dev ) ) ;
2014-12-10 18:23:54 +02:00
if ( ! data - > dready_trig ) {
ret = - ENOMEM ;
goto err_poweroff ;
}
2014-11-06 23:07:00 +00:00
2014-08-22 20:01:00 +01:00
data - > motion_trig = devm_iio_trigger_alloc ( & client - > dev ,
" %s-any-motion-dev%d " ,
indio_dev - > name ,
2021-04-26 18:49:03 +01:00
iio_device_id ( indio_dev ) ) ;
2014-12-10 18:23:54 +02:00
if ( ! data - > motion_trig ) {
ret = - ENOMEM ;
goto err_poweroff ;
}
2014-11-06 23:07:00 +00:00
2014-08-22 20:01:00 +01:00
data - > dready_trig - > ops = & kxcjk1013_trigger_ops ;
iio_trigger_set_drvdata ( data - > dready_trig , indio_dev ) ;
indio_dev - > trig = data - > dready_trig ;
2014-07-17 01:42:00 +01:00
iio_trigger_get ( indio_dev - > trig ) ;
2014-08-22 20:01:00 +01:00
ret = iio_trigger_register ( data - > dready_trig ) ;
2014-11-06 23:07:00 +00:00
if ( ret )
2014-12-10 18:23:54 +02:00
goto err_poweroff ;
2014-08-22 20:01:00 +01:00
data - > motion_trig - > ops = & kxcjk1013_trigger_ops ;
iio_trigger_set_drvdata ( data - > motion_trig , indio_dev ) ;
ret = iio_trigger_register ( data - > motion_trig ) ;
if ( ret ) {
data - > motion_trig = NULL ;
goto err_trigger_unregister ;
}
2015-04-03 15:03:02 +03:00
}
2014-11-06 23:07:00 +00:00
2015-04-03 15:03:02 +03:00
ret = iio_triggered_buffer_setup ( indio_dev ,
& iio_pollfunc_store_time ,
kxcjk1013_trigger_handler ,
& kxcjk1013_buffer_setup_ops ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " iio triggered buffer setup failed \n " ) ;
goto err_trigger_unregister ;
2014-11-06 23:07:00 +00:00
}
2014-05-08 22:58:00 +01:00
ret = pm_runtime_set_active ( & client - > dev ) ;
if ( ret )
2015-11-05 16:25:29 +02:00
goto err_buffer_cleanup ;
2014-05-08 22:58:00 +01:00
pm_runtime_enable ( & client - > dev ) ;
pm_runtime_set_autosuspend_delay ( & client - > dev ,
KXCJK1013_SLEEP_DELAY_MS ) ;
pm_runtime_use_autosuspend ( & client - > dev ) ;
2015-11-05 16:25:29 +02:00
ret = iio_device_register ( indio_dev ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " unable to register iio device \n " ) ;
goto err_buffer_cleanup ;
}
2014-11-06 23:07:00 +00:00
return 0 ;
err_buffer_cleanup :
2014-08-22 20:01:00 +01:00
if ( data - > dready_trig )
2014-11-06 23:07:00 +00:00
iio_triggered_buffer_cleanup ( indio_dev ) ;
err_trigger_unregister :
2014-08-22 20:01:00 +01:00
if ( data - > dready_trig )
iio_trigger_unregister ( data - > dready_trig ) ;
if ( data - > motion_trig )
iio_trigger_unregister ( data - > motion_trig ) ;
2014-12-10 18:23:54 +02:00
err_poweroff :
kxcjk1013_set_mode ( data , STANDBY ) ;
2014-11-06 23:07:00 +00:00
return ret ;
}
static int kxcjk1013_remove ( struct i2c_client * client )
{
struct iio_dev * indio_dev = i2c_get_clientdata ( client ) ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2015-11-05 16:25:29 +02:00
iio_device_unregister ( indio_dev ) ;
2014-05-08 22:58:00 +01:00
pm_runtime_disable ( & client - > dev ) ;
pm_runtime_set_suspended ( & client - > dev ) ;
2014-08-22 20:01:00 +01:00
if ( data - > dready_trig ) {
2014-11-06 23:07:00 +00:00
iio_triggered_buffer_cleanup ( indio_dev ) ;
2014-08-22 20:01:00 +01:00
iio_trigger_unregister ( data - > dready_trig ) ;
iio_trigger_unregister ( data - > motion_trig ) ;
2014-11-06 23:07:00 +00:00
}
mutex_lock ( & data - > mutex ) ;
kxcjk1013_set_mode ( data , STANDBY ) ;
mutex_unlock ( & data - > mutex ) ;
return 0 ;
}
# ifdef CONFIG_PM_SLEEP
static int kxcjk1013_suspend ( struct device * dev )
{
struct iio_dev * indio_dev = i2c_get_clientdata ( to_i2c_client ( dev ) ) ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2014-05-08 22:58:00 +01:00
int ret ;
2014-11-06 23:07:00 +00:00
mutex_lock ( & data - > mutex ) ;
2014-05-08 22:58:00 +01:00
ret = kxcjk1013_set_mode ( data , STANDBY ) ;
2014-11-06 23:07:00 +00:00
mutex_unlock ( & data - > mutex ) ;
2014-05-08 22:58:00 +01:00
return ret ;
2014-11-06 23:07:00 +00:00
}
static int kxcjk1013_resume ( struct device * dev )
{
struct iio_dev * indio_dev = i2c_get_clientdata ( to_i2c_client ( dev ) ) ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2014-05-08 22:58:00 +01:00
int ret = 0 ;
2014-11-06 23:07:00 +00:00
mutex_lock ( & data - > mutex ) ;
2014-12-06 00:18:07 +02:00
ret = kxcjk1013_set_mode ( data , OPERATION ) ;
2019-03-06 10:32:20 +08:00
if ( ret = = 0 )
ret = kxcjk1013_set_range ( data , data - > range ) ;
2014-05-08 22:58:00 +01:00
mutex_unlock ( & data - > mutex ) ;
2014-11-06 23:07:00 +00:00
2014-05-08 22:58:00 +01:00
return ret ;
}
# endif
2014-11-06 23:07:00 +00:00
2014-12-04 01:08:13 +01:00
# ifdef CONFIG_PM
2014-05-08 22:58:00 +01:00
static int kxcjk1013_runtime_suspend ( struct device * dev )
{
struct iio_dev * indio_dev = i2c_get_clientdata ( to_i2c_client ( dev ) ) ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
2014-12-10 18:23:53 +02:00
int ret ;
2014-11-06 23:07:00 +00:00
2014-12-10 18:23:53 +02:00
ret = kxcjk1013_set_mode ( data , STANDBY ) ;
if ( ret < 0 ) {
dev_err ( & data - > client - > dev , " powering off device failed \n " ) ;
return - EAGAIN ;
}
return 0 ;
2014-11-06 23:07:00 +00:00
}
2014-05-08 22:58:00 +01:00
static int kxcjk1013_runtime_resume ( struct device * dev )
{
struct iio_dev * indio_dev = i2c_get_clientdata ( to_i2c_client ( dev ) ) ;
struct kxcjk1013_data * data = iio_priv ( indio_dev ) ;
int ret ;
int sleep_val ;
ret = kxcjk1013_set_mode ( data , OPERATION ) ;
if ( ret < 0 )
return ret ;
sleep_val = kxcjk1013_get_startup_times ( data ) ;
if ( sleep_val < 20000 )
usleep_range ( sleep_val , 20000 ) ;
else
msleep_interruptible ( sleep_val / 1000 ) ;
return 0 ;
}
2014-11-06 23:07:00 +00:00
# endif
2014-05-08 22:58:00 +01:00
static const struct dev_pm_ops kxcjk1013_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS ( kxcjk1013_suspend , kxcjk1013_resume )
SET_RUNTIME_PM_OPS ( kxcjk1013_runtime_suspend ,
kxcjk1013_runtime_resume , NULL )
} ;
2014-11-06 23:07:00 +00:00
static const struct acpi_device_id kx_acpi_match [ ] = {
2014-03-09 08:33:00 +00:00
{ " KXCJ1013 " , KXCJK1013 } ,
{ " KXCJ1008 " , KXCJ91008 } ,
2015-05-04 11:13:03 +02:00
{ " KXCJ9000 " , KXCJ91008 } ,
2019-03-31 14:54:08 +00:00
{ " KIOX0008 " , KXCJ91008 } ,
2018-10-12 12:17:50 +02:00
{ " KIOX0009 " , KXTJ21009 } ,
2016-07-17 10:15:15 +02:00
{ " KIOX000A " , KXCJ91008 } ,
2019-08-18 13:23:06 +02:00
{ " KIOX010A " , KXCJ91008 } , /* KXCJ91008 in the display of a yoga 2-in-1 */
{ " KIOX020A " , KXCJ91008 } , /* KXCJ91008 in the base of a yoga 2-in-1 */
2014-03-09 08:33:00 +00:00
{ " KXTJ1009 " , KXTJ21009 } ,
2018-11-24 17:22:20 +01:00
{ " KXJ2109 " , KXTJ21009 } ,
2014-05-11 22:09:00 +01:00
{ " SMO8500 " , KXCJ91008 } ,
2014-11-06 23:07:00 +00:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( acpi , kx_acpi_match ) ;
static const struct i2c_device_id kxcjk1013_id [ ] = {
2014-03-09 08:33:00 +00:00
{ " kxcjk1013 " , KXCJK1013 } ,
{ " kxcj91008 " , KXCJ91008 } ,
{ " kxtj21009 " , KXTJ21009 } ,
2017-09-17 17:01:04 +02:00
{ " kxtf9 " , KXTF9 } ,
2021-05-11 16:24:02 +02:00
{ " kx023-1025 " , KX0231025 } ,
2014-05-11 22:09:00 +01:00
{ " SMO8500 " , KXCJ91008 } ,
2014-11-06 23:07:00 +00:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , kxcjk1013_id ) ;
2019-03-04 10:19:12 -05:00
static const struct of_device_id kxcjk1013_of_match [ ] = {
{ . compatible = " kionix,kxcjk1013 " , } ,
{ . compatible = " kionix,kxcj91008 " , } ,
{ . compatible = " kionix,kxtj21009 " , } ,
{ . compatible = " kionix,kxtf9 " , } ,
2021-05-11 16:24:02 +02:00
{ . compatible = " kionix,kx023-1025 " , } ,
2019-03-04 10:19:12 -05:00
{ }
} ;
MODULE_DEVICE_TABLE ( of , kxcjk1013_of_match ) ;
2014-11-06 23:07:00 +00:00
static struct i2c_driver kxcjk1013_driver = {
. driver = {
. name = KXCJK1013_DRV_NAME ,
. acpi_match_table = ACPI_PTR ( kx_acpi_match ) ,
2019-03-04 10:19:12 -05:00
. of_match_table = kxcjk1013_of_match ,
2014-05-08 22:58:00 +01:00
. pm = & kxcjk1013_pm_ops ,
2014-11-06 23:07:00 +00:00
} ,
. probe = kxcjk1013_probe ,
. remove = kxcjk1013_remove ,
. id_table = kxcjk1013_id ,
} ;
module_i2c_driver ( kxcjk1013_driver ) ;
MODULE_AUTHOR ( " Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " KXCJK1013 accelerometer driver " ) ;