First round of new IIO drivers and cleanups for the 3.11 cycle.

1) New driver for MCP3204/08 12 bit ADCs
 2) Move the sysfs trigger out of staging.  This has been pretty clean for a
    long time so lets finally move it out.
 3) New functionality for the ak8975 magnetometer (DT and data ready interrupt
    handling)
 4) Use devm_ioremap_resource in exynos_adc.  We have 3 separate versions of
    this patch proposed but this one got there first.
 5) A couple of other tiny fixes.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.20 (GNU/Linux)
 
 iQIcBAABAgAGBQJRnULuAAoJEFSFNJnE9BaIafsP/3Po/mMZmWiERT8awNSKiqcT
 Hb8EhKUl79zbLUi4zi+xGbR4ai8ds5T3UlvAlCMeBAboC+EQY+2pXNVhJQvgp2qw
 4+L3BgQ11wtFud9bg/EERmxU4lMIlQW8PaOwdqKmjMhlny1uxHEvTbwvt+nqNIpC
 6wnZyS8t74S6lDTRkvo328fEVHtckFQZ/a2Ko9lW6DJPBBYjON/Slg9XYtlNTb1Y
 1bt+I0VOV4EWVHSl/tt/x+Y6FuzvkvzMglDqA2j3emnGcPbuUj497xABlh4btEgM
 sabhk3isoQUi+N9xPtWD5tZCtDcx2/RnAGpYpH9hrGbXFI+4HwB1+uhZw583vKcG
 dP3BmJX/2AnqXeY3WkjiHOqPTw7M1rsotKqTcQfINkXW2ulnyerM117sC/X6cDgW
 rxp+fislmeWFbwM/IxDLcosOXL7Deord4x8/vmPaNsAVcleDIAODb20nPMm+hCAc
 t/iRhsdXAJlA6RXrdQC1lzBoGLLAyu6lIdOpl8Z0YM3l2IWM3RelXOlYCTnFV9Vu
 xZ9Aq3tBaJIxFjl80S/zWKq2fCKGYfyH+L+UXlWA7lXIx6bHA1ITE7qCnNEl6Yk3
 bp5blUqIsU3+Rr6nVao4sBTFGiRurfIbsSXz5/iXqAe/5b1rCACZe1BaojDcrrfc
 IMGZIzpft2u5EkGb8tfo
 =bjgs
 -----END PGP SIGNATURE-----

Merge tag 'iio-for-3.11a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

First round of new IIO drivers and cleanups for the 3.11 cycle.

1) New driver for MCP3204/08 12 bit ADCs
2) Move the sysfs trigger out of staging.  This has been pretty clean for a
   long time so lets finally move it out.
3) New functionality for the ak8975 magnetometer (DT and data ready interrupt
   handling)
4) Use devm_ioremap_resource in exynos_adc.  We have 3 separate versions of
   this patch proposed but this one got there first.
5) A couple of other tiny fixes.
This commit is contained in:
Greg Kroah-Hartman 2013-05-22 15:22:44 -07:00
commit d3f1c3f31d
19 changed files with 425 additions and 37 deletions

View file

@ -0,0 +1,18 @@
* AsahiKASEI AK8975 magnetometer sensor
Required properties:
- compatible : should be "asahi-kasei,ak8975"
- reg : the I2C address of the magnetometer
Optional properties:
- gpios : should be device tree identifier of the magnetometer DRDY pin
Example:
ak8975@0c {
compatible = "asahi-kasei,ak8975";
reg = <0x0c>;
gpios = <&gpj0 7 0>;
};

View file

@ -70,5 +70,8 @@ source "drivers/iio/gyro/Kconfig"
source "drivers/iio/imu/Kconfig" source "drivers/iio/imu/Kconfig"
source "drivers/iio/light/Kconfig" source "drivers/iio/light/Kconfig"
source "drivers/iio/magnetometer/Kconfig" source "drivers/iio/magnetometer/Kconfig"
if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
endif #IIO_TRIGGER
endif # IIO endif # IIO

