summaryrefslogtreecommitdiff
path: root/drivers/staging/iio/adc/max1363_core.c
diff options
context:
space:
mode:
authorJonathan Cameron <jic23@cam.ac.uk>2011-05-18 14:42:37 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-19 16:15:05 -0700
commit6fe8135fccd66aedcc55ded70824342587fd2499 (patch)
tree3afc7acfd0edc052ba93241761e935af9a3b6ebc /drivers/staging/iio/adc/max1363_core.c
parenta3f02370c9fa6d85fbee2c11649ebc9c84bae919 (diff)
staging:iio: implement an iio_info structure to take some of the constant elements out of iio_dev.
This was suggested by Arnd Bergmann, Other elements may well move in here in future, but it definitely makes sense for these. Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/iio/adc/max1363_core.c')
-rw-r--r--drivers/staging/iio/adc/max1363_core.c770
1 files changed, 406 insertions, 364 deletions
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 0c80abb7e753..8d09bf3d450a 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -472,47 +472,409 @@ enum { max1361,
max11647
};
+static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600,
+ 8300, 4200, 2000, 1000 };
+
+static ssize_t max1363_monitor_show_freq(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct max1363_state *st = iio_priv(dev_get_drvdata(dev));
+ return sprintf(buf, "%d\n", max1363_monitor_speeds[st->monitor_speed]);
+}
+
+static ssize_t max1363_monitor_store_freq(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct max1363_state *st = iio_priv(indio_dev);
+ int i, ret;
+ unsigned long val;
+ bool found = false;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret)
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(max1363_monitor_speeds); i++)
+ if (val == max1363_monitor_speeds[i]) {
+ found = true;
+ break;
+ }
+ if (!found)
+ return -EINVAL;
+
+ mutex_lock(&indio_dev->mlock);
+ st->monitor_speed = i;
+ mutex_unlock(&indio_dev->mlock);
+
+ return 0;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR,
+ max1363_monitor_show_freq,
+ max1363_monitor_store_freq);
+
+static IIO_CONST_ATTR(sampling_frequency_available,
+ "133000 665000 33300 16600 8300 4200 2000 1000");
+
+static int max1363_read_thresh(struct iio_dev *indio_dev,
+ int event_code,
+ int *val)
+{
+ struct max1363_state *st = iio_priv(indio_dev);
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
+ *val = st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)];
+ else
+ *val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)];
+ return 0;
+}
+
+static int max1363_write_thresh(struct iio_dev *indio_dev,
+ int event_code,
+ int val)
+{
+ struct max1363_state *st = iio_priv(indio_dev);
+ /* make it handle signed correctly as well */
+ switch (st->chip_info->bits) {
+ case 10:
+ if (val > 0x3FF)
+ return -EINVAL;
+ break;
+ case 12:
+ if (val > 0xFFF)
+ return -EINVAL;
+ break;
+ }
+
+ switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+ case IIO_EV_DIR_FALLING:
+ st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val;
+ break;
+ case IIO_EV_DIR_RISING:
+ st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val;
+ break;
+ }
+
+ return 0;
+}
+
+static irqreturn_t max1363_event_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct max1363_state *st = iio_priv(indio_dev);
+ s64 timestamp = iio_get_time_ns();
+ u8 rx;
+ u8 tx[2] = { st->setupbyte,
+ MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 };
+
+ i2c_master_recv(st->client, &rx, 1);
+ /* todo - begging for use of for_each_set_bit */
+ if (rx & (1 << 0))
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_IN_LOW_THRESH(3),
+ timestamp);
+ if (rx & (1 << 1))
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_IN_HIGH_THRESH(3),
+ timestamp);
+ if (rx & (1 << 2))
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_IN_LOW_THRESH(2),
+ timestamp);
+ if (rx & (1 << 3))
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_IN_HIGH_THRESH(2),
+ timestamp);
+ if (rx & (1 << 4))
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_IN_LOW_THRESH(1),
+ timestamp);
+ if (rx & (1 << 5))
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_IN_HIGH_THRESH(1),
+ timestamp);
+ if (rx & (1 << 6))
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_IN_LOW_THRESH(0),
+ timestamp);
+ if (rx & (1 << 7))
+ iio_push_event(indio_dev, 0,
+ IIO_EVENT_CODE_IN_HIGH_THRESH(0),
+ timestamp);
+ i2c_master_send(st->client, tx, 2);
+
+ return IRQ_HANDLED;
+}
+
+static int max1363_read_event_config(struct iio_dev *indio_dev,
+ int event_code)
+{
+ struct max1363_state *st = iio_priv(indio_dev);
+
+ int val;
+ int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
+ mutex_lock(&indio_dev->mlock);
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
+ val = (1 << number) & st->mask_low;
+ else
+ val = (1 << number) & st->mask_high;
+ mutex_unlock(&indio_dev->mlock);
+
+ return val;
+}
+
+static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
+{
+ u8 *tx_buf;
+ int ret, i = 3, j;
+ unsigned long numelements;
+ int len;
+ long modemask;
+
+ if (!enabled) {
+ /* transition to ring capture is not currently supported */
+ st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP;
+ st->configbyte &= ~MAX1363_SCAN_MASK;
+ st->monitor_on = false;
+ return max1363_write_basic_config(st->client,
+ st->setupbyte,
+ st->configbyte);
+ }
+
+ /* Ensure we are in the relevant mode */
+ st->setupbyte |= MAX1363_SETUP_MONITOR_SETUP;
+ st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
+ | MAX1363_SCAN_MASK
+ | MAX1363_SE_DE_MASK);
+ st->configbyte |= MAX1363_CONFIG_SCAN_MONITOR_MODE;
+ if ((st->mask_low | st->mask_high) & 0x0F) {
+ st->configbyte |= max1363_mode_table[s0to3].conf;
+ modemask = max1363_mode_table[s0to3].modemask;
+ } else if ((st->mask_low | st->mask_high) & 0x30) {
+ st->configbyte |= max1363_mode_table[d0m1to2m3].conf;
+ modemask = max1363_mode_table[d0m1to2m3].modemask;
+ } else {
+ st->configbyte |= max1363_mode_table[d1m0to3m2].conf;
+ modemask = max1363_mode_table[d1m0to3m2].modemask;
+ }
+ numelements = hweight_long(modemask);
+ len = 3 * numelements + 3;
+ tx_buf = kmalloc(len, GFP_KERNEL);
+ if (!tx_buf) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ tx_buf[0] = st->configbyte;
+ tx_buf[1] = st->setupbyte;
+ tx_buf[2] = (st->monitor_speed << 1);
+
+ /*
+ * So we need to do yet another bit of nefarious scan mode
+ * setup to match what we need.
+ */
+ for (j = 0; j < 8; j++)
+ if (modemask & (1 << j)) {
+ /* Establish the mode is in the scan */
+ if (st->mask_low & (1 << j)) {
+ tx_buf[i] = (st->thresh_low[j] >> 4) & 0xFF;
+ tx_buf[i + 1] = (st->thresh_low[j] << 4) & 0xF0;
+ } else if (j < 4) {
+ tx_buf[i] = 0;
+ tx_buf[i + 1] = 0;
+ } else {
+ tx_buf[i] = 0x80;
+ tx_buf[i + 1] = 0;
+ }
+ if (st->mask_high & (1 << j)) {
+ tx_buf[i + 1] |=
+ (st->thresh_high[j] >> 8) & 0x0F;
+ tx_buf[i + 2] = st->thresh_high[j] & 0xFF;
+ } else if (j < 4) {
+ tx_buf[i + 1] |= 0x0F;
+ tx_buf[i + 2] = 0xFF;
+ } else {
+ tx_buf[i + 1] |= 0x07;
+ tx_buf[i + 2] = 0xFF;
+ }
+ i += 3;
+ }
+
+
+ ret = i2c_master_send(st->client, tx_buf, len);
+ if (ret < 0)
+ goto error_ret;
+ if (ret != len) {
+ ret = -EIO;
+ goto error_ret;
+ }
+
+ /*
+ * Now that we hopefully have sensible thresholds in place it is
+ * time to turn the interrupts on.
+ * It is unclear from the data sheet if this should be necessary
+ * (i.e. whether monitor mode setup is atomic) but it appears to
+ * be in practice.
+ */
+ tx_buf[0] = st->setupbyte;
+ tx_buf[1] = MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0;
+ ret = i2c_master_send(st->client, tx_buf, 2);
+ if (ret < 0)
+ goto error_ret;
+ if (ret != 2) {
+ ret = -EIO;
+ goto error_ret;
+ }
+ ret = 0;
+ st->monitor_on = true;
+error_ret:
+
+ kfree(tx_buf);
+
+ return ret;
+}
+
+/*
+ * To keep this manageable we always use one of 3 scan modes.
+ * Scan 0...3, 0-1,2-3 and 1-0,3-2
+ */
+
+static inline int __max1363_check_event_mask(int thismask, int checkmask)
+{
+ int ret = 0;
+ /* Is it unipolar */
+ if (thismask < 4) {
+ if (checkmask & ~0x0F) {
+ ret = -EBUSY;
+ goto error_ret;
+ }
+ } else if (thismask < 6) {
+ if (checkmask & ~0x30) {
+ ret = -EBUSY;
+ goto error_ret;
+ }
+ } else if (checkmask & ~0xC0)
+ ret = -EBUSY;
+error_ret:
+ return ret;
+}
+
+static int max1363_write_event_config(struct iio_dev *indio_dev,
+ int event_code,
+ int state)
+{
+ int ret = 0;
+ struct max1363_state *st = iio_priv(indio_dev);
+ u16 unifiedmask;
+ int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
+
+ mutex_lock(&indio_dev->mlock);
+ unifiedmask = st->mask_low | st->mask_high;
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) {
+
+ if (state == 0)
+ st->mask_low &= ~(1 << number);
+ else {
+ ret = __max1363_check_event_mask((1 << number),
+ unifiedmask);
+ if (ret)
+ goto error_ret;
+ st->mask_low |= (1 << number);
+ }
+ } else {
+ if (state == 0)
+ st->mask_high &= ~(1 << number);
+ else {
+ ret = __max1363_check_event_mask((1 << number),
+ unifiedmask);
+ if (ret)
+ goto error_ret;
+ st->mask_high |= (1 << number);
+ }
+ }
+
+ max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
+error_ret:
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+/*
+ * As with scan_elements, only certain sets of these can
+ * be combined.
+ */
+static struct attribute *max1363_event_attributes[] = {
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL,
+};
+
+static struct attribute_group max1363_event_attribute_group = {
+ .attrs = max1363_event_attributes,
+};
+
+#define MAX1363_EVENT_FUNCS \
+
+
+static const struct iio_info max1238_info = {
+ .read_raw = &max1363_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info max1363_info = {
+ .read_event_value = &max1363_read_thresh,
+ .write_event_value = &max1363_write_thresh,
+ .read_event_config = &max1363_read_event_config,
+ .write_event_config = &max1363_write_event_config,
+ .read_raw = &max1363_read_raw,
+ .driver_module = THIS_MODULE,
+ .num_interrupt_lines = 1,
+ .event_attrs = &max1363_event_attribute_group,
+};
+
/* max1363 and max1368 tested - rest from data sheet */
static const struct max1363_chip_info max1363_chip_info_tbl[] = {
[max1361] = {
.bits = 10,
.int_vref_mv = 2048,
- .monitor_mode = 1,
.mode_list = max1363_mode_list,
.num_modes = ARRAY_SIZE(max1363_mode_list),
.default_mode = s0to3,
.channels = max1361_channels,
.num_channels = ARRAY_SIZE(max1361_channels),
+ .info = &max1363_info,
},
[max1362] = {
.bits = 10,
.int_vref_mv = 4096,
- .monitor_mode = 1,
.mode_list = max1363_mode_list,
.num_modes = ARRAY_SIZE(max1363_mode_list),
.default_mode = s0to3,
.channels = max1361_channels,
.num_channels = ARRAY_SIZE(max1361_channels),
+ .info = &max1363_info,
},
[max1363] = {
.bits = 12,
.int_vref_mv = 2048,
- .monitor_mode = 1,
.mode_list = max1363_mode_list,
.num_modes = ARRAY_SIZE(max1363_mode_list),
.default_mode = s0to3,
.channels = max1363_channels,
.num_channels = ARRAY_SIZE(max1363_channels),
+ .info = &max1363_info,
},
[max1364] = {
.bits = 12,
.int_vref_mv = 4096,
- .monitor_mode = 1,
.mode_list = max1363_mode_list,
.num_modes = ARRAY_SIZE(max1363_mode_list),
.default_mode = s0to3,
.channels = max1363_channels,
.num_channels = ARRAY_SIZE(max1363_channels),
+ .info = &max1363_info,
},
[max1036] = {
.bits = 8,
@@ -520,6 +882,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1236_mode_list,
.num_modes = ARRAY_SIZE(max1236_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1036_channels,
.num_channels = ARRAY_SIZE(max1036_channels),
},
@@ -529,6 +892,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1236_mode_list,
.num_modes = ARRAY_SIZE(max1236_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1036_channels,
.num_channels = ARRAY_SIZE(max1036_channels),
},
@@ -538,6 +902,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1038_channels,
.num_channels = ARRAY_SIZE(max1038_channels),
},
@@ -547,6 +912,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1038_channels,
.num_channels = ARRAY_SIZE(max1038_channels),
},
@@ -556,6 +922,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1236_mode_list,
.num_modes = ARRAY_SIZE(max1236_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1136_channels,
.num_channels = ARRAY_SIZE(max1136_channels),
},
@@ -565,6 +932,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1236_mode_list,
.num_modes = ARRAY_SIZE(max1236_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1136_channels,
.num_channels = ARRAY_SIZE(max1136_channels),
},
@@ -574,6 +942,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1138_channels,
.num_channels = ARRAY_SIZE(max1138_channels),
},
@@ -583,6 +952,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1138_channels,
.num_channels = ARRAY_SIZE(max1138_channels),
},
@@ -592,6 +962,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1236_mode_list,
.num_modes = ARRAY_SIZE(max1236_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1236_channels,
.num_channels = ARRAY_SIZE(max1236_channels),
},
@@ -601,6 +972,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1236_mode_list,
.num_modes = ARRAY_SIZE(max1236_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1236_channels,
.num_channels = ARRAY_SIZE(max1236_channels),
},
@@ -610,6 +982,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1238_channels,
.num_channels = ARRAY_SIZE(max1238_channels),
},
@@ -619,6 +992,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1238_channels,
.num_channels = ARRAY_SIZE(max1238_channels),
},
@@ -628,6 +1002,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11607_mode_list,
.num_modes = ARRAY_SIZE(max11607_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1036_channels,
.num_channels = ARRAY_SIZE(max1036_channels),
},
@@ -637,6 +1012,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11607_mode_list,
.num_modes = ARRAY_SIZE(max11607_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1036_channels,
.num_channels = ARRAY_SIZE(max1036_channels),
},
@@ -646,6 +1022,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11608_mode_list,
.num_modes = ARRAY_SIZE(max11608_mode_list),
.default_mode = s0to7,
+ .info = &max1238_info,
.channels = max11602_channels,
.num_channels = ARRAY_SIZE(max11602_channels),
},
@@ -655,6 +1032,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11608_mode_list,
.num_modes = ARRAY_SIZE(max11608_mode_list),
.default_mode = s0to7,
+ .info = &max1238_info,
.channels = max11602_channels,
.num_channels = ARRAY_SIZE(max11602_channels),
},
@@ -664,6 +1042,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1238_channels,
.num_channels = ARRAY_SIZE(max1238_channels),
},
@@ -673,6 +1052,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1238_channels,
.num_channels = ARRAY_SIZE(max1238_channels),
},
@@ -682,6 +1062,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11607_mode_list,
.num_modes = ARRAY_SIZE(max11607_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1136_channels,
.num_channels = ARRAY_SIZE(max1136_channels),
},
@@ -691,6 +1072,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11607_mode_list,
.num_modes = ARRAY_SIZE(max11607_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1136_channels,
.num_channels = ARRAY_SIZE(max1136_channels),
},
@@ -700,6 +1082,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11608_mode_list,
.num_modes = ARRAY_SIZE(max11608_mode_list),
.default_mode = s0to7,
+ .info = &max1238_info,
.channels = max11608_channels,
.num_channels = ARRAY_SIZE(max11608_channels),
},
@@ -709,6 +1092,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11608_mode_list,
.num_modes = ARRAY_SIZE(max11608_mode_list),
.default_mode = s0to7,
+ .info = &max1238_info,
.channels = max11608_channels,
.num_channels = ARRAY_SIZE(max11608_channels),
},
@@ -718,6 +1102,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1238_channels,
.num_channels = ARRAY_SIZE(max1238_channels),
},
@@ -727,6 +1112,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1238_channels,
.num_channels = ARRAY_SIZE(max1238_channels),
},
@@ -736,6 +1122,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11607_mode_list,
.num_modes = ARRAY_SIZE(max11607_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1363_channels,
.num_channels = ARRAY_SIZE(max1363_channels),
},
@@ -745,6 +1132,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11607_mode_list,
.num_modes = ARRAY_SIZE(max11607_mode_list),
.default_mode = s0to3,
+ .info = &max1238_info,
.channels = max1363_channels,
.num_channels = ARRAY_SIZE(max1363_channels),
},
@@ -754,6 +1142,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11608_mode_list,
.num_modes = ARRAY_SIZE(max11608_mode_list),
.default_mode = s0to7,
+ .info = &max1238_info,
.channels = max11614_channels,
.num_channels = ARRAY_SIZE(max11614_channels),
},
@@ -763,6 +1152,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11608_mode_list,
.num_modes = ARRAY_SIZE(max11608_mode_list),
.default_mode = s0to7,
+ .info = &max1238_info,
.channels = max11614_channels,
.num_channels = ARRAY_SIZE(max11614_channels),
},
@@ -772,6 +1162,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1238_channels,
.num_channels = ARRAY_SIZE(max1238_channels),
},
@@ -781,6 +1172,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
+ .info = &max1238_info,
.channels = max1238_channels,
.num_channels = ARRAY_SIZE(max1238_channels),
},
@@ -790,6 +1182,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11644_mode_list,
.num_modes = ARRAY_SIZE(max11644_mode_list),
.default_mode = s0to1,
+ .info = &max1238_info,
.channels = max11644_channels,
.num_channels = ARRAY_SIZE(max11644_channels),
},
@@ -799,6 +1192,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11644_mode_list,
.num_modes = ARRAY_SIZE(max11644_mode_list),
.default_mode = s0to1,
+ .info = &max1238_info,
.channels = max11644_channels,
.num_channels = ARRAY_SIZE(max11644_channels),
},
@@ -808,7 +1202,8 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11644_mode_list,
.num_modes = ARRAY_SIZE(max11644_mode_list),
.default_mode = s0to1,
- .channels = max11644_channels,
+ .info = &max1238_info,
+ .channels = max11646_channels,
.num_channels = ARRAY_SIZE(max11646_channels),
},
[max11647] = {
@@ -817,353 +1212,13 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
.mode_list = max11644_mode_list,
.num_modes = ARRAY_SIZE(max11644_mode_list),
.default_mode = s0to1,
- .channels = max11644_channels,
+ .info = &max1238_info,
+ .channels = max11646_channels,
.num_channels = ARRAY_SIZE(max11646_channels),
},
};
-static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600,
- 8300, 4200, 2000, 1000 };
-
-static ssize_t max1363_monitor_show_freq(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct max1363_state *st = iio_priv(dev_get_drvdata(dev));
- return sprintf(buf, "%d\n", max1363_monitor_speeds[st->monitor_speed]);
-}
-
-static ssize_t max1363_monitor_store_freq(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct max1363_state *st = iio_priv(indio_dev);
- int i, ret;
- unsigned long val;
- bool found = false;
-
- ret = strict_strtoul(buf, 10, &val);
- if (ret)
- return -EINVAL;
- for (i = 0; i < ARRAY_SIZE(max1363_monitor_speeds); i++)
- if (val == max1363_monitor_speeds[i]) {
- found = true;
- break;
- }
- if (!found)
- return -EINVAL;
-
- mutex_lock(&indio_dev->mlock);
- st->monitor_speed = i;
- mutex_unlock(&indio_dev->mlock);
-
- return 0;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR,
- max1363_monitor_show_freq,
- max1363_monitor_store_freq);
-
-static IIO_CONST_ATTR(sampling_frequency_available,
- "133000 665000 33300 16600 8300 4200 2000 1000");
-
-static int max1363_read_thresh(struct iio_dev *indio_dev,
- int event_code,
- int *val)
-{
- struct max1363_state *st = iio_priv(indio_dev);
- if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
- *val = st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)];
- else
- *val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)];
- return 0;
-}
-
-static int max1363_write_thresh(struct iio_dev *indio_dev,
- int event_code,
- int val)
-{
- struct max1363_state *st = iio_priv(indio_dev);
- /* make it handle signed correctly as well */
- switch (st->chip_info->bits) {
- case 10:
- if (val > 0x3FF)
- return -EINVAL;
- break;
- case 12:
- if (val > 0xFFF)
- return -EINVAL;
- break;
- }
-
- switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
- case IIO_EV_DIR_FALLING:
- st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val;
- break;
- case IIO_EV_DIR_RISING:
- st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val;
- break;
- }
-
- return 0;
-}
-static irqreturn_t max1363_event_handler(int irq, void *private)
-{
- struct iio_dev *indio_dev = private;
- struct max1363_state *st = iio_priv(indio_dev);
- s64 timestamp = iio_get_time_ns();
- u8 rx;
- u8 tx[2] = { st->setupbyte,
- MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 };
-
- i2c_master_recv(st->client, &rx, 1);
- /* todo - begging for use of for_each_set_bit */
- if (rx & (1 << 0))
- iio_push_event(indio_dev, 0,
- IIO_EVENT_CODE_IN_LOW_THRESH(3),
- timestamp);
- if (rx & (1 << 1))
- iio_push_event(indio_dev, 0,
- IIO_EVENT_CODE_IN_HIGH_THRESH(3),
- timestamp);
- if (rx & (1 << 2))
- iio_push_event(indio_dev, 0,
- IIO_EVENT_CODE_IN_LOW_THRESH(2),
- timestamp);
- if (rx & (1 << 3))
- iio_push_event(indio_dev, 0,
- IIO_EVENT_CODE_IN_HIGH_THRESH(2),
- timestamp);
- if (rx & (1 << 4))
- iio_push_event(indio_dev, 0,
- IIO_EVENT_CODE_IN_LOW_THRESH(1),
- timestamp);
- if (rx & (1 << 5))
- iio_push_event(indio_dev, 0,
- IIO_EVENT_CODE_IN_HIGH_THRESH(1),
- timestamp);
- if (rx & (1 << 6))
- iio_push_event(indio_dev, 0,
- IIO_EVENT_CODE_IN_LOW_THRESH(0),
- timestamp);
- if (rx & (1 << 7))
- iio_push_event(indio_dev, 0,
- IIO_EVENT_CODE_IN_HIGH_THRESH(0),
- timestamp);
- i2c_master_send(st->client, tx, 2);
-
- return IRQ_HANDLED;
-}
-
-static int max1363_read_event_config(struct iio_dev *indio_dev,
- int event_code)
-{
- struct max1363_state *st = iio_priv(indio_dev);
-
- int val;
- int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
- mutex_lock(&indio_dev->mlock);
- if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
- val = (1 << number) & st->mask_low;
- else
- val = (1 << number) & st->mask_high;
- mutex_unlock(&indio_dev->mlock);
-
- return val;
-}
-
-static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
-{
- u8 *tx_buf;
- int ret, i = 3, j;
- unsigned long numelements;
- int len;
- long modemask;
-
- if (!enabled) {
- /* transition to ring capture is not currently supported */
- st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP;
- st->configbyte &= ~MAX1363_SCAN_MASK;
- st->monitor_on = false;
- return max1363_write_basic_config(st->client,
- st->setupbyte,
- st->configbyte);
- }
-
- /* Ensure we are in the relevant mode */
- st->setupbyte |= MAX1363_SETUP_MONITOR_SETUP;
- st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
- | MAX1363_SCAN_MASK
- | MAX1363_SE_DE_MASK);
- st->configbyte |= MAX1363_CONFIG_SCAN_MONITOR_MODE;
- if ((st->mask_low | st->mask_high) & 0x0F) {
- st->configbyte |= max1363_mode_table[s0to3].conf;
- modemask = max1363_mode_table[s0to3].modemask;
- } else if ((st->mask_low | st->mask_high) & 0x30) {
- st->configbyte |= max1363_mode_table[d0m1to2m3].conf;
- modemask = max1363_mode_table[d0m1to2m3].modemask;
- } else {
- st->configbyte |= max1363_mode_table[d1m0to3m2].conf;
- modemask = max1363_mode_table[d1m0to3m2].modemask;
- }
- numelements = hweight_long(modemask);
- len = 3 * numelements + 3;
- tx_buf = kmalloc(len, GFP_KERNEL);
- if (!tx_buf) {
- ret = -ENOMEM;
- goto error_ret;
- }
- tx_buf[0] = st->configbyte;
- tx_buf[1] = st->setupbyte;
- tx_buf[2] = (st->monitor_speed << 1);
-
- /*
- * So we need to do yet another bit of nefarious scan mode
- * setup to match what we need.
- */
- for (j = 0; j < 8; j++)
- if (modemask & (1 << j)) {
- /* Establish the mode is in the scan */
- if (st->mask_low & (1 << j)) {
- tx_buf[i] = (st->thresh_low[j] >> 4) & 0xFF;
- tx_buf[i + 1] = (st->thresh_low[j] << 4) & 0xF0;
- } else if (j < 4) {
- tx_buf[i] = 0;
- tx_buf[i + 1] = 0;
- } else {
- tx_buf[i] = 0x80;
- tx_buf[i + 1] = 0;
- }
- if (st->mask_high & (1 << j)) {
- tx_buf[i + 1] |=
- (st->thresh_high[j] >> 8) & 0x0F;
- tx_buf[i + 2] = st->thresh_high[j] & 0xFF;
- } else if (j < 4) {
- tx_buf[i + 1] |= 0x0F;
- tx_buf[i + 2] = 0xFF;
- } else {
- tx_buf[i + 1] |= 0x07;
- tx_buf[i + 2] = 0xFF;
- }
- i += 3;
- }
-
-
- ret = i2c_master_send(st->client, tx_buf, len);
- if (ret < 0)
- goto error_ret;
- if (ret != len) {
- ret = -EIO;
- goto error_ret;
- }
-
- /*
- * Now that we hopefully have sensible thresholds in place it is
- * time to turn the interrupts on.
- * It is unclear from the data sheet if this should be necessary
- * (i.e. whether monitor mode setup is atomic) but it appears to
- * be in practice.
- */
- tx_buf[0] = st->setupbyte;
- tx_buf[1] = MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0;
- ret = i2c_master_send(st->client, tx_buf, 2);
- if (ret < 0)
- goto error_ret;
- if (ret != 2) {
- ret = -EIO;
- goto error_ret;
- }
- ret = 0;
- st->monitor_on = true;
-error_ret:
-
- kfree(tx_buf);
-
- return ret;
-}
-
-/*
- * To keep this manageable we always use one of 3 scan modes.
- * Scan 0...3, 0-1,2-3 and 1-0,3-2
- */
-
-static inline int __max1363_check_event_mask(int thismask, int checkmask)
-{
- int ret = 0;
- /* Is it unipolar */
- if (thismask < 4) {
- if (checkmask & ~0x0F) {
- ret = -EBUSY;
- goto error_ret;
- }
- } else if (thismask < 6) {
- if (checkmask & ~0x30) {
- ret = -EBUSY;
- goto error_ret;
- }
- } else if (checkmask & ~0xC0)
- ret = -EBUSY;
-error_ret:
- return ret;
-}
-
-static int max1363_write_event_config(struct iio_dev *indio_dev,
- int event_code,
- int state)
-{
- int ret = 0;
- struct max1363_state *st = iio_priv(indio_dev);
- u16 unifiedmask;
- int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
-
- mutex_lock(&indio_dev->mlock);
- unifiedmask = st->mask_low | st->mask_high;
- if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) {
-
- if (state == 0)
- st->mask_low &= ~(1 << number);
- else {
- ret = __max1363_check_event_mask((1 << number),
- unifiedmask);
- if (ret)
- goto error_ret;
- st->mask_low |= (1 << number);
- }
- } else {
- if (state == 0)
- st->mask_high &= ~(1 << number);
- else {
- ret = __max1363_check_event_mask((1 << number),
- unifiedmask);
- if (ret)
- goto error_ret;
- st->mask_high |= (1 << number);
- }
- }
-
- max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-/*
- * As with scan_elements, only certain sets of these can
- * be combined.
- */
-static struct attribute *max1363_event_attributes[] = {
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- NULL,
-};
-
-static struct attribute_group max1363_event_attribute_group = {
- .attrs = max1363_event_attributes,
-};
static int max1363_initial_setup(struct max1363_state *st)
{
@@ -1224,22 +1279,9 @@ static int __devinit max1363_probe(struct i2c_client *client,
/* Estabilish that the iio_dev is a child of the i2c device */
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
- indio_dev->read_event_value = &max1363_read_thresh;
- indio_dev->write_event_value = &max1363_write_thresh;
- indio_dev->read_event_config = &max1363_read_event_config;
- indio_dev->write_event_config = &max1363_write_event_config;
- indio_dev->channels = st->chip_info->channels;
- indio_dev->num_channels = st->chip_info->num_channels;
- indio_dev->read_raw = &max1363_read_raw;
- /* Todo: this shouldn't be here. */
- indio_dev->driver_module = THIS_MODULE;
- indio_dev->modes = INDIO_DIRECT_MODE;
- if (st->chip_info->monitor_mode && client->irq) {
- indio_dev->num_interrupt_lines = 1;
- indio_dev->event_attrs
- = &max1363_event_attribute_group;
- }
+ indio_dev->info = st->chip_info->info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
ret = max1363_initial_setup(st);
if (ret)
goto error_free_available_scan_masks;
@@ -1258,7 +1300,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
if (ret)
goto error_cleanup_ring;
- if (st->chip_info->monitor_mode && client->irq) {
+ if (client->irq) {
ret = request_threaded_irq(st->client->irq,
NULL,
&max1363_event_handler,
@@ -1298,7 +1340,7 @@ static int max1363_remove(struct i2c_client *client)
struct max1363_state *st = iio_priv(indio_dev);
struct regulator *reg = st->reg;
- if (st->chip_info->monitor_mode && client->irq)
+ if (client->irq)
free_irq(st->client->irq, indio_dev);
iio_ring_buffer_unregister(indio_dev->ring);
max1363_ring_cleanup(indio_dev);