diff options
Diffstat (limited to 'drivers/iio')
32 files changed, 2226 insertions, 119 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 1e120fa1e156..12addf272a61 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -77,4 +77,16 @@ config MMA8452 To compile this driver as a module, choose M here: the module will be called mma8452. +config KXCJK1013 + tristate "Kionix 3-Axis Accelerometer Driver" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here if you want to build a driver for the Kionix KXCJK-1013 + triaxial acceleration sensor. + + To compile this driver as a module, choose M here: the module will + be called kxcjk-1013. + endmenu diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index dc0e379c2592..6578ca1a8e09 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -5,6 +5,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o +obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o obj-$(CONFIG_MMA8452) += mma8452.o diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c new file mode 100644 index 000000000000..72a6dbbc18d1 --- /dev/null +++ b/drivers/iio/accel/kxcjk-1013.c @@ -0,0 +1,764 @@ +/* + * KXCJK-1013 3-axis accelerometer driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/bitops.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/acpi.h> +#include <linux/gpio/consumer.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/accel/kxcjk_1013.h> + +#define KXCJK1013_DRV_NAME "kxcjk1013" +#define KXCJK1013_IRQ_NAME "kxcjk1013_event" + +#define KXCJK1013_REG_XOUT_L 0x06 +/* + * From low byte X axis register, all the other addresses of Y and Z can be + * obtained by just applying axis offset. The following axis defines are just + * provide clarity, but not used. + */ +#define KXCJK1013_REG_XOUT_H 0x07 +#define KXCJK1013_REG_YOUT_L 0x08 +#define KXCJK1013_REG_YOUT_H 0x09 +#define KXCJK1013_REG_ZOUT_L 0x0A +#define KXCJK1013_REG_ZOUT_H 0x0B + +#define KXCJK1013_REG_DCST_RESP 0x0C +#define KXCJK1013_REG_WHO_AM_I 0x0F +#define KXCJK1013_REG_INT_SRC1 0x16 +#define KXCJK1013_REG_INT_SRC2 0x17 +#define KXCJK1013_REG_STATUS_REG 0x18 +#define KXCJK1013_REG_INT_REL 0x1A +#define KXCJK1013_REG_CTRL1 0x1B +#define KXCJK1013_REG_CTRL2 0x1D +#define KXCJK1013_REG_INT_CTRL1 0x1E +#define KXCJK1013_REG_INT_CTRL2 0x1F +#define KXCJK1013_REG_DATA_CTRL 0x21 +#define KXCJK1013_REG_WAKE_TIMER 0x29 +#define KXCJK1013_REG_SELF_TEST 0x3A +#define KXCJK1013_REG_WAKE_THRES 0x6A + +#define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7) +#define KXCJK1013_REG_CTRL1_BIT_RES BIT(6) +#define KXCJK1013_REG_CTRL1_BIT_DRDY BIT(5) +#define KXCJK1013_REG_CTRL1_BIT_GSEL1 BIT(4) +#define KXCJK1013_REG_CTRL1_BIT_GSEL0 BIT(3) +#define KXCJK1013_REG_CTRL1_BIT_WUFE BIT(1) +#define KXCJK1013_REG_INT_REG1_BIT_IEA BIT(4) +#define KXCJK1013_REG_INT_REG1_BIT_IEN BIT(5) + +#define KXCJK1013_DATA_MASK_12_BIT 0x0FFF +#define KXCJK1013_MAX_STARTUP_TIME_US 100000 + +struct kxcjk1013_data { + struct i2c_client *client; + struct iio_trigger *trig; + bool trig_mode; + struct mutex mutex; + s16 buffer[8]; + int power_state; + u8 odr_bits; + bool active_high_intr; +}; + +enum kxcjk1013_axis { + AXIS_X, + AXIS_Y, + AXIS_Z, +}; + +enum kxcjk1013_mode { + STANDBY, + OPERATION, +}; + +static const struct { + int val; + int val2; + int odr_bits; +} samp_freq_table[] = { {0, 781000, 0x08}, {1, 563000, 0x09}, + {3, 125000, 0x0A}, {6, 25000, 0x0B}, {12, 5000, 0}, + {25, 0, 0x01}, {50, 0, 0x02}, {100, 0, 0x03}, + {200, 0, 0x04}, {400, 0, 0x05}, {800, 0, 0x06}, + {1600, 0, 0x07} }; + +/* Refer to section 4 of the specification */ +static const struct { + int odr_bits; + int usec; +} odr_start_up_times[] = { {0x08, 100000}, {0x09, 100000}, {0x0A, 100000}, + {0x0B, 100000}, { 0, 80000}, {0x01, 41000}, + {0x02, 21000}, {0x03, 11000}, {0x04, 6400}, + {0x05, 3900}, {0x06, 2700}, {0x07, 2100} }; + +static int kxcjk1013_set_mode(struct kxcjk1013_data *data, + enum kxcjk1013_mode mode) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + if (mode == STANDBY) + ret &= ~KXCJK1013_REG_CTRL1_BIT_PC1; + else + ret |= KXCJK1013_REG_CTRL1_BIT_PC1; + + ret = i2c_smbus_write_byte_data(data->client, + KXCJK1013_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + + return 0; +} + +static int kxcjk1013_chip_ack_intr(struct kxcjk1013_data *data) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_int_rel\n"); + return ret; + } + + return ret; +} + +static int kxcjk1013_chip_init(struct kxcjk1013_data *data) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading who_am_i\n"); + return ret; + } + + dev_dbg(&data->client->dev, "KXCJK1013 Chip Id %x\n", ret); + + ret = kxcjk1013_set_mode(data, STANDBY); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + /* Setting range to 4G */ + ret |= KXCJK1013_REG_CTRL1_BIT_GSEL0; + ret &= ~KXCJK1013_REG_CTRL1_BIT_GSEL1; + + /* Set 12 bit mode */ + ret |= KXCJK1013_REG_CTRL1_BIT_RES; + + ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL1, + ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl\n"); + return ret; + } + + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); + return ret; + } + + data->odr_bits = ret; + + /* Set up INT polarity */ + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); + return ret; + } + + if (data->active_high_intr) + ret |= KXCJK1013_REG_INT_REG1_BIT_IEA; + else + ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEA; + + ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, + ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); + return ret; + } + + return 0; +} + +static int kxcjk1013_chip_setup_interrupt(struct kxcjk1013_data *data, + bool status) +{ + int ret; + + /* This is requirement by spec to change state to STANDBY */ + ret = kxcjk1013_set_mode(data, STANDBY); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); + return ret; + } + + if (status) + ret |= KXCJK1013_REG_INT_REG1_BIT_IEN; + else + ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEN; + + ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, + ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); + return ret; + } + + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + if (status) + ret |= KXCJK1013_REG_CTRL1_BIT_DRDY; + else + ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; + + ret = i2c_smbus_write_byte_data(data->client, + KXCJK1013_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + + return ret; +} + +static int kxcjk1013_convert_freq_to_bit(int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(samp_freq_table); ++i) { + if (samp_freq_table[i].val == val && + samp_freq_table[i].val2 == val2) { + return samp_freq_table[i].odr_bits; + } + } + + return -EINVAL; +} + +static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) +{ + int ret; + int odr_bits; + + odr_bits = kxcjk1013_convert_freq_to_bit(val, val2); + if (odr_bits < 0) + return odr_bits; + + /* To change ODR, the chip must be set to STANDBY as per spec */ + ret = kxcjk1013_set_mode(data, STANDBY); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_DATA_CTRL, + odr_bits); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing data_ctrl\n"); + return ret; + } + + data->odr_bits = odr_bits; + + /* Check, if the ODR is changed after data enable */ + if (data->power_state) { + /* Set the state back to operation */ + ret = kxcjk1013_set_mode(data, OPERATION); + if (ret < 0) + return ret; + } + + return 0; +} + +static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(samp_freq_table); ++i) { + if (samp_freq_table[i].odr_bits == data->odr_bits) { + *val = samp_freq_table[i].val; + *val2 = samp_freq_table[i].val2; + return IIO_VAL_INT_PLUS_MICRO; + } + } + + return -EINVAL; +} + +static int kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis) +{ + u8 reg = KXCJK1013_REG_XOUT_L + axis * 2; + int ret; + + ret = i2c_smbus_read_word_data(data->client, reg); + if (ret < 0) { + dev_err(&data->client->dev, + "failed to read accel_%c registers\n", 'x' + axis); + return ret; + } + + return ret; +} + +static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(odr_start_up_times); ++i) { + if (odr_start_up_times[i].odr_bits == data->odr_bits) + return odr_start_up_times[i].usec; + } + + return KXCJK1013_MAX_STARTUP_TIME_US; +} + +static int kxcjk1013_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct kxcjk1013_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&data->mutex); + if (iio_buffer_enabled(indio_dev)) + ret = -EBUSY; + else { + int sleep_val; + + ret = kxcjk1013_set_mode(data, OPERATION); + if (ret < 0) { + mutex_unlock(&data->mutex); + return ret; + } + ++data->power_state; + sleep_val = kxcjk1013_get_startup_times(data); + if (sleep_val < 20000) + usleep_range(sleep_val, 20000); + else + msleep_interruptible(sleep_val/1000); + ret = kxcjk1013_get_acc_reg(data, chan->scan_index); + if (--data->power_state == 0) + kxcjk1013_set_mode(data, STANDBY); + } + mutex_unlock(&data->mutex); + + if (ret < 0) + return ret; + + *val = sign_extend32(ret >> 4, 11); + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 19163; /* range +-4g (4/2047*9.806650) */ + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&data->mutex); + ret = kxcjk1013_get_odr(data, val, val2); + mutex_unlock(&data->mutex); + return ret; + + default: + return -EINVAL; + } +} + +static int kxcjk1013_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct kxcjk1013_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&data->mutex); + ret = kxcjk1013_set_odr(data, val, val2); + mutex_unlock(&data->mutex); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct kxcjk1013_data *data = iio_priv(indio_dev); + + if (data->trig != trig) + return -EINVAL; + + return 0; +} + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( + "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600"); + +static struct attribute *kxcjk1013_attributes[] = { + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group kxcjk1013_attrs_group = { + .attrs = kxcjk1013_attributes, +}; + +#define KXCJK1013_CHANNEL(_axis) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_##_axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = AXIS_##_axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_LE, \ + }, \ +} + +static const struct iio_chan_spec kxcjk1013_channels[] = { + KXCJK1013_CHANNEL(X), + KXCJK1013_CHANNEL(Y), + KXCJK1013_CHANNEL(Z), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +static const struct iio_info kxcjk1013_info = { + .attrs = &kxcjk1013_attrs_group, + .read_raw = kxcjk1013_read_raw, + .write_raw = kxcjk1013_write_raw, + .validate_trigger = kxcjk1013_validate_trigger, + .driver_module = THIS_MODULE, +}; + +static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct kxcjk1013_data *data = iio_priv(indio_dev); + int bit, ret, i = 0; + + mutex_lock(&data->mutex); + + for_each_set_bit(bit, indio_dev->buffer->scan_mask, + indio_dev->masklength) { + ret = kxcjk1013_get_acc_reg(data, bit); + if (ret < 0) { + kxcjk1013_chip_ack_intr(data); + mutex_unlock(&data->mutex); + goto err; + } + data->buffer[i++] = ret; + } + + kxcjk1013_chip_ack_intr(data); + + mutex_unlock(&data->mutex); + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + pf->timestamp); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct kxcjk1013_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + if (state) { + kxcjk1013_chip_setup_interrupt(data, true); + kxcjk1013_set_mode(data, OPERATION); + ++data->power_state; + } else { + if (--data->power_state) { + mutex_unlock(&data->mutex); + return 0; + } + kxcjk1013_chip_setup_interrupt(data, false); + kxcjk1013_set_mode(data, STANDBY); + } + mutex_unlock(&data->mutex); + + return 0; +} + +static const struct iio_trigger_ops kxcjk1013_trigger_ops = { + .set_trigger_state = kxcjk1013_data_rdy_trigger_set_state, + .owner = THIS_MODULE, +}; + +static int kxcjk1013_acpi_gpio_probe(struct i2c_client *client, + struct kxcjk1013_data *data) +{ + const struct acpi_device_id *id; + struct device *dev; + struct gpio_desc *gpio; + int ret; + + if (!client) + return -EINVAL; + + dev = &client->dev; + if (!ACPI_HANDLE(dev)) + return -ENODEV; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return -ENODEV; + + /* data ready gpio interrupt pin */ + gpio = devm_gpiod_get_index(dev, "kxcjk1013_int", 0); + if (IS_ERR(gpio)) { + dev_err(dev, "acpi gpio get index failed\n"); + return PTR_ERR(gpio); + } + + ret = gpiod_direction_input(gpio); + if (ret) + return ret; + + ret = gpiod_to_irq(gpio); + + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); + + return ret; +} + +static int kxcjk1013_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct kxcjk1013_data *data; + struct iio_dev *indio_dev; + struct iio_trigger *trig = NULL; + struct kxcjk_1013_platform_data *pdata; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + pdata = dev_get_platdata(&client->dev); + if (pdata) + data->active_high_intr = pdata->active_high_intr; + else + data->active_high_intr = true; /* default polarity */ + + ret = kxcjk1013_chip_init(data); + if (ret < 0) + return ret; + + mutex_init(&data->mutex); + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = kxcjk1013_channels; + indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels); + indio_dev->name = KXCJK1013_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &kxcjk1013_info; + + if (client->irq < 0) + client->irq = kxcjk1013_acpi_gpio_probe(client, data); + + if (client->irq >= 0) { + trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, + indio_dev->id); + if (!trig) + return -ENOMEM; + + data->trig_mode = true; + + ret = devm_request_irq(&client->dev, client->irq, + iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING, + KXCJK1013_IRQ_NAME, + trig); + if (ret) { + dev_err(&client->dev, "unable to request IRQ\n"); + goto err_trigger_free; + } + + trig->dev.parent = &client->dev; + trig->ops = &kxcjk1013_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + data->trig = trig; + indio_dev->trig = trig; + + ret = iio_trigger_register(trig); + if (ret) + goto err_trigger_free; + + ret = iio_triggered_buffer_setup(indio_dev, + &iio_pollfunc_store_time, + kxcjk1013_trigger_handler, + NULL); + if (ret < 0) { + dev_err(&client->dev, + "iio triggered buffer setup failed\n"); + goto err_trigger_unregister; + } + } + + ret = devm_iio_device_register(&client->dev, indio_dev); + if (ret < 0) { + dev_err(&client->dev, "unable to register iio device\n"); + goto err_buffer_cleanup; + } + + return 0; + +err_buffer_cleanup: + if (data->trig_mode) + iio_triggered_buffer_cleanup(indio_dev); +err_trigger_unregister: + if (data->trig_mode) + iio_trigger_unregister(trig); +err_trigger_free: + if (data->trig_mode) + iio_trigger_free(trig); + + return ret; +} + +static int kxcjk1013_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct kxcjk1013_data *data = iio_priv(indio_dev); + + if (data->trig_mode) { + iio_triggered_buffer_cleanup(indio_dev); + iio_trigger_unregister(data->trig); + iio_trigger_free(data->trig); + } + + mutex_lock(&data->mutex); + kxcjk1013_set_mode(data, STANDBY); + mutex_unlock(&data->mutex); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int kxcjk1013_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kxcjk1013_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + kxcjk1013_set_mode(data, STANDBY); + mutex_unlock(&data->mutex); + + return 0; +} + +static int kxcjk1013_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kxcjk1013_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + + if (data->power_state) + kxcjk1013_set_mode(data, OPERATION); + + mutex_unlock(&data->mutex); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(kxcjk1013_pm_ops, kxcjk1013_suspend, kxcjk1013_resume); +#define KXCJK1013_PM_OPS (&kxcjk1013_pm_ops) +#else +#define KXCJK1013_PM_OPS NULL +#endif + +static const struct acpi_device_id kx_acpi_match[] = { + {"KXCJ1013", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, kx_acpi_match); + +static const struct i2c_device_id kxcjk1013_id[] = { + {"kxcjk1013", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, kxcjk1013_id); + +static struct i2c_driver kxcjk1013_driver = { + .driver = { + .name = KXCJK1013_DRV_NAME, + .acpi_match_table = ACPI_PTR(kx_acpi_match), + .pm = KXCJK1013_PM_OPS, + }, + .probe = kxcjk1013_probe, + .remove = kxcjk1013_remove, + .id_table = kxcjk1013_id, +}; +module_i2c_driver(kxcjk1013_driver); + +MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("KXCJK1013 accelerometer driver"); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a80d23628f14..20a7073f1dd6 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -131,6 +131,15 @@ config LP8788_ADC help Say yes here to build support for TI LP8788 ADC. +config MAX1027 + tristate "Maxim max1027 ADC driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Maxim SPI ADC models + max1027, max1029 and max1031. + config MAX1363 tristate "Maxim max1363 ADC driver" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 9d60f2deaaaf..38cf5c3f5631 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o +obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c index 2a3b65c74af9..4a8c0a2f49b6 100644 --- a/drivers/iio/adc/ad7298.c +++ b/drivers/iio/adc/ad7298.c @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/interrupt.h> +#include <linux/bitops.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -25,23 +26,19 @@ #include <linux/platform_data/ad7298.h> -#define AD7298_WRITE (1 << 15) /* write to the control register */ -#define AD7298_REPEAT (1 << 14) /* repeated conversion enable */ -#define AD7298_CH(x) (1 << (13 - (x))) /* channel select */ -#define AD7298_TSENSE (1 << 5) /* temperature conversion enable */ -#define AD7298_EXTREF (1 << 2) /* external reference enable */ -#define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */ -#define AD7298_PDD (1 << 0) /* partial power down enable */ +#define AD7298_WRITE BIT(15) /* write to the control register */ +#define AD7298_REPEAT BIT(14) /* repeated conversion enable */ +#define AD7298_CH(x) BIT(13 - (x)) /* channel select */ +#define AD7298_TSENSE BIT(5) /* temperature conversion enable */ +#define AD7298_EXTREF BIT(2) /* external reference enable */ +#define AD7298_TAVG BIT(1) /* temperature sensor averaging enable */ +#define AD7298_PDD BIT(0) /* partial power down enable */ #define AD7298_MAX_CHAN 8 -#define AD7298_BITS 12 -#define AD7298_STORAGE_BITS 16 #define AD7298_INTREF_mV 2500 #define AD7298_CH_TEMP 9 -#define RES_MASK(bits) ((1 << (bits)) - 1) - struct ad7298_state { struct spi_device *spi; struct regulator *reg; @@ -257,7 +254,7 @@ static int ad7298_read_raw(struct iio_dev *indio_dev, return ret; if (chan->address != AD7298_CH_TEMP) - *val = ret & RES_MASK(AD7298_BITS); + *val = ret & GENMASK(chan->scan_type.realbits - 1, 0); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c index d141d452c3d1..ce400ec176f1 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -14,6 +14,7 @@ #include <linux/regulator/consumer.h> #include <linux/err.h> #include <linux/module.h> +#include <linux/bitops.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -21,8 +22,6 @@ #include <linux/iio/trigger_consumer.h> #include <linux/iio/triggered_buffer.h> -#define RES_MASK(bits) ((1 << (bits)) - 1) - struct ad7476_state; struct ad7476_chip_info { @@ -117,7 +116,7 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; *val = (ret >> st->chip_info->channel[0].scan_type.shift) & - RES_MASK(st->chip_info->channel[0].scan_type.realbits); + GENMASK(st->chip_info->channel[0].scan_type.realbits - 1, 0); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: if (!st->chip_info->int_vref_uv) { diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c index 749a6cadab8b..2fd012ee99f5 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -15,6 +15,7 @@ #include <linux/err.h> #include <linux/module.h> #include <linux/interrupt.h> +#include <linux/bitops.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -25,14 +26,14 @@ #include <linux/platform_data/ad7887.h> -#define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */ -#define AD7887_DUAL (1 << 4) /* dual-channel mode */ -#define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */ -#define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */ -#define AD7887_PM_MODE1 (0) /* CS based shutdown */ -#define AD7887_PM_MODE2 (1) /* full on */ -#define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */ -#define AD7887_PM_MODE4 (3) /* standby mode */ +#define AD7887_REF_DIS BIT(5) /* on-chip reference disable */ +#define AD7887_DUAL BIT(4) /* dual-channel mode */ +#define AD7887_CH_AIN1 BIT(3) /* convert on channel 1, DUAL=1 */ +#define AD7887_CH_AIN0 0 /* convert on channel 0, DUAL=0,1 */ +#define AD7887_PM_MODE1 0 /* CS based shutdown */ +#define AD7887_PM_MODE2 1 /* full on */ +#define AD7887_PM_MODE3 2 /* auto shutdown after conversion */ +#define AD7887_PM_MODE4 3 /* standby mode */ enum ad7887_channels { AD7887_CH0, @@ -40,8 +41,6 @@ enum ad7887_channels { AD7887_CH1, }; -#define RES_MASK(bits) ((1 << (bits)) - 1) - /** * struct ad7887_chip_info - chip specifc information * @int_vref_mv: the internal reference voltage @@ -167,7 +166,7 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; *val = ret >> chan->scan_type.shift; - *val &= RES_MASK(chan->scan_type.realbits); + *val &= GENMASK(chan->scan_type.realbits - 1, 0); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: if (st->reg) { diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 6eba301ee03d..6cf9ee18a216 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -105,9 +105,8 @@ enum { * struct ad799x_chip_info - chip specific information * @channel: channel specification * @num_channels: number of channels - * @monitor_mode: whether the chip supports monitor interrupts * @default_config: device default configuration - * @event_attrs: pointer to the monitor event attribute group + * @info: pointer to iio_info struct */ struct ad799x_chip_info { struct iio_chan_spec channel[9]; diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 9a4e0e32a771..c55b81f7f970 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -410,7 +410,7 @@ static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private) complete(&sigma_delta->completion); disable_irq_nosync(irq); sigma_delta->irq_dis = true; - iio_trigger_poll(sigma_delta->trig, iio_get_time_ns()); + iio_trigger_poll(sigma_delta->trig); return IRQ_HANDLED; } diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 2b6a9ce9927c..772e869c280e 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -272,7 +272,7 @@ void handle_adc_eoc_trigger(int irq, struct iio_dev *idev) if (iio_buffer_enabled(idev)) { disable_irq_nosync(irq); - iio_trigger_poll(idev->trig, iio_get_time_ns()); + iio_trigger_poll(idev->trig); } else { st->last_value = at91_adc_readl(st, AT91_ADC_LCDR); st->done = true; diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c new file mode 100644 index 000000000000..87ee1c7d0b54 --- /dev/null +++ b/drivers/iio/adc/max1027.c @@ -0,0 +1,521 @@ + /* + * iio/adc/max1027.c + * Copyright (C) 2014 Philippe Reynes + * + * based on linux/drivers/iio/ad7923.c + * Copyright 2011 Analog Devices Inc (from AD7923 Driver) + * Copyright 2012 CS Systemes d'Information + * + * 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. + * + * max1027.c + * + * Partial support for max1027 and similar chips. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> + +#define MAX1027_CONV_REG BIT(7) +#define MAX1027_SETUP_REG BIT(6) +#define MAX1027_AVG_REG BIT(5) +#define MAX1027_RST_REG BIT(4) + +/* conversion register */ +#define MAX1027_TEMP BIT(0) +#define MAX1027_SCAN_0_N (0x00 << 1) +#define MAX1027_SCAN_N_M (0x01 << 1) +#define MAX1027_SCAN_N (0x02 << 1) +#define MAX1027_NOSCAN (0x03 << 1) +#define MAX1027_CHAN(n) ((n) << 3) + +/* setup register */ +#define MAX1027_UNIPOLAR 0x02 +#define MAX1027_BIPOLAR 0x03 +#define MAX1027_REF_MODE0 (0x00 << 2) +#define MAX1027_REF_MODE1 (0x01 << 2) +#define MAX1027_REF_MODE2 (0x02 << 2) +#define MAX1027_REF_MODE3 (0x03 << 2) +#define MAX1027_CKS_MODE0 (0x00 << 4) +#define MAX1027_CKS_MODE1 (0x01 << 4) +#define MAX1027_CKS_MODE2 (0x02 << 4) +#define MAX1027_CKS_MODE3 (0x03 << 4) + +/* averaging register */ +#define MAX1027_NSCAN_4 0x00 +#define MAX1027_NSCAN_8 0x01 +#define MAX1027_NSCAN_12 0x02 +#define MAX1027_NSCAN_16 0x03 +#define MAX1027_NAVG_4 (0x00 << 2) +#define MAX1027_NAVG_8 (0x01 << 2) +#define MAX1027_NAVG_16 (0x02 << 2) +#define MAX1027_NAVG_32 (0x03 << 2) +#define MAX1027_AVG_EN BIT(4) + +enum max1027_id { + max1027, + max1029, + max1031, +}; + +static const struct spi_device_id max1027_id[] = { + {"max1027", max1027}, + {"max1029", max1029}, + {"max1031", max1031}, + {} +}; +MODULE_DEVICE_TABLE(spi, max1027_id); + +#ifdef CONFIG_OF +static const struct of_device_id max1027_adc_dt_ids[] = { + { .compatible = "maxim,max1027" }, + { .compatible = "maxim,max1029" }, + { .compatible = "maxim,max1031" }, + {}, +}; +MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids); +#endif + +#define MAX1027_V_CHAN(index) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = index, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = index + 1, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 10, \ + .storagebits = 16, \ + .shift = 2, \ + .endianness = IIO_BE, \ + }, \ + } + +#define MAX1027_T_CHAN \ + { \ + .type = IIO_TEMP, \ + .channel = 0, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = 0, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 12, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec max1027_channels[] = { + MAX1027_T_CHAN, + MAX1027_V_CHAN(0), + MAX1027_V_CHAN(1), + MAX1027_V_CHAN(2), + MAX1027_V_CHAN(3), + MAX1027_V_CHAN(4), + MAX1027_V_CHAN(5), + MAX1027_V_CHAN(6), + MAX1027_V_CHAN(7) +}; + +static const struct iio_chan_spec max1029_channels[] = { + MAX1027_T_CHAN, + MAX1027_V_CHAN(0), + MAX1027_V_CHAN(1), + MAX1027_V_CHAN(2), + MAX1027_V_CHAN(3), + MAX1027_V_CHAN(4), + MAX1027_V_CHAN(5), + MAX1027_V_CHAN(6), + MAX1027_V_CHAN(7), + MAX1027_V_CHAN(8), + MAX1027_V_CHAN(9), + MAX1027_V_CHAN(10), + MAX1027_V_CHAN(11) +}; + +static const struct iio_chan_spec max1031_channels[] = { + MAX1027_T_CHAN, + MAX1027_V_CHAN(0), + MAX1027_V_CHAN(1), + MAX1027_V_CHAN(2), + MAX1027_V_CHAN(3), + MAX1027_V_CHAN(4), + MAX1027_V_CHAN(5), + MAX1027_V_CHAN(6), + MAX1027_V_CHAN(7), + MAX1027_V_CHAN(8), + MAX1027_V_CHAN(9), + MAX1027_V_CHAN(10), + MAX1027_V_CHAN(11), + MAX1027_V_CHAN(12), + MAX1027_V_CHAN(13), + MAX1027_V_CHAN(14), + MAX1027_V_CHAN(15) +}; + +static const unsigned long max1027_available_scan_masks[] = { + 0x000001ff, + 0x00000000, +}; + +static const unsigned long max1029_available_scan_masks[] = { + 0x00001fff, + 0x00000000, +}; + +static const unsigned long max1031_available_scan_masks[] = { + 0x0001ffff, + 0x00000000, +}; + +struct max1027_chip_info { + const struct iio_chan_spec *channels; + unsigned int num_channels; + const unsigned long *available_scan_masks; +}; + +static const struct max1027_chip_info max1027_chip_info_tbl[] = { + [max1027] = { + .channels = max1027_channels, + .num_channels = ARRAY_SIZE(max1027_channels), + .available_scan_masks = max1027_available_scan_masks, + }, + [max1029] = { + .channels = max1029_channels, + .num_channels = ARRAY_SIZE(max1029_channels), + .available_scan_masks = max1029_available_scan_masks, + }, + [max1031] = { + .channels = max1031_channels, + .num_channels = ARRAY_SIZE(max1031_channels), + .available_scan_masks = max1031_available_scan_masks, + }, +}; + +struct max1027_state { + const struct max1027_chip_info *info; + struct spi_device *spi; + struct iio_trigger *trig; + __be16 *buffer; + struct mutex lock; + + u8 reg ____cacheline_aligned; +}; + +static int max1027_read_single_value(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val) +{ + int ret; + struct max1027_state *st = iio_priv(indio_dev); + + if (iio_buffer_enabled(indio_dev)) { + dev_warn(&indio_dev->dev, "trigger mode already enabled"); + return -EBUSY; + } + + /* Start acquisition on conversion register write */ + st->reg = MAX1027_SETUP_REG | MAX1027_REF_MODE2 | MAX1027_CKS_MODE2; + ret = spi_write(st->spi, &st->reg, 1); + if (ret < 0) { + dev_err(&indio_dev->dev, + "Failed to configure setup register\n"); + return ret; + } + + /* Configure conversion register with the requested chan */ + st->reg = MAX1027_CONV_REG | MAX1027_CHAN(chan->channel) | + MAX1027_NOSCAN | !!(chan->type == IIO_TEMP); + ret = spi_write(st->spi, &st->reg, 1); + if (ret < 0) { + dev_err(&indio_dev->dev, + "Failed to configure conversion register\n"); + return ret; + } + + /* + * For an unknown reason, when we use the mode "10" (write + * conversion register), the interrupt doesn't occur every time. + * So we just wait 1 ms. + */ + mdelay(1); + + /* Read result */ + ret = spi_read(st->spi, st->buffer, (chan->type == IIO_TEMP) ? 4 : 2); + if (ret < 0) + return ret; + + *val = be16_to_cpu(st->buffer[0]); + + return IIO_VAL_INT; +} + +static int max1027_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret = 0; + struct max1027_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = max1027_read_single_value(indio_dev, chan, val); + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + *val = 1; + *val2 = 8; + ret = IIO_VAL_FRACTIONAL; + break; + case IIO_VOLTAGE: + *val = 2500; + *val2 = 10; + ret = IIO_VAL_FRACTIONAL_LOG2; + break; + default: + ret = -EINVAL; + break; + } + break; + default: + ret = -EINVAL; + break; + } + + mutex_unlock(&st->lock); + + return ret; +} + +static int max1027_debugfs_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct max1027_state *st = iio_priv(indio_dev); + u8 *val = (u8 *)st->buffer; + + if (readval != NULL) + return -EINVAL; + + *val = (u8)writeval; + return spi_write(st->spi, val, 1); +} + +static int max1027_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct max1027_state *st = iio_priv(indio_dev); + + if (st->trig != trig) + return -EINVAL; + + return 0; +} + +static int max1027_set_trigger_state(struct iio_trigger *trig, bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct max1027_state *st = iio_priv(indio_dev); + int ret; + + if (state) { + /* Start acquisition on cnvst */ + st->reg = MAX1027_SETUP_REG | MAX1027_CKS_MODE0 | + MAX1027_REF_MODE2; + ret = spi_write(st->spi, &st->reg, 1); + if (ret < 0) + return ret; + + /* Scan from 0 to max */ + st->reg = MAX1027_CONV_REG | MAX1027_CHAN(0) | + MAX1027_SCAN_N_M | MAX1027_TEMP; + ret = spi_write(st->spi, &st->reg, 1); + if (ret < 0) + return ret; + } else { + /* Start acquisition on conversion register write */ + st->reg = MAX1027_SETUP_REG | MAX1027_CKS_MODE2 | + MAX1027_REF_MODE2; + ret = spi_write(st->spi, &st->reg, 1); + if (ret < 0) + return ret; + } + + return 0; +} + +static int max1027_validate_device(struct iio_trigger *trig, + struct iio_dev *indio_dev) +{ + struct iio_dev *indio = iio_trigger_get_drvdata(trig); + + if (indio != indio_dev) + return -EINVAL; + + return 0; +} + +static irqreturn_t max1027_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = (struct iio_poll_func *)private; + struct iio_dev *indio_dev = pf->indio_dev; + struct max1027_state *st = iio_priv(indio_dev); + + pr_debug("%s(irq=%d, private=0x%p)\n", __func__, irq, private); + + /* fill buffer with all channel */ + spi_read(st->spi, st->buffer, indio_dev->masklength * 2); + + iio_push_to_buffers(indio_dev, st->buffer); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_trigger_ops max1027_trigger_ops = { + .owner = THIS_MODULE, + .validate_device = &max1027_validate_device, + .set_trigger_state = &max1027_set_trigger_state, +}; + +static const struct iio_info max1027_info = { + .driver_module = THIS_MODULE, + .read_raw = &max1027_read_raw, + .validate_trigger = &max1027_validate_trigger, + .debugfs_reg_access = &max1027_debugfs_reg_access, +}; + +static int max1027_probe(struct spi_device *spi) +{ + int ret; + struct iio_dev *indio_dev; + struct max1027_state *st; + + pr_debug("%s: probe(spi = 0x%p)\n", __func__, spi); + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (indio_dev == NULL) { + pr_err("Can't allocate iio device\n"); + return -ENOMEM; + } + + spi_set_drvdata(spi, indio_dev); + + st = iio_priv(indio_dev); + st->spi = spi; + st->info = &max1027_chip_info_tbl[spi_get_device_id(spi)->driver_data]; + + mutex_init(&st->lock); + + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &max1027_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->info->channels; + indio_dev->num_channels = st->info->num_channels; + indio_dev->available_scan_masks = st->info->available_scan_masks; + + st->buffer = devm_kmalloc(&indio_dev->dev, + indio_dev->num_channels * 2, + GFP_KERNEL); + if (st->buffer == NULL) { + dev_err(&indio_dev->dev, "Can't allocate bufffer\n"); + return -ENOMEM; + } + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &max1027_trigger_handler, NULL); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed to setup buffer\n"); + return ret; + } + + st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-trigger", + indio_dev->name); + if (st->trig == NULL) { + ret = -ENOMEM; + dev_err(&indio_dev->dev, "Failed to allocate iio trigger\n"); + goto fail_trigger_alloc; + } + + st->trig->ops = &max1027_trigger_ops; + st->trig->dev.parent = &spi->dev; + iio_trigger_set_drvdata(st->trig, indio_dev); + iio_trigger_register(st->trig); + + ret = devm_request_threaded_irq(&spi->dev, spi->irq, + iio_trigger_generic_data_rdy_poll, + NULL, + IRQF_TRIGGER_FALLING, + spi->dev.driver->name, st->trig); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n"); + goto fail_dev_register; + } + + /* Disable averaging */ + st->reg = MAX1027_AVG_REG; + ret = spi_write(st->spi, &st->reg, 1); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed to configure averaging register\n"); + goto fail_dev_register; + } + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed to register iio device\n"); + goto fail_dev_register; + } + + return 0; + +fail_dev_register: +fail_trigger_alloc: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; +} + +static int max1027_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + pr_debug("%s: remove(spi = 0x%p)\n", __func__, spi); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + return 0; +} + +static struct spi_driver max1027_driver = { + .driver = { + .name = "max1027", + .owner = THIS_MODULE, + }, + .probe = max1027_probe, + .remove = max1027_remove, + .id_table = max1027_id, +}; +module_spi_driver(max1027_driver); + +MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>"); +MODULE_DESCRIPTION("MAX1027/MAX1029/MAX1031 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index ab52be29141b..fd2745c62943 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -486,7 +486,7 @@ static irqreturn_t xadc_axi_interrupt_handler(int irq, void *devid) return IRQ_NONE; if ((status & XADC_AXI_INT_EOS) && xadc->trigger) - iio_trigger_poll(xadc->trigger, 0); + iio_trigger_poll(xadc->trigger); if (status & XADC_AXI_INT_ALARM_MASK) { /* diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index f378ca8033db..f278eff42a4c 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -163,4 +163,14 @@ config MCP4725 To compile this driver as a module, choose M here: the module will be called mcp4725. +config MCP4922 + tristate "MCP4902, MCP4912, MCP4922 DAC driver" + depends on SPI + help + Say yes here to build the driver for the Microchip MCP4902 + MCP4912, and MCP4922 DAC devices. + + To compile this driver as a module, choose M here: the module + will be called mcp4922. + endmenu diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index bb84ad64463f..10107640bb46 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD7303) += ad7303.o obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MCP4725) += mcp4725.o +obj-$(CONFIG_MCP4922) += mcp4922.o diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index 1e6449346b50..c917dd24090a 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -15,17 +15,16 @@ #include <linux/sysfs.h> #include <linux/regulator/consumer.h> #include <linux/module.h> +#include <linux/bitops.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/events.h> #include <linux/iio/dac/ad5504.h> -#define AD5505_BITS 12 -#define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1) - -#define AD5504_CMD_READ (1 << 15) -#define AD5504_CMD_WRITE (0 << 15) +#define AD5504_RES_MASK GENMASK(11, 0) +#define AD5504_CMD_READ BIT(15) +#define AD5504_CMD_WRITE 0 #define AD5504_ADDR(addr) ((addr) << 12) /* Registers */ @@ -42,7 +41,7 @@ /** * struct ad5446_state - driver instance specific data - * @us: spi_device + * @spi: spi_device * @reg: supply regulator * @vref_mv: actual reference voltage used * @pwr_down_mask power down mask diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index ae49afe2b380..5ba785f18589 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -16,17 +16,16 @@ #include <linux/sysfs.h> #include <linux/regulator/consumer.h> #include <linux/module.h> +#include <linux/bitops.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/dac/ad5791.h> -#define AD5791_RES_MASK(x) ((1 << (x)) - 1) -#define AD5791_DAC_MASK AD5791_RES_MASK(20) -#define AD5791_DAC_MSB (1 << 19) +#define AD5791_DAC_MASK GENMASK(19, 0) -#define AD5791_CMD_READ (1 << 23) -#define AD5791_CMD_WRITE (0 << 23) +#define AD5791_CMD_READ BIT(23) +#define AD5791_CMD_WRITE 0 #define AD5791_ADDR(addr) ((addr) << 20) /* Registers */ @@ -37,11 +36,11 @@ #define AD5791_ADDR_SW_CTRL 4 /* Control Register */ -#define AD5791_CTRL_RBUF (1 << 1) -#define AD5791_CTRL_OPGND (1 << 2) -#define AD5791_CTRL_DACTRI (1 << 3) -#define AD5791_CTRL_BIN2SC (1 << 4) -#define AD5791_CTRL_SDODIS (1 << 5) +#define AD5791_CTRL_RBUF BIT(1) +#define AD5791_CTRL_OPGND BIT(2) +#define AD5791_CTRL_DACTRI BIT(3) +#define AD5791_CTRL_BIN2SC BIT(4) +#define AD5791_CTRL_SDODIS BIT(5) #define AD5761_CTRL_LINCOMP(x) ((x) << 6) #define AD5791_LINCOMP_0_10 0 @@ -54,9 +53,9 @@ #define AD5780_LINCOMP_10_20 12 /* Software Control Register */ -#define AD5791_SWCTRL_LDAC (1 << 0) -#define AD5791_SWCTRL_CLR (1 << 1) -#define AD5791_SWCTRL_RESET (1 << 2) +#define AD5791_SWCTRL_LDAC BIT(0) +#define AD5791_SWCTRL_CLR BIT(1) +#define AD5791_SWCTRL_RESET BIT(2) #define AD5791_DAC_PWRDN_6K 0 #define AD5791_DAC_PWRDN_3STATE 1 @@ -72,7 +71,7 @@ struct ad5791_chip_info { /** * struct ad5791_state - driver instance specific data - * @us: spi_device + * @spi: spi_device * @reg_vdd: positive supply regulator * @reg_vss: negative supply regulator * @chip_info: chip model specific constants @@ -328,7 +327,7 @@ static int ad5791_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - val &= AD5791_RES_MASK(chan->scan_type.realbits); + val &= GENMASK(chan->scan_type.realbits - 1, 0); val <<= chan->scan_type.shift; return ad5791_spi_write(st, chan->address, val); diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c new file mode 100644 index 000000000000..92cf4ca6981d --- /dev/null +++ b/drivers/iio/dac/mcp4922.c @@ -0,0 +1,216 @@ +/* + * mcp4922.c + * + * Driver for Microchip Digital to Analog Converters. + * Supports MCP4902, MCP4912, and MCP4922. + * + * Copyright (c) 2014 EMAC Inc. + * + * 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 + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/spi/spi.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/regulator/consumer.h> +#include <linux/bitops.h> + +#define MCP4922_NUM_CHANNELS 2 + +enum mcp4922_supported_device_ids { + ID_MCP4902, + ID_MCP4912, + ID_MCP4922, +}; + +struct mcp4922_state { + struct spi_device *spi; + unsigned int value[MCP4922_NUM_CHANNELS]; + unsigned int vref_mv; + struct regulator *vref_reg; + u8 mosi[2] ____cacheline_aligned; +}; + +#define MCP4922_CHAN(chan, bits) { \ + .type = IIO_VOLTAGE, \ + .output = 1, \ + .indexed = 1, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = (bits), \ + .storagebits = 16, \ + .shift = 12 - (bits), \ + }, \ +} + +static int mcp4922_spi_write(struct mcp4922_state *state, u8 addr, u32 val) +{ + state->mosi[1] = val & 0xff; + state->mosi[0] = (addr == 0) ? 0x00 : 0x80; + state->mosi[0] |= 0x30 | ((val >> 8) & 0x0f); + + return spi_write(state->spi, state->mosi, 2); +} + +static int mcp4922_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct mcp4922_state *state = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + *val = state->value[chan->channel]; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = state->vref_mv; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } +} + +static int mcp4922_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct mcp4922_state *state = iio_priv(indio_dev); + + if (val2 != 0) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val > GENMASK(chan->scan_type.realbits-1, 0)) + return -EINVAL; + val <<= chan->scan_type.shift; + state->value[chan->channel] = val; + return mcp4922_spi_write(state, chan->channel, val); + default: + return -EINVAL; + } +} + +static const struct iio_chan_spec mcp4922_channels[3][MCP4922_NUM_CHANNELS] = { + [ID_MCP4902] = { MCP4922_CHAN(0, 8), MCP4922_CHAN(1, 8) }, + [ID_MCP4912] = { MCP4922_CHAN(0, 10), MCP4922_CHAN(1, 10) }, + [ID_MCP4922] = { MCP4922_CHAN(0, 12), MCP4922_CHAN(1, 12) }, +}; + +static const struct iio_info mcp4922_info = { + .read_raw = &mcp4922_read_raw, + .write_raw = &mcp4922_write_raw, + .driver_module = THIS_MODULE, +}; + +static int mcp4922_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct mcp4922_state *state; + const struct spi_device_id *id; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state)); + if (indio_dev == NULL) + return -ENOMEM; + + state = iio_priv(indio_dev); + state->spi = spi; + state->vref_reg = devm_regulator_get(&spi->dev, "vref"); + if (IS_ERR(state->vref_reg)) { + dev_err(&spi->dev, "Vref regulator not specified\n"); + return PTR_ERR(state->vref_reg); + } + + ret = regulator_enable(state->vref_reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable vref regulator: %d\n", + ret); + return ret; + } + + ret = regulator_get_voltage(state->vref_reg); + if (ret < 0) { + dev_err(&spi->dev, "Failed to read vref regulator: %d\n", + ret); + goto error_disable_reg; + } + state->vref_mv = ret / 1000; + + spi_set_drvdata(spi, indio_dev); + id = spi_get_device_id(spi); + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &mcp4922_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = mcp4922_channels[id->driver_data]; + indio_dev->num_channels = MCP4922_NUM_CHANNELS; + indio_dev->name = id->name; + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register iio device: %d\n", + ret); + goto error_disable_reg; + } + + return 0; + +error_disable_reg: + regulator_disable(state->vref_reg); + + return ret; +} + +static int mcp4922_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct mcp4922_state *state; + + iio_device_unregister(indio_dev); + state = iio_priv(indio_dev); + regulator_disable(state->vref_reg); + + return 0; +} + +static const struct spi_device_id mcp4922_id[] = { + {"mcp4902", ID_MCP4902}, + {"mcp4912", ID_MCP4912}, + {"mcp4922", ID_MCP4922}, + {} +}; +MODULE_DEVICE_TABLE(spi, mcp4922_id); + +static struct spi_driver mcp4922_driver = { + .driver = { + .name = "mcp4922", + .owner = THIS_MODULE, + }, + .probe = mcp4922_probe, + .remove = mcp4922_remove, + .id_table = mcp4922_id, +}; +module_spi_driver(mcp4922_driver); + +MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>"); +MODULE_DESCRIPTION("Microchip MCP4902, MCP4912, MCP4922 DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 36b1ae92e239..2952ee038477 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -39,10 +39,7 @@ static bool iio_buffer_is_active(struct iio_buffer *buf) static bool iio_buffer_data_available(struct iio_buffer *buf) { - if (buf->access->data_available) - return buf->access->data_available(buf); - - return buf->stufftoread; + return buf->access->data_available(buf); } /** diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 3383b025f62e..d31098e0c43f 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -114,7 +114,7 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name, return trig; } -void iio_trigger_poll(struct iio_trigger *trig, s64 time) +void iio_trigger_poll(struct iio_trigger *trig) { int i; @@ -133,12 +133,12 @@ EXPORT_SYMBOL(iio_trigger_poll); irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private) { - iio_trigger_poll(private, iio_get_time_ns()); + iio_trigger_poll(private); return IRQ_HANDLED; } EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); -void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) +void iio_trigger_poll_chained(struct iio_trigger *trig) { int i; @@ -161,7 +161,7 @@ void iio_trigger_notify_done(struct iio_trigger *trig) trig->ops->try_reenable) if (trig->ops->try_reenable(trig)) /* Missed an interrupt so launch new poll now */ - iio_trigger_poll(trig, 0); + iio_trigger_poll(trig); } EXPORT_SYMBOL(iio_trigger_notify_done); diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c index d976e6ce60db..ad36b294e4d5 100644 --- a/drivers/iio/light/cm32181.c +++ b/drivers/iio/light/cm32181.c @@ -331,7 +331,7 @@ static int cm32181_probe(struct i2c_client *client, return ret; } - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&client->dev, indio_dev); if (ret) { dev_err(&client->dev, "%s: regist device failed\n", @@ -342,14 +342,6 @@ static int cm32181_probe(struct i2c_client *client, return 0; } -static int cm32181_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - return 0; -} - static const struct i2c_device_id cm32181_id[] = { { "cm32181", 0 }, { } @@ -370,7 +362,6 @@ static struct i2c_driver cm32181_driver = { }, .id_table = cm32181_id, .probe = cm32181_probe, - .remove = cm32181_remove, }; module_i2c_driver(cm32181_driver); diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index 04bdb85d2d9f..221ed16de1f7 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -827,7 +827,7 @@ static void gp2ap020a00f_iio_trigger_work(struct irq_work *work) struct gp2ap020a00f_data *data = container_of(work, struct gp2ap020a00f_data, work); - iio_trigger_poll(data->trig, 0); + iio_trigger_poll(data->trig); } static irqreturn_t gp2ap020a00f_prox_sensing_handler(int irq, void *data) diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 05a364c543f8..b2dba9e506ab 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -17,6 +17,16 @@ config AK8975 To compile this driver as a module, choose M here: the module will be called ak8975. +config AK09911 + tristate "Asahi Kasei AK09911 3-axis Compass" + depends on I2C + help + Say yes here to build support for Asahi Kasei AK09911 3-Axis + Magnetometer. + + To compile this driver as a module, choose M here: the module + will be called ak09911. + config MAG3110 tristate "Freescale MAG3110 3-Axis Magnetometer" depends on I2C diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index 0f5d3c985799..b91315e0b826 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AK09911) += ak09911.o obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_MAG3110) += mag3110.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o diff --git a/drivers/iio/magnetometer/ak09911.c b/drivers/iio/magnetometer/ak09911.c new file mode 100644 index 000000000000..b2bc942ff6b8 --- /dev/null +++ b/drivers/iio/magnetometer/ak09911.c @@ -0,0 +1,326 @@ +/* + * AK09911 3-axis compass driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/acpi.h> +#include <linux/iio/iio.h> + +#define AK09911_REG_WIA1 0x00 +#define AK09911_REG_WIA2 0x01 +#define AK09911_WIA1_VALUE 0x48 +#define AK09911_WIA2_VALUE 0x05 + +#define AK09911_REG_ST1 0x10 +#define AK09911_REG_HXL 0x11 +#define AK09911_REG_HXH 0x12 +#define AK09911_REG_HYL 0x13 +#define AK09911_REG_HYH 0x14 +#define AK09911_REG_HZL 0x15 +#define AK09911_REG_HZH 0x16 + +#define AK09911_REG_ASAX 0x60 +#define AK09911_REG_ASAY 0x61 +#define AK09911_REG_ASAZ 0x62 + +#define AK09911_REG_CNTL1 0x30 +#define AK09911_REG_CNTL2 0x31 +#define AK09911_REG_CNTL3 0x32 + +#define AK09911_MODE_SNG_MEASURE 0x01 +#define AK09911_MODE_SELF_TEST 0x10 +#define AK09911_MODE_FUSE_ACCESS 0x1F +#define AK09911_MODE_POWERDOWN 0x00 +#define AK09911_RESET_DATA 0x01 + +#define AK09911_REG_CNTL1 0x30 +#define AK09911_REG_CNTL2 0x31 +#define AK09911_REG_CNTL3 0x32 + +#define AK09911_RAW_TO_GAUSS(asa) ((((asa) + 128) * 6000) / 256) + +#define AK09911_MAX_CONVERSION_TIMEOUT_MS 500 +#define AK09911_CONVERSION_DONE_POLL_TIME_MS 10 + +struct ak09911_data { + struct i2c_client *client; + struct mutex lock; + u8 asa[3]; + long raw_to_gauss[3]; +}; + +static const int ak09911_index_to_reg[] = { + AK09911_REG_HXL, AK09911_REG_HYL, AK09911_REG_HZL, +}; + +static int ak09911_set_mode(struct i2c_client *client, u8 mode) +{ + int ret; + + switch (mode) { + case AK09911_MODE_SNG_MEASURE: + case AK09911_MODE_SELF_TEST: + case AK09911_MODE_FUSE_ACCESS: + case AK09911_MODE_POWERDOWN: + ret = i2c_smbus_write_byte_data(client, + AK09911_REG_CNTL2, mode); + if (ret < 0) { + dev_err(&client->dev, "set_mode error\n"); + return ret; + } + /* After mode change wait atleast 100us */ + usleep_range(100, 500); + break; + default: + dev_err(&client->dev, + "%s: Unknown mode(%d).", __func__, mode); + return -EINVAL; + } + + return ret; +} + +/* Get Sensitivity Adjustment value */ +static int ak09911_get_asa(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ak09911_data *data = iio_priv(indio_dev); + int ret; + + ret = ak09911_set_mode(client, AK09911_MODE_FUSE_ACCESS); + if (ret < 0) + return ret; + + /* Get asa data and store in the device data. */ + ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_ASAX, + 3, data->asa); + if (ret < 0) { + dev_err(&client->dev, "Not able to read asa data\n"); + return ret; + } + + ret = ak09911_set_mode(client, AK09911_MODE_POWERDOWN); + if (ret < 0) + return ret; + + data->raw_to_gauss[0] = AK09911_RAW_TO_GAUSS(data->asa[0]); + data->raw_to_gauss[1] = AK09911_RAW_TO_GAUSS(data->asa[1]); + data->raw_to_gauss[2] = AK09911_RAW_TO_GAUSS(data->asa[2]); + + return 0; +} + +static int ak09911_verify_chip_id(struct i2c_client *client) +{ + u8 wia_val[2]; + int ret; + + ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_WIA1, + 2, wia_val); + if (ret < 0) { + dev_err(&client->dev, "Error reading WIA\n"); + return ret; + } + + dev_dbg(&client->dev, "WIA %02x %02x\n", wia_val[0], wia_val[1]); + + if (wia_val[0] != AK09911_WIA1_VALUE || + wia_val[1] != AK09911_WIA2_VALUE) { + dev_err(&client->dev, "Device ak09911 not found\n"); + return -ENODEV; + } + + return 0; +} + +static int wait_conversion_complete_polled(struct ak09911_data *data) +{ + struct i2c_client *client = data->client; + u8 read_status; + u32 timeout_ms = AK09911_MAX_CONVERSION_TIMEOUT_MS; + int ret; + + /* Wait for the conversion to complete. */ + while (timeout_ms) { + msleep_interruptible(AK09911_CONVERSION_DONE_POLL_TIME_MS); + ret = i2c_smbus_read_byte_data(client, AK09911_REG_ST1); + if (ret < 0) { + dev_err(&client->dev, "Error in reading ST1\n"); + return ret; + } + read_status = ret & 0x01; + if (read_status) + break; + timeout_ms -= AK09911_CONVERSION_DONE_POLL_TIME_MS; + } + if (!timeout_ms) { + dev_err(&client->dev, "Conversion timeout happened\n"); + return -EIO; + } + + return read_status; +} + +static int ak09911_read_axis(struct iio_dev *indio_dev, int index, int *val) +{ + struct ak09911_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + int ret; + + mutex_lock(&data->lock); + + ret = ak09911_set_mode(client, AK09911_MODE_SNG_MEASURE); + if (ret < 0) + goto fn_exit; + + ret = wait_conversion_complete_polled(data); + if (ret < 0) + goto fn_exit; + + /* Read data */ + ret = i2c_smbus_read_word_data(client, ak09911_index_to_reg[index]); + if (ret < 0) { + dev_err(&client->dev, "Read axis data fails\n"); + goto fn_exit; + } + + mutex_unlock(&data->lock); + + /* Clamp to valid range. */ + *val = sign_extend32(clamp_t(s16, ret, -8192, 8191), 13); + + return IIO_VAL_INT; + +fn_exit: + mutex_unlock(&data->lock); + + return ret; +} + +static int ak09911_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct ak09911_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + return ak09911_read_axis(indio_dev, chan->address, val); + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = data->raw_to_gauss[chan->address]; + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; +} + +#define AK09911_CHANNEL(axis, index) \ + { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .address = index, \ + } + +static const struct iio_chan_spec ak09911_channels[] = { + AK09911_CHANNEL(X, 0), AK09911_CHANNEL(Y, 1), AK09911_CHANNEL(Z, 2), +}; + +static const struct iio_info ak09911_info = { + .read_raw = &ak09911_read_raw, + .driver_module = THIS_MODULE, +}; + +static const struct acpi_device_id ak_acpi_match[] = { + {"AK009911", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, ak_acpi_match); + +static int ak09911_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ak09911_data *data; + const char *name; + int ret; + + ret = ak09911_verify_chip_id(client); + if (ret) { + dev_err(&client->dev, "AK00911 not detected\n"); + return -ENODEV; + } + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (indio_dev == NULL) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + + data->client = client; + mutex_init(&data->lock); + + ret = ak09911_get_asa(client); + if (ret) + return ret; + + if (id) + name = id->name; + else if (ACPI_HANDLE(&client->dev)) + name = dev_name(&client->dev); + else + return -ENODEV; + + dev_dbg(&client->dev, "Asahi compass chip %s\n", name); + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = ak09911_channels; + indio_dev->num_channels = ARRAY_SIZE(ak09911_channels); + indio_dev->info = &ak09911_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = name; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id ak09911_id[] = { + {"ak09911", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ak09911_id); + +static struct i2c_driver ak09911_driver = { + .driver = { + .name = "ak09911", + .acpi_match_table = ACPI_PTR(ak_acpi_match), + }, + .probe = ak09911_probe, + .id_table = ak09911_id, +}; +module_i2c_driver(ak09911_driver); + +MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("AK09911 Compass driver"); diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index ea08313af0d2..a2357921d761 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -165,7 +165,7 @@ static int ak8975_setup_irq(struct ak8975_data *data) else irq = gpio_to_irq(data->eoc_gpio); - rc = request_irq(irq, ak8975_irq_handler, + rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, dev_name(&client->dev), data); if (rc < 0) { @@ -513,21 +513,21 @@ static int ak8975_probe(struct i2c_client *client, /* We may not have a GPIO based IRQ to scan, that is fine, we will poll if so */ if (gpio_is_valid(eoc_gpio)) { - err = gpio_request_one(eoc_gpio, GPIOF_IN, "ak_8975"); + err = devm_gpio_request_one(&client->dev, eoc_gpio, + GPIOF_IN, "ak_8975"); if (err < 0) { dev_err(&client->dev, "failed to request GPIO %d, error %d\n", eoc_gpio, err); - goto exit; + return err; } } /* Register with IIO */ - indio_dev = iio_device_alloc(sizeof(*data)); - if (indio_dev == NULL) { - err = -ENOMEM; - goto exit_gpio; - } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (indio_dev == NULL) + return -ENOMEM; + data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); @@ -542,17 +542,16 @@ static int ak8975_probe(struct i2c_client *client, name = (char *) id->name; } else if (ACPI_HANDLE(&client->dev)) name = ak8975_match_acpi_device(&client->dev, &data->chipset); - else { - err = -ENOSYS; - goto exit_free_iio; - } + else + return -ENOSYS; + dev_dbg(&client->dev, "Asahi compass chip %s\n", name); /* Perform some basic start-of-day setup of the device. */ err = ak8975_setup(client); if (err < 0) { dev_err(&client->dev, "AK8975 initialization fails\n"); - goto exit_free_iio; + return err; } data->client = client; @@ -564,37 +563,9 @@ static int ak8975_probe(struct i2c_client *client, indio_dev->info = &ak8975_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = name; - err = iio_device_register(indio_dev); + err = devm_iio_device_register(&client->dev, indio_dev); if (err < 0) - goto exit_free_iio; - - return 0; - -exit_free_iio: - iio_device_free(indio_dev); - if (data->eoc_irq) - free_irq(data->eoc_irq, data); -exit_gpio: - if (gpio_is_valid(eoc_gpio)) - gpio_free(eoc_gpio); -exit: - return err; -} - -static int ak8975_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ak8975_data *data = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - if (data->eoc_irq) - free_irq(data->eoc_irq, data); - - if (gpio_is_valid(data->eoc_gpio)) - gpio_free(data->eoc_gpio); - - iio_device_free(indio_dev); + return err; return 0; } @@ -621,7 +592,6 @@ static struct i2c_driver ak8975_driver = { .acpi_match_table = ACPI_PTR(ak_acpi_match), }, .probe = ak8975_probe, - .remove = ak8975_remove, .id_table = ak8975_id, }; module_i2c_driver(ak8975_driver); diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index ffac8ac1efca..15afbc919521 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -70,4 +70,14 @@ config IIO_ST_PRESS_SPI depends on IIO_ST_PRESS depends on IIO_ST_SENSORS_SPI +config T5403 + tristate "EPCOS T5403 digital barometric pressure sensor driver" + depends on I2C + help + Say yes here to build support for the EPCOS T5403 pressure sensor + connected via I2C. + + To compile this driver as a module, choose M here: the module + will be called t5403. + endmenu diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index c53d2500737a..90a37e85cf21 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_MPL3115) += mpl3115.o obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o st_pressure-y := st_pressure_core.o st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o +obj-$(CONFIG_T5403) += t5403.o obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o diff --git a/drivers/iio/pressure/t5403.c b/drivers/iio/pressure/t5403.c new file mode 100644 index 000000000000..e11cd3938d67 --- /dev/null +++ b/drivers/iio/pressure/t5403.c @@ -0,0 +1,275 @@ +/* + * t5403.c - Support for EPCOS T5403 pressure/temperature sensor + * + * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * (7-bit I2C slave address 0x77) + * + * TODO: end-of-conversion irq + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/delay.h> + +#define T5403_DATA 0xf5 /* data, LSB first, 16 bit */ +#define T5403_CALIB_DATA 0x8e /* 10 calibration coeff., LSB first, 16 bit */ +#define T5403_SLAVE_ADDR 0x88 /* I2C slave address, 0x77 */ +#define T5403_COMMAND 0xf1 + +/* command bits */ +#define T5403_MODE_SHIFT 3 /* conversion time: 2, 8, 16, 66 ms */ +#define T5403_PT BIT(1) /* 0 .. pressure, 1 .. temperature measurement */ +#define T5403_SCO BIT(0) /* start conversion */ + +#define T5403_MODE_LOW 0 +#define T5403_MODE_STANDARD 1 +#define T5403_MODE_HIGH 2 +#define T5403_MODE_ULTRA_HIGH 3 + +#define T5403_I2C_MASK (~BIT(7)) +#define T5403_I2C_ADDR 0x77 + +static const int t5403_pressure_conv_ms[] = {2, 8, 16, 66}; + +struct t5403_data { + struct i2c_client *client; + struct mutex lock; + int mode; + __le16 c[10]; +}; + +#define T5403_C_U16(i) le16_to_cpu(data->c[(i) - 1]) +#define T5403_C(i) sign_extend32(T5403_C_U16(i), 15) + +static int t5403_read(struct t5403_data *data, bool pressure) +{ + int wait_time = 3; /* wakeup time in ms */ + + int ret = i2c_smbus_write_byte_data(data->client, T5403_COMMAND, + (pressure ? (data->mode << T5403_MODE_SHIFT) : T5403_PT) | + T5403_SCO); + if (ret < 0) + return ret; + + wait_time += pressure ? t5403_pressure_conv_ms[data->mode] : 2; + + msleep(wait_time); + + return i2c_smbus_read_word_data(data->client, T5403_DATA); +} + +static int t5403_comp_pressure(struct t5403_data *data, int *val, int *val2) +{ + int ret; + s16 t_r; + u16 p_r; + s32 S, O, X; + + mutex_lock(&data->lock); + + ret = t5403_read(data, false); + if (ret < 0) + goto done; + t_r = ret; + + ret = t5403_read(data, true); + if (ret < 0) + goto done; + p_r = ret; + + /* see EPCOS application note */ + S = T5403_C_U16(3) + (s32) T5403_C_U16(4) * t_r / 0x20000 + + T5403_C(5) * t_r / 0x8000 * t_r / 0x80000 + + T5403_C(9) * t_r / 0x8000 * t_r / 0x8000 * t_r / 0x10000; + + O = T5403_C(6) * 0x4000 + T5403_C(7) * t_r / 8 + + T5403_C(8) * t_r / 0x8000 * t_r / 16 + + T5403_C(9) * t_r / 0x8000 * t_r / 0x10000 * t_r; + + X = (S * p_r + O) / 0x4000; + + X += ((X - 75000) * (X - 75000) / 0x10000 - 9537) * + T5403_C(10) / 0x10000; + + *val = X / 1000; + *val2 = (X % 1000) * 1000; + +done: + mutex_unlock(&data->lock); + return ret; +} + +static int t5403_comp_temp(struct t5403_data *data, int *val) +{ + int ret; + s16 t_r; + + mutex_lock(&data->lock); + ret = t5403_read(data, false); + if (ret < 0) + goto done; + t_r = ret; + + /* see EPCOS application note */ + *val = ((s32) T5403_C_U16(1) * t_r / 0x100 + + (s32) T5403_C_U16(2) * 0x40) * 1000 / 0x10000; + +done: + mutex_unlock(&data->lock); + return ret; +} + +static int t5403_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct t5403_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_PRESSURE: + ret = t5403_comp_pressure(data, val, val2); + if (ret < 0) + return ret; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_TEMP: + ret = t5403_comp_temp(data, val); + if (ret < 0) + return ret; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_INT_TIME: + *val = 0; + *val2 = t5403_pressure_conv_ms[data->mode] * 1000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int t5403_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct t5403_data *data = iio_priv(indio_dev); + int i; + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + if (val != 0) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(t5403_pressure_conv_ms); i++) + if (val2 == t5403_pressure_conv_ms[i] * 1000) { + mutex_lock(&data->lock); + data->mode = i; + mutex_unlock(&data->lock); + return 0; + } + return -EINVAL; + default: + return -EINVAL; + } +} + +static const struct iio_chan_spec t5403_channels[] = { + { + .type = IIO_PRESSURE, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_INT_TIME), + }, + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + }, +}; + +static IIO_CONST_ATTR_INT_TIME_AVAIL("0.002 0.008 0.016 0.066"); + +static struct attribute *t5403_attributes[] = { + &iio_const_attr_integration_time_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group t5403_attribute_group = { + .attrs = t5403_attributes, +}; + +static const struct iio_info t5403_info = { + .read_raw = &t5403_read_raw, + .write_raw = &t5403_write_raw, + .attrs = &t5403_attribute_group, + .driver_module = THIS_MODULE, +}; + +static int t5403_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct t5403_data *data; + struct iio_dev *indio_dev; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) + return -ENODEV; + + ret = i2c_smbus_read_byte_data(client, T5403_SLAVE_ADDR); + if (ret < 0) + return ret; + if ((ret & T5403_I2C_MASK) != T5403_I2C_ADDR) + return -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + mutex_init(&data->lock); + + i2c_set_clientdata(client, indio_dev); + indio_dev->info = &t5403_info; + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = t5403_channels; + indio_dev->num_channels = ARRAY_SIZE(t5403_channels); + + data->mode = T5403_MODE_STANDARD; + + ret = i2c_smbus_read_i2c_block_data(data->client, T5403_CALIB_DATA, + sizeof(data->c), (u8 *) data->c); + if (ret < 0) + return ret; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id t5403_id[] = { + { "t5403", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, t5403_id); + +static struct i2c_driver t5403_driver = { + .driver = { + .name = "t5403", + }, + .probe = t5403_probe, + .id_table = t5403_id, +}; +module_i2c_driver(t5403_driver); + +MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); +MODULE_DESCRIPTION("EPCOS T5403 pressure/temperature sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index bf677bfe8eb2..5e780ef206f3 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -232,7 +232,7 @@ static void as3935_event_work(struct work_struct *work) switch (val) { case AS3935_EVENT_INT: - iio_trigger_poll(st->trig, iio_get_time_ns()); + iio_trigger_poll(st->trig); break; case AS3935_NOISE_INT: dev_warn(&st->spi->dev, "noise level is too high"); diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c index 02577ec54c6b..7a149a7822bc 100644 --- a/drivers/iio/trigger/iio-trig-interrupt.c +++ b/drivers/iio/trigger/iio-trig-interrupt.c @@ -24,8 +24,7 @@ struct iio_interrupt_trigger_info { static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private) { - /* Timestamp not currently provided */ - iio_trigger_poll(private, 0); + iio_trigger_poll(private); return IRQ_HANDLED; } diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c index 15e3b850f513..254c7e906127 100644 --- a/drivers/iio/trigger/iio-trig-sysfs.c +++ b/drivers/iio/trigger/iio-trig-sysfs.c @@ -96,7 +96,7 @@ static void iio_sysfs_trigger_work(struct irq_work *work) struct iio_sysfs_trig *trig = container_of(work, struct iio_sysfs_trig, work); - iio_trigger_poll(trig->trig, 0); + iio_trigger_poll(trig->trig); } static ssize_t iio_sysfs_trigger_poll(struct device *dev, |