View file

@ -21,3 +21,4 @@ obj-y += frequency/
obj-y += imu/ obj-y += imu/
obj-y += light/ obj-y += light/
obj-y += magnetometer/ obj-y += magnetometer/
obj-y += trigger/

View file

@ -28,7 +28,6 @@ config IIO_ST_ACCEL_3AXIS
select IIO_ST_ACCEL_I2C_3AXIS if (I2C) select IIO_ST_ACCEL_I2C_3AXIS if (I2C)
select IIO_ST_ACCEL_SPI_3AXIS if (SPI_MASTER) select IIO_ST_ACCEL_SPI_3AXIS if (SPI_MASTER)
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
select IIO_ST_ACCEL_BUFFER if (IIO_TRIGGERED_BUFFER)
help help
Say yes here to build support for STMicroelectronics accelerometers: Say yes here to build support for STMicroelectronics accelerometers:
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,

View file

@ -133,6 +133,16 @@ config MAX1363
max11646, max11647) Provides direct access via sysfs and buffered max11646, max11647) Provides direct access via sysfs and buffered
data via the iio dev interface. data via the iio dev interface.
config MCP320X
tristate "Microchip Technology MCP3204/08"
depends on SPI
help
Say yes here to build support for Microchip Technology's MCP3204 or
MCP3208 analog to digital converter.
This driver can also be built as a module. If so, the module will be
called mcp320x.
config TI_ADC081C config TI_ADC081C
tristate "Texas Instruments ADC081C021/027" tristate "Texas Instruments ADC081C021/027"
depends on I2C depends on I2C

View file

@ -14,6 +14,7 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o

View file

