linux/drivers/iio/accel/kionix-kx022a.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2022 ROHM Semiconductors
 *
 * ROHM/KIONIX 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_choices.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
#define KX022A_FIFO_FULL_VALUE
#define KX022A_SOFT_RESET_WAIT_TIME_US
#define KX022A_SOFT_RESET_TOTAL_WAIT_TIME_US

/* 3 axis, 2 bytes of data for each of the axis */
#define KX022A_FIFO_SAMPLES_SIZE_BYTES
#define KX022A_FIFO_MAX_BYTES

enum {};

/* kx022a Regmap configs */
static const struct regmap_range kx022a_volatile_ranges[] =;

static const struct regmap_access_table kx022a_volatile_regs =;

static const struct regmap_range kx022a_precious_ranges[] =;

static const struct regmap_access_table kx022a_precious_regs =;

/*
 * 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[] =;

static const struct regmap_access_table kx022a_ro_regs =;

static const struct regmap_range kx022a_write_only_ranges[] =;

static const struct regmap_access_table kx022a_wo_regs =;

static const struct regmap_range kx022a_noinc_read_ranges[] =;

static const struct regmap_access_table kx022a_nir_regs =;

static const struct regmap_config kx022a_regmap_config =;

/* Regmap configs kx132 */
static const struct regmap_range kx132_volatile_ranges[] =;

static const struct regmap_access_table kx132_volatile_regs =;

static const struct regmap_range kx132_precious_ranges[] =;

static const struct regmap_access_table kx132_precious_regs =;

static const struct regmap_range kx132_read_only_ranges[] =;

static const struct regmap_access_table kx132_ro_regs =;

static const struct regmap_range kx132_write_only_ranges[] =;

static const struct regmap_access_table kx132_wo_regs =;

static const struct regmap_range kx132_noinc_read_ranges[] =;

static const struct regmap_access_table kx132_nir_regs =;

static const struct regmap_config kx132_regmap_config =;

struct kx022a_data {};

static const struct iio_mount_matrix *
kx022a_get_mount_matrix(const struct iio_dev *idev,
			const struct iio_chan_spec *chan)
{}

enum {};

static const unsigned long kx022a_scan_masks[] =;

static const struct iio_chan_spec_ext_info kx022a_ext_info[] =;

#define KX022A_ACCEL_CHAN(axis, reg, index)

static const struct iio_chan_spec kx022a_channels[] =;

static const struct iio_chan_spec kx132_channels[] =;

/*
 * The sensor HW can support ODR up to 1600 Hz, which is beyond what most of the
 * Linux CPUs can handle without dropping samples. Also, the low power mode is
 * not available for higher sample rates. Thus, the driver only supports 200 Hz
 * and slower ODRs. The slowest is 0.78 Hz.
 */
static const int kx022a_accel_samp_freq_table[][2] =;

static const unsigned int kx022a_odrs[] =;

/*
 * range is typically +-2G/4G/8G/16G, distributed over the amount of bits.
 * The scale table can be calculated using
 *	(range / 2^bits) * g = (range / 2^bits) * 9.80665 m/s^2
 *	=> KX022A uses 16 bit (HiRes mode - assume the low 8 bits are zeroed
 *	in low-power mode(?) )
 *	=> +/-2G  => 4 / 2^16 * 9,80665
 *	=> +/-2G  - 0.000598550415
 *	   +/-4G  - 0.00119710083
 *	   +/-8G  - 0.00239420166
 *	   +/-16G - 0.00478840332
 */
static const int kx022a_scale_table[][2] =;

static int kx022a_read_avail(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     const int **vals, int *type, int *length,
			     long mask)
{}

#define KX022A_DEFAULT_PERIOD_NS

static void kx022a_reg2freq(unsigned int val,  int *val1, int *val2)
{}

static void kx022a_reg2scale(unsigned int val, unsigned int *val1,
			     unsigned int *val2)
{}

static int kx022a_turn_on_off_unlocked(struct kx022a_data *data, bool on)
{}

static int kx022a_turn_off_lock(struct kx022a_data *data)
{}

static int kx022a_turn_on_unlock(struct kx022a_data *data)
{}

static int kx022a_write_raw_get_fmt(struct iio_dev *idev,
				    struct iio_chan_spec const *chan,
				    long mask)
{}

static int kx022a_write_raw(struct iio_dev *idev,
			    struct iio_chan_spec const *chan,
			    int val, int val2, long mask)
{}

static int kx022a_fifo_set_wmi(struct kx022a_data *data)
{}

