// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2022 ROHM Semiconductors
*
* ROHM/KIONIX KX022A accelerometer driver
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
#include <linux/units.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include "kionix-kx022a.h"
/*
* The KX022A has FIFO which can store 43 samples of HiRes data from 2
* channels. This equals to 43 (samples) * 3 (channels) * 2 (bytes/sample) to
* 258 bytes of sample data. The quirk to know is that the amount of bytes in
* the FIFO is advertised via 8 bit register (max value 255). The thing to note
* is that full 258 bytes of data is indicated using the max value 255.
*/
#define KX022A_FIFO_LENGTH 43
#define KX022A_FIFO_FULL_VALUE 255
#define KX022A_SOFT_RESET_WAIT_TIME_US (5 * USEC_PER_MSEC)
#define KX022A_SOFT_RESET_TOTAL_WAIT_TIME_US (500 * USEC_PER_MSEC)
/* 3 axis, 2 bytes of data for each of the axis */
#define KX022A_FIFO_SAMPLES_SIZE_BYTES 6
#define KX022A_FIFO_MAX_BYTES \
(KX022A_FIFO_LENGTH * KX022A_FIFO_SAMPLES_SIZE_BYTES)
enum {
KX022A_STATE_SAMPLE,
KX022A_STATE_FIFO,
};
/* Regmap configs */
static const struct regmap_range kx022a_volatile_ranges[] = {
{
.range_min = KX022A_REG_XHP_L,
.range_max = KX022A_REG_COTR,
}, {
.range_min = KX022A_REG_TSCP,
.range_max = KX022A_REG_INT_REL,
}, {
/* The reset bit will be cleared by sensor */
.range_min = KX022A_REG_CNTL2,
.range_max = KX022A_REG_CNTL2,
}, {
.range_min = KX022A_REG_BUF_STATUS_1,
.range_max = KX022A_REG_BUF_READ,
},
};
static const struct regmap_access_table kx022a_volatile_regs = {
.yes_ranges = &kx022a_volatile_ranges[0],
.n_yes_ranges = ARRAY_SIZE(kx022a_volatile_ranges),
};
static const struct regmap_range kx022a_precious_ranges[] = {
{
.range_min = KX022A_REG_INT_REL,
.range_max = KX022A_REG_INT_REL,
},
};
static const struct regmap_access_table kx022a_precious_regs = {
.yes_ranges = &kx022a_precious_ranges[0],
.n_yes_ranges = ARRAY_SIZE(kx022a_precious_ranges),
};
/*
* The HW does not set WHO_AM_I reg as read-only but we don't want to write it
* so we still include it in the read-only ranges.
*/
static const struct regmap_range kx022a_read_only_ranges[] = {
{
.range_min = KX022A_REG_XHP_L,
.range_max = KX022A_REG_INT_REL,
}, {
.range_min = KX022A_REG_BUF_STATUS_1,
.range_max = KX022A_REG_BUF_STATUS_2,
}, {
.range_min = KX022A_REG_BUF_READ,
.range_max = KX022A_REG_BUF_READ,
},
};
static const struct regmap_access_table kx022a_ro_regs = {
.no_ranges = &kx022a_read_only_ranges[0],
.n_no_ranges = ARRAY_SIZE(kx022a_read_only_ranges),
};
static const struct regmap_range kx022a_write_only_ranges[] = {
{
.range_min = KX022A_REG_BTS_WUF_TH,
.range_max = KX022A_REG_BTS_WUF_TH,
}, {
.range_min = KX022A_REG_MAN_WAKE,
.range_max = KX022A_REG_MAN_WAKE,
}, {
.range_min = KX022A_REG_SELF_TEST,
.range_max = KX022A_REG_SELF_TEST,
}, {
.range_min = KX022A_REG_BUF_CLEAR,
.range_max = KX022A_REG_BUF_CLEAR,
},
};
static const struct regmap_access_table kx022a_wo_regs = {
.no_ranges = &kx022a_write_only_ranges[0],
.n_no_ranges = ARRAY_SIZE(kx022a_write_only_ranges),
};
static const struct regmap_range kx022a_noinc_read_ranges[] = {
{
.range_min = KX022A_REG_BUF_READ,
.range_max = KX022A_REG_BUF_READ,
},
};
static const struct regmap_access_table kx022a_nir_regs = {
.yes_ranges = &kx022a_noinc_read_ranges[0],
.n_yes_ranges = ARRAY_SIZE(kx022a_noinc_read_ranges),
};
const struct regmap_config kx022a_regmap = {
.reg_bits = 8,
.val_bits = 8,
.volatile_table = &kx022a_volatile_regs,
.rd_table = &kx022a_wo_regs,
.wr_table = &kx022a_ro_regs,
.rd_noinc_table = &kx022a_nir_regs,
.precious_table = &kx022a_precious_regs,
.max_register = KX022A_MAX_REGISTER,
.cache_type = REGCACHE_RBTREE,
};
EXPORT_SYMBOL_NS_GPL(kx022a_regmap, IIO_KX022A);
struct kx022a_data {
struct regmap *regmap;
struct iio_trigger *trig;
struct device *dev;
struct iio_mount_matrix orientation;
int64_t timestamp, old_timestamp;
int irq;
int inc_reg;
int ien_reg;
unsigned int state;
unsigned int odr_ns;
bool trigger_enabled;
/*
* Prevent toggling the sensor stby/active state (PC1 bit) in the
* middle of a configuration, or when the fifo is enabled. Also,
* protect the data stored/retrieved from this structure from
* concurrent accesses.
*/
struct mutex mutex;
u8 watermark;
/* 3 x 16bit accel data + timestamp */
__le16 buffer[8] __aligned(IIO_DMA_MINALIGN);
struct {