@ -270,16 +270,16 @@ static int exynos_adc_probe(struct platform_device *pdev)
info = iio_priv(indio_dev); info = iio_priv(indio_dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
info->regs = devm_request_and_ioremap(&pdev->dev, mem); info->regs = devm_ioremap_resource(&pdev->dev, mem);
if (!info->regs) { if (IS_ERR(info->regs)) {
ret = -ENOMEM; ret = PTR_ERR(info->regs);
goto err_iio; goto err_iio;
} }
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
info->enable_reg = devm_request_and_ioremap(&pdev->dev, mem); info->enable_reg = devm_ioremap_resource(&pdev->dev, mem);
if (!info->enable_reg) { if (IS_ERR(info->enable_reg)) {
ret = -ENOMEM; ret = PTR_ERR(info->enable_reg);
goto err_iio; goto err_iio;
} }

257
drivers/iio/adc/mcp320x.c Normal file
View file

@ -0,0 +1,257 @@
/*
* Copyright (C) 2013 Oskar Andero <oskar.andero@gmail.com>
*
* Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips.
* Datasheet can be found here:
* http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf
*
* 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/err.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
#define MCP_SINGLE_ENDED (1 << 3)
#define MCP_START_BIT (1 << 4)
enum {
mcp3204,
mcp3208,
};
struct mcp320x {
struct spi_device *spi;
struct spi_message msg;
struct spi_transfer transfer[2];
u8 tx_buf;
u8 rx_buf[2];
struct regulator *reg;
struct mutex lock;
};
static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg)
{
int ret;
adc->tx_buf = msg;
ret = spi_sync(adc->spi, &adc->msg);
if (ret < 0)
return ret;
return ((adc->rx_buf[0] & 0x3f) << 6) |
(adc->rx_buf[1] >> 2);
}
static int mcp320x_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int *val,
int *val2, long mask)
{
struct mcp320x *adc = iio_priv(indio_dev);
int ret = -EINVAL;
mutex_lock(&adc->lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (channel->differential)
ret = mcp320x_adc_conversion(adc,
MCP_START_BIT | channel->address);
else
ret = mcp320x_adc_conversion(adc,
MCP_START_BIT | MCP_SINGLE_ENDED |
channel->address);
if (ret < 0)
goto out;
*val = ret;
ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
/* Digital output code = (4096 * Vin) / Vref */
ret = regulator_get_voltage(adc->reg);
if (ret < 0)
goto out;
*val = ret / 1000;
*val2 = 12;
ret = IIO_VAL_FRACTIONAL_LOG2;
break;
default:
break;
}
out:
mutex_unlock(&adc->lock);
return ret;
}
#define MCP320X_VOLTAGE_CHANNEL(num) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (num), \
.address = (num), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
#define MCP320X_VOLTAGE_CHANNEL_DIFF(num) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (num * 2), \
.channel2 = (num * 2 + 1), \
.address = (num * 2), \
.differential = 1, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec mcp3204_channels[] = {
MCP320X_VOLTAGE_CHANNEL(0),
MCP320X_VOLTAGE_CHANNEL(1),
MCP320X_VOLTAGE_CHANNEL(2),
MCP320X_VOLTAGE_CHANNEL(3),
MCP320X_VOLTAGE_CHANNEL_DIFF(0),
MCP320X_VOLTAGE_CHANNEL_DIFF(1),
};
static const struct iio_chan_spec mcp3208_channels[] = {
MCP320X_VOLTAGE_CHANNEL(0),
MCP320X_VOLTAGE_CHANNEL(1),
MCP320X_VOLTAGE_CHANNEL(2),
MCP320X_VOLTAGE_CHANNEL(3),
MCP320X_VOLTAGE_CHANNEL(4),
MCP320X_VOLTAGE_CHANNEL(5),
MCP320X_VOLTAGE_CHANNEL(6),
MCP320X_VOLTAGE_CHANNEL(7),
MCP320X_VOLTAGE_CHANNEL_DIFF(0),
MCP320X_VOLTAGE_CHANNEL_DIFF(1),
MCP320X_VOLTAGE_CHANNEL_DIFF(2),
MCP320X_VOLTAGE_CHANNEL_DIFF(3),
};
static const struct iio_info mcp320x_info = {
.read_raw = mcp320x_read_raw,
.driver_module = THIS_MODULE,
};
struct mcp3208_chip_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
};
static const struct mcp3208_chip_info mcp3208_chip_infos[] = {
[mcp3204] = {
.channels = mcp3204_channels,
.num_channels = ARRAY_SIZE(mcp3204_channels)
},
[mcp3208] = {
.channels = mcp3208_channels,
.num_channels = ARRAY_SIZE(mcp3208_channels)
},
};
static int mcp320x_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct mcp320x *adc;
const struct mcp3208_chip_info *chip_info;
int ret;
indio_dev = iio_device_alloc(sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->spi = spi;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mcp320x_info;
chip_info = &mcp3208_chip_infos[spi_get_device_id(spi)->driver_data];
indio_dev->channels = chip_info->channels;
indio_dev->num_channels = chip_info->num_channels;
adc->transfer[0].tx_buf = &adc->tx_buf;
adc->transfer[0].len = sizeof(adc->tx_buf);
adc->transfer[1].rx_buf = adc->rx_buf;
adc->transfer[1].len = sizeof(adc->rx_buf);
spi_message_init_with_transfers(&adc->msg, adc->transfer,
ARRAY_SIZE(adc->transfer));
adc->reg = regulator_get(&spi->dev, "vref");
if (IS_ERR(adc->reg)) {
ret = PTR_ERR(adc->reg);
goto iio_free;
}
ret = regulator_enable(adc->reg);
if (ret < 0)
goto reg_free;
mutex_init(&adc->lock);
ret = iio_device_register(indio_dev);
if (ret < 0)
goto reg_disable;
return 0;
reg_disable:
regulator_disable(adc->reg);
reg_free:
regulator_put(adc->reg);
iio_free:
iio_device_free(indio_dev);
return ret;
}
static int mcp320x_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct mcp320x *adc = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(adc->reg);
regulator_put(adc->reg);
iio_device_free(indio_dev);
return 0;
}
static const struct spi_device_id mcp320x_id[] = {
{ "mcp3204", mcp3204 },
{ "mcp3208", mcp3208 },
{ }
};
MODULE_DEVICE_TABLE(spi, mcp320x_id);
static struct spi_driver mcp320x_driver = {
.driver = {
.name = "mcp320x",
.owner = THIS_MODULE,
},
.probe = mcp320x_probe,
.remove = mcp320x_remove,
.id_table = mcp320x_id,
};
module_spi_driver(mcp320x_driver);
MODULE_AUTHOR("Oskar Andero <oskar.andero@gmail.com>");
MODULE_DESCRIPTION("Microchip Technology MCP3204/08");
MODULE_LICENSE("GPL v2");

