summaryrefslogtreecommitdiffstats
path: root/drivers/iio/adc/ti-ads1015.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-24 16:55:23 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-24 16:55:23 -0700
commit25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f (patch)
treec8d66d65eb0910a2dc8e00a96c1a4da1fc9e33d4 /drivers/iio/adc/ti-ads1015.c
parent9d0be76f52faff97fd9581eba70870f27061ae93 (diff)
parent6c71ee3b6157fdbde5c839405b593876d3687eb9 (diff)
downloadlinux-stable-25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f.tar.gz
linux-stable-25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f.tar.bz2
linux-stable-25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f.zip
Merge tag 'staging-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging and IIO driver updates from Greg KH: "Here is the big Staging and IIO driver update for 4.8-rc1. We ended up adding more code than removing, again, but it's not all that bad. Lots of cleanups all over the staging tree, and new IIO drivers, full details in the shortlog. All of these have been in linux-next for a while with no reported issues" * tag 'staging-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (417 commits) drivers:iio:accel:mma8452: removed unwanted return statements drivers:iio:accel:mma8452: added cleanup provision in case of failure. iio: Add iio.git tree to MAINTAINERS iio:st_pressure: clean useless static channel initializers iio:st_pressure:lps22hb: temperature support iio:st_pressure:lps22hb: open drain support iio:st_pressure: temperature triggered buffering iio:st_pressure: document sampling gains iio:st_pressure: align storagebits on power of 2 iio:st_sensors: align on storagebits boundaries staging:iio:lis3l02dq drop separate driver iio: accel: st_accel: Add lis3l02dq support iio: adc: add missing of_node references to iio_dev iio: adc: ti-ads1015: add indio_dev->dev.of_node reference iio: potentiometer: Fix typo in Kconfig iio: potentiometer: mcp4531: Add device tree binding iio: potentiometer: mcp4531: Add device tree binding documentation iio: potentiometer: mcp4531: Add support for MCP454x, MCP456x, MCP464x and MCP466x iio:imu:mpu6050: icm20608 initial support iio: adc: max1363: Add device tree binding ...
Diffstat (limited to 'drivers/iio/adc/ti-ads1015.c')
-rw-r--r--drivers/iio/adc/ti-ads1015.c132
1 files changed, 116 insertions, 16 deletions
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 73cbf0b54e54..1ef398770a1f 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -55,6 +55,11 @@
#define ADS1015_DEFAULT_DATA_RATE 4
#define ADS1015_DEFAULT_CHAN 0
+enum {
+ ADS1015,
+ ADS1115,
+};
+
enum ads1015_channels {
ADS1015_AIN0_AIN1 = 0,
ADS1015_AIN0_AIN3,
@@ -71,6 +76,10 @@ static const unsigned int ads1015_data_rate[] = {
128, 250, 490, 920, 1600, 2400, 3300, 3300
};
+static const unsigned int ads1115_data_rate[] = {
+ 8, 16, 32, 64, 128, 250, 475, 860
+};
+
static const struct {
int scale;
int uscale;
@@ -101,6 +110,7 @@ static const struct {
.shift = 4, \
.endianness = IIO_CPU, \
}, \
+ .datasheet_name = "AIN"#_chan, \
}
#define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \
@@ -121,6 +131,45 @@ static const struct {
.shift = 4, \
.endianness = IIO_CPU, \
}, \
+ .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
+}
+
+#define ADS1115_V_CHAN(_chan, _addr) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .address = _addr, \
+ .channel = _chan, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = _addr, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+ .datasheet_name = "AIN"#_chan, \
+}
+
+#define ADS1115_V_DIFF_CHAN(_chan, _chan2, _addr) { \
+ .type = IIO_VOLTAGE, \
+ .differential = 1, \
+ .indexed = 1, \
+ .address = _addr, \
+ .channel = _chan, \
+ .channel2 = _chan2, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = _addr, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+ .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
}
struct ads1015_data {
@@ -131,6 +180,8 @@ struct ads1015_data {
*/
struct mutex lock;
struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
+
+ unsigned int *data_rate;
};
static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg)
@@ -157,6 +208,18 @@ static const struct iio_chan_spec ads1015_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
};
+static const struct iio_chan_spec ads1115_channels[] = {
+ ADS1115_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1),
+ ADS1115_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3),
+ ADS1115_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3),
+ ADS1115_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3),
+ ADS1115_V_CHAN(0, ADS1015_AIN0),
+ ADS1115_V_CHAN(1, ADS1015_AIN1),
+ ADS1115_V_CHAN(2, ADS1015_AIN2),
+ ADS1115_V_CHAN(3, ADS1015_AIN3),
+ IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
+};
+
static int ads1015_set_power_state(struct ads1015_data *data, bool on)
{
int ret;
@@ -196,7 +259,7 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
return ret;
if (change) {
- conv_time = DIV_ROUND_UP(USEC_PER_SEC, ads1015_data_rate[dr]);
+ conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
usleep_range(conv_time, conv_time + 1);
}
@@ -225,7 +288,8 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p)
buf[0] = res;
mutex_unlock(&data->lock);
- iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns());
+ iio_push_to_buffers_with_timestamp(indio_dev, buf,
+ iio_get_time_ns(indio_dev));
err:
iio_trigger_notify_done(indio_dev->trig);
@@ -263,7 +327,7 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate)
int i, ret, rindex = -1;
for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++)
- if (ads1015_data_rate[i] == rate) {
+ if (data->data_rate[i] == rate) {
rindex = i;
break;
}
@@ -291,7 +355,9 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
mutex_lock(&data->lock);
switch (mask) {
- case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_RAW: {
+ int shift = chan->scan_type.shift;
+
if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY;
break;
@@ -307,8 +373,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
break;
}
- /* 12 bit res, D0 is bit 4 in conversion register */
- *val = sign_extend32(*val >> 4, 11);
+ *val = sign_extend32(*val >> shift, 15 - shift);
ret = ads1015_set_power_state(data, false);
if (ret < 0)
@@ -316,6 +381,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
break;
+ }
case IIO_CHAN_INFO_SCALE:
idx = data->channel_data[chan->address].pga;
*val = ads1015_scale[idx].scale;
@@ -324,7 +390,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_SAMP_FREQ:
idx = data->channel_data[chan->address].data_rate;
- *val = ads1015_data_rate[idx];
+ *val = data->data_rate[idx];
ret = IIO_VAL_INT;
break;
default:
@@ -380,12 +446,15 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = {
};
static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125");
-static IIO_CONST_ATTR(sampling_frequency_available,
- "128 250 490 920 1600 2400 3300");
+
+static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available,
+ sampling_frequency_available, "128 250 490 920 1600 2400 3300");
+static IIO_CONST_ATTR_NAMED(ads1115_sampling_frequency_available,
+ sampling_frequency_available, "8 16 32 64 128 250 475 860");
static struct attribute *ads1015_attributes[] = {
&iio_const_attr_scale_available.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr,
NULL,
};
@@ -393,11 +462,28 @@ static const struct attribute_group ads1015_attribute_group = {
.attrs = ads1015_attributes,
};
-static const struct iio_info ads1015_info = {
+static struct attribute *ads1115_attributes[] = {
+ &iio_const_attr_scale_available.dev_attr.attr,
+ &iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ads1115_attribute_group = {
+ .attrs = ads1115_attributes,
+};
+
+static struct iio_info ads1015_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = ads1015_read_raw,
+ .write_raw = ads1015_write_raw,
+ .attrs = &ads1015_attribute_group,
+};
+
+static struct iio_info ads1115_info = {
.driver_module = THIS_MODULE,
.read_raw = ads1015_read_raw,
.write_raw = ads1015_write_raw,
- .attrs = &ads1015_attribute_group,
+ .attrs = &ads1115_attribute_group,
};
#ifdef CONFIG_OF
@@ -500,12 +586,25 @@ static int ads1015_probe(struct i2c_client *client,
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
- indio_dev->info = &ads1015_info;
+ indio_dev->dev.of_node = client->dev.of_node;
indio_dev->name = ADS1015_DRV_NAME;
- indio_dev->channels = ads1015_channels;
- indio_dev->num_channels = ARRAY_SIZE(ads1015_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
+ switch (id->driver_data) {
+ case ADS1015:
+ indio_dev->channels = ads1015_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ads1015_channels);
+ indio_dev->info = &ads1015_info;
+ data->data_rate = (unsigned int *) &ads1015_data_rate;
+ break;
+ case ADS1115:
+ indio_dev->channels = ads1115_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ads1115_channels);
+ indio_dev->info = &ads1115_info;
+ data->data_rate = (unsigned int *) &ads1115_data_rate;
+ break;
+ }
+
/* we need to keep this ABI the same as used by hwmon ADS1015 driver */
ads1015_get_channels_config(client);
@@ -590,7 +689,8 @@ static const struct dev_pm_ops ads1015_pm_ops = {
};
static const struct i2c_device_id ads1015_id[] = {
- {"ads1015", 0},
+ {"ads1015", ADS1015},
+ {"ads1115", ADS1115},
{}
};
MODULE_DEVICE_TABLE(i2c, ads1015_id);