/*
* BMC150 3-axis accelerometer driver
* Copyright (c) 2014, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/events.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#define BMC150_ACCEL_DRV_NAME "bmc150_accel"
#define BMC150_ACCEL_IRQ_NAME "bmc150_accel_event"
#define BMC150_ACCEL_GPIO_NAME "bmc150_accel_int"
#define BMC150_ACCEL_REG_CHIP_ID 0x00
#define BMC150_ACCEL_CHIP_ID_VAL 0xFA
#define BMC150_ACCEL_REG_INT_STATUS_2 0x0B
#define BMC150_ACCEL_ANY_MOTION_MASK 0x07
#define BMC150_ACCEL_ANY_MOTION_BIT_SIGN BIT(3)
#define BMC150_ACCEL_REG_PMU_LPW 0x11
#define BMC150_ACCEL_PMU_MODE_MASK 0xE0
#define BMC150_ACCEL_PMU_MODE_SHIFT 5
#define BMC150_ACCEL_PMU_BIT_SLEEP_DUR_MASK 0x17
#define BMC150_ACCEL_PMU_BIT_SLEEP_DUR_SHIFT 1
#define BMC150_ACCEL_REG_PMU_RANGE 0x0F
#define BMC150_ACCEL_DEF_RANGE_2G 0x03
#define BMC150_ACCEL_DEF_RANGE_4G 0x05
#define BMC150_ACCEL_DEF_RANGE_8G 0x08
#define BMC150_ACCEL_DEF_RANGE_16G 0x0C
/* Default BW: 125Hz */
#define BMC150_ACCEL_REG_PMU_BW 0x10
#define BMC150_ACCEL_DEF_BW 125
#define BMC150_ACCEL_REG_INT_MAP_0 0x19
#define BMC150_ACCEL_INT_MAP_0_BIT_SLOPE BIT(2)
#define BMC150_ACCEL_REG_INT_MAP_1 0x1A
#define BMC150_ACCEL_INT_MAP_1_BIT_DATA BIT(0)
#define BMC150_ACCEL_REG_INT_RST_LATCH 0x21
#define BMC150_ACCEL_INT_MODE_LATCH_RESET 0x80
#define BMC150_ACCEL_INT_MODE_LATCH_INT 0x0F
#define BMC150_ACCEL_INT_MODE_NON_LATCH_INT 0x00
#define BMC150_ACCEL_REG_INT_EN_0 0x16
#define BMC150_ACCEL_INT_EN_BIT_SLP_X BIT(0)
#define BMC150_ACCEL_INT_EN_BIT_SLP_Y BIT(1)
#define BMC150_ACCEL_INT_EN_BIT_SLP_Z BIT(2)
#define BMC150_ACCEL_REG_INT_EN_1 0x17
#define BMC150_ACCEL_INT_EN_BIT_DATA_EN BIT(4)
#define BMC150_ACCEL_REG_INT_OUT_CTRL 0x20
#define BMC150_ACCEL_INT_OUT_CTRL_INT1_LVL BIT(0)
#define BMC150_ACCEL_REG_INT_5 0x27
#define BMC150_ACCEL_SLOPE_DUR_MASK 0x03
#define BMC150_ACCEL_REG_INT_6 0x28
#define BMC150_ACCEL_SLOPE_THRES_MASK 0xFF
/* Slope duration in terms of number of samples */
#define BMC150_ACCEL_DEF_SLOPE_DURATION 2
/* in terms of multiples of g's/LSB, based on range */
#define BMC150_ACCEL_DEF_SLOPE_THRESHOLD 5
#define BMC150_ACCEL_REG_XOUT_L 0x02
#define BMC150_ACCEL_MAX_STARTUP_TIME_MS 100
/* Sleep Duration values */
#define BMC150_ACCEL_SLEEP_500_MICRO 0x05
#define BMC150_ACCEL_SLEEP_1_MS 0x06
#define BMC150_ACCEL_SLEEP_2_MS 0x07
#define BMC150_ACCEL_SLEEP_4_MS 0x08
#define BMC150_ACCEL_SLEEP_6_MS 0x09
#define BMC150_ACCEL_SLEEP_10_MS 0x0A
#define BMC150_ACCEL_SLEEP_25_MS 0x0B
#define BMC150_ACCEL_SLEEP_50_MS 0x0C
#define BMC150_ACCEL_SLEEP_100_MS 0x0D
#define BMC150_ACCEL_SLEEP_500_MS 0x0E
#define BMC150_ACCEL_SLEEP_1_SEC 0x0F
#define BMC150_ACCEL_REG_TEMP 0x08
#define BMC150_ACCEL_TEMP_CENTER_VAL 24
#define BMC150_ACCEL_AXIS_TO_REG(axis) (BMC150_ACCEL_REG_XOUT_L + (axis * 2))
#define BMC150_AUTO_SUSPEND_DELAY_MS 2000
enum bmc150_accel_axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
};
enum bmc150_power_modes {
BMC150_ACCEL_SLEEP_MODE_NORMAL,
BMC150_ACCEL_SLEEP_MODE_DEEP_SUSPEND,
BMC150_ACCEL_SLEEP_MODE_LPM,
BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
};
struct bmc150_accel_data {
struct i2c_client *client;
struct iio_trigger *dready_trig;
struct iio_trigger *motion_trig;
struct mutex mutex;
s16 buffer[8];
u8 bw_bits;
u32 slope_dur;
u32 slope_thres;
u32 range;
int ev_enable_state;
bool dready_trigger_on;
bool motion_trigger_on;
int64_t timestamp;
};
static const struct {
int val;
int val2;
u8 bw_bits;
} bmc150_accel_samp_freq_table[] = { {7, 810000, 0x08},
{15, 630000, 0x09},
{