View file

@ -47,7 +47,6 @@ config IIO_ST_GYRO_3AXIS
select IIO_ST_GYRO_I2C_3AXIS if (I2C) select IIO_ST_GYRO_I2C_3AXIS if (I2C)
select IIO_ST_GYRO_SPI_3AXIS if (SPI_MASTER) select IIO_ST_GYRO_SPI_3AXIS if (SPI_MASTER)
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
select IIO_ST_GYRO_BUFFER if (IIO_TRIGGERED_BUFFER)
help help
Say yes here to build support for STMicroelectronics gyroscopes: Say yes here to build support for STMicroelectronics gyroscopes:
L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330. L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.

View file

@ -542,8 +542,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
ret = indio_dev->setup_ops->preenable(indio_dev); ret = indio_dev->setup_ops->preenable(indio_dev);
if (ret) { if (ret) {
printk(KERN_ERR printk(KERN_ERR
"Buffer not started:" "Buffer not started: buffer preenable failed (%d)\n", ret);
"buffer preenable failed\n");
goto error_remove_inserted; goto error_remove_inserted;
} }
} }
@ -556,8 +555,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
ret = buffer->access->request_update(buffer); ret = buffer->access->request_update(buffer);
if (ret) { if (ret) {
printk(KERN_INFO printk(KERN_INFO
"Buffer not started:" "Buffer not started: buffer parameter update failed (%d)\n", ret);
"buffer parameter update failed\n");
goto error_run_postdisable; goto error_run_postdisable;
} }
} }
@ -566,7 +564,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
->update_scan_mode(indio_dev, ->update_scan_mode(indio_dev,
indio_dev->active_scan_mask); indio_dev->active_scan_mask);
if (ret < 0) { if (ret < 0) {
printk(KERN_INFO "update scan mode failed\n"); printk(KERN_INFO "Buffer not started: update scan mode failed (%d)\n", ret);
goto error_run_postdisable; goto error_run_postdisable;
} }
} }
@ -590,7 +588,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
ret = indio_dev->setup_ops->postenable(indio_dev); ret = indio_dev->setup_ops->postenable(indio_dev);
if (ret) { if (ret) {
printk(KERN_INFO printk(KERN_INFO
"Buffer not started: postenable failed\n"); "Buffer not started: postenable failed (%d)\n", ret);
indio_dev->currentmode = INDIO_DIRECT_MODE; indio_dev->currentmode = INDIO_DIRECT_MODE;
if (indio_dev->setup_ops->postdisable) if (indio_dev->setup_ops->postdisable)
indio_dev->setup_ops->postdisable(indio_dev); indio_dev->setup_ops->postdisable(indio_dev);

View file

@ -31,7 +31,7 @@
#include "../common/hid-sensors/hid-sensor-trigger.h" #include "../common/hid-sensors/hid-sensor-trigger.h"
/*Format: HID-SENSOR-usage_id_in_hex*/ /*Format: HID-SENSOR-usage_id_in_hex*/
/*Usage ID from spec for Accelerometer-3D: 0x200041*/ /*Usage ID from spec for Ambiant-Light: 0x200041*/
#define DRIVER_NAME "HID-SENSOR-200041" #define DRIVER_NAME "HID-SENSOR-200041"
#define CHANNEL_SCAN_INDEX_ILLUM 0 #define CHANNEL_SCAN_INDEX_ILLUM 0

View file

@ -32,7 +32,6 @@ config IIO_ST_MAGN_3AXIS
select IIO_ST_MAGN_I2C_3AXIS if (I2C) select IIO_ST_MAGN_I2C_3AXIS if (I2C)
select IIO_ST_MAGN_SPI_3AXIS if (SPI_MASTER) select IIO_ST_MAGN_SPI_3AXIS if (SPI_MASTER)
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
select IIO_ST_MAGN_BUFFER if (IIO_TRIGGERED_BUFFER)
help help
Say yes here to build support for STMicroelectronics magnetometers: Say yes here to build support for STMicroelectronics magnetometers:
LSM303DLHC, LSM303DLM, LIS3MDL. LSM303DLHC, LSM303DLM, LIS3MDL.

View file

@ -24,11 +24,13 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/bitops.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
@ -82,6 +84,7 @@
*/ */
#define AK8975_MAX_CONVERSION_TIMEOUT 500 #define AK8975_MAX_CONVERSION_TIMEOUT 500
#define AK8975_CONVERSION_DONE_POLL_TIME 10 #define AK8975_CONVERSION_DONE_POLL_TIME 10
#define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000)
/* /*
* Per-instance context data for the device. * Per-instance context data for the device.
@ -94,6 +97,9 @@ struct ak8975_data {
long raw_to_gauss[3]; long raw_to_gauss[3];
u8 reg_cache[AK8975_MAX_REGS]; u8 reg_cache[AK8975_MAX_REGS];
int eoc_gpio; int eoc_gpio;
int eoc_irq;
wait_queue_head_t data_ready_queue;
unsigned long flags;
}; };
static const int ak8975_index_to_reg[] = { static const int ak8975_index_to_reg[] = {
@ -122,6 +128,51 @@ static int ak8975_write_data(struct i2c_client *client,
return 0; return 0;
} }
/*
* Handle data ready irq
*/
static irqreturn_t ak8975_irq_handler(int irq, void *data)
{
struct ak8975_data *ak8975 = data;
set_bit(0, &ak8975->flags);
wake_up(&ak8975->data_ready_queue);
return IRQ_HANDLED;
}
/*
* Install data ready interrupt handler
*/
static int ak8975_setup_irq(struct ak8975_data *data)
{
struct i2c_client *client = data->client;
int rc;
int irq;
if (client->irq)
irq = client->irq;
else
irq = gpio_to_irq(data->eoc_gpio);
rc = request_irq(irq, ak8975_irq_handler,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
dev_name(&client->dev), data);
if (rc < 0) {
dev_err(&client->dev,
"irq %d request failed, (gpio %d): %d\n",
irq, data->eoc_gpio, rc);
return rc;
}
init_waitqueue_head(&data->data_ready_queue);
clear_bit(0, &data->flags);
data->eoc_irq = irq;
return rc;
}
/* /*
* Perform some start-of-day setup, including reading the asa calibration * Perform some start-of-day setup, including reading the asa calibration
* values and caching them. * values and caching them.
@ -170,6 +221,16 @@ static int ak8975_setup(struct i2c_client *client)
AK8975_REG_CNTL_MODE_POWER_DOWN, AK8975_REG_CNTL_MODE_POWER_DOWN,
AK8975_REG_CNTL_MODE_MASK, AK8975_REG_CNTL_MODE_MASK,
AK8975_REG_CNTL_MODE_SHIFT); AK8975_REG_CNTL_MODE_SHIFT);
if (data->eoc_gpio > 0 || client->irq) {
ret = ak8975_setup_irq(data);
if (ret < 0) {
dev_err(&client->dev,
"Error setting data ready interrupt\n");
return ret;
}
}
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Error in setting power-down mode\n"); dev_err(&client->dev, "Error in setting power-down mode\n");
return ret; return ret;
@ -266,9 +327,23 @@ static int wait_conversion_complete_polled(struct ak8975_data *data)
dev_err(&client->dev, "Conversion timeout happened\n"); dev_err(&client->dev, "Conversion timeout happened\n");
return -EINVAL; return -EINVAL;
} }
return read_status; return read_status;
} }
/* Returns 0 if the end of conversion interrupt occured or -ETIME otherwise */
static int wait_conversion_complete_interrupt(struct ak8975_data *data)
{
int ret;
ret = wait_event_timeout(data->data_ready_queue,
test_bit(0, &data->flags),
AK8975_DATA_READY_TIMEOUT);
clear_bit(0, &data->flags);
return ret > 0 ? 0 : -ETIME;
}
/* /*
* Emits the raw flux value for the x, y, or z axis. * Emits the raw flux value for the x, y, or z axis.
*/ */
@ -294,13 +369,16 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
} }
/* Wait for the conversion to complete. */ /* Wait for the conversion to complete. */
if (gpio_is_valid(data->eoc_gpio)) if (data->eoc_irq)
ret = wait_conversion_complete_interrupt(data);
else if (gpio_is_valid(data->eoc_gpio))
ret = wait_conversion_complete_gpio(data); ret = wait_conversion_complete_gpio(data);
else else
ret = wait_conversion_complete_polled(data); ret = wait_conversion_complete_polled(data);
if (ret < 0) if (ret < 0)
goto exit; goto exit;
/* This will be executed only for non-interrupt based waiting case */
if (ret & AK8975_REG_ST1_DRDY_MASK) { if (ret & AK8975_REG_ST1_DRDY_MASK) {
ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2); ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2);
if (ret < 0) { if (ret < 0) {
@ -384,10 +462,15 @@ static int ak8975_probe(struct i2c_client *client,
int err; int err;
/* Grab and set up the supplied GPIO. */ /* Grab and set up the supplied GPIO. */
if (client->dev.platform_data == NULL) if (client->dev.platform_data)
eoc_gpio = -1;
else
eoc_gpio = *(int *)(client->dev.platform_data); eoc_gpio = *(int *)(client->dev.platform_data);
else if (client->dev.of_node)
eoc_gpio = of_get_gpio(client->dev.of_node, 0);
else
eoc_gpio = -1;
if (eoc_gpio == -EPROBE_DEFER)
return -EPROBE_DEFER;
/* We may not have a GPIO based IRQ to scan, that is fine, we will /* We may not have a GPIO based IRQ to scan, that is fine, we will
poll if so */ poll if so */
@ -409,6 +492,11 @@ static int ak8975_probe(struct i2c_client *client,
} }
data = iio_priv(indio_dev); data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
data->client = client;
data->eoc_gpio = eoc_gpio;
data->eoc_irq = 0;
/* Perform some basic start-of-day setup of the device. */ /* Perform some basic start-of-day setup of the device. */
err = ak8975_setup(client); err = ak8975_setup(client);
if (err < 0) { if (err < 0) {
@ -433,6 +521,8 @@ static int ak8975_probe(struct i2c_client *client,
exit_free_iio: exit_free_iio:
iio_device_free(indio_dev); iio_device_free(indio_dev);
if (data->eoc_irq)
free_irq(data->eoc_irq, data);
exit_gpio: exit_gpio:
if (gpio_is_valid(eoc_gpio)) if (gpio_is_valid(eoc_gpio))
gpio_free(eoc_gpio); gpio_free(eoc_gpio);
@ -447,6 +537,9 @@ static int ak8975_remove(struct i2c_client *client)
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
if (data->eoc_irq)
free_irq(data->eoc_irq, data);
if (gpio_is_valid(data->eoc_gpio)) if (gpio_is_valid(data->eoc_gpio))
gpio_free(data->eoc_gpio); gpio_free(data->eoc_gpio);

View file

@ -0,0 +1,17 @@
#
# Industrial I/O standalone triggers
#
menu "Triggers - standalone"
config IIO_SYSFS_TRIGGER
tristate "SYSFS trigger"
depends on SYSFS
select IRQ_WORK
help
Provides support for using SYSFS entry as IIO triggers.
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called iio-trig-sysfs.
endmenu

View file

@ -0,0 +1,5 @@
#
# Makefile for triggers not associated with iio-devices
#
obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o

View file

@ -620,7 +620,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
unsigned int i, j = 0; unsigned int i, j = 0;
for_each_set_bit(i, iio->active_scan_mask, iio->masklength) { for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
writel(chan_value, lradc->base + LRADC_CH(j)); writel(chan_value, lradc->base + LRADC_CH(j));
lradc->buffer[j] &= LRADC_CH_VALUE_MASK; lradc->buffer[j] &= LRADC_CH_VALUE_MASK;
@ -775,8 +775,7 @@ static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio,
const unsigned long *mask) const unsigned long *mask)
{ {
struct mxs_lradc *lradc = iio_priv(iio); struct mxs_lradc *lradc = iio_priv(iio);
const int len = iio->masklength; const int map_chans = bitmap_weight(mask, LRADC_MAX_TOTAL_CHANS);
const int map_chans = bitmap_weight(mask, len);
int rsvd_chans = 0; int rsvd_chans = 0;
unsigned long rsvd_mask = 0; unsigned long rsvd_mask = 0;
@ -793,7 +792,7 @@ static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio,
rsvd_chans++; rsvd_chans++;
/* Test for attempts to map channels with special mode of operation. */ /* Test for attempts to map channels with special mode of operation. */
if (bitmap_intersects(mask, &rsvd_mask, len)) if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS))
return false; return false;
/* Test for attempts to map more channels then available slots. */ /* Test for attempts to map more channels then available slots. */
@ -969,6 +968,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
iio->modes = INDIO_DIRECT_MODE; iio->modes = INDIO_DIRECT_MODE;
iio->channels = mxs_lradc_chan_spec; iio->channels = mxs_lradc_chan_spec;
iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec); iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec);
iio->masklength = LRADC_MAX_TOTAL_CHANS;
ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time, ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
&mxs_lradc_trigger_handler, &mxs_lradc_trigger_handler,

View file

@ -18,17 +18,6 @@ config IIO_GPIO_TRIGGER
help help
Provides support for using GPIO pins as IIO triggers. Provides support for using GPIO pins as IIO triggers.
config IIO_SYSFS_TRIGGER
tristate "SYSFS trigger"
depends on SYSFS
select IRQ_WORK
help
Provides support for using SYSFS entry as IIO triggers.
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called iio-trig-sysfs.
config IIO_BFIN_TMR_TRIGGER config IIO_BFIN_TMR_TRIGGER
tristate "Blackfin TIMER trigger" tristate "Blackfin TIMER trigger"
depends on BLACKFIN depends on BLACKFIN

View file

@ -4,5 +4,4 @@
obj-$(CONFIG_IIO_PERIODIC_RTC_TRIGGER) += iio-trig-periodic-rtc.o obj-$(CONFIG_IIO_PERIODIC_RTC_TRIGGER) += iio-trig-periodic-rtc.o
obj-$(CONFIG_IIO_GPIO_TRIGGER) += iio-trig-gpio.o obj-$(CONFIG_IIO_GPIO_TRIGGER) += iio-trig-gpio.o
obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o
obj-$(CONFIG_IIO_BFIN_TMR_TRIGGER) += iio-trig-bfin-timer.o obj-$(CONFIG_IIO_BFIN_TMR_TRIGGER) += iio-trig-bfin-timer.o