#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#define ADUX1020_REGMAP_NAME …
#define ADUX1020_DRV_NAME …
#define ADUX1020_REG_CHIP_ID …
#define ADUX1020_REG_SLAVE_ADDRESS …
#define ADUX1020_REG_SW_RESET …
#define ADUX1020_REG_INT_ENABLE …
#define ADUX1020_REG_INT_POLARITY …
#define ADUX1020_REG_PROX_TH_ON1 …
#define ADUX1020_REG_PROX_TH_OFF1 …
#define ADUX1020_REG_PROX_TYPE …
#define ADUX1020_REG_TEST_MODES_3 …
#define ADUX1020_REG_FORCE_MODE …
#define ADUX1020_REG_FREQUENCY …
#define ADUX1020_REG_LED_CURRENT …
#define ADUX1020_REG_OP_MODE …
#define ADUX1020_REG_INT_MASK …
#define ADUX1020_REG_INT_STATUS …
#define ADUX1020_REG_DATA_BUFFER …
#define ADUX1020_CHIP_ID_MASK …
#define ADUX1020_CHIP_ID …
#define ADUX1020_SW_RESET …
#define ADUX1020_FIFO_FLUSH …
#define ADUX1020_OP_MODE_MASK …
#define ADUX1020_DATA_OUT_MODE_MASK …
#define ADUX1020_DATA_OUT_PROX_I …
#define ADUX1020_MODE_INT_MASK …
#define ADUX1020_INT_ENABLE …
#define ADUX1020_INT_DISABLE …
#define ADUX1020_PROX_INT_ENABLE …
#define ADUX1020_PROX_ON1_INT …
#define ADUX1020_PROX_OFF1_INT …
#define ADUX1020_FIFO_INT_ENABLE …
#define ADUX1020_MODE_INT_DISABLE …
#define ADUX1020_MODE_INT_STATUS_MASK …
#define ADUX1020_FIFO_STATUS_MASK …
#define ADUX1020_INT_CLEAR …
#define ADUX1020_PROX_TYPE …
#define ADUX1020_INT_PROX_ON1 …
#define ADUX1020_INT_PROX_OFF1 …
#define ADUX1020_FORCE_CLOCK_ON …
#define ADUX1020_FORCE_CLOCK_RESET …
#define ADUX1020_ACTIVE_4_STATE …
#define ADUX1020_PROX_FREQ_MASK …
#define ADUX1020_PROX_FREQ(x) …
#define ADUX1020_LED_CURRENT_MASK …
#define ADUX1020_LED_PIREF_EN …
enum adux1020_op_modes { … };
struct adux1020_data { … };
struct adux1020_mode_data { … };
static const struct adux1020_mode_data adux1020_modes[] = …;
static const struct regmap_config adux1020_regmap_config = …;
static const struct reg_sequence adux1020_def_conf[] = …;
static const int adux1020_rates[][2] = …;
static const int adux1020_led_currents[][2] = …;
static int adux1020_flush_fifo(struct adux1020_data *data)
{ … }
static int adux1020_read_fifo(struct adux1020_data *data, u16 *buf, u8 buf_len)
{ … }
static int adux1020_set_mode(struct adux1020_data *data,
enum adux1020_op_modes mode)
{ … }
static int adux1020_measure(struct adux1020_data *data,
enum adux1020_op_modes mode,
u16 *val)
{ … }
static int adux1020_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct adux1020_data *data = iio_priv(indio_dev);
u16 buf[3];
int ret = -EINVAL;
unsigned int regval;
mutex_lock(&data->lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_PROXIMITY:
ret = adux1020_set_mode(data, ADUX1020_MODE_PROX_I);
if (ret < 0)
goto fail;
ret = adux1020_measure(data, ADUX1020_MODE_PROX_I, buf);
if (ret < 0)
goto fail;
*val = buf[0];
ret = IIO_VAL_INT;
break;
default:
break;
}
break;
case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_CURRENT:
ret = regmap_read(data->regmap,
ADUX1020_REG_LED_CURRENT, ®val);
if (ret < 0)
goto fail;
regval = regval & ADUX1020_LED_CURRENT_MASK;
*val = adux1020_led_currents[regval][0];
*val2 = adux1020_led_currents[regval][1];
ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
break;
}
break;
case IIO_CHAN_INFO_SAMP_FREQ:
switch (chan->type) {
case IIO_PROXIMITY:
ret = regmap_read(data->regmap, ADUX1020_REG_FREQUENCY,
®val);
if (ret < 0)
goto fail;
regval = FIELD_GET(ADUX1020_PROX_FREQ_MASK, regval);
*val = adux1020_rates[regval][0];
*val2 = adux1020_rates[regval][1];
ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
break;
}
break;
default:
break;
}
fail:
mutex_unlock(&data->lock);
return ret;
};
static inline int adux1020_find_index(const int array[][2], int count, int val,
int val2)
{ … }
static int adux1020_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{ … }
static int adux1020_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)
{ … }
static int adux1020_read_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{ … }
static int adux1020_read_thresh(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)
{ … }
static int adux1020_write_thresh(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)
{ … }
static const struct iio_event_spec adux1020_proximity_event[] = …;
static const struct iio_chan_spec adux1020_channels[] = …;
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
"0.1 0.2 0.5 1 2 5 10 20 50 100 190 450 820 1400");
static struct attribute *adux1020_attributes[] = …;
static const struct attribute_group adux1020_attribute_group = …;
static const struct iio_info adux1020_info = …;
static irqreturn_t adux1020_interrupt_handler(int irq, void *private)
{ … }
static int adux1020_chip_init(struct adux1020_data *data)
{ … }
static int adux1020_probe(struct i2c_client *client)
{ … }
static const struct i2c_device_id adux1020_id[] = …;
MODULE_DEVICE_TABLE(i2c, adux1020_id);
static const struct of_device_id adux1020_of_match[] = …;
MODULE_DEVICE_TABLE(of, adux1020_of_match);
static struct i2c_driver adux1020_driver = …;
module_i2c_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;