/*
* KMX61 - Kionix 6-axis Accelerometer/Magnetometer
*
* Copyright (c) 2014, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F).
*
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/iio/trigger.h>
#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#define KMX61_DRV_NAME "kmx61"
#define KMX61_GPIO_NAME "kmx61_int"
#define KMX61_IRQ_NAME "kmx61_event"
#define KMX61_REG_WHO_AM_I 0x00
#define KMX61_REG_INS1 0x01
#define KMX61_REG_INS2 0x02
/*
* three 16-bit accelerometer output registers for X/Y/Z axis
* we use only XOUT_L as a base register, all other addresses
* can be obtained by applying an offset and are provided here
* only for clarity.
*/
#define KMX61_ACC_XOUT_L 0x0A
#define KMX61_ACC_XOUT_H 0x0B
#define KMX61_ACC_YOUT_L 0x0C
#define KMX61_ACC_YOUT_H 0x0D
#define KMX61_ACC_ZOUT_L 0x0E
#define KMX61_ACC_ZOUT_H 0x0F
/*
* one 16-bit temperature output register
*/
#define KMX61_TEMP_L 0x10
#define KMX61_TEMP_H 0x11
/*
* three 16-bit magnetometer output registers for X/Y/Z axis
*/
#define KMX61_MAG_XOUT_L 0x12
#define KMX61_MAG_XOUT_H 0x13
#define KMX61_MAG_YOUT_L 0x14
#define KMX61_MAG_YOUT_H 0x15
#define KMX61_MAG_ZOUT_L 0x16
#define KMX61_MAG_ZOUT_H 0x17
#define KMX61_REG_INL 0x28
#define KMX61_REG_STBY 0x29
#define KMX61_REG_CTRL1 0x2A
#define KMX61_REG_CTRL2 0x2B
#define KMX61_REG_ODCNTL 0x2C
#define KMX61_REG_INC1 0x2D
#define KMX61_REG_WUF_THRESH 0x3D
#define KMX61_REG_WUF_TIMER 0x3E
#define KMX61_ACC_STBY_BIT BIT(0)
#define KMX61_MAG_STBY_BIT BIT(1)
#define KMX61_ACT_STBY_BIT BIT(7)
#define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT)
#define KMX61_REG_INS1_BIT_WUFS BIT(1)
#define KMX61_REG_INS2_BIT_ZP BIT(0)
#define KMX61_REG_INS2_BIT_ZN BIT(1)
#define KMX61_REG_INS2_BIT_YP BIT(2)
#define KMX61_REG_INS2_BIT_YN BIT(3)
#define KMX61_REG_INS2_BIT_XP BIT(4)
#define KMX61_REG_INS2_BIT_XN BIT(5)
#define KMX61_REG_CTRL1_GSEL_MASK 0x03
#define KMX61_REG_CTRL1_BIT_RES BIT(4)
#define KMX61_REG_CTRL1_BIT_DRDYE BIT(5)
#define KMX61_REG_CTRL1_BIT_WUFE BIT(6)
#define KMX61_REG_CTRL1_BIT_BTSE BIT(7)
#define KMX61_REG_INC1_BIT_WUFS BIT(0)
#define KMX61_REG_INC1_BIT_DRDYM BIT(1)
#define KMX61_REG_INC1_BIT_DRDYA BIT(2)
#define KMX61_REG_INC1_BIT_IEN BIT(5)
#define KMX61_ACC_ODR_SHIFT 0
#define KMX61_MAG_ODR_SHIFT 4
#define KMX61_ACC_ODR_MASK 0x0F
#define KMX61_MAG_ODR_MASK 0xF0
#define KMX61_OWUF_MASK 0x7
#define KMX61_DEFAULT_WAKE_THRESH 1
#define KMX61_DEFAULT_WAKE_DURATION 1
#define KMX61_SLEEP_DELAY_MS 2000
#define KMX61_CHIP_ID 0x12
/* KMX61 devices */
#define KMX61_ACC 0x01
#define KMX61_MAG 0x02
struct kmx61_data {
struct i2c_client *client;
/* serialize access to non-atomic ops, e.g set_mode */
struct mutex lock;
/* standby state */
bool acc_stby;
bool mag_stby;
/* power state */
bool acc_ps;
bool mag_ps;
/* config bits */
u8 range;
u8 odr_bits;
u8 wake_thresh;
u8 wake_duration;
/* accelerometer specific data */
struct iio_dev *acc_indio_dev;
struct iio_trigger *acc_dready_trig;
struct iio_trigger *motion_trig;
bool acc_dready_trig_on;
bool motion_trig_on;
bool ev_enable_state;
/* magnetometer specific data */
struct iio_dev *mag_indio_dev;
struct iio_trigger *mag_dready_trig;
bool mag_dready_trig_on;
};
enum kmx61_range {
KMX61_RANGE_2G,
KMX61_RANGE_4G,
KMX61_RANGE_8G,
};
enum kmx61_axis {
KMX61_AXIS_X,
KMX61_AXIS_Y,
KMX61_AXIS_Z,
};
static const u16 kmx61_uscale_table[] = {9582, 19163, 38326};
static const struct {
int val;
int val2;
} kmx61_samp_freq_table[] = { {12, 500000},
{25, 0},
{50, 0},
{100, 0},
{200, 0},
{400, 0},
{800, 0},
{1600, 0},
{0, 781000},
{1, 563000},
{3, 125000},
{6, 250000} };
static const struct {
int val;
int val2;
int odr_bits;
} kmx61_wake_up_odr_table[] = { {0, 781000, 0x00},
{1, 563000, 0x01},
{3, 125000, 0x02},
{6, 250000, 0x03},
{12, 500000, 0x04},
{25, 0, 0x05},
{50, 0, 0x06},
{100, 0, 0x06},
{200, 0, 0x06},
{400, 0, 0x06},
{800, 0, 0x06},
{1600, 0, 0x06} };
static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326");
static IIO_CONST_ATTR(magn_scale_available, "0.001465");
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800");
static struct attribute *kmx61_acc_attributes[] = {
&iio_const_attr_accel_scale_available.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL,
};
static struct attribute *kmx61_mag_attributes[] = {
&iio_const_attr_magn_scale_available.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL,
};
static const struct attribute_group kmx61_acc_attribute_group = {
.attrs = kmx61_acc_attributes,
};
static const struct attribute_group kmx61_mag_attribute_group = {
.attrs = kmx61_mag_attributes,
};
static const struct iio_event_spec kmx61_event = {
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_EITHER,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE) |
BIT(IIO_EV_INFO_PERIOD),
};
#define KMX61_ACC
|