a99773d9ac
[ Upstream commit 020e71c7ffc25dfe29ed9be6c2d39af7bd7f661f ] AD7091R-5 devices are supported by the ad7091r-5 driver together with the ad7091r-base driver. Those drivers declared iio events for notifying user space when ADC readings fall bellow the thresholds of low limit registers or above the values set in high limit registers. However, to configure iio events and their thresholds, a set of callback functions must be implemented and those were not present until now. The consequence of trying to configure ad7091r-5 events without the proper callback functions was a null pointer dereference in the kernel because the pointers to the callback functions were not set. Implement event configuration callbacks allowing users to read/write event thresholds and enable/disable event generation. Since the event spec structs are generic to AD7091R devices, also move those from the ad7091r-5 driver the base driver so they can be reused when support for ad7091r-2/-4/-8 be added. Fixes: ca69300173b6 ("iio: adc: Add support for AD7091R5 ADC") Suggested-by: David Lechner <dlechner@baylibre.com> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com> Link: https://lore.kernel.org/r/59552d3548dabd56adc3107b7b4869afee2b0c3c.1703013352.git.marcelo.schmitt1@gmail.com Cc: <Stable@vger.kernel.org> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
93 lines
2.5 KiB
C
Executable file
93 lines
2.5 KiB
C
Executable file
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* AD7091R5 Analog to Digital converter driver
|
|
*
|
|
* Copyright 2014-2019 Analog Devices Inc.
|
|
*/
|
|
|
|
#include <linux/i2c.h>
|
|
#include <linux/iio/iio.h>
|
|
#include <linux/module.h>
|
|
#include <linux/regmap.h>
|
|
|
|
#include "ad7091r-base.h"
|
|
|
|
#define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \
|
|
.type = IIO_VOLTAGE, \
|
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
|
.indexed = 1, \
|
|
.channel = idx, \
|
|
.event_spec = ev, \
|
|
.num_event_specs = num_ev, \
|
|
.scan_type.storagebits = 16, \
|
|
.scan_type.realbits = bits, \
|
|
}
|
|
static const struct iio_chan_spec ad7091r5_channels_irq[] = {
|
|
AD7091R_CHANNEL(0, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
|
|
AD7091R_CHANNEL(1, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
|
|
AD7091R_CHANNEL(2, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
|
|
AD7091R_CHANNEL(3, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
|
|
};
|
|
|
|
static const struct iio_chan_spec ad7091r5_channels_noirq[] = {
|
|
AD7091R_CHANNEL(0, 12, NULL, 0),
|
|
AD7091R_CHANNEL(1, 12, NULL, 0),
|
|
AD7091R_CHANNEL(2, 12, NULL, 0),
|
|
AD7091R_CHANNEL(3, 12, NULL, 0),
|
|
};
|
|
|
|
static const struct ad7091r_chip_info ad7091r5_chip_info_irq = {
|
|
.channels = ad7091r5_channels_irq,
|
|
.num_channels = ARRAY_SIZE(ad7091r5_channels_irq),
|
|
.vref_mV = 2500,
|
|
};
|
|
|
|
static const struct ad7091r_chip_info ad7091r5_chip_info_noirq = {
|
|
.channels = ad7091r5_channels_noirq,
|
|
.num_channels = ARRAY_SIZE(ad7091r5_channels_noirq),
|
|
.vref_mV = 2500,
|
|
};
|
|
|
|
static int ad7091r5_i2c_probe(struct i2c_client *i2c,
|
|
const struct i2c_device_id *id)
|
|
{
|
|
const struct ad7091r_chip_info *chip_info;
|
|
struct regmap *map = devm_regmap_init_i2c(i2c, &ad7091r_regmap_config);
|
|
|
|
if (IS_ERR(map))
|
|
return PTR_ERR(map);
|
|
|
|
if (i2c->irq)
|
|
chip_info = &ad7091r5_chip_info_irq;
|
|
else
|
|
chip_info = &ad7091r5_chip_info_noirq;
|
|
|
|
return ad7091r_probe(&i2c->dev, id->name, chip_info, map, i2c->irq);
|
|
}
|
|
|
|
static const struct of_device_id ad7091r5_dt_ids[] = {
|
|
{ .compatible = "adi,ad7091r5" },
|
|
{},
|
|
};
|
|
MODULE_DEVICE_TABLE(of, ad7091r5_dt_ids);
|
|
|
|
static const struct i2c_device_id ad7091r5_i2c_ids[] = {
|
|
{"ad7091r5", 0},
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(i2c, ad7091r5_i2c_ids);
|
|
|
|
static struct i2c_driver ad7091r5_driver = {
|
|
.driver = {
|
|
.name = "ad7091r5",
|
|
.of_match_table = ad7091r5_dt_ids,
|
|
},
|
|
.probe = ad7091r5_i2c_probe,
|
|
.id_table = ad7091r5_i2c_ids,
|
|
};
|
|
module_i2c_driver(ad7091r5_driver);
|
|
|
|
MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>");
|
|
MODULE_DESCRIPTION("Analog Devices AD7091R5 multi-channel ADC driver");
|
|
MODULE_LICENSE("GPL v2");
|