diff options
Diffstat (limited to 'drivers/staging/iio')
32 files changed, 547 insertions, 885 deletions
diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c index 40d0ecac047f..044ea196aa6f 100644 --- a/drivers/staging/iio/Documentation/generic_buffer.c +++ b/drivers/staging/iio/Documentation/generic_buffer.c @@ -305,9 +305,12 @@ int main(int argc, char **argv) read_size = read(fp, data, toread*scan_size); - if (read_size == -EAGAIN) { - printf("nothing available\n"); - continue; + if (read_size < 0) { + if (errno == -EAGAIN) { + printf("nothing available\n"); + continue; + } else + break; } for (i = 0; i < read_size/scan_size; i++) process_scan(data + scan_size*i, diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 3a9b00087403..569d6f8face5 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -46,6 +46,9 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_TIMESTAMP] = "timestamp", [IIO_CAPACITANCE] = "capacitance", [IIO_ALTVOLTAGE] = "altvoltage", + [IIO_CCT] = "cct", + [IIO_PRESSURE] = "pressure", + [IIO_HUMIDITYRELATIVE] = "humidityrelative", }; static const char * const iio_ev_type_text[] = { @@ -70,6 +73,8 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_LIGHT_IR] = "ir", [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)", [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", + [IIO_MOD_LIGHT_BOTH] = "both", + [IIO_MOD_LIGHT_IR] = "ir", [IIO_MOD_LIGHT_CLEAR] = "clear", [IIO_MOD_LIGHT_RED] = "red", [IIO_MOD_LIGHT_GREEN] = "green", @@ -100,6 +105,9 @@ static bool event_is_known(struct iio_event_data *event) case IIO_TIMESTAMP: case IIO_CAPACITANCE: case IIO_ALTVOLTAGE: + case IIO_CCT: + case IIO_PRESSURE: + case IIO_HUMIDITYRELATIVE: break; default: return false; diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h index a9cfc06edb01..0973a092224a 100644 --- a/drivers/staging/iio/Documentation/iio_utils.h +++ b/drivers/staging/iio/Documentation/iio_utils.h @@ -633,7 +633,7 @@ error_free: int read_sysfs_float(char *filename, char *basedir, float *val) { - float ret = 0; + int ret = 0; FILE *sysfsfp; char *temp = malloc(strlen(basedir) + strlen(filename) + 2); if (temp == NULL) { @@ -653,9 +653,9 @@ error_free: return ret; } -read_sysfs_string(const char *filename, const char *basedir, char *str) +int read_sysfs_string(const char *filename, const char *basedir, char *str) { - float ret = 0; + int ret = 0; FILE *sysfsfp; char *temp = malloc(strlen(basedir) + strlen(filename) + 2); if (temp == NULL) { diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs b/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs deleted file mode 100644 index 5235e6c749ab..000000000000 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs +++ /dev/null @@ -1,11 +0,0 @@ -What: /sys/bus/iio/devices/triggerX/trigger_now -KernelVersion: 2.6.38 -Contact: linux-iio@vger.kernel.org -Description: - This file is provided by the iio-trig-sysfs stand-alone trigger - driver. Writing this file with any value triggers an event - driven driver, associated with this trigger, to capture data - into an in kernel buffer. This approach can be valuable during - automated testing or in situations, where other trigger methods - are not applicable. For example no RTC or spare GPIOs. - X is the IIO index of the trigger. diff --git a/drivers/staging/iio/Documentation/trigger.txt b/drivers/staging/iio/Documentation/trigger.txt index 64e2e08fb4d0..7c0e505e4f04 100644 --- a/drivers/staging/iio/Documentation/trigger.txt +++ b/drivers/staging/iio/Documentation/trigger.txt @@ -31,5 +31,5 @@ consumers. Trigger Consumers Currently triggers are only used for the filling of software -buffers and as such any device supporting INDIO_RING_TRIGGERED has the +buffers and as such any device supporting INDIO_BUFFER_TRIGGERED has the consumer interface automatically created. diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index b36feb080cba..fa38be0982f9 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -36,10 +36,11 @@ config IIO_SIMPLE_DUMMY_EVENTS Add some dummy events to the simple dummy driver. config IIO_SIMPLE_DUMMY_BUFFER - boolean "Buffered capture support" - select IIO_KFIFO_BUF - help - Add buffered data capture to the simple dummy driver. + boolean "Buffered capture support" + select IIO_BUFFER + select IIO_KFIFO_BUF + help + Add buffered data capture to the simple dummy driver. endif # IIO_SIMPLE_DUMMY diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 2105576fa77c..50ba1fa7f98a 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -131,17 +131,17 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16201_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12), - ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12), + ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12), + ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12), ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), - ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), + ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 0, 12), ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), IIO_CHAN_SOFT_TIMESTAMP(7) }; diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 409a28ed9043..f472137b0069 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -99,13 +99,14 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16203_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12), - ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12), + ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 0, 12), + ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 0, 12), ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), /* Fixme: Not what it appears to be - see data sheet */ - ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14), - ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12), + ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, + 0, 0, 14), + ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 0, 12), IIO_CHAN_SOFT_TIMESTAMP(5), }; diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index b8ea76857cd6..19eaebc77d7a 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -136,15 +136,15 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16204_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 12), - ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12), - ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12), + ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 0, 12), + ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12), + ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12), ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14), ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14), ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT, - ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 14), + ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14), IIO_CHAN_SOFT_TIMESTAMP(5), }; diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 4492e51d8886..374dc6edbcf5 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -130,16 +130,18 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16209_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14), - ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12), + ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 0, 14), + ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 0, 12), ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), - ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12), - ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14), - ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14), - ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), + ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 0, 12), + ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, + 0, 0, 14), + ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, + 0, 0, 14), + ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 0, 14), IIO_CHAN_SOFT_TIMESTAMP(8) }; diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 3a303a03d028..74ace2a8769d 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -173,15 +173,15 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16240_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10), - ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10), + ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 0, 10), + ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 0, 10), ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), - ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), + ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 0, 10), IIO_CHAN_SOFT_TIMESTAMP(6) }; diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 79cefe0a516a..bf33fdead479 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -31,7 +31,7 @@ irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private) struct lis3l02dq_state *st = iio_priv(indio_dev); if (st->trigger_on) { - iio_trigger_poll(st->trig, iio_get_time_ns()); + iio_trigger_poll(st->trig); return IRQ_HANDLED; } else return IRQ_WAKE_THREAD; diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 198710651e0e..33f0e9235be7 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -141,6 +141,11 @@ static int sca3000_ring_get_bytes_per_datum(struct iio_buffer *r) return 6; } +static bool sca3000_ring_buf_data_available(struct iio_buffer *r) +{ + return r->stufftoread; +} + static IIO_BUFFER_ENABLE_ATTR; static IIO_BUFFER_LENGTH_ATTR; @@ -274,6 +279,7 @@ static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, .get_length = &sca3000_ring_get_length, .get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum, + .data_available = sca3000_ring_buf_data_available, .release = sca3000_ring_release, }; diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index b87e382ad768..d01c7076a342 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -3,13 +3,6 @@ # menu "Analog to digital converters" -config AD7291 - tristate "Analog Devices AD7291 ADC driver" - depends on I2C - help - Say yes here to build support for Analog Devices AD7291 - 8 Channel ADC with temperature sensor. - config AD7606 tristate "Analog Devices AD7606 ADC driver" depends on GPIOLIB @@ -94,7 +87,7 @@ config LPC32XX_ADC config MXS_LRADC tristate "Freescale i.MX23/i.MX28 LRADC" - depends on ARCH_MXS || COMPILE_TEST + depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM depends on INPUT select STMP_DEVICE select IIO_BUFFER diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index afdcd1ff08ff..1c4277dbd318 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -8,7 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o obj-$(CONFIG_AD7606) += ad7606.o -obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7780) += ad7780.o obj-$(CONFIG_AD7816) += ad7816.o obj-$(CONFIG_AD7192) += ad7192.o diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c deleted file mode 100644 index 357cef2a6f4c..000000000000 --- a/drivers/staging/iio/adc/ad7291.c +++ /dev/null @@ -1,580 +0,0 @@ -/* - * AD7291 8-Channel, I2C, 12-Bit SAR ADC with Temperature Sensor - * - * Copyright 2010-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/i2c.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/regulator/consumer.h> -#include <linux/err.h> - -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/iio/events.h> - -#include "ad7291.h" - -/* - * Simplified handling - * - * If no events enabled - single polled channel read - * If event enabled direct reads disable unless channel - * is in the read mask. - * - * The noise-delayed bit as per datasheet suggestion is always enabled. - * - */ - -/* - * AD7291 registers definition - */ -#define AD7291_COMMAND 0x00 -#define AD7291_VOLTAGE 0x01 -#define AD7291_T_SENSE 0x02 -#define AD7291_T_AVERAGE 0x03 -#define AD7291_DATA_HIGH(x) ((x) * 3 + 0x4) -#define AD7291_DATA_LOW(x) ((x) * 3 + 0x5) -#define AD7291_HYST(x) ((x) * 3 + 0x6) -#define AD7291_VOLTAGE_ALERT_STATUS 0x1F -#define AD7291_T_ALERT_STATUS 0x20 - -#define AD7291_VOLTAGE_LIMIT_COUNT 8 - - -/* - * AD7291 command - */ -#define AD7291_AUTOCYCLE (1 << 0) -#define AD7291_RESET (1 << 1) -#define AD7291_ALERT_CLEAR (1 << 2) -#define AD7291_ALERT_POLARITY (1 << 3) -#define AD7291_EXT_REF (1 << 4) -#define AD7291_NOISE_DELAY (1 << 5) -#define AD7291_T_SENSE_MASK (1 << 7) -#define AD7291_VOLTAGE_MASK 0xFF00 -#define AD7291_VOLTAGE_OFFSET 0x8 - -/* - * AD7291 value masks - */ -#define AD7291_CHANNEL_MASK 0xF000 -#define AD7291_BITS 12 -#define AD7291_VALUE_MASK 0xFFF -#define AD7291_T_VALUE_SIGN 0x400 -#define AD7291_T_VALUE_FLOAT_OFFSET 2 -#define AD7291_T_VALUE_FLOAT_MASK 0x2 - -#define AD7291_BITS 12 - -struct ad7291_chip_info { - struct i2c_client *client; - struct regulator *reg; - u16 command; - u16 c_mask; /* Active voltage channels for events */ - struct mutex state_lock; -}; - -static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data) -{ - struct i2c_client *client = chip->client; - int ret = 0; - - ret = i2c_smbus_read_word_swapped(client, reg); - if (ret < 0) { - dev_err(&client->dev, "I2C read error\n"); - return ret; - } - - *data = ret; - - return 0; -} - -static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data) -{ - return i2c_smbus_write_word_swapped(chip->client, reg, data); -} - -static irqreturn_t ad7291_event_handler(int irq, void *private) -{ - struct iio_dev *indio_dev = private; - struct ad7291_chip_info *chip = iio_priv(private); - u16 t_status, v_status; - u16 command; - int i; - s64 timestamp = iio_get_time_ns(); - - if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status)) - return IRQ_HANDLED; - - if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status)) - return IRQ_HANDLED; - - if (!(t_status || v_status)) - return IRQ_HANDLED; - - command = chip->command | AD7291_ALERT_CLEAR; - ad7291_i2c_write(chip, AD7291_COMMAND, command); - - command = chip->command & ~AD7291_ALERT_CLEAR; - ad7291_i2c_write(chip, AD7291_COMMAND, command); - - /* For now treat t_sense and t_sense_average the same */ - if ((t_status & (1 << 0)) || (t_status & (1 << 2))) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - timestamp); - if ((t_status & (1 << 1)) || (t_status & (1 << 3))) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - - for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) { - if (v_status & (1 << i)) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, - i/2, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - timestamp); - if (v_status & (1 << (i + 1))) - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, - i/2, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - timestamp); - } - - return IRQ_HANDLED; -} - -static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan, - enum iio_event_direction dir, enum iio_event_info info) -{ - unsigned int offset; - - switch (chan->type) { - case IIO_VOLTAGE: - offset = chan->channel; - break; - case IIO_TEMP: - offset = 8; - break; - default: - return 0; - } - - switch (info) { - case IIO_EV_INFO_VALUE: - if (dir == IIO_EV_DIR_FALLING) - return AD7291_DATA_HIGH(offset); - else - return AD7291_DATA_LOW(offset); - case IIO_EV_INFO_HYSTERESIS: - return AD7291_HYST(offset); - default: - break; - } - return 0; -} - -static int ad7291_read_event_value(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) -{ - struct ad7291_chip_info *chip = iio_priv(indio_dev); - int ret; - u16 uval; - - ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info), - &uval); - if (ret < 0) - return ret; - - if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) - *val = uval & AD7291_VALUE_MASK; - - else - *val = sign_extend32(uval, 11); - - return IIO_VAL_INT; -} - -static int ad7291_write_event_value(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) -{ - struct ad7291_chip_info *chip = iio_priv(indio_dev); - - if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) { - if (val > AD7291_VALUE_MASK || val < 0) - return -EINVAL; - } else { - if (val > 2047 || val < -2048) - return -EINVAL; - } - - return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info), - val); -} - -static int ad7291_read_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir) -{ - struct ad7291_chip_info *chip = iio_priv(indio_dev); - /* To be enabled the channel must simply be on. If any are enabled - we are in continuous sampling mode */ - - switch (chan->type) { - case IIO_VOLTAGE: - if (chip->c_mask & (1 << (15 - chan->channel))) - return 1; - else - return 0; - case IIO_TEMP: - /* always on */ - return 1; - default: - return -EINVAL; - } - -} - -static int ad7291_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) -{ - int ret = 0; - struct ad7291_chip_info *chip = iio_priv(indio_dev); - unsigned int mask; - u16 regval; - - mutex_lock(&chip->state_lock); - regval = chip->command; - /* - * To be enabled the channel must simply be on. If any are enabled - * use continuous sampling mode. - * Possible to disable temp as well but that makes single read tricky. - */ - - mask = BIT(15 - chan->channel); - - switch (chan->type) { - case IIO_VOLTAGE: - if ((!state) && (chip->c_mask & mask)) - chip->c_mask &= ~mask; - else if (state && (!(chip->c_mask & mask))) - chip->c_mask |= mask; - else - break; - - regval &= ~AD7291_AUTOCYCLE; - regval |= chip->c_mask; - if (chip->c_mask) /* Enable autocycle? */ - regval |= AD7291_AUTOCYCLE; - - ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval); - if (ret < 0) - goto error_ret; - - chip->command = regval; - break; - default: - ret = -EINVAL; - } - -error_ret: - mutex_unlock(&chip->state_lock); - return ret; -} - -static int ad7291_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - int ret; - struct ad7291_chip_info *chip = iio_priv(indio_dev); - u16 regval; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - switch (chan->type) { - case IIO_VOLTAGE: - mutex_lock(&chip->state_lock); - /* If in autocycle mode drop through */ - if (chip->command & AD7291_AUTOCYCLE) { - mutex_unlock(&chip->state_lock); - return -EBUSY; - } - /* Enable this channel alone */ - regval = chip->command & (~AD7291_VOLTAGE_MASK); - regval |= 1 << (15 - chan->channel); - ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval); - if (ret < 0) { - mutex_unlock(&chip->state_lock); - return ret; - } - /* Read voltage */ - ret = i2c_smbus_read_word_swapped(chip->client, - AD7291_VOLTAGE); - if (ret < 0) { - mutex_unlock(&chip->state_lock); - return ret; - } - *val = ret & AD7291_VALUE_MASK; - mutex_unlock(&chip->state_lock); - return IIO_VAL_INT; - case IIO_TEMP: - /* Assumes tsense bit of command register always set */ - ret = i2c_smbus_read_word_swapped(chip->client, - AD7291_T_SENSE); - if (ret < 0) - return ret; - *val = sign_extend32(ret, 11); - return IIO_VAL_INT; - default: - return -EINVAL; - } - case IIO_CHAN_INFO_AVERAGE_RAW: - ret = i2c_smbus_read_word_swapped(chip->client, - AD7291_T_AVERAGE); - if (ret < 0) - return ret; - *val = sign_extend32(ret, 11); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_VOLTAGE: - if (chip->reg) { - int vref; - vref = regulator_get_voltage(chip->reg); - if (vref < 0) - return vref; - *val = vref / 1000; - } else { - *val = 2500; - } - *val2 = AD7291_BITS; - return IIO_VAL_FRACTIONAL_LOG2; - case IIO_TEMP: - /* - * One LSB of the ADC corresponds to 0.25 deg C. - * The temperature reading is in 12-bit twos - * complement format - */ - *val = 250; - return IIO_VAL_INT; - default: - return -EINVAL; - } - default: - return -EINVAL; - } -} - -static const struct iio_event_spec ad7291_events[] = { - { - .type = IIO_EV_TYPE_THRESH, - .dir = IIO_EV_DIR_RISING, - .mask_separate = BIT(IIO_EV_INFO_VALUE) | - BIT(IIO_EV_INFO_ENABLE), - }, { - .type = IIO_EV_TYPE_THRESH, - .dir = IIO_EV_DIR_FALLING, - .mask_separate = BIT(IIO_EV_INFO_VALUE) | - BIT(IIO_EV_INFO_ENABLE), - }, { - .type = IIO_EV_TYPE_THRESH, - .dir = IIO_EV_DIR_EITHER, - .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), - }, -}; - -#define AD7291_VOLTAGE_CHAN(_chan) \ -{ \ - .type = IIO_VOLTAGE, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .indexed = 1, \ - .channel = _chan, \ - .event_spec = ad7291_events, \ - .num_event_specs = ARRAY_SIZE(ad7291_events), \ -} - -static const struct iio_chan_spec ad7291_channels[] = { - AD7291_VOLTAGE_CHAN(0), - AD7291_VOLTAGE_CHAN(1), - AD7291_VOLTAGE_CHAN(2), - AD7291_VOLTAGE_CHAN(3), - AD7291_VOLTAGE_CHAN(4), - AD7291_VOLTAGE_CHAN(5), - AD7291_VOLTAGE_CHAN(6), - AD7291_VOLTAGE_CHAN(7), - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_AVERAGE_RAW) | - BIT(IIO_CHAN_INFO_SCALE), - .indexed = 1, - .channel = 0, - .event_spec = ad7291_events, - .num_event_specs = ARRAY_SIZE(ad7291_events), - } -}; - -static const struct iio_info ad7291_info = { - .read_raw = &ad7291_read_raw, - .read_event_config = &ad7291_read_event_config, - .write_event_config = &ad7291_write_event_config, - .read_event_value = &ad7291_read_event_value, - .write_event_value = &ad7291_write_event_value, - .driver_module = THIS_MODULE, -}; - -static int ad7291_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ad7291_platform_data *pdata = client->dev.platform_data; - struct ad7291_chip_info *chip; - struct iio_dev *indio_dev; - int ret = 0; - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); - if (!indio_dev) - return -ENOMEM; - chip = iio_priv(indio_dev); - - if (pdata && pdata->use_external_ref) { - chip->reg = devm_regulator_get(&client->dev, "vref"); - if (IS_ERR(chip->reg)) - return ret; - - ret = regulator_enable(chip->reg); - if (ret) - return ret; - } - - mutex_init(&chip->state_lock); - /* this is only used for device removal purposes */ - i2c_set_clientdata(client, indio_dev); - - chip->client = client; - - chip->command = AD7291_NOISE_DELAY | - AD7291_T_SENSE_MASK | /* Tsense always enabled */ - AD7291_ALERT_POLARITY; /* set irq polarity low level */ - - if (pdata && pdata->use_external_ref) - chip->command |= AD7291_EXT_REF; - - indio_dev->name = id->name; - indio_dev->channels = ad7291_channels; - indio_dev->num_channels = ARRAY_SIZE(ad7291_channels); - - indio_dev->dev.parent = &client->dev; - indio_dev->info = &ad7291_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = ad7291_i2c_write(chip, AD7291_COMMAND, AD7291_RESET); - if (ret) { - ret = -EIO; - goto error_disable_reg; - } - - ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command); - if (ret) { - ret = -EIO; - goto error_disable_reg; - } - - if (client->irq > 0) { - ret = request_threaded_irq(client->irq, - NULL, - &ad7291_event_handler, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - id->name, - indio_dev); - if (ret) - goto error_disable_reg; - } - - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_irq; - - return 0; - -error_unreg_irq: - if (client->irq) - free_irq(client->irq, indio_dev); -error_disable_reg: - if (chip->reg) - regulator_disable(chip->reg); - - return ret; -} - -static int ad7291_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ad7291_chip_info *chip = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - if (client->irq) - free_irq(client->irq, indio_dev); - - if (chip->reg) - regulator_disable(chip->reg); - - return 0; -} - -static const struct i2c_device_id ad7291_id[] = { - { "ad7291", 0 }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ad7291_id); - -static struct i2c_driver ad7291_driver = { - .driver = { - .name = KBUILD_MODNAME, - }, - .probe = ad7291_probe, - .remove = ad7291_remove, - .id_table = ad7291_id, -}; -module_i2c_driver(ad7291_driver); - -MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("Analog Devices AD7291 ADC driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7291.h b/drivers/staging/iio/adc/ad7291.h deleted file mode 100644 index bbd89fa51188..000000000000 --- a/drivers/staging/iio/adc/ad7291.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __IIO_AD7291_H__ -#define __IIO_AD7291_H__ - -/** - * struct ad7291_platform_data - AD7291 platform data - * @use_external_ref: Whether to use an external or internal reference voltage - */ -struct ad7291_platform_data { - bool use_external_ref; -}; - -#endif diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index 8a48d18de788..7511839ba94e 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -53,7 +53,7 @@ static int ad7606_par_probe(struct platform_device *pdev) struct iio_dev *indio_dev; void __iomem *addr; resource_size_t remap_size; - int ret, irq; + int irq; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -62,56 +62,31 @@ static int ad7606_par_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; + addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(addr)) + return PTR_ERR(addr); remap_size = resource_size(res); - /* Request the regions */ - if (!request_mem_region(res->start, remap_size, "iio-ad7606")) { - ret = -EBUSY; - goto out1; - } - addr = ioremap(res->start, remap_size); - if (!addr) { - ret = -ENOMEM; - goto out1; - } - indio_dev = ad7606_probe(&pdev->dev, irq, addr, platform_get_device_id(pdev)->driver_data, remap_size > 1 ? &ad7606_par16_bops : &ad7606_par8_bops); - if (IS_ERR(indio_dev)) { - ret = PTR_ERR(indio_dev); - goto out2; - } + if (IS_ERR(indio_dev)) + return PTR_ERR(indio_dev); platform_set_drvdata(pdev, indio_dev); return 0; - -out2: - iounmap(addr); -out1: - release_mem_region(res->start, remap_size); - - return ret; } static int ad7606_par_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); - struct resource *res; - struct ad7606_state *st = iio_priv(indio_dev); ad7606_remove(indio_dev, platform_get_irq(pdev, 0)); - iounmap(st->base_address); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - return 0; } diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index dae8d1a9038e..468327f4a753 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -846,6 +846,14 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val) LRADC_CTRL1); mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); + /* Enable / disable the divider per requirement */ + if (test_bit(chan, &lradc->is_divided)) + mxs_lradc_reg_set(lradc, 1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, + LRADC_CTRL2); + else + mxs_lradc_reg_clear(lradc, + 1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, LRADC_CTRL2); + /* Clean the slot's previous content, then set new one. */ mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), LRADC_CTRL4); @@ -961,15 +969,11 @@ static int mxs_lradc_write_raw(struct iio_dev *iio_dev, if (val == scale_avail[MXS_LRADC_DIV_DISABLED].integer && val2 == scale_avail[MXS_LRADC_DIV_DISABLED].nano) { /* divider by two disabled */ - writel(1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, - lradc->base + LRADC_CTRL2 + STMP_OFFSET_REG_CLR); clear_bit(chan->channel, &lradc->is_divided); ret = 0; } else if (val == scale_avail[MXS_LRADC_DIV_ENABLED].integer && val2 == scale_avail[MXS_LRADC_DIV_ENABLED].nano) { /* divider by two enabled */ - writel(1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, - lradc->base + LRADC_CTRL2 + STMP_OFFSET_REG_SET); set_bit(chan->channel, &lradc->is_divided); ret = 0; } @@ -1166,7 +1170,7 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) mxs_lradc_handle_touch(lradc); if (iio_buffer_enabled(iio)) - iio_trigger_poll(iio->trig, iio_get_time_ns()); + iio_trigger_poll(iio->trig); else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) complete(&lradc->completion); diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index c7d0307c8e76..cf68159a5848 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -57,7 +57,7 @@ static int ad9832_write_frequency(struct ad9832_state *st, } static int ad9832_write_phase(struct ad9832_state *st, - unsigned long addr, unsigned long phase) + unsigned long addr, unsigned long phase) { if (phase > (1 << AD9832_PHASE_BITS)) return -EINVAL; @@ -72,10 +72,8 @@ static int ad9832_write_phase(struct ad9832_state *st, return spi_sync(st->spi, &st->phase_msg); } -static ssize_t ad9832_write(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad9832_state *st = iio_priv(indio_dev); @@ -109,11 +107,11 @@ static ssize_t ad9832_write(struct device *dev, ret = spi_sync(st->spi, &st->msg); break; case AD9832_FREQ_SYM: - if (val == 1) + if (val == 1) { st->ctrl_fp |= AD9832_FREQ; - else if (val == 0) + } else if (val == 0) { st->ctrl_fp &= ~AD9832_FREQ; - else { + } else { ret = -EINVAL; break; } @@ -122,7 +120,7 @@ static ssize_t ad9832_write(struct device *dev, ret = spi_sync(st->spi, &st->msg); break; case AD9832_PHASE_SYM: - if (val < 0 || val > 3) { + if (val > 3) { ret = -EINVAL; break; } diff --git a/drivers/staging/iio/frequency/ad9850.c b/drivers/staging/iio/frequency/ad9850.c index af877ff680e9..8727933cafcf 100644 --- a/drivers/staging/iio/frequency/ad9850.c +++ b/drivers/staging/iio/frequency/ad9850.c @@ -21,9 +21,6 @@ #define DRV_NAME "ad9850" -#define value_mask (u16)0xf000 -#define addr_shift 12 - /* Register format: 4 bits addr + 12 bits value */ struct ad9850_config { u8 control[5]; @@ -50,9 +47,6 @@ static ssize_t ad9850_set_parameter(struct device *dev, mutex_lock(&st->lock); ret = spi_sync_transfer(st->sdev, &xfer, 1); - if (ret) - goto error_ret; -error_ret: mutex_unlock(&st->lock); return ret ? ret : len; diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index fd334a03a49a..bf78e6f0311f 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -550,6 +550,7 @@ error_ret: static __init int iio_dummy_init(void) { int i, ret; + if (instances > 10) { instances = 1; return -EINVAL; @@ -577,6 +578,7 @@ module_init(iio_dummy_init); static __exit void iio_dummy_exit(void) { int i; + for (i = 0; i < instances; i++) iio_dummy_remove(i); kfree(iio_dummy_devs); diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 9e0f2a9c73ae..ab338e3ddd05 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -667,9 +667,13 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) chip->tsl2x7x_config[TSL2X7X_PRX_COUNT] = chip->tsl2x7x_settings.prox_pulse_count; chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHLO] = - chip->tsl2x7x_settings.prox_thres_low; + (chip->tsl2x7x_settings.prox_thres_low) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHHI] = + (chip->tsl2x7x_settings.prox_thres_low >> 8) & 0xFF; chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHLO] = - chip->tsl2x7x_settings.prox_thres_high; + (chip->tsl2x7x_settings.prox_thres_high) & 0xFF; + chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHHI] = + (chip->tsl2x7x_settings.prox_thres_high >> 8) & 0xFF; /* and make sure we're not already on */ if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) { diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig index 34634da1f9f7..dec814a7a073 100644 --- a/drivers/staging/iio/magnetometer/Kconfig +++ b/drivers/staging/iio/magnetometer/Kconfig @@ -4,15 +4,37 @@ menu "Magnetometer sensors" config SENSORS_HMC5843 - tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer" - depends on I2C + tristate select IIO_BUFFER select IIO_TRIGGERED_BUFFER + +config SENSORS_HMC5843_I2C + tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer (I2C)" + depends on I2C + select SENSORS_HMC5843 + select REGMAP_I2C help Say Y here to add support for the Honeywell HMC5843, HMC5883 and HMC5883L 3-Axis Magnetometer (digital compass). - To compile this driver as a module, choose M here: the module - will be called hmc5843. + This driver can also be compiled as a set of modules. + If so, these modules will be created: + - hmc5843_core (core functions) + - hmc5843_i2c (support for HMC5843, HMC5883, HMC5883L and HMC5983) + +config SENSORS_HMC5843_SPI + tristate "Honeywell HMC5983 3-Axis Magnetometer (SPI)" + depends on SPI_MASTER + select SENSORS_HMC5843 + select REGMAP_SPI + help + Say Y here to add support for the Honeywell HMC5983 3-Axis Magnetometer + (digital compass). + + This driver can also be compiled as a set of modules. + If so, these modules will be created: + - hmc5843_core (core functions) + - hmc5843_spi (support for HMC5983) + endmenu diff --git a/drivers/staging/iio/magnetometer/Makefile b/drivers/staging/iio/magnetometer/Makefile index f9bfb2e11d7d..33761a19a956 100644 --- a/drivers/staging/iio/magnetometer/Makefile +++ b/drivers/staging/iio/magnetometer/Makefile @@ -2,4 +2,6 @@ # Makefile for industrial I/O Magnetometer sensors # -obj-$(CONFIG_SENSORS_HMC5843) += hmc5843.o +obj-$(CONFIG_SENSORS_HMC5843) += hmc5843_core.o +obj-$(CONFIG_SENSORS_HMC5843_I2C) += hmc5843_i2c.o +obj-$(CONFIG_SENSORS_HMC5843_SPI) += hmc5843_spi.o diff --git a/drivers/staging/iio/magnetometer/hmc5843.h b/drivers/staging/iio/magnetometer/hmc5843.h new file mode 100644 index 000000000000..b784e3eb4591 --- /dev/null +++ b/drivers/staging/iio/magnetometer/hmc5843.h @@ -0,0 +1,59 @@ +/* + * Header file for hmc5843 driver + * + * Split from hmc5843.c + * Copyright (C) Josef Gajdusek <atx@atx.name> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * */ + + +#ifndef HMC5843_CORE_H +#define HMC5843_CORE_H + +#include <linux/regmap.h> +#include <linux/iio/iio.h> + +#define HMC5843_CONFIG_REG_A 0x00 +#define HMC5843_CONFIG_REG_B 0x01 +#define HMC5843_MODE_REG 0x02 +#define HMC5843_DATA_OUT_MSB_REGS 0x03 +#define HMC5843_STATUS_REG 0x09 +#define HMC5843_ID_REG 0x0a +#define HMC5843_ID_END 0x0c + +enum hmc5843_ids { + HMC5843_ID, + HMC5883_ID, + HMC5883L_ID, + HMC5983_ID, +}; + +struct hmc5843_data { + struct device *dev; + struct mutex lock; + struct regmap *regmap; + const struct hmc5843_chip_info *variant; + __be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */ +}; + +int hmc5843_common_probe(struct device *dev, struct regmap *regmap, + enum hmc5843_ids id); +int hmc5843_common_remove(struct device *dev); + +int hmc5843_common_suspend(struct device *dev); +int hmc5843_common_resume(struct device *dev); + +#ifdef CONFIG_PM_SLEEP +static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, + hmc5843_common_suspend, + hmc5843_common_resume); +#define HMC5843_PM_OPS (&hmc5843_pm_ops) +#else +#define HMC5843_PM_OPS NULL +#endif + +#endif /* HMC5843_CORE_H */ diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843_core.c index d4f4dd90c699..914ae1acd31d 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843_core.c @@ -4,6 +4,8 @@ Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>. + Split to multiple files by Josef Gajdusek <atx@atx.name> - 2014 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -20,7 +22,7 @@ */ #include <linux/module.h> -#include <linux/i2c.h> +#include <linux/regmap.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/trigger_consumer.h> @@ -28,18 +30,7 @@ #include <linux/iio/triggered_buffer.h> #include <linux/delay.h> -#define HMC5843_CONFIG_REG_A 0x00 -#define HMC5843_CONFIG_REG_B 0x01 -#define HMC5843_MODE_REG 0x02 -#define HMC5843_DATA_OUT_MSB_REGS 0x03 -#define HMC5843_STATUS_REG 0x09 -#define HMC5843_ID_REG 0x0a - -enum hmc5843_ids { - HMC5843_ID, - HMC5883_ID, - HMC5883L_ID, -}; +#include "hmc5843.h" /* * Range gain settings in (+-)Ga @@ -48,7 +39,7 @@ enum hmc5843_ids { */ #define HMC5843_RANGE_GAIN_OFFSET 0x05 #define HMC5843_RANGE_GAIN_DEFAULT 0x01 -#define HMC5843_RANGE_GAINS 8 +#define HMC5843_RANGE_GAIN_MASK 0xe0 /* Device status */ #define HMC5843_DATA_READY 0x01 @@ -67,7 +58,7 @@ enum hmc5843_ids { */ #define HMC5843_RATE_OFFSET 0x02 #define HMC5843_RATE_DEFAULT 0x04 -#define HMC5843_RATES 7 +#define HMC5843_RATE_MASK 0x1c /* Device measurement configuration */ #define HMC5843_MEAS_CONF_NORMAL 0x00 @@ -76,15 +67,15 @@ enum hmc5843_ids { #define HMC5843_MEAS_CONF_MASK 0x03 /* Scaling factors: 10000000/Gain */ -static const int hmc5843_regval_to_nanoscale[HMC5843_RANGE_GAINS] = { +static const int hmc5843_regval_to_nanoscale[] = { 6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714 }; -static const int hmc5883_regval_to_nanoscale[HMC5843_RANGE_GAINS] = { +static const int hmc5883_regval_to_nanoscale[] = { 7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662 }; -static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = { +static const int hmc5883l_regval_to_nanoscale[] = { 7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478 }; @@ -101,32 +92,27 @@ static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = { * 6 | 50 | 75 * 7 | Not used | Not used */ -static const int hmc5843_regval_to_samp_freq[7][2] = { +static const int hmc5843_regval_to_samp_freq[][2] = { {0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0} }; -static const int hmc5883_regval_to_samp_freq[7][2] = { +static const int hmc5883_regval_to_samp_freq[][2] = { {0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0}, {75, 0} }; +static const int hmc5983_regval_to_samp_freq[][2] = { + {0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0}, + {75, 0}, {220, 0} +}; + /* Describe chip variants */ struct hmc5843_chip_info { const struct iio_chan_spec *channels; const int (*regval_to_samp_freq)[2]; + const int n_regval_to_samp_freq; const int *regval_to_nanoscale; -}; - -/* Each client has this additional data */ -struct hmc5843_data { - struct i2c_client *client; - struct mutex lock; - u8 rate; - u8 meas_conf; - u8 operating_mode; - u8 range; - const struct hmc5843_chip_info *variant; - __be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */ + const int n_regval_to_nanoscale; }; /* The lower two bits contain the current conversion mode */ @@ -135,10 +121,8 @@ static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode) int ret; mutex_lock(&data->lock); - ret = i2c_smbus_write_byte_data(data->client, HMC5843_MODE_REG, - operating_mode & HMC5843_MODE_MASK); - if (ret >= 0) - data->operating_mode = operating_mode; + ret = regmap_update_bits(data->regmap, HMC5843_MODE_REG, + HMC5843_MODE_MASK, operating_mode); mutex_unlock(&data->lock); return ret; @@ -146,21 +130,21 @@ static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode) static int hmc5843_wait_measurement(struct hmc5843_data *data) { - s32 result; int tries = 150; + int val; + int ret; while (tries-- > 0) { - result = i2c_smbus_read_byte_data(data->client, - HMC5843_STATUS_REG); - if (result < 0) - return result; - if (result & HMC5843_DATA_READY) + ret = regmap_read(data->regmap, HMC5843_STATUS_REG, &val); + if (ret < 0) + return ret; + if (val & HMC5843_DATA_READY) break; msleep(20); } if (tries < 0) { - dev_err(&data->client->dev, "data not ready\n"); + dev_err(data->dev, "data not ready\n"); return -EIO; } @@ -171,20 +155,20 @@ static int hmc5843_wait_measurement(struct hmc5843_data *data) static int hmc5843_read_measurement(struct hmc5843_data *data, int idx, int *val) { - s32 result; __be16 values[3]; + int ret; mutex_lock(&data->lock); - result = hmc5843_wait_measurement(data); - if (result < 0) { + ret = hmc5843_wait_measurement(data); + if (ret < 0) { mutex_unlock(&data->lock); - return result; + return ret; } - result = i2c_smbus_read_i2c_block_data(data->client, - HMC5843_DATA_OUT_MSB_REGS, sizeof(values), (u8 *) values); + ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS, + values, sizeof(values)); mutex_unlock(&data->lock); - if (result < 0) - return -EINVAL; + if (ret < 0) + return ret; *val = sign_extend32(be16_to_cpu(values[idx]), 15); return IIO_VAL_INT; @@ -208,16 +192,13 @@ static int hmc5843_read_measurement(struct hmc5843_data *data, * and BN. * */ -static s32 hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf) +static int hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf) { int ret; mutex_lock(&data->lock); - ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A, - (meas_conf & HMC5843_MEAS_CONF_MASK) | - (data->rate << HMC5843_RATE_OFFSET)); - if (ret >= 0) - data->meas_conf = meas_conf; + ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A, + HMC5843_MEAS_CONF_MASK, meas_conf); mutex_unlock(&data->lock); return ret; @@ -228,7 +209,15 @@ static ssize_t hmc5843_show_measurement_configuration(struct device *dev, char *buf) { struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); - return sprintf(buf, "%d\n", data->meas_conf); + int val; + int ret; + + ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &val); + if (ret) + return ret; + val &= HMC5843_MEAS_CONF_MASK; + + return sprintf(buf, "%d\n", val); } static ssize_t hmc5843_set_measurement_configuration(struct device *dev, @@ -264,7 +253,7 @@ static ssize_t hmc5843_show_samp_freq_avail(struct device *dev, size_t len = 0; int i; - for (i = 0; i < HMC5843_RATES; i++) + for (i = 0; i < data->variant->n_regval_to_samp_freq; i++) len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%d ", data->variant->regval_to_samp_freq[i][0], data->variant->regval_to_samp_freq[i][1]); @@ -282,10 +271,8 @@ static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate) int ret; mutex_lock(&data->lock); - ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A, - data->meas_conf | (rate << HMC5843_RATE_OFFSET)); - if (ret >= 0) - data->rate = rate; + ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A, + HMC5843_RATE_MASK, rate << HMC5843_RATE_OFFSET); mutex_unlock(&data->lock); return ret; @@ -296,7 +283,7 @@ static int hmc5843_get_samp_freq_index(struct hmc5843_data *data, { int i; - for (i = 0; i < HMC5843_RATES; i++) + for (i = 0; i < data->variant->n_regval_to_samp_freq; i++) if (val == data->variant->regval_to_samp_freq[i][0] && val2 == data->variant->regval_to_samp_freq[i][1]) return i; @@ -309,10 +296,9 @@ static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range) int ret; mutex_lock(&data->lock); - ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_B, - range << HMC5843_RANGE_GAIN_OFFSET); - if (ret >= 0) - data->range = range; + ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_B, + HMC5843_RANGE_GAIN_MASK, + range << HMC5843_RANGE_GAIN_OFFSET); mutex_unlock(&data->lock); return ret; @@ -326,7 +312,7 @@ static ssize_t hmc5843_show_scale_avail(struct device *dev, size_t len = 0; int i; - for (i = 0; i < HMC5843_RANGE_GAINS; i++) + for (i = 0; i < data->variant->n_regval_to_nanoscale; i++) len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09d ", data->variant->regval_to_nanoscale[i]); @@ -346,7 +332,7 @@ static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2) if (val != 0) return -EINVAL; - for (i = 0; i < HMC5843_RANGE_GAINS; i++) + for (i = 0; i < data->variant->n_regval_to_nanoscale; i++) if (val2 == data->variant->regval_to_nanoscale[i]) return i; @@ -358,17 +344,27 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct hmc5843_data *data = iio_priv(indio_dev); + int rval; + int ret; switch (mask) { case IIO_CHAN_INFO_RAW: return hmc5843_read_measurement(data, chan->scan_index, val); case IIO_CHAN_INFO_SCALE: + ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval); + if (ret < 0) + return ret; + rval >>= HMC5843_RANGE_GAIN_OFFSET; *val = 0; - *val2 = data->variant->regval_to_nanoscale[data->range]; + *val2 = data->variant->regval_to_nanoscale[rval]; return IIO_VAL_INT_PLUS_NANO; case IIO_CHAN_INFO_SAMP_FREQ: - *val = data->variant->regval_to_samp_freq[data->rate][0]; - *val2 = data->variant->regval_to_samp_freq[data->rate][1]; + ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval); + if (ret < 0) + return ret; + rval >>= HMC5843_RATE_OFFSET; + *val = data->variant->regval_to_samp_freq[rval][0]; + *val2 = data->variant->regval_to_samp_freq[rval][1]; return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; @@ -426,9 +422,9 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p) goto done; } - ret = i2c_smbus_read_i2c_block_data(data->client, - HMC5843_DATA_OUT_MSB_REGS, 3 * sizeof(__be16), - (u8 *) data->buffer); + ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS, + data->buffer, 3 * sizeof(__be16)); + mutex_unlock(&data->lock); if (ret < 0) goto done; @@ -466,7 +462,7 @@ static const struct iio_chan_spec hmc5843_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(3), }; -/* Beware: Y and Z are exchanged on HMC5883 */ +/* Beware: Y and Z are exchanged on HMC5883 and 5983 */ static const struct iio_chan_spec hmc5883_channels[] = { HMC5843_CHANNEL(X, 0), HMC5843_CHANNEL(Z, 1), @@ -489,18 +485,39 @@ static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = { [HMC5843_ID] = { .channels = hmc5843_channels, .regval_to_samp_freq = hmc5843_regval_to_samp_freq, + .n_regval_to_samp_freq = + ARRAY_SIZE(hmc5843_regval_to_samp_freq), .regval_to_nanoscale = hmc5843_regval_to_nanoscale, + .n_regval_to_nanoscale = + ARRAY_SIZE(hmc5843_regval_to_nanoscale), }, [HMC5883_ID] = { .channels = hmc5883_channels, .regval_to_samp_freq = hmc5883_regval_to_samp_freq, + .n_regval_to_samp_freq = + ARRAY_SIZE(hmc5883_regval_to_samp_freq), .regval_to_nanoscale = hmc5883_regval_to_nanoscale, + .n_regval_to_nanoscale = + ARRAY_SIZE(hmc5883_regval_to_nanoscale), }, [HMC5883L_ID] = { .channels = hmc5883_channels, .regval_to_samp_freq = hmc5883_regval_to_samp_freq, + .n_regval_to_samp_freq = + ARRAY_SIZE(hmc5883_regval_to_samp_freq), .regval_to_nanoscale = hmc5883l_regval_to_nanoscale, + .n_regval_to_nanoscale = + ARRAY_SIZE(hmc5883l_regval_to_nanoscale), }, + [HMC5983_ID] = { + .channels = hmc5883_channels, + .regval_to_samp_freq = hmc5983_regval_to_samp_freq, + .n_regval_to_samp_freq = + ARRAY_SIZE(hmc5983_regval_to_samp_freq), + .regval_to_nanoscale = hmc5883l_regval_to_nanoscale, + .n_regval_to_nanoscale = + ARRAY_SIZE(hmc5883l_regval_to_nanoscale), + } }; static int hmc5843_init(struct hmc5843_data *data) @@ -508,12 +525,12 @@ static int hmc5843_init(struct hmc5843_data *data) int ret; u8 id[3]; - ret = i2c_smbus_read_i2c_block_data(data->client, HMC5843_ID_REG, - sizeof(id), id); + ret = regmap_bulk_read(data->regmap, HMC5843_ID_REG, + id, ARRAY_SIZE(id)); if (ret < 0) return ret; if (id[0] != 'H' || id[1] != '4' || id[2] != '3') { - dev_err(&data->client->dev, "no HMC5843/5883/5883L sensor\n"); + dev_err(data->dev, "no HMC5843/5883/5883L/5983 sensor\n"); return -ENODEV; } @@ -539,27 +556,43 @@ static const struct iio_info hmc5843_info = { static const unsigned long hmc5843_scan_masks[] = {0x7, 0}; -static int hmc5843_probe(struct i2c_client *client, - const struct i2c_device_id *id) + +int hmc5843_common_suspend(struct device *dev) +{ + return hmc5843_set_mode(iio_priv(dev_get_drvdata(dev)), + HMC5843_MODE_CONVERSION_CONTINUOUS); +} +EXPORT_SYMBOL(hmc5843_common_suspend); + +int hmc5843_common_resume(struct device *dev) +{ + return hmc5843_set_mode(iio_priv(dev_get_drvdata(dev)), + HMC5843_MODE_SLEEP); +} +EXPORT_SYMBOL(hmc5843_common_resume); + +int hmc5843_common_probe(struct device *dev, struct regmap *regmap, + enum hmc5843_ids id) { struct hmc5843_data *data; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (indio_dev == NULL) return -ENOMEM; + dev_set_drvdata(dev, indio_dev); + /* default settings at probe */ data = iio_priv(indio_dev); - data->client = client; - data->variant = &hmc5843_chip_info_tbl[id->driver_data]; + data->dev = dev; + data->regmap = regmap; + data->variant = &hmc5843_chip_info_tbl[id]; mutex_init(&data->lock); - i2c_set_clientdata(client, indio_dev); + indio_dev->dev.parent = dev; indio_dev->info = &hmc5843_info; - indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = data->variant->channels; indio_dev->num_channels = 4; @@ -584,10 +617,11 @@ buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); return ret; } +EXPORT_SYMBOL(hmc5843_common_probe); -static int hmc5843_remove(struct i2c_client *client) +int hmc5843_common_remove(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct iio_dev *indio_dev = dev_get_drvdata(dev); iio_device_unregister(indio_dev); iio_triggered_buffer_cleanup(indio_dev); @@ -597,56 +631,8 @@ static int hmc5843_remove(struct i2c_client *client) return 0; } - -#ifdef CONFIG_PM_SLEEP -static int hmc5843_suspend(struct device *dev) -{ - struct hmc5843_data *data = iio_priv(i2c_get_clientdata( - to_i2c_client(dev))); - - return hmc5843_set_mode(data, HMC5843_MODE_SLEEP); -} - -static int hmc5843_resume(struct device *dev) -{ - struct hmc5843_data *data = iio_priv(i2c_get_clientdata( - to_i2c_client(dev))); - - return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS); -} - -static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, hmc5843_suspend, hmc5843_resume); -#define HMC5843_PM_OPS (&hmc5843_pm_ops) -#else -#define HMC5843_PM_OPS NULL -#endif - -static const struct i2c_device_id hmc5843_id[] = { - { "hmc5843", HMC5843_ID }, - { "hmc5883", HMC5883_ID }, - { "hmc5883l", HMC5883L_ID }, - { } -}; -MODULE_DEVICE_TABLE(i2c, hmc5843_id); - -static const struct of_device_id hmc5843_of_match[] = { - { .compatible = "honeywell,hmc5843" }, - {} -}; -MODULE_DEVICE_TABLE(of, hmc5843_of_match); - -static struct i2c_driver hmc5843_driver = { - .driver = { - .name = "hmc5843", - .pm = HMC5843_PM_OPS, - .of_match_table = hmc5843_of_match, - }, - .id_table = hmc5843_id, - .probe = hmc5843_probe, - .remove = hmc5843_remove, -}; -module_i2c_driver(hmc5843_driver); +EXPORT_SYMBOL(hmc5843_common_remove); MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>"); -MODULE_DESCRIPTION("HMC5843/5883/5883L driver"); +MODULE_DESCRIPTION("HMC5843/5883/5883L/5983 core driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/magnetometer/hmc5843_i2c.c b/drivers/staging/iio/magnetometer/hmc5843_i2c.c new file mode 100644 index 000000000000..6acd614cdbc6 --- /dev/null +++ b/drivers/staging/iio/magnetometer/hmc5843_i2c.c @@ -0,0 +1,104 @@ +/* + * i2c driver for hmc5843/5843/5883/5883l/5983 + * + * Split from hmc5843.c + * Copyright (C) Josef Gajdusek <atx@atx.name> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/iio/iio.h> +#include <linux/iio/triggered_buffer.h> + +#include "hmc5843.h" + +static const struct regmap_range hmc5843_readable_ranges[] = { + regmap_reg_range(0, HMC5843_ID_END), +}; + +static struct regmap_access_table hmc5843_readable_table = { + .yes_ranges = hmc5843_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges), +}; + +static const struct regmap_range hmc5843_writable_ranges[] = { + regmap_reg_range(0, HMC5843_MODE_REG), +}; + +static struct regmap_access_table hmc5843_writable_table = { + .yes_ranges = hmc5843_writable_ranges, + .n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges), +}; + +static const struct regmap_range hmc5843_volatile_ranges[] = { + regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG), +}; + +static struct regmap_access_table hmc5843_volatile_table = { + .yes_ranges = hmc5843_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges), +}; + +static struct regmap_config hmc5843_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .rd_table = &hmc5843_readable_table, + .wr_table = &hmc5843_writable_table, + .volatile_table = &hmc5843_volatile_table, + + .cache_type = REGCACHE_RBTREE, +}; + +static int hmc5843_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return hmc5843_common_probe(&client->dev, + devm_regmap_init_i2c(client, &hmc5843_i2c_regmap_config), + id->driver_data); +} + +static int hmc5843_i2c_remove(struct i2c_client *client) +{ + return hmc5843_common_remove(&client->dev); +} + +static const struct i2c_device_id hmc5843_id[] = { + { "hmc5843", HMC5843_ID }, + { "hmc5883", HMC5883_ID }, + { "hmc5883l", HMC5883L_ID }, + { "hmc5983", HMC5983_ID }, + { } +}; +MODULE_DEVICE_TABLE(i2c, hmc5843_id); + +static const struct of_device_id hmc5843_of_match[] = { + { .compatible = "honeywell,hmc5843", .data = (void *)HMC5843_ID }, + { .compatible = "honeywell,hmc5883", .data = (void *)HMC5883_ID }, + { .compatible = "honeywell,hmc5883l", .data = (void *)HMC5883L_ID }, + { .compatible = "honeywell,hmc5983", .data = (void *)HMC5983_ID }, + {} +}; +MODULE_DEVICE_TABLE(of, hmc5843_of_match); + +static struct i2c_driver hmc5843_driver = { + .driver = { + .name = "hmc5843", + .pm = HMC5843_PM_OPS, + .of_match_table = hmc5843_of_match, + }, + .id_table = hmc5843_id, + .probe = hmc5843_i2c_probe, + .remove = hmc5843_i2c_remove, +}; +module_i2c_driver(hmc5843_driver); + +MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>"); +MODULE_DESCRIPTION("HMC5843/5883/5883L/5983 i2c driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/magnetometer/hmc5843_spi.c b/drivers/staging/iio/magnetometer/hmc5843_spi.c new file mode 100644 index 000000000000..98c4b57101c9 --- /dev/null +++ b/drivers/staging/iio/magnetometer/hmc5843_spi.c @@ -0,0 +1,100 @@ +/* + * SPI driver for hmc5983 + * + * Copyright (C) Josef Gajdusek <atx@atx.name> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * */ + +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/iio/iio.h> + +#include "hmc5843.h" + +static const struct regmap_range hmc5843_readable_ranges[] = { + regmap_reg_range(0, HMC5843_ID_END), +}; + +static struct regmap_access_table hmc5843_readable_table = { + .yes_ranges = hmc5843_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges), +}; + +static const struct regmap_range hmc5843_writable_ranges[] = { + regmap_reg_range(0, HMC5843_MODE_REG), +}; + +static struct regmap_access_table hmc5843_writable_table = { + .yes_ranges = hmc5843_writable_ranges, + .n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges), +}; + +static const struct regmap_range hmc5843_volatile_ranges[] = { + regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG), +}; + +static struct regmap_access_table hmc5843_volatile_table = { + .yes_ranges = hmc5843_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges), +}; + +static struct regmap_config hmc5843_spi_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .rd_table = &hmc5843_readable_table, + .wr_table = &hmc5843_writable_table, + .volatile_table = &hmc5843_volatile_table, + + /* Autoincrement address pointer */ + .read_flag_mask = 0xc0, + + .cache_type = REGCACHE_RBTREE, +}; + +static int hmc5843_spi_probe(struct spi_device *spi) +{ + int ret; + + spi->mode = SPI_MODE_3; + spi->max_speed_hz = 8000000; + spi->bits_per_word = 8; + ret = spi_setup(spi); + if (ret) + return ret; + + return hmc5843_common_probe(&spi->dev, + devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config), + HMC5983_ID); +} + +static int hmc5843_spi_remove(struct spi_device *spi) +{ + return hmc5843_common_remove(&spi->dev); +} + +static const struct spi_device_id hmc5843_id[] = { + { "hmc5983", HMC5983_ID }, + { } +}; + +static struct spi_driver hmc5843_driver = { + .driver = { + .name = "hmc5843", + .pm = HMC5843_PM_OPS, + .owner = THIS_MODULE, + }, + .id_table = hmc5843_id, + .probe = hmc5843_spi_probe, + .remove = hmc5843_spi_remove, +}; + +module_spi_driver(hmc5843_driver); + +MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>"); +MODULE_DESCRIPTION("HMC5983 SPI driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c index 7a94ddd42f59..ea01b8f7a2c3 100644 --- a/drivers/staging/iio/meter/ade7758_trigger.c +++ b/drivers/staging/iio/meter/ade7758_trigger.c @@ -21,7 +21,7 @@ static irqreturn_t ade7758_data_rdy_trig_poll(int irq, void *private) { disable_irq_nosync(irq); - iio_trigger_poll(private, iio_get_time_ns()); + iio_trigger_poll(private); return IRQ_HANDLED; } diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 26e1ca0b7800..a21b7c514776 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -154,7 +154,7 @@ static irqreturn_t iio_bfin_tmr_trigger_isr(int irq, void *devid) struct bfin_tmr_state *st = devid; clear_gptimer_intr(st->t->id); - iio_trigger_poll(st->trig, 0); + iio_trigger_poll(st->trig); return IRQ_HANDLED; } @@ -182,45 +182,40 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) unsigned int config; int ret; - st = kzalloc(sizeof(*st), GFP_KERNEL); - if (st == NULL) { - ret = -ENOMEM; - goto out; - } + st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL); + if (st == NULL) + return -ENOMEM; st->irq = platform_get_irq(pdev, 0); if (!st->irq) { dev_err(&pdev->dev, "No IRQs specified"); - ret = -ENODEV; - goto out1; + return -ENODEV; } ret = iio_bfin_tmr_get_number(st->irq); if (ret < 0) - goto out1; + return ret; st->timer_num = ret; st->t = &iio_bfin_timer_code[st->timer_num]; st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num); - if (!st->trig) { - ret = -ENOMEM; - goto out1; - } + if (!st->trig) + return -ENOMEM; st->trig->ops = &iio_bfin_tmr_trigger_ops; st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups; iio_trigger_set_drvdata(st->trig, st); ret = iio_trigger_register(st->trig); if (ret) - goto out2; + goto out; ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr, 0, st->trig->name, st); if (ret) { dev_err(&pdev->dev, "request IRQ-%d failed", st->irq); - goto out4; + goto out1; } config = PWM_OUT | PERIOD_CNT | IRQ_ENA; @@ -260,13 +255,10 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) return 0; out_free_irq: free_irq(st->irq, st); -out4: - iio_trigger_unregister(st->trig); -out2: - iio_trigger_put(st->trig); out1: - kfree(st); + iio_trigger_unregister(st->trig); out: + iio_trigger_put(st->trig); return ret; } @@ -280,7 +272,6 @@ static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev) free_irq(st->irq, st); iio_trigger_unregister(st->trig); iio_trigger_put(st->trig); - kfree(st); return 0; } diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c index 38ecb4bb6e4c..b1aeb88273c9 100644 --- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c @@ -26,16 +26,22 @@ struct iio_prtc_trigger_info { struct rtc_device *rtc; int frequency; struct rtc_task task; + bool state; }; static int iio_trig_periodic_rtc_set_state(struct iio_trigger *trig, bool state) { struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig); - if (trig_info->frequency == 0) + int ret; + if (trig_info->frequency == 0 && state) return -EINVAL; - dev_info(&trig_info->rtc->dev, "trigger frequency is %d\n", + dev_dbg(&trig_info->rtc->dev, "trigger frequency is %d\n", trig_info->frequency); - return rtc_irq_set_state(trig_info->rtc, &trig_info->task, state); + ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, state); + if (ret == 0) + trig_info->state = state; + + return ret; } static ssize_t iio_trig_periodic_read_freq(struct device *dev, @@ -61,7 +67,14 @@ static ssize_t iio_trig_periodic_write_freq(struct device *dev, if (ret) goto error_ret; - ret = rtc_irq_set_freq(trig_info->rtc, &trig_info->task, val); + if (val > 0) { + ret = rtc_irq_set_freq(trig_info->rtc, &trig_info->task, val); + if (ret == 0 && trig_info->state && trig_info->frequency == 0) + ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, 1); + } else if (val == 0) { + ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, 0); + } else + ret = -EINVAL; if (ret) goto error_ret; @@ -93,8 +106,7 @@ static const struct attribute_group *iio_trig_prtc_attr_groups[] = { static void iio_prtc_trigger_poll(void *private_data) { - /* Timestamp is not provided currently */ - iio_trigger_poll(private_data, 0); + iio_trigger_poll(private_data); } static const struct iio_trigger_ops iio_prtc_trigger_ops = { @@ -128,8 +140,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev) iio_trigger_set_drvdata(trig, trig_info); trig->ops = &iio_prtc_trigger_ops; /* RTC access */ - trig_info->rtc - = rtc_class_open(pdata[i]); + trig_info->rtc = rtc_class_open(pdata[i]); if (trig_info->rtc == NULL) { ret = -EINVAL; goto error_free_trig_info; @@ -199,5 +210,5 @@ static struct platform_driver iio_trig_periodic_rtc_driver = { module_platform_driver(iio_trig_periodic_rtc_driver); MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); -MODULE_DESCRIPTION("Periodic realtime clock trigger for the iio subsystem"); +MODULE_DESCRIPTION("Periodic realtime clock trigger for the iio subsystem"); MODULE_LICENSE("GPL v2"); |