static int kx022a_get_axis(struct kx022a_data *data,
			   struct iio_chan_spec const *chan,
			   int *val)
{}

static int kx022a_read_raw(struct iio_dev *idev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2, long mask)
{
	struct kx022a_data *data = iio_priv(idev);
	unsigned int regval;
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		ret = iio_device_claim_direct_mode(idev);
		if (ret)
			return ret;

		mutex_lock(&data->mutex);
		ret = kx022a_get_axis(data, chan, val);
		mutex_unlock(&data->mutex);

		iio_device_release_direct_mode(idev);

		return ret;

	case IIO_CHAN_INFO_SAMP_FREQ:
		ret = regmap_read(data->regmap, data->chip_info->odcntl, &regval);
		if (ret)
			return ret;

		if ((regval & KX022A_MASK_ODR) >
		    ARRAY_SIZE(kx022a_accel_samp_freq_table)) {
			dev_err(data->dev, "Invalid ODR\n");
			return -EINVAL;
		}

		kx022a_reg2freq(regval, val, val2);

		return IIO_VAL_INT_PLUS_MICRO;

	case IIO_CHAN_INFO_SCALE:
		ret = regmap_read(data->regmap, data->chip_info->cntl, &regval);
		if (ret < 0)
			return ret;

		kx022a_reg2scale(regval, val, val2);

		return IIO_VAL_INT_PLUS_NANO;
	}

	return -EINVAL;
};

static int kx022a_set_watermark(struct iio_dev *idev, unsigned int val)
{}

static ssize_t hwfifo_enabled_show(struct device *dev,
				   struct device_attribute *attr,
				   char *buf)
{}

static ssize_t hwfifo_watermark_show(struct device *dev,
				     struct device_attribute *attr,
				     char *buf)
{}

static IIO_DEVICE_ATTR_RO(hwfifo_enabled, 0);
static IIO_DEVICE_ATTR_RO(hwfifo_watermark, 0);

static const struct iio_dev_attr *kx022a_fifo_attributes[] =;

static int kx022a_drop_fifo_contents(struct kx022a_data *data)
{}

static int kx022a_get_fifo_bytes_available(struct kx022a_data *data)
{}

static int kx132_get_fifo_bytes_available(struct kx022a_data *data)
{}

static int __kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples,
			       bool irq)
{}

static int kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples)
{}

static const struct iio_info kx022a_info =;

static int kx022a_set_drdy_irq(struct kx022a_data *data, bool en)
{}

static int kx022a_prepare_irq_pin(struct kx022a_data *data)
{}

static int kx022a_fifo_disable(struct kx022a_data *data)
{}

static int kx022a_buffer_predisable(struct iio_dev *idev)
{}

static int kx022a_fifo_enable(struct kx022a_data *data)
{}

static int kx022a_buffer_postenable(struct iio_dev *idev)
{}

static const struct iio_buffer_setup_ops kx022a_buffer_ops =;

static irqreturn_t kx022a_trigger_handler(int irq, void *p)
{}

/* Get timestamps and wake the thread if we need to read data */
static irqreturn_t kx022a_irq_handler(int irq, void *private)
{}

/*
 * WMI and data-ready IRQs are acked when results are read. If we add
 * TILT/WAKE or other IRQs - then we may need to implement the acking
 * (which is racy).
 */
static irqreturn_t kx022a_irq_thread_handler(int irq, void *private)
{}

static int kx022a_trigger_set_state(struct iio_trigger *trig,
				    bool state)
{}

static const struct iio_trigger_ops kx022a_trigger_ops =;

static int kx022a_chip_init(struct kx022a_data *data)
{}

const struct kx022a_chip_info kx022a_chip_info =;
EXPORT_SYMBOL_NS_GPL();

const struct kx022a_chip_info kx132_chip_info =;
EXPORT_SYMBOL_NS_GPL();

/*
 * Despite the naming, KX132ACR-LBZ is not similar to KX132-1211 but it is
 * exact subset of KX022A. KX132ACR-LBZ is meant to be used for industrial
 * applications and the tap/double tap, free fall and tilt engines were
 * removed. Rest of the registers and functionalities (excluding the ID
 * register) are exact match to what is found in KX022.
 */
const struct kx022a_chip_info kx132acr_chip_info =;
EXPORT_SYMBOL_NS_GPL();

int kx022a_probe_internal(struct device *dev, const struct kx022a_chip_info *chip_info)
{}
EXPORT_SYMBOL_NS_GPL();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();