#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/interrupt.h>
#include <linux/iio/iio.h>
#include <linux/iio/events.h>
#define VCNL3020_PROD_ID …
#define VCNL_COMMAND …
#define VCNL_PROD_REV …
#define VCNL_PROXIMITY_RATE …
#define VCNL_LED_CURRENT …
#define VCNL_PS_RESULT_HI …
#define VCNL_PS_RESULT_LO …
#define VCNL_PS_ICR …
#define VCNL_PS_LO_THR_HI …
#define VCNL_PS_LO_THR_LO …
#define VCNL_PS_HI_THR_HI …
#define VCNL_PS_HI_THR_LO …
#define VCNL_ISR …
#define VCNL_PS_MOD_ADJ …
#define VCNL_PS_RDY …
#define VCNL_PS_OD …
#define VCNL_PS_EN …
#define VCNL_PS_SELFTIMED_EN …
#define VCNL_ICR_THRES_EN …
#define VCNL_INT_TH_HI …
#define VCNL_INT_TH_LOW …
#define VCNL_ON_DEMAND_TIMEOUT_US …
#define VCNL_POLL_US …
static const int vcnl3020_prox_sampling_frequency[][2] = …;
struct vcnl3020_data { … };
struct vcnl3020_property { … };
static u32 microamp_to_reg(u32 *val)
{
return *val /= 10000;
};
static struct vcnl3020_property vcnl3020_led_current_property = …;
static int vcnl3020_get_and_apply_property(struct vcnl3020_data *data,
struct vcnl3020_property prop)
{ … }
static int vcnl3020_init(struct vcnl3020_data *data)
{
int rc;
unsigned int reg;
rc = regmap_read(data->regmap, VCNL_PROD_REV, ®);
if (rc) {
dev_err(data->dev,
"Error (%d) reading product revision\n", rc);
return rc;
}
if (reg != VCNL3020_PROD_ID) {
dev_err(data->dev,
"Product id (%x) did not match vcnl3020 (%x)\n", reg,
VCNL3020_PROD_ID);
return -ENODEV;
}
data->rev = reg;
mutex_init(&data->lock);
return vcnl3020_get_and_apply_property(data,
vcnl3020_led_current_property);
};
static bool vcnl3020_is_in_periodic_mode(struct vcnl3020_data *data)
{ … }
static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val)
{ … }
static int vcnl3020_read_proxy_samp_freq(struct vcnl3020_data *data, int *val,
int *val2)
{ … }
static int vcnl3020_write_proxy_samp_freq(struct vcnl3020_data *data, int val,
int val2)
{ … }
static bool vcnl3020_is_thr_enabled(struct vcnl3020_data *data)
{ … }
static int vcnl3020_read_event(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 vcnl3020_write_event(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 vcnl3020_enable_periodic(struct iio_dev *indio_dev,
struct vcnl3020_data *data)
{ … }
static int vcnl3020_disable_periodic(struct iio_dev *indio_dev,
struct vcnl3020_data *data)
{ … }
static int vcnl3020_config_threshold(struct iio_dev *indio_dev, bool state)
{ … }
static int vcnl3020_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 vcnl3020_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 const struct iio_event_spec vcnl3020_event_spec[] = …;
static const struct iio_chan_spec vcnl3020_channels[] = …;
static int vcnl3020_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
{ … }
static int vcnl3020_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{ … }
static int vcnl3020_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long mask)
{ … }
static const struct iio_info vcnl3020_info = …;
static const struct regmap_config vcnl3020_regmap_config = …;
static irqreturn_t vcnl3020_handle_irq_thread(int irq, void *p)
{ … }
static int vcnl3020_probe(struct i2c_client *client)
{ … }
static const struct of_device_id vcnl3020_of_match[] = …;
MODULE_DEVICE_TABLE(of, vcnl3020_of_match);
static struct i2c_driver vcnl3020_driver = …;
module_i2c_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;