Second set of IIO rework and new drivers for the 3.7 cycle.

Firstly we have the second half of a series reworking support for
 the various sigma delta ADCs from Analog.  The first half was fixes
 that have already merged in the v3.6 cycle.  Other than some
 little cleanups this mainly consists of a unifying library module
 that the various drivers can then use.  Another new driver is
 using this undergoing revisions and the code reduction already
 seen from this is considerable.  A nice piece of work.
 
 Secondly we have a good number of tidying up patches from various
 sources doing things like adding include guards and removing
 unintended header ordering requirements.  Also a mass annotation
 of missing __devinit/exit.  Peter Meerwald has been getting around
 with cleanup of lis3l02dq, documentation fixes, white space clenaups
 and a small issue with my spelling ;)
 
 Thirdly we have some improvements to our kfifo usage that have
 been around for a while but are now suddenly in demand from a
 number of users.
 
 Forth we have some clk_prepare_enable and clk_prepare_disable
 cleanups.
 
 Fifth is the addition of i2c dacs to the ad5446 driver
 
 Finally we have some email address updates. I'll do the
 MAINTAINERS one separately.
 
 So a general mixed bag but nothing terribly controversial
 or 'exciting'.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIcBAABAgAGBQJQRQpqAAoJEFSFNJnE9BaIa7IQALon1R0vcjaiUOhOEUCeYu7H
 kS9RHPZ0Gq8H8Hl/7Opdn44PwbvduBrr0X/HcI7x02T3nVYTCk1udGBBIRRMJtdd
 N+YNXGSDunbvfpJ9G785439lJPuGBoA/QgBmiL1Tx3DQQTF66Yrh7sQguNNY31GP
 1+wRYp9ILhDVa4saWgCGW8K7acfoFJVYjSCeFTAACcNa5f6vUpO+yFHf92cWGNmk
 2odGtHJo5Kfcr8IzpHAH0twCUjNFKzEzNhkJRNV7KZnHpTO0+Q9lBGAExGNkGWFo
 NtG5tZ5NAX+YstDKGXAu80xb9wcmnvtif7aoqyKpZA2/AabHiNW6gLAOONdvdVrs
 9ljiHv6DKgJvf4rNCxufRgE5OD0BItGECJENiuFsTktsUePF2yMPrQZzocYB7hVu
 Wf3tEppWnRLw9OPuDqkj7Rna8WkVVo8U+xhnu80AM7gGpOkciHm7YyS8DkPfxQaW
 j2kGslJCvSoerEtoXfaPoKIybH2h0GrSKWKHXqJxaKsXOjNIwZNzm02UgdiuRlO3
 IHqJr9y31pwlgc83OSA6UK5jXXX4PPiyV7+sR1bBr1F9k3MG4wSzsDRXRI90h24G
 ruhiTkW6J+I+HjHSw8G6g2WJbC+oWHcQHpvKDexwNPsEWDzjb+zEdO1ArnBpp+Fb
 mAp4Qv3PaI0LyQP8Y1xZ
 =jZe0
 -----END PGP SIGNATURE-----

Merge tag 'iio-for-v3.7b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into work-next

Second set of IIO rework and new drivers for the 3.7 cycle.

Firstly we have the second half of a series reworking support for
the various sigma delta ADCs from Analog.  The first half was fixes
that have already merged in the v3.6 cycle.  Other than some
little cleanups this mainly consists of a unifying library module
that the various drivers can then use.  Another new driver is
using this undergoing revisions and the code reduction already
seen from this is considerable.  A nice piece of work.

Secondly we have a good number of tidying up patches from various
sources doing things like adding include guards and removing
unintended header ordering requirements.  Also a mass annotation
of missing __devinit/exit.  Peter Meerwald has been getting around
with cleanup of lis3l02dq, documentation fixes, white space clenaups
and a small issue with my spelling ;)

Thirdly we have some improvements to our kfifo usage that have
been around for a while but are now suddenly in demand from a
number of users.

Forth we have some clk_prepare_enable and clk_prepare_disable
cleanups.

Fifth is the addition of i2c dacs to the ad5446 driver

Finally we have some email address updates. I'll do the
MAINTAINERS one separately.

So a general mixed bag but nothing terribly controversial
or 'exciting'.
This commit is contained in:
Greg Kroah-Hartman 2012-09-04 12:12:05 -07:00
commit 79e3f02887
63 changed files with 1575 additions and 1554 deletions

View File

@ -1,5 +1,5 @@
#
# Industrial I/O subsytem configuration
# Industrial I/O subsystem configuration
#
menuconfig IIO

View File

@ -3,6 +3,11 @@
#
menu "Analog to digital converters"
config AD_SIGMA_DELTA
tristate
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
config AD7266
tristate "Analog Devices AD7265/AD7266 ADC driver"
depends on SPI_MASTER

View File

@ -2,5 +2,6 @@
# Makefile for IIO ADC drivers
#
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o

View File

@ -0,0 +1,558 @@
/*
* Support code for Analog Devices Sigma-Delta ADCs
*
* Copyright 2012 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/err.h>
#include <linux/module.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/adc/ad_sigma_delta.h>
#include <asm/unaligned.h>
#define AD_SD_COMM_CHAN_MASK 0x3
#define AD_SD_REG_COMM 0x00
#define AD_SD_REG_DATA 0x03
/**
* ad_sd_set_comm() - Set communications register
*
* @sigma_delta: The sigma delta device
* @comm: New value for the communications register
*/
void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm)
{
/* Some variants use the lower two bits of the communications register
* to select the channel */
sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK;
}
EXPORT_SYMBOL_GPL(ad_sd_set_comm);
/**
* ad_sd_write_reg() - Write a register
*
* @sigma_delta: The sigma delta device
* @reg: Address of the register
* @size: Size of the register (0-3)
* @val: Value to write to the register
*
* Returns 0 on success, an error code otherwise.
**/
int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
unsigned int size, unsigned int val)
{
uint8_t *data = sigma_delta->data;
struct spi_transfer t = {
.tx_buf = data,
.len = size + 1,
.cs_change = sigma_delta->bus_locked,
};
struct spi_message m;
int ret;
data[0] = (reg << sigma_delta->info->addr_shift) | sigma_delta->comm;
switch (size) {
case 3:
data[1] = val >> 16;
data[2] = val >> 8;
data[3] = val;
break;
case 2:
put_unaligned_be16(val, &data[1]);
break;
case 1:
data[1] = val;
break;
case 0:
break;
default:
return -EINVAL;
}
spi_message_init(&m);
spi_message_add_tail(&t, &m);
if (sigma_delta->bus_locked)
ret = spi_sync_locked(sigma_delta->spi, &m);
else
ret = spi_sync(sigma_delta->spi, &m);
return ret;
}
EXPORT_SYMBOL_GPL(ad_sd_write_reg);
static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta,
unsigned int reg, unsigned int size, uint8_t *val)
{
uint8_t *data = sigma_delta->data;
int ret;
struct spi_transfer t[] = {
{
.tx_buf = data,
.len = 1,
}, {
.rx_buf = val,
.len = size,
.cs_change = sigma_delta->bus_locked,
},
};
struct spi_message m;
spi_message_init(&m);
if (sigma_delta->info->has_registers) {
data[0] = reg << sigma_delta->info->addr_shift;
data[0] |= sigma_delta->info->read_mask;
spi_message_add_tail(&t[0], &m);
}
spi_message_add_tail(&t[1], &m);
if (sigma_delta->bus_locked)
ret = spi_sync_locked(sigma_delta->spi, &m);
else
ret = spi_sync(sigma_delta->spi, &m);
return ret;
}
/**
* ad_sd_read_reg() - Read a register
*
* @sigma_delta: The sigma delta device
* @reg: Address of the register
* @size: Size of the register (1-4)
* @val: Read value
*
* Returns 0 on success, an error code otherwise.
**/
int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
unsigned int reg, unsigned int size, unsigned int *val)
{
int ret;
ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->data);
if (ret < 0)
goto out;
switch (size) {
case 4:
*val = get_unaligned_be32(sigma_delta->data);
break;
case 3:
*val = (sigma_delta->data[0] << 16) |
(sigma_delta->data[1] << 8) |
sigma_delta->data[2];
break;
case 2:
*val = get_unaligned_be16(sigma_delta->data);
break;
case 1:
*val = sigma_delta->data[0];
break;
default:
ret = -EINVAL;
break;
}
out:
return ret;
}
EXPORT_SYMBOL_GPL(ad_sd_read_reg);
static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
unsigned int mode, unsigned int channel)
{
int ret;
ret = ad_sigma_delta_set_channel(sigma_delta, channel);
if (ret)
return ret;
spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
INIT_COMPLETION(sigma_delta->completion);
ret = ad_sigma_delta_set_mode(sigma_delta, mode);
if (ret < 0)
goto out;
sigma_delta->irq_dis = false;
enable_irq(sigma_delta->spi->irq);
ret = wait_for_completion_timeout(&sigma_delta->completion, 2*HZ);
if (ret == 0) {
sigma_delta->irq_dis = true;
disable_irq_nosync(sigma_delta->spi->irq);
ret = -EIO;
} else {
ret = 0;
}
out:
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->master);
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
return ret;
}
/**
* ad_sd_calibrate_all() - Performs channel calibration
* @sigma_delta: The sigma delta device
* @cb: Array of channels and calibration type to perform
* @n: Number of items in cb
*
* Returns 0 on success, an error code otherwise.
**/
int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
const struct ad_sd_calib_data *cb, unsigned int n)
{
unsigned int i;
int ret;
for (i = 0; i < n; i++) {
ret = ad_sd_calibrate(sigma_delta, cb[i].mode, cb[i].channel);
if (ret)
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(ad_sd_calibrate_all);
/**
* ad_sigma_delta_single_conversion() - Performs a single data conversion
* @indio_dev: The IIO device
* @chan: The conversion is done for this channel
* @val: Pointer to the location where to store the read value
*
* Returns: 0 on success, an error value otherwise.
*/
int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, int *val)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
unsigned int sample, raw_sample;
int ret = 0;
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
mutex_lock(&indio_dev->mlock);
ad_sigma_delta_set_channel(sigma_delta, chan->address);
spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
INIT_COMPLETION(sigma_delta->completion);
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
sigma_delta->irq_dis = false;
enable_irq(sigma_delta->spi->irq);
ret = wait_for_completion_interruptible_timeout(
&sigma_delta->completion, HZ);
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->master);
if (ret == 0)
ret = -EIO;
if (ret < 0)
goto out;
ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_DATA,
DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 8),
&raw_sample);
out:
if (!sigma_delta->irq_dis) {
disable_irq_nosync(sigma_delta->spi->irq);
sigma_delta->irq_dis = true;
}
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
mutex_unlock(&indio_dev->mlock);
if (ret)
return ret;
sample = raw_sample >> chan->scan_type.shift;
sample &= (1 << chan->scan_type.realbits) - 1;
*val = sample;
ret = ad_sigma_delta_postprocess_sample(sigma_delta, raw_sample);
if (ret)
return ret;
return IIO_VAL_INT;
}
EXPORT_SYMBOL_GPL(ad_sigma_delta_single_conversion);
static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
unsigned int channel;
int ret;
ret = iio_triggered_buffer_postenable(indio_dev);
if (ret < 0)
return ret;
channel = find_first_bit(indio_dev->active_scan_mask,
indio_dev->masklength);
ret = ad_sigma_delta_set_channel(sigma_delta,
indio_dev->channels[channel].address);
if (ret)
goto err_predisable;
spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
if (ret)
goto err_unlock;
sigma_delta->irq_dis = false;
enable_irq(sigma_delta->spi->irq);
return 0;
err_unlock:
spi_bus_unlock(sigma_delta->spi->master);
err_predisable:
return ret;
}
static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
INIT_COMPLETION(sigma_delta->completion);
wait_for_completion_timeout(&sigma_delta->completion, HZ);
if (!sigma_delta->irq_dis) {
disable_irq_nosync(sigma_delta->spi->irq);
sigma_delta->irq_dis = true;
}
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
sigma_delta->bus_locked = false;
return spi_bus_unlock(sigma_delta->spi->master);
}
static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
unsigned int reg_size;
uint8_t data[16];
int ret;
memset(data, 0x00, 16);
/* Guaranteed to be aligned with 8 byte boundary */
if (indio_dev->scan_timestamp)
((s64 *)data)[1] = pf->timestamp;
reg_size = indio_dev->channels[0].scan_type.realbits +
indio_dev->channels[0].scan_type.shift;
reg_size = DIV_ROUND_UP(reg_size, 8);
switch (reg_size) {
case 4:
case 2:
case 1:
ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
reg_size, &data[0]);
break;
case 3:
/* We store 24 bit samples in a 32 bit word. Keep the upper
* byte set to zero. */
ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
reg_size, &data[1]);
break;
}
iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data, pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
sigma_delta->irq_dis = false;
enable_irq(sigma_delta->spi->irq);
return IRQ_HANDLED;
}
static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &ad_sd_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
.postdisable = &ad_sd_buffer_postdisable,
.validate_scan_mask = &iio_validate_scan_mask_onehot,
};
static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
{
struct ad_sigma_delta *sigma_delta = private;
complete(&sigma_delta->completion);
disable_irq_nosync(irq);
sigma_delta->irq_dis = true;
iio_trigger_poll(sigma_delta->trig, iio_get_time_ns());
return IRQ_HANDLED;
}
/**
* ad_sd_validate_trigger() - validate_trigger callback for ad_sigma_delta devices
* @indio_dev: The IIO device
* @trig: The new trigger
*
* Returns: 0 if the 'trig' matches the trigger registered by the ad_sigma_delta
* device, -EINVAL otherwise.
*/
int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
if (sigma_delta->trig != trig)
return -EINVAL;
return 0;
}
EXPORT_SYMBOL_GPL(ad_sd_validate_trigger);
static const struct iio_trigger_ops ad_sd_trigger_ops = {
.owner = THIS_MODULE,
};
static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
int ret;
sigma_delta->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
indio_dev->id);
if (sigma_delta->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
}
sigma_delta->trig->ops = &ad_sd_trigger_ops;
init_completion(&sigma_delta->completion);
ret = request_irq(sigma_delta->spi->irq,
ad_sd_data_rdy_trig_poll,
IRQF_TRIGGER_LOW,
indio_dev->name,
sigma_delta);
if (ret)
goto error_free_trig;
if (!sigma_delta->irq_dis) {
sigma_delta->irq_dis = true;
disable_irq_nosync(sigma_delta->spi->irq);
}
sigma_delta->trig->dev.parent = &sigma_delta->spi->dev;
sigma_delta->trig->private_data = sigma_delta;
ret = iio_trigger_register(sigma_delta->trig);
if (ret)
goto error_free_irq;
/* select default trigger */
indio_dev->trig = sigma_delta->trig;
return 0;
error_free_irq:
free_irq(sigma_delta->spi->irq, sigma_delta);
error_free_trig:
iio_trigger_free(sigma_delta->trig);
error_ret:
return ret;
}
static void ad_sd_remove_trigger(struct iio_dev *indio_dev)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
iio_trigger_unregister(sigma_delta->trig);
free_irq(sigma_delta->spi->irq, sigma_delta);
iio_trigger_free(sigma_delta->trig);
}
/**
* ad_sd_setup_buffer_and_trigger() -
* @indio_dev: The IIO device
*/
int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev)
{
int ret;
ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
&ad_sd_trigger_handler, &ad_sd_buffer_setup_ops);
if (ret)
return ret;
ret = ad_sd_probe_trigger(indio_dev);
if (ret) {
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger);
/**
* ad_sd_cleanup_buffer_and_trigger() -
* @indio_dev: The IIO device
*/
void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev)
{
ad_sd_remove_trigger(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
}
EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger);
/**
* ad_sd_init() - Initializes a ad_sigma_delta struct
* @sigma_delta: The ad_sigma_delta device
* @indio_dev: The IIO device which the Sigma Delta device is used for
* @spi: The SPI device for the ad_sigma_delta device
* @info: Device specific callbacks and options
*
* This function needs to be called before any other operations are performed on
* the ad_sigma_delta struct.
*/
int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
struct spi_device *spi, const struct ad_sigma_delta_info *info)
{
sigma_delta->spi = spi;
sigma_delta->info = info;
iio_device_set_drvdata(indio_dev, sigma_delta);
return 0;
}
EXPORT_SYMBOL_GPL(ad_sd_init);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs");
MODULE_LICENSE("GPL v2");

View File

@ -589,18 +589,13 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)
goto error_free_irq;
}
ret = clk_prepare(st->clk);
ret = clk_prepare_enable(st->clk);
if (ret) {
dev_err(&pdev->dev, "Could not prepare the clock.\n");
dev_err(&pdev->dev,
"Could not prepare or enable the clock.\n");
goto error_free_irq;
}
ret = clk_enable(st->clk);
if (ret) {
dev_err(&pdev->dev, "Could not enable the clock.\n");
goto error_unprepare_clk;
}
st->adc_clk = devm_clk_get(&pdev->dev, "adc_op_clk");
if (IS_ERR(st->adc_clk)) {
dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
@ -608,18 +603,13 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)
goto error_disable_clk;
}
ret = clk_prepare(st->adc_clk);
ret = clk_prepare_enable(st->adc_clk);
if (ret) {
dev_err(&pdev->dev, "Could not prepare the ADC clock.\n");
dev_err(&pdev->dev,
"Could not prepare or enable the ADC clock.\n");
goto error_disable_clk;
}
ret = clk_enable(st->adc_clk);
if (ret) {
dev_err(&pdev->dev, "Could not enable the ADC clock.\n");
goto error_unprepare_adc_clk;
}
/*
* Prescaler rate computation using the formula from the Atmel's
* datasheet : ADC Clock = MCK / ((Prescaler + 1) * 2), ADC Clock being
@ -681,13 +671,9 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)
error_unregister_buffer:
at91_adc_buffer_remove(idev);
error_disable_adc_clk:
clk_disable(st->adc_clk);
error_unprepare_adc_clk:
clk_unprepare(st->adc_clk);
clk_disable_unprepare(st->adc_clk);
error_disable_clk:
clk_disable(st->clk);
error_unprepare_clk:
clk_unprepare(st->clk);
clk_disable_unprepare(st->clk);
error_free_irq:
free_irq(st->irq, idev);
error_free_device:
@ -705,8 +691,7 @@ static int __devexit at91_adc_remove(struct platform_device *pdev)
at91_adc_trigger_remove(idev);
at91_adc_buffer_remove(idev);
clk_disable_unprepare(st->adc_clk);
clk_disable(st->clk);
clk_unprepare(st->clk);
clk_disable_unprepare(st->clk);
free_irq(st->irq, idev);
iio_device_free(idev);

View File

@ -57,11 +57,12 @@ config AD5624R_SPI
config AD5446
tristate "Analog Devices AD5446 and similar single channel DACs driver"
depends on SPI
depends on (SPI_MASTER || I2C)
help
Say yes here to build support for Analog Devices AD5444, AD5446, AD5450,
AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601,
AD5611, AD5620, AD5621, AD5640, AD5660, AD5662 DACs.
Say yes here to build support for Analog Devices AD5602, AD5612, AD5622,
AD5444, AD5446, AD5450, AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A,
AD5543, AD5553, AD5601, AD5611, AD5620, AD5621, AD5640, AD5660, AD5662
DACs.
To compile this driver as a module, choose M here: the
module will be called ad5446.

View File

@ -14,6 +14,7 @@
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/spi/spi.h>
#include <linux/i2c.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/module.h>
@ -21,24 +22,40 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "ad5446.h"
#define MODE_PWRDWN_1k 0x1
#define MODE_PWRDWN_100k 0x2
#define MODE_PWRDWN_TRISTATE 0x3
static int ad5446_write(struct ad5446_state *st, unsigned val)
{
__be16 data = cpu_to_be16(val);
return spi_write(st->spi, &data, sizeof(data));
}
/**
* struct ad5446_state - driver instance specific data
* @spi: spi_device
* @chip_info: chip model specific constants, available modes etc
* @reg: supply regulator
* @vref_mv: actual reference voltage used
*/
static int ad5660_write(struct ad5446_state *st, unsigned val)
{
uint8_t data[3];
struct ad5446_state {
struct device *dev;
const struct ad5446_chip_info *chip_info;
struct regulator *reg;
unsigned short vref_mv;
unsigned cached_val;
unsigned pwr_down_mode;
unsigned pwr_down;
};
data[0] = (val >> 16) & 0xFF;
data[1] = (val >> 8) & 0xFF;
data[2] = val & 0xFF;
/**
* struct ad5446_chip_info - chip specific information
* @channel: channel spec for the DAC
* @int_vref_mv: AD5620/40/60: the internal reference voltage
* @write: chip specific helper function to write to the register
*/
return spi_write(st->spi, data, sizeof(data));
}
struct ad5446_chip_info {
struct iio_chan_spec channel;
u16 int_vref_mv;
int (*write)(struct ad5446_state *st, unsigned val);
};
static const char * const ad5446_powerdown_modes[] = {
"1kohm_to_gnd", "100kohm_to_gnd", "three_state"
@ -110,7 +127,7 @@ static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
return ret ? ret : len;
}
static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = {
static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
{
.name = "powerdown",
.read = ad5446_read_dac_powerdown,
@ -136,9 +153,194 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = {
_AD5446_CHANNEL(bits, storage, shift, NULL)
#define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \
_AD5446_CHANNEL(bits, storage, shift, ad5064_ext_info_powerdown)
_AD5446_CHANNEL(bits, storage, shift, ad5446_ext_info_powerdown)
static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
static int ad5446_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long m)
{
struct ad5446_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
*val = st->cached_val;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int ad5446_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long mask)
{
struct ad5446_state *st = iio_priv(indio_dev);
int ret = 0;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
val <<= chan->scan_type.shift;
mutex_lock(&indio_dev->mlock);
st->cached_val = val;
if (!st->pwr_down)
ret = st->chip_info->write(st, val);
mutex_unlock(&indio_dev->mlock);
break;
default:
ret = -EINVAL;
}
return ret;
}
static const struct iio_info ad5446_info = {
.read_raw = ad5446_read_raw,
.write_raw = ad5446_write_raw,
.driver_module = THIS_MODULE,
};
static int __devinit ad5446_probe(struct device *dev, const char *name,
const struct ad5446_chip_info *chip_info)
{
struct ad5446_state *st;
struct iio_dev *indio_dev;
struct regulator *reg;
int ret, voltage_uv = 0;
reg = regulator_get(dev, "vcc");
if (!IS_ERR(reg)) {
ret = regulator_enable(reg);
if (ret)
goto error_put_reg;
voltage_uv = regulator_get_voltage(reg);
}
indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
st = iio_priv(indio_dev);
st->chip_info = chip_info;
dev_set_drvdata(dev, indio_dev);
st->reg = reg;
st->dev = dev;
/* Establish that the iio_dev is a child of the device */
indio_dev->dev.parent = dev;
indio_dev->name = name;
indio_dev->info = &ad5446_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = &st->chip_info->channel;
indio_dev->num_channels = 1;
st->pwr_down_mode = MODE_PWRDWN_1k;
if (st->chip_info->int_vref_mv)
st->vref_mv = st->chip_info->int_vref_mv;
else if (voltage_uv)
st->vref_mv = voltage_uv / 1000;
else
dev_warn(dev, "reference voltage unspecified\n");
ret = iio_device_register(indio_dev);
if (ret)
goto error_free_device;
return 0;
error_free_device:
iio_device_free(indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
error_put_reg:
if (!IS_ERR(reg))
regulator_put(reg);
return ret;
}
static int ad5446_remove(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad5446_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
iio_device_free(indio_dev);
return 0;
}
#if IS_ENABLED(CONFIG_SPI_MASTER)
static int ad5446_write(struct ad5446_state *st, unsigned val)
{
struct spi_device *spi = to_spi_device(st->dev);
__be16 data = cpu_to_be16(val);
return spi_write(spi, &data, sizeof(data));
}
static int ad5660_write(struct ad5446_state *st, unsigned val)
{
struct spi_device *spi = to_spi_device(st->dev);
uint8_t data[3];
data[0] = (val >> 16) & 0xFF;
data[1] = (val >> 8) & 0xFF;
data[2] = val & 0xFF;
return spi_write(spi, data, sizeof(data));
}
/**
* ad5446_supported_spi_device_ids:
* The AD5620/40/60 parts are available in different fixed internal reference
* voltage options. The actual part numbers may look differently
* (and a bit cryptic), however this style is used to make clear which
* parts are supported here.
*/
enum ad5446_supported_spi_device_ids {
ID_AD5444,
ID_AD5446,
ID_AD5450,
ID_AD5451,
ID_AD5541A,
ID_AD5512A,
ID_AD5553,
ID_AD5601,
ID_AD5611,
ID_AD5621,
ID_AD5620_2500,
ID_AD5620_1250,
ID_AD5640_2500,
ID_AD5640_1250,
ID_AD5660_2500,
ID_AD5660_1250,
ID_AD5662,
};
static const struct ad5446_chip_info ad5446_spi_chip_info[] = {
[ID_AD5444] = {
.channel = AD5446_CHANNEL(12, 16, 2),
.write = ad5446_write,
@ -215,143 +417,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
},
};
static int ad5446_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long m)
{
struct ad5446_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
*val = st->cached_val;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int ad5446_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long mask)
{
struct ad5446_state *st = iio_priv(indio_dev);
int ret = 0;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
val <<= chan->scan_type.shift;
mutex_lock(&indio_dev->mlock);
st->cached_val = val;
if (!st->pwr_down)
ret = st->chip_info->write(st, val);
mutex_unlock(&indio_dev->mlock);
break;
default:
ret = -EINVAL;
}
return ret;
}
static const struct iio_info ad5446_info = {
.read_raw = ad5446_read_raw,
.write_raw = ad5446_write_raw,
.driver_module = THIS_MODULE,
};
static int __devinit ad5446_probe(struct spi_device *spi)
{
struct ad5446_state *st;
struct iio_dev *indio_dev;
struct regulator *reg;
int ret, voltage_uv = 0;
reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(reg)) {
ret = regulator_enable(reg);
if (ret)
goto error_put_reg;
voltage_uv = regulator_get_voltage(reg);
}
indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
st = iio_priv(indio_dev);
st->chip_info =
&ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
spi_set_drvdata(spi, indio_dev);
st->reg = reg;
st->spi = spi;
/* Establish that the iio_dev is a child of the spi device */
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad5446_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = &st->chip_info->channel;
indio_dev->num_channels = 1;
st->pwr_down_mode = MODE_PWRDWN_1k;
if (st->chip_info->int_vref_mv)
st->vref_mv = st->chip_info->int_vref_mv;
else if (voltage_uv)
st->vref_mv = voltage_uv / 1000;
else
dev_warn(&spi->dev, "reference voltage unspecified\n");
ret = iio_device_register(indio_dev);
if (ret)
goto error_free_device;
return 0;
error_free_device:
iio_device_free(indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
error_put_reg:
if (!IS_ERR(reg))
regulator_put(reg);
return ret;
}
static int ad5446_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad5446_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
iio_device_free(indio_dev);
return 0;
}
static const struct spi_device_id ad5446_id[] = {
static const struct spi_device_id ad5446_spi_ids[] = {
{"ad5444", ID_AD5444},
{"ad5446", ID_AD5446},
{"ad5450", ID_AD5450},
@ -375,18 +441,157 @@ static const struct spi_device_id ad5446_id[] = {
{"ad5662", ID_AD5662},
{}
};
MODULE_DEVICE_TABLE(spi, ad5446_id);
MODULE_DEVICE_TABLE(spi, ad5446_spi_ids);
static struct spi_driver ad5446_driver = {
static int __devinit ad5446_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
return ad5446_probe(&spi->dev, id->name,
&ad5446_spi_chip_info[id->driver_data]);
}
static int __devexit ad5446_spi_remove(struct spi_device *spi)
{
return ad5446_remove(&spi->dev);
}
static struct spi_driver ad5446_spi_driver = {
.driver = {
.name = "ad5446",
.owner = THIS_MODULE,
},
.probe = ad5446_probe,
.remove = __devexit_p(ad5446_remove),
.id_table = ad5446_id,
.probe = ad5446_spi_probe,
.remove = __devexit_p(ad5446_spi_remove),
.id_table = ad5446_spi_ids,
};
module_spi_driver(ad5446_driver);
static int __init ad5446_spi_register_driver(void)
{
return spi_register_driver(&ad5446_spi_driver);
}
static void ad5446_spi_unregister_driver(void)
{
spi_unregister_driver(&ad5446_spi_driver);
}
#else
static inline int ad5446_spi_register_driver(void) { return 0; }
static inline void ad5446_spi_unregister_driver(void) { }
#endif
#if IS_ENABLED(CONFIG_I2C)
static int ad5622_write(struct ad5446_state *st, unsigned val)
{
struct i2c_client *client = to_i2c_client(st->dev);
__be16 data = cpu_to_be16(val);
return i2c_master_send(client, (char *)&data, sizeof(data));
}
/**
* ad5446_supported_i2c_device_ids:
* The AD5620/40/60 parts are available in different fixed internal reference
* voltage options. The actual part numbers may look differently
* (and a bit cryptic), however this style is used to make clear which
* parts are supported here.
*/
enum ad5446_supported_i2c_device_ids {
ID_AD5602,
ID_AD5612,
ID_AD5622,
};
static const struct ad5446_chip_info ad5446_i2c_chip_info[] = {
[ID_AD5602] = {
.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4),
.write = ad5622_write,
},
[ID_AD5612] = {
.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2),
.write = ad5622_write,
},
[ID_AD5622] = {
.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0),
.write = ad5622_write,
},
};
static int __devinit ad5446_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
return ad5446_probe(&i2c->dev, id->name,
&ad5446_i2c_chip_info[id->driver_data]);
}
static int __devexit ad5446_i2c_remove(struct i2c_client *i2c)
{
return ad5446_remove(&i2c->dev);
}
static const struct i2c_device_id ad5446_i2c_ids[] = {
{"ad5602", ID_AD5602},
{"ad5612", ID_AD5612},
{"ad5622", ID_AD5622},
{}
};
MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids);
static struct i2c_driver ad5446_i2c_driver = {
.driver = {
.name = "ad5446",
.owner = THIS_MODULE,
},
.probe = ad5446_i2c_probe,
.remove = __devexit_p(ad5446_i2c_remove),
.id_table = ad5446_i2c_ids,
};
static int __init ad5446_i2c_register_driver(void)
{
return i2c_add_driver(&ad5446_i2c_driver);
}
static void __exit ad5446_i2c_unregister_driver(void)
{
i2c_del_driver(&ad5446_i2c_driver);
}
#else
static inline int ad5446_i2c_register_driver(void) { return 0; }
static inline void ad5446_i2c_unregister_driver(void) { }
#endif
static int __init ad5446_init(void)
{
int ret;
ret = ad5446_spi_register_driver();
if (ret)
return ret;
ret = ad5446_i2c_register_driver();
if (ret) {
ad5446_spi_unregister_driver();
return ret;
}
return 0;
}
module_init(ad5446_init);
static void __exit ad5446_exit(void)
{
ad5446_i2c_unregister_driver();
ad5446_spi_unregister_driver();
}
module_exit(ad5446_exit);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");

View File

@ -1,91 +0,0 @@
/*
* AD5446 SPI DAC driver
*
* Copyright 2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#ifndef IIO_DAC_AD5446_H_
#define IIO_DAC_AD5446_H_
/* DAC Control Bits */
#define AD5446_LOAD (0x0 << 14) /* Load and update */
#define AD5446_SDO_DIS (0x1 << 14) /* Disable SDO */
#define AD5446_NOP (0x2 << 14) /* No operation */
#define AD5446_CLK_RISING (0x3 << 14) /* Clock data on rising edge */
#define AD5620_LOAD (0x0 << 14) /* Load and update Norm Operation*/
#define AD5620_PWRDWN_1k (0x1 << 14) /* Power-down: 1kOhm to GND */
#define AD5620_PWRDWN_100k (0x2 << 14) /* Power-down: 100kOhm to GND */
#define AD5620_PWRDWN_TRISTATE (0x3 << 14) /* Power-down: Three-state */
#define AD5660_LOAD (0x0 << 16) /* Load and update Norm Operation*/
#define AD5660_PWRDWN_1k (0x1 << 16) /* Power-down: 1kOhm to GND */
#define AD5660_PWRDWN_100k (0x2 << 16) /* Power-down: 100kOhm to GND */
#define AD5660_PWRDWN_TRISTATE (0x3 << 16) /* Power-down: Three-state */
#define MODE_PWRDWN_1k 0x1
#define MODE_PWRDWN_100k 0x2
#define MODE_PWRDWN_TRISTATE 0x3
/**
* struct ad5446_state - driver instance specific data
* @spi: spi_device
* @chip_info: chip model specific constants, available modes etc
* @reg: supply regulator
* @vref_mv: actual reference voltage used
*/
struct ad5446_state {
struct spi_device *spi;
const struct ad5446_chip_info *chip_info;
struct regulator *reg;
unsigned short vref_mv;
unsigned cached_val;
unsigned pwr_down_mode;
unsigned pwr_down;
};
/**
* struct ad5446_chip_info - chip specific information
* @channel: channel spec for the DAC
* @int_vref_mv: AD5620/40/60: the internal reference voltage
* @write: chip specific helper function to write to the register
*/
struct ad5446_chip_info {
struct iio_chan_spec channel;
u16 int_vref_mv;
int (*write)(struct ad5446_state *st, unsigned val);
};
/**
* ad5446_supported_device_ids:
* The AD5620/40/60 parts are available in different fixed internal reference
* voltage options. The actual part numbers may look differently
* (and a bit cryptic), however this style is used to make clear which
* parts are supported here.
*/
enum ad5446_supported_device_ids {
ID_AD5444,
ID_AD5446,
ID_AD5450,
ID_AD5451,
ID_AD5541A,
ID_AD5512A,
ID_AD5553,
ID_AD5601,
ID_AD5611,
ID_AD5621,
ID_AD5620_2500,
ID_AD5620_1250,
ID_AD5640_2500,
ID_AD5640_1250,
ID_AD5660_2500,
ID_AD5660_1250,
ID_AD5662,
};
#endif /* IIO_DAC_AD5446_H_ */

View File

@ -422,7 +422,7 @@ ssize_t iio_buffer_store_enable(struct device *dev,
ret = indio_dev->setup_ops->preenable(indio_dev);
if (ret) {
printk(KERN_ERR
"Buffer not started:"
"Buffer not started: "
"buffer preenable failed\n");
goto error_ret;
}
@ -431,12 +431,12 @@ ssize_t iio_buffer_store_enable(struct device *dev,
ret = buffer->access->request_update(buffer);
if (ret) {
printk(KERN_INFO
"Buffer not started:"
"Buffer not started: "
"buffer parameter update failed\n");
goto error_ret;
}
}
/* Definitely possible for devices to support both of these.*/
/* Definitely possible for devices to support both of these. */
if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
if (!indio_dev->trig) {
printk(KERN_INFO
@ -456,7 +456,7 @@ ssize_t iio_buffer_store_enable(struct device *dev,
ret = indio_dev->setup_ops->postenable(indio_dev);
if (ret) {
printk(KERN_INFO
"Buffer not started:"
"Buffer not started: "
"postenable failed\n");
indio_dev->currentmode = previous_mode;
if (indio_dev->setup_ops->postdisable)
@ -657,7 +657,7 @@ EXPORT_SYMBOL_GPL(iio_scan_mask_query);
/**
* struct iio_demux_table() - table describing demux memcpy ops
* @from: index to copy from
* @to: index to copy to
* @to: index to copy to
* @length: how many bytes to copy
* @l: list head used for management
*/

View File

@ -29,7 +29,7 @@
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
/* IDA to assign each registered device a unique id*/
/* IDA to assign each registered device a unique id */
static DEFINE_IDA(iio_ida);
static dev_t iio_devt;
@ -729,7 +729,7 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
attrcount = attrcount_orig;
/*
* New channel registration method - relies on the fact a group does
* not need to be initialized if it is name is NULL.
* not need to be initialized if its name is NULL.
*/
if (indio_dev->channels)
for (i = 0; i < indio_dev->num_channels; i++) {
@ -980,6 +980,6 @@ EXPORT_SYMBOL(iio_device_unregister);
subsys_initcall(iio_init);
module_exit(iio_exit);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("Industrial I/O core");
MODULE_LICENSE("GPL");

View File

@ -239,8 +239,10 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val)
goto err_unlock;
}
ret = chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel,
val, &val2, 0);
ret = chan->indio_dev->info->read_raw(chan->indio_dev,
chan->channel,
val, &val2,
IIO_CHAN_INFO_RAW);
err_unlock:
mutex_unlock(&chan->indio_dev->info_exist_lock);

View File

@ -6,6 +6,7 @@
#include <linux/kfifo.h>
#include <linux/mutex.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/sched.h>
struct iio_kfifo {
struct iio_buffer buffer;
@ -22,7 +23,8 @@ static inline int __iio_allocate_kfifo(struct iio_kfifo *buf,
return -EINVAL;
__iio_update_buffer(&buf->buffer, bytes_per_datum, length);
return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL);
return __kfifo_alloc((struct __kfifo *)&buf->kf, length,
bytes_per_datum, GFP_KERNEL);
}
static int iio_request_update_kfifo(struct iio_buffer *r)
@ -35,6 +37,7 @@ static int iio_request_update_kfifo(struct iio_buffer *r)
kfifo_free(&buf->kf);
ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
buf->buffer.length);
r->stufftoread = false;
error_ret:
return ret;
}
@ -81,6 +84,9 @@ static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd)
static int iio_set_length_kfifo(struct iio_buffer *r, int length)
{
/* Avoid an invalid state */
if (length < 2)
length = 2;
if (r->length != length) {
r->length = length;
iio_mark_update_needed_kfifo(r);
@ -94,9 +100,12 @@ static int iio_store_to_kfifo(struct iio_buffer *r,
{
int ret;
struct iio_kfifo *kf = iio_to_kfifo(r);
ret = kfifo_in(&kf->kf, data, r->bytes_per_datum);
if (ret != r->bytes_per_datum)
ret = kfifo_in(&kf->kf, data, 1);
if (ret != 1)
return -EBUSY;
r->stufftoread = true;
wake_up_interruptible(&r->pollq);
return 0;
}
@ -106,11 +115,18 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r,
int ret, copied;
struct iio_kfifo *kf = iio_to_kfifo(r);
if (n < r->bytes_per_datum)
if (n < r->bytes_per_datum || r->bytes_per_datum == 0)
return -EINVAL;
n = rounddown(n, r->bytes_per_datum);
ret = kfifo_to_user(&kf->kf, buf, n, &copied);
if (ret < 0)
return ret;
if (kfifo_is_empty(&kf->kf))
r->stufftoread = false;
/* verify it is still empty to avoid race */
if (!kfifo_is_empty(&kf->kf))
r->stufftoread = true;
return copied;
}
@ -136,7 +152,7 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
iio_buffer_init(&kf->buffer);
kf->buffer.attrs = &iio_kfifo_attribute_group;
kf->buffer.access = &kfifo_access_funcs;
kf->buffer.length = 2;
return &kf->buffer;
}
EXPORT_SYMBOL(iio_kfifo_allocate);

View File

@ -1,5 +1,5 @@
#
# Industrial I/O subsytem configuration
# Industrial I/O subsystem configuration
#
menu "IIO staging drivers"
depends on IIO

View File

@ -69,5 +69,5 @@ Documentation
1) Lots of cleanup and expansion.
2) Some device require individual docs.
Contact: Jonathan Cameron <jic23@cam.ac.uk>.
Contact: Jonathan Cameron <jic23@kernel.org>.
Mailing list: linux-iio@vger.kernel.org

View File

@ -565,7 +565,7 @@ static int __devinit adis16201_probe(struct spi_device *spi)
return ret;
}
static int adis16201_remove(struct spi_device *spi)
static int __devexit adis16201_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -500,7 +500,7 @@ static int __devinit adis16203_probe(struct spi_device *spi)
return ret;
}
static int adis16203_remove(struct spi_device *spi)
static int __devexit adis16203_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -558,7 +558,7 @@ static int __devinit adis16204_probe(struct spi_device *spi)
return ret;
}
static int adis16204_remove(struct spi_device *spi)
static int __devexit adis16204_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -573,7 +573,7 @@ static int __devinit adis16209_probe(struct spi_device *spi)
return ret;
}
static int adis16209_remove(struct spi_device *spi)
static int __devexit adis16209_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -663,7 +663,7 @@ static int __devinit adis16220_probe(struct spi_device *spi)
return ret;
}
static int adis16220_remove(struct spi_device *spi)
static int __devexit adis16220_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -619,7 +619,7 @@ static int __devinit adis16240_probe(struct spi_device *spi)
return ret;
}
static int adis16240_remove(struct spi_device *spi)
static int __devexit adis16240_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -2,7 +2,7 @@
* kxsd9.c simple support for the Kionix KXSD9 3D
* accelerometer.
*
* Copyright (c) 2008-2009 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2008-2009 Jonathan Cameron <jic23@kernel.org>
*
* 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
@ -286,6 +286,6 @@ static struct spi_driver kxsd9_driver = {
};
module_spi_driver(kxsd9_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("Kionix KXSD9 SPI driver");
MODULE_LICENSE("GPL v2");

View File

@ -2,7 +2,7 @@
* LISL02DQ.h -- support STMicroelectronics LISD02DQ
* 3d 2g Linear Accelerometers via SPI
*
* Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
*
* Loosely based upon tle62x0.c
*
@ -28,7 +28,7 @@
/* Control Register (1 of 2) */
#define LIS3L02DQ_REG_CTRL_1_ADDR 0x20
/* Power ctrl - either bit set corresponds to on*/
#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0
#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0
/* Decimation Factor */
#define LIS3L02DQ_DEC_MASK 0x30
@ -73,14 +73,14 @@
/* Interrupt related stuff */
#define LIS3L02DQ_REG_WAKE_UP_CFG_ADDR 0x23
/* Switch from or combination fo conditions to and */
/* Switch from or combination of conditions to and */
#define LIS3L02DQ_REG_WAKE_UP_CFG_BOOLEAN_AND 0x80
/* Latch interrupt request,
* if on ack must be given by reading the ack register */
#define LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC 0x40
/* Z Interrupt on High (above threshold)*/
/* Z Interrupt on High (above threshold) */
#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH 0x20
/* Z Interrupt on Low */
#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW 0x10
@ -117,13 +117,13 @@
#define LIS3L02DQ_REG_STATUS_Y_OVERRUN 0x20
#define LIS3L02DQ_REG_STATUS_X_OVERRUN 0x10
/* XYZ new data available - first is all 3 available? */
#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08
#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08
#define LIS3L02DQ_REG_STATUS_Z_NEW_DATA 0x04
#define LIS3L02DQ_REG_STATUS_Y_NEW_DATA 0x02
#define LIS3L02DQ_REG_STATUS_X_NEW_DATA 0x01
/* The accelerometer readings - low and high bytes.
Form of high byte dependent on justification set in ctrl reg */
* Form of high byte dependent on justification set in ctrl reg */
#define LIS3L02DQ_REG_OUT_X_L_ADDR 0x28
#define LIS3L02DQ_REG_OUT_X_H_ADDR 0x29
#define LIS3L02DQ_REG_OUT_Y_L_ADDR 0x2A
@ -150,9 +150,9 @@ Form of high byte dependent on justification set in ctrl reg */
* struct lis3l02dq_state - device instance specific data
* @us: actual spi_device
* @trig: data ready trigger registered with iio
* @buf_lock: mutex to protect tx and rx
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct lis3l02dq_state {
struct spi_device *us;

View File

@ -2,7 +2,7 @@
* lis3l02dq.c support STMicroelectronics LISD02DQ
* 3d 2g Linear Accelerometers via SPI
*
* Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
*
* 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
@ -392,7 +392,7 @@ static int lis3l02dq_initial_setup(struct iio_dev *indio_dev)
dev_err(&st->us->dev, "problem with setup control register 1");
goto err_ret;
}
/* Repeat as sometimes doesn't work first time?*/
/* Repeat as sometimes doesn't work first time? */
ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_1_ADDR,
val);
@ -686,7 +686,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
goto error_ret;
}
st = iio_priv(indio_dev);
/* this is only used tor removal purposes */
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
st->us = spi;
@ -780,7 +780,7 @@ static int lis3l02dq_stop_device(struct iio_dev *indio_dev)
}
/* fixme, confirm ordering in this function */
static int lis3l02dq_remove(struct spi_device *spi)
static int __devexit lis3l02dq_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);
@ -818,7 +818,7 @@ static struct spi_driver lis3l02dq_driver = {
};
module_spi_driver(lis3l02dq_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("ST LIS3L02DQ Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:lis3l02dq");

View File

@ -14,7 +14,7 @@
#include "lis3l02dq.h"
/**
* combine_8_to_16() utility function to munge to u8s into u16
* combine_8_to_16() utility function to munge two u8s into u16
**/
static inline u16 combine_8_to_16(u8 lower, u8 upper)
{
@ -49,7 +49,7 @@ static const u8 read_all_tx_array[] = {
/**
* lis3l02dq_read_all() Reads all channels currently selected
* @st: device specific state
* @indio_dev: IIO device state
* @rx_array: (dma capable) receive array, must be at least
* 4*number of channels
**/
@ -170,22 +170,22 @@ __lis3l02dq_write_data_ready_config(struct iio_dev *indio_dev, bool state)
bool currentlyset;
struct lis3l02dq_state *st = iio_priv(indio_dev);
/* Get the current event mask register */
/* Get the current event mask register */
ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_2_ADDR,
&valold);
if (ret)
goto error_ret;
/* Find out if data ready is already on */
/* Find out if data ready is already on */
currentlyset
= valold & LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION;
/* Disable requested */
/* Disable requested */
if (!state && currentlyset) {
/* disable the data ready signal */
/* Disable the data ready signal */
valold &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION;
/* The double write is to overcome a hardware bug?*/
/* The double write is to overcome a hardware bug? */
ret = lis3l02dq_spi_write_reg_8(indio_dev,
LIS3L02DQ_REG_CTRL_2_ADDR,
valold);
@ -197,10 +197,10 @@ __lis3l02dq_write_data_ready_config(struct iio_dev *indio_dev, bool state)
if (ret)
goto error_ret;
st->trigger_on = false;
/* Enable requested */
/* Enable requested */
} else if (state && !currentlyset) {
/* if not set, enable requested */
/* first disable all events */
/* If not set, enable requested
* first disable all events */
ret = lis3l02dq_disable_all_events(indio_dev);
if (ret < 0)
goto error_ret;
@ -239,7 +239,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
if (state == false) {
/*
* A possible quirk with the handler is currently worked around
* by ensuring outstanding read events are cleared.
* by ensuring outstanding read events are cleared.
*/
ret = lis3l02dq_read_all(indio_dev, NULL);
}
@ -250,7 +250,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
}
/**
* lis3l02dq_trig_try_reen() try renabling irq for data rdy trigger
* lis3l02dq_trig_try_reen() try reenabling irq for data rdy trigger
* @trig: the datardy trigger
*/
static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
@ -259,8 +259,8 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
struct lis3l02dq_state *st = iio_priv(indio_dev);
int i;
/* If gpio still high (or high again) */
/* In theory possible we will need to do this several times */
/* If gpio still high (or high again)
* In theory possible we will need to do this several times */
for (i = 0; i < 5; i++)
if (gpio_get_value(irq_to_gpio(st->us->irq)))
lis3l02dq_read_all(indio_dev, NULL);

View File

@ -2,7 +2,7 @@
* sca3000.c -- support VTI sca3000 series accelerometers
* via SPI
*
* Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
*
* Partly based upon tle62x0.c
*

View File

@ -5,7 +5,7 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* Copyright (c) 2009 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org>
*
* See industrialio/accels/sca3000.h for comments.
*/
@ -1233,7 +1233,7 @@ static int sca3000_stop_all_interrupts(struct sca3000_state *st)
return ret;
}
static int sca3000_remove(struct spi_device *spi)
static int __devexit sca3000_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct sca3000_state *st = iio_priv(indio_dev);
@ -1272,6 +1272,6 @@ static struct spi_driver sca3000_driver = {
};
module_spi_driver(sca3000_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver");
MODULE_LICENSE("GPL v2");

View File

@ -5,7 +5,7 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* Copyright (c) 2009 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org>
*
*/

View File

@ -99,6 +99,7 @@ config AD7780
tristate "Analog Devices AD7780 AD7781 ADC driver"
depends on SPI
depends on GPIOLIB
select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices
AD7780 and AD7781 SPI analog to digital converters (ADC).
@ -108,13 +109,12 @@ config AD7780
module will be called ad7780.
config AD7793
tristate "Analog Devices AD7792 AD7793 ADC driver"
tristate "Analog Devices AD7793 and similar ADCs driver"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices
AD7792 and AD7793 SPI analog to digital converters (ADC).
Say yes here to build support for Analog Devices AD7785, AD7792, AD7793,
AD7794 and AD7795 SPI analog to digital converters (ADC).
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
@ -131,8 +131,7 @@ config AD7816
config AD7192
tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices AD7190,
AD7192 or AD7195 SPI analog to digital converters (ADC).

View File

@ -23,6 +23,7 @@
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/adc/ad_sigma_delta.h>
#include "ad7192.h"
@ -57,6 +58,7 @@
/* Mode Register Bit Designations (AD7192_REG_MODE) */
#define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */
#define AD7192_MODE_SEL_MASK (0x7 << 21) /* Operation Mode Select Mask */
#define AD7192_MODE_DAT_STA (1 << 20) /* Status Register transmission */
#define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */
#define AD7192_MODE_SINC3 (1 << 15) /* SINC3 Filter Select */
@ -91,7 +93,8 @@
#define AD7192_CONF_CHOP (1 << 23) /* CHOP enable */
#define AD7192_CONF_REFSEL (1 << 20) /* REFIN1/REFIN2 Reference Select */
#define AD7192_CONF_CHAN(x) (((x) & 0xFF) << 8) /* Channel select */
#define AD7192_CONF_CHAN(x) (((1 << (x)) & 0xFF) << 8) /* Channel select */
#define AD7192_CONF_CHAN_MASK (0xFF << 8) /* Channel select mask */
#define AD7192_CONF_BURN (1 << 7) /* Burnout current enable */
#define AD7192_CONF_REFDET (1 << 6) /* Reference detect enable */
#define AD7192_CONF_BUF (1 << 4) /* Buffered Mode Enable */
@ -133,13 +136,7 @@
*/
struct ad7192_state {
struct spi_device *spi;
struct iio_trigger *trig;
struct regulator *reg;
struct ad7192_platform_data *pdata;
wait_queue_head_t wq_data_avail;
bool done;
bool irq_dis;
u16 int_vref_mv;
u32 mclk;
u32 f_order;
@ -148,178 +145,45 @@ struct ad7192_state {
u32 scale_avail[8][2];
u8 gpocon;
u8 devid;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
u8 data[4] ____cacheline_aligned;
struct ad_sigma_delta sd;
};
static int __ad7192_write_reg(struct ad7192_state *st, bool locked,
bool cs_change, unsigned char reg,
unsigned size, unsigned val)
static struct ad7192_state *ad_sigma_delta_to_ad7192(struct ad_sigma_delta *sd)
{
u8 *data = st->data;
struct spi_transfer t = {
.tx_buf = data,
.len = size + 1,
.cs_change = cs_change,
};
struct spi_message m;
data[0] = AD7192_COMM_WRITE | AD7192_COMM_ADDR(reg);
switch (size) {
case 3:
data[1] = val >> 16;
data[2] = val >> 8;
data[3] = val;
break;
case 2:
data[1] = val >> 8;
data[2] = val;
break;
case 1:
data[1] = val;
break;
default:
return -EINVAL;
}
spi_message_init(&m);
spi_message_add_tail(&t, &m);
if (locked)
return spi_sync_locked(st->spi, &m);
else
return spi_sync(st->spi, &m);
return container_of(sd, struct ad7192_state, sd);
}
static int ad7192_write_reg(struct ad7192_state *st,
unsigned reg, unsigned size, unsigned val)
static int ad7192_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
{
return __ad7192_write_reg(st, false, false, reg, size, val);
struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
st->conf &= ~AD7192_CONF_CHAN_MASK;
st->conf |= AD7192_CONF_CHAN(channel);
return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
}
static int __ad7192_read_reg(struct ad7192_state *st, bool locked,
bool cs_change, unsigned char reg,
int *val, unsigned size)
static int ad7192_set_mode(struct ad_sigma_delta *sd,
enum ad_sigma_delta_mode mode)
{
u8 *data = st->data;
int ret;
struct spi_transfer t[] = {
{
.tx_buf = data,
.len = 1,
}, {
.rx_buf = data,
.len = size,
.cs_change = cs_change,
},
};
struct spi_message m;
struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
data[0] = AD7192_COMM_READ | AD7192_COMM_ADDR(reg);
st->mode &= ~AD7192_MODE_SEL_MASK;
st->mode |= AD7192_MODE_SEL(mode);
spi_message_init(&m);
spi_message_add_tail(&t[0], &m);
spi_message_add_tail(&t[1], &m);
if (locked)
ret = spi_sync_locked(st->spi, &m);
else
ret = spi_sync(st->spi, &m);
if (ret < 0)
return ret;
switch (size) {
case 3:
*val = data[0] << 16 | data[1] << 8 | data[2];
break;
case 2:
*val = data[0] << 8 | data[1];
break;
case 1:
*val = data[0];
break;
default:
return -EINVAL;
}
return 0;
return ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
}
static int ad7192_read_reg(struct ad7192_state *st,
unsigned reg, int *val, unsigned size)
{
return __ad7192_read_reg(st, 0, 0, reg, val, size);
}
static const struct ad_sigma_delta_info ad7192_sigma_delta_info = {
.set_channel = ad7192_set_channel,
.set_mode = ad7192_set_mode,
.has_registers = true,
.addr_shift = 3,
.read_mask = BIT(6),
};
static int ad7192_read(struct ad7192_state *st, unsigned ch,
unsigned len, int *val)
{
int ret;
st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
AD7192_CONF_CHAN(1 << ch);
st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
AD7192_MODE_SEL(AD7192_MODE_SINGLE);
ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
spi_bus_lock(st->spi->master);
st->done = false;
ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode);
if (ret < 0)
goto out;
st->irq_dis = false;
enable_irq(st->spi->irq);
wait_event_interruptible(st->wq_data_avail, st->done);
ret = __ad7192_read_reg(st, 1, 0, AD7192_REG_DATA, val, len);
out:
spi_bus_unlock(st->spi->master);
return ret;
}
static int ad7192_calibrate(struct ad7192_state *st, unsigned mode, unsigned ch)
{
int ret;
st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
AD7192_CONF_CHAN(1 << ch);
st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | AD7192_MODE_SEL(mode);
ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
spi_bus_lock(st->spi->master);
st->done = false;
ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3,
(st->devid != ID_AD7195) ?
st->mode | AD7192_MODE_CLKDIV :
st->mode);
if (ret < 0)
goto out;
st->irq_dis = false;
enable_irq(st->spi->irq);
wait_event_interruptible(st->wq_data_avail, st->done);
st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
AD7192_MODE_SEL(AD7192_MODE_IDLE);
ret = __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode);
out:
spi_bus_unlock(st->spi->master);
return ret;
}
static const u8 ad7192_calib_arr[8][2] = {
static const struct ad_sd_calib_data ad7192_calib_arr[8] = {
{AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1},
{AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1},
{AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN2},
@ -332,45 +196,34 @@ static const u8 ad7192_calib_arr[8][2] = {
static int ad7192_calibrate_all(struct ad7192_state *st)
{
int i, ret;
for (i = 0; i < ARRAY_SIZE(ad7192_calib_arr); i++) {
ret = ad7192_calibrate(st, ad7192_calib_arr[i][0],
ad7192_calib_arr[i][1]);
if (ret)
goto out;
}
return 0;
out:
dev_err(&st->spi->dev, "Calibration failed\n");
return ret;
return ad_sd_calibrate_all(&st->sd, ad7192_calib_arr,
ARRAY_SIZE(ad7192_calib_arr));
}
static int ad7192_setup(struct ad7192_state *st)
static int ad7192_setup(struct ad7192_state *st,
const struct ad7192_platform_data *pdata)
{
struct iio_dev *indio_dev = spi_get_drvdata(st->spi);
struct ad7192_platform_data *pdata = st->pdata;
struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi);
unsigned long long scale_uv;
int i, ret, id;
u8 ones[6];
/* reset the serial interface */
memset(&ones, 0xFF, 6);
ret = spi_write(st->spi, &ones, 6);
ret = spi_write(st->sd.spi, &ones, 6);
if (ret < 0)
goto out;
msleep(1); /* Wait for at least 500us */
/* write/read test for device presence */
ret = ad7192_read_reg(st, AD7192_REG_ID, &id, 1);
ret = ad_sd_read_reg(&st->sd, AD7192_REG_ID, 1, &id);
if (ret)
goto out;
id &= AD7192_ID_MASK;
if (id != st->devid)
dev_warn(&st->spi->dev, "device ID query failed (0x%X)\n", id);
dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n", id);
switch (pdata->clock_source_sel) {
case AD7192_CLK_EXT_MCLK1_2:
@ -423,11 +276,11 @@ static int ad7192_setup(struct ad7192_state *st)
if (pdata->burnout_curr_en)
st->conf |= AD7192_CONF_BURN;
ret = ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
if (ret)
goto out;
ret = ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
if (ret)
goto out;
@ -448,181 +301,10 @@ static int ad7192_setup(struct ad7192_state *st)
return 0;
out:
dev_err(&st->spi->dev, "setup failed\n");
dev_err(&st->sd.spi->dev, "setup failed\n");
return ret;
}
static int ad7192_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
unsigned channel;
int ret;
if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
ret = iio_sw_buffer_preenable(indio_dev);
if (ret < 0)
return ret;
channel = find_first_bit(indio_dev->active_scan_mask,
indio_dev->masklength);
st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
AD7192_MODE_SEL(AD7192_MODE_CONT);
st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
AD7192_CONF_CHAN(1 << indio_dev->channels[channel].address);
ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
spi_bus_lock(st->spi->master);
__ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode);
st->irq_dis = false;
enable_irq(st->spi->irq);
return 0;
}
static int ad7192_ring_postdisable(struct iio_dev *indio_dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
AD7192_MODE_SEL(AD7192_MODE_IDLE);
st->done = false;
wait_event_interruptible(st->wq_data_avail, st->done);
if (!st->irq_dis)
disable_irq_nosync(st->spi->irq);
__ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode);
return spi_bus_unlock(st->spi->master);
}
/**
* ad7192_trigger_handler() bh of trigger launched polling to ring buffer
**/
static irqreturn_t ad7192_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct iio_buffer *ring = indio_dev->buffer;
struct ad7192_state *st = iio_priv(indio_dev);
s64 dat64[2];
s32 *dat32 = (s32 *)dat64;
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
__ad7192_read_reg(st, 1, 1, AD7192_REG_DATA,
dat32,
indio_dev->channels[0].scan_type.realbits/8);
/* Guaranteed to be aligned with 8 byte boundary */
if (indio_dev->scan_timestamp)
dat64[1] = pf->timestamp;
ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
st->irq_dis = false;
enable_irq(st->spi->irq);
return IRQ_HANDLED;
}
static const struct iio_buffer_setup_ops ad7192_ring_setup_ops = {
.preenable = &ad7192_ring_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
.postdisable = &ad7192_ring_postdisable,
.validate_scan_mask = &iio_validate_scan_mask_onehot,
};
static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
&ad7192_trigger_handler, &ad7192_ring_setup_ops);
}
static void ad7192_ring_cleanup(struct iio_dev *indio_dev)
{
iio_triggered_buffer_cleanup(indio_dev);
}
/**
* ad7192_data_rdy_trig_poll() the event handler for the data rdy trig
**/
static irqreturn_t ad7192_data_rdy_trig_poll(int irq, void *private)
{
struct ad7192_state *st = iio_priv(private);
st->done = true;
wake_up_interruptible(&st->wq_data_avail);
disable_irq_nosync(irq);
st->irq_dis = true;
iio_trigger_poll(st->trig, iio_get_time_ns());
return IRQ_HANDLED;
}
static struct iio_trigger_ops ad7192_trigger_ops = {
.owner = THIS_MODULE,
};
static int ad7192_probe_trigger(struct iio_dev *indio_dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
int ret;
st->trig = iio_trigger_alloc("%s-dev%d",
spi_get_device_id(st->spi)->name,
indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
}
st->trig->ops = &ad7192_trigger_ops;
ret = request_irq(st->spi->irq,
ad7192_data_rdy_trig_poll,
IRQF_TRIGGER_LOW,
spi_get_device_id(st->spi)->name,
indio_dev);
if (ret)
goto error_free_trig;
disable_irq_nosync(st->spi->irq);
st->irq_dis = true;
st->trig->dev.parent = &st->spi->dev;
st->trig->private_data = indio_dev;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(st->spi->irq, indio_dev);
error_free_trig:
iio_trigger_free(st->trig);
error_ret:
return ret;
}
static void ad7192_remove_trigger(struct iio_dev *indio_dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
iio_trigger_unregister(st->trig);
free_irq(st->spi->irq, indio_dev);
iio_trigger_free(st->trig);
}
static ssize_t ad7192_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
@ -662,7 +344,7 @@ static ssize_t ad7192_write_frequency(struct device *dev,
st->mode &= ~AD7192_MODE_RATE(-1);
st->mode |= AD7192_MODE_RATE(div);
ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
out:
mutex_unlock(&indio_dev->mlock);
@ -674,7 +356,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ad7192_read_frequency,
ad7192_write_frequency);
static ssize_t ad7192_show_scale_available(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -746,7 +427,7 @@ static ssize_t ad7192_set(struct device *dev,
else
st->gpocon &= ~AD7192_GPOCON_BPDSW;
ad7192_write_reg(st, AD7192_REG_GPOCON, 1, st->gpocon);
ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon);
break;
case AD7192_REG_MODE:
if (val)
@ -754,7 +435,7 @@ static ssize_t ad7192_set(struct device *dev,
else
st->mode &= ~AD7192_MODE_ACX;
ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
break;
default:
ret = -EINVAL;
@ -810,27 +491,11 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7192_state *st = iio_priv(indio_dev);
int ret, smpl = 0;
bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR);
switch (m) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
else
ret = ad7192_read(st, chan->address,
chan->scan_type.realbits / 8, &smpl);
mutex_unlock(&indio_dev->mlock);
if (ret < 0)
return ret;
*val = (smpl >> chan->scan_type.shift) &
((1 << (chan->scan_type.realbits)) - 1);
return IIO_VAL_INT;
return ad_sigma_delta_single_conversion(indio_dev, chan, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
@ -881,16 +546,16 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
if (val2 == st->scale_avail[i][1]) {
ret = 0;
tmp = st->conf;
st->conf &= ~AD7192_CONF_GAIN(-1);
st->conf |= AD7192_CONF_GAIN(i);
if (tmp != st->conf) {
ad7192_write_reg(st, AD7192_REG_CONF,
3, st->conf);
ad7192_calibrate_all(st);
}
ret = 0;
if (tmp == st->conf)
break;
ad_sd_write_reg(&st->sd, AD7192_REG_CONF,
3, st->conf);
ad7192_calibrate_all(st);
break;
}
break;
default:
@ -902,15 +567,6 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
return ret;
}
static int ad7192_validate_trigger(struct iio_dev *indio_dev,
struct iio_trigger *trig)
{
if (indio_dev->trig != trig)
return -EINVAL;
return 0;
}
static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask)
@ -923,7 +579,7 @@ static const struct iio_info ad7192_info = {
.write_raw = &ad7192_write_raw,
.write_raw_get_fmt = &ad7192_write_raw_get_fmt,
.attrs = &ad7192_attribute_group,
.validate_trigger = ad7192_validate_trigger,
.validate_trigger = ad_sd_validate_trigger,
.driver_module = THIS_MODULE,
};
@ -932,60 +588,25 @@ static const struct iio_info ad7195_info = {
.write_raw = &ad7192_write_raw,
.write_raw_get_fmt = &ad7192_write_raw_get_fmt,
.attrs = &ad7195_attribute_group,
.validate_trigger = ad7192_validate_trigger,
.validate_trigger = ad_sd_validate_trigger,
.driver_module = THIS_MODULE,
};
#define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \
{ .type = IIO_VOLTAGE, \
.differential = 1, \
.indexed = 1, \
.extend_name = _name, \
.channel = _chan, \
.channel2 = _chan2, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('u', 24, 32, 0)}
#define AD7192_CHAN(_chan, _address, _si) \
{ .type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _chan, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('u', 24, 32, 0)}
#define AD7192_CHAN_TEMP(_chan, _address, _si) \
{ .type = IIO_TEMP, \
.indexed = 1, \
.channel = _chan, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('u', 24, 32, 0)}
static const struct iio_chan_spec ad7192_channels[] = {
AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0),
AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1),
AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2),
AD7192_CHAN_DIFF(2, 2, "shorted", AD7192_CH_AIN2P_AIN2M, 3),
AD7192_CHAN(1, AD7192_CH_AIN1, 4),
AD7192_CHAN(2, AD7192_CH_AIN2, 5),
AD7192_CHAN(3, AD7192_CH_AIN3, 6),
AD7192_CHAN(4, AD7192_CH_AIN4, 7),
AD_SD_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M, 24, 32, 0),
AD_SD_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M, 24, 32, 0),
AD_SD_TEMP_CHANNEL(2, AD7192_CH_TEMP, 24, 32, 0),
AD_SD_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M, 24, 32, 0),
AD_SD_CHANNEL(4, 1, AD7192_CH_AIN1, 24, 32, 0),
AD_SD_CHANNEL(5, 2, AD7192_CH_AIN2, 24, 32, 0),
AD_SD_CHANNEL(6, 3, AD7192_CH_AIN3, 24, 32, 0),
AD_SD_CHANNEL(7, 4, AD7192_CH_AIN4, 24, 32, 0),
IIO_CHAN_SOFT_TIMESTAMP(8),
};
static int __devinit ad7192_probe(struct spi_device *spi)
{
struct ad7192_platform_data *pdata = spi->dev.platform_data;
const struct ad7192_platform_data *pdata = spi->dev.platform_data;
struct ad7192_state *st;
struct iio_dev *indio_dev;
int ret , voltage_uv = 0;
@ -1015,8 +636,6 @@ static int __devinit ad7192_probe(struct spi_device *spi)
voltage_uv = regulator_get_voltage(st->reg);
}
st->pdata = pdata;
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
else if (voltage_uv)
@ -1025,7 +644,6 @@ static int __devinit ad7192_probe(struct spi_device *spi)
dev_warn(&spi->dev, "reference voltage undefined\n");
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->devid = spi_get_device_id(spi)->driver_data;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
@ -1037,17 +655,13 @@ static int __devinit ad7192_probe(struct spi_device *spi)
else
indio_dev->info = &ad7192_info;
init_waitqueue_head(&st->wq_data_avail);
ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info);
ret = ad7192_register_ring_funcs_and_init(indio_dev);
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
if (ret)
goto error_disable_reg;
ret = ad7192_probe_trigger(indio_dev);
if (ret)
goto error_ring_cleanup;
ret = ad7192_setup(st);
ret = ad7192_setup(st, pdata);
if (ret)
goto error_remove_trigger;
@ -1057,9 +671,7 @@ static int __devinit ad7192_probe(struct spi_device *spi)
return 0;
error_remove_trigger:
ad7192_remove_trigger(indio_dev);
error_ring_cleanup:
ad7192_ring_cleanup(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
@ -1072,14 +684,13 @@ static int __devinit ad7192_probe(struct spi_device *spi)
return ret;
}
static int ad7192_remove(struct spi_device *spi)
static int __devexit ad7192_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7192_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
ad7192_remove_trigger(indio_dev);
ad7192_ring_cleanup(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);

View File

@ -196,7 +196,7 @@ static int __devinit ad7476_probe(struct spi_device *spi)
return ret;
}
static int ad7476_remove(struct spi_device *spi)
static int __devexit ad7476_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7476_state *st = iio_priv(indio_dev);

View File

@ -20,6 +20,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/adc/ad_sigma_delta.h>
#include "ad7780.h"
@ -37,20 +38,13 @@ struct ad7780_chip_info {
};
struct ad7780_state {
struct spi_device *spi;
const struct ad7780_chip_info *chip_info;
struct regulator *reg;
struct ad7780_platform_data *pdata;
wait_queue_head_t wq_data_avail;
bool done;
int powerdown_gpio;
unsigned int gain;
u16 int_vref_mv;
struct spi_transfer xfer;
struct spi_message msg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
unsigned int data ____cacheline_aligned;
struct ad_sigma_delta sd;
};
enum ad7780_supported_device_ids {
@ -58,28 +52,30 @@ enum ad7780_supported_device_ids {
ID_AD7781,
};
static int ad7780_read(struct ad7780_state *st, int *val)
static struct ad7780_state *ad_sigma_delta_to_ad7780(struct ad_sigma_delta *sd)
{
int ret;
return container_of(sd, struct ad7780_state, sd);
}
spi_bus_lock(st->spi->master);
static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
enum ad_sigma_delta_mode mode)
{
struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
unsigned val;
enable_irq(st->spi->irq);
st->done = false;
gpio_set_value(st->pdata->gpio_pdrst, 1);
switch (mode) {
case AD_SD_MODE_SINGLE:
case AD_SD_MODE_CONTINUOUS:
val = 1;
break;
default:
val = 0;
break;
}
ret = wait_event_interruptible(st->wq_data_avail, st->done);
disable_irq_nosync(st->spi->irq);
if (ret)
goto out;
gpio_set_value(st->powerdown_gpio, val);
ret = spi_sync_locked(st->spi, &st->msg);
*val = be32_to_cpu(st->data);
out:
gpio_set_value(st->pdata->gpio_pdrst, 0);
spi_bus_unlock(st->spi->master);
return ret;
return 0;
}
static int ad7780_read_raw(struct iio_dev *indio_dev,
@ -89,87 +85,55 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7780_state *st = iio_priv(indio_dev);
struct iio_chan_spec channel = st->chip_info->channel;
int ret, smpl = 0;
unsigned long scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
ret = ad7780_read(st, &smpl);
mutex_unlock(&indio_dev->mlock);
if (ret < 0)
return ret;
if ((smpl & AD7780_ERR) ||
!((smpl & AD7780_PAT0) && !(smpl & AD7780_PAT1)))
return -EIO;
*val = (smpl >> channel.scan_type.shift) &
((1 << (channel.scan_type.realbits)) - 1);
*val -= (1 << (channel.scan_type.realbits - 1));
if (!(smpl & AD7780_GAIN))
*val *= 128;
return IIO_VAL_INT;
return ad_sigma_delta_single_conversion(indio_dev, chan, val);
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->int_vref_mv * 100000)
>> (channel.scan_type.realbits - 1);
scale_uv = (st->int_vref_mv * 100000 * st->gain)
>> (chan->scan_type.realbits - 1);
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OFFSET:
*val -= (1 << (chan->scan_type.realbits - 1));
return IIO_VAL_INT;
}
return -EINVAL;
}
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7780] = {
.channel = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_type = {
.sign = 'u',
.realbits = 24,
.storagebits = 32,
.shift = 8,
},
},
},
[ID_AD7781] = {
.channel = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_type = {
.sign = 'u',
.realbits = 20,
.storagebits = 32,
.shift = 12,
},
},
},
static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
unsigned int raw_sample)
{
struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
if ((raw_sample & AD7780_ERR) ||
!((raw_sample & AD7780_PAT0) && !(raw_sample & AD7780_PAT1)))
return -EIO;
if (raw_sample & AD7780_GAIN)
st->gain = 1;
else
st->gain = 128;
return 0;
}
static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
.set_mode = ad7780_set_mode,
.postprocess_sample = ad7780_postprocess_sample,
.has_registers = false,
};
/**
* Interrupt handler
*/
static irqreturn_t ad7780_interrupt(int irq, void *dev_id)
{
struct ad7780_state *st = dev_id;
st->done = true;
wake_up_interruptible(&st->wq_data_avail);
return IRQ_HANDLED;
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7780] = {
.channel = AD_SD_CHANNEL(1, 0, 0, 24, 32, 8),
},
[ID_AD7781] = {
.channel = AD_SD_CHANNEL(1, 0, 0, 20, 32, 12),
},
};
static const struct iio_info ad7780_info = {
@ -194,6 +158,9 @@ static int __devinit ad7780_probe(struct spi_device *spi)
return -ENOMEM;
st = iio_priv(indio_dev);
st->gain = 1;
ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
@ -207,7 +174,7 @@ static int __devinit ad7780_probe(struct spi_device *spi)
st->chip_info =
&ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
st->pdata = pdata;
st->powerdown_gpio = pdata->gpio_pdrst;
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
@ -217,7 +184,6 @@ static int __devinit ad7780_probe(struct spi_device *spi)
dev_warn(&spi->dev, "reference voltage unspecified\n");
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
@ -226,40 +192,27 @@ static int __devinit ad7780_probe(struct spi_device *spi)
indio_dev->num_channels = 1;
indio_dev->info = &ad7780_info;
init_waitqueue_head(&st->wq_data_avail);
/* Setup default message */
st->xfer.rx_buf = &st->data;
st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8;
spi_message_init(&st->msg);
spi_message_add_tail(&st->xfer, &st->msg);
ret = gpio_request_one(st->pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
"AD7780 /PDRST");
if (ret) {
dev_err(&spi->dev, "failed to request GPIO PDRST\n");
goto error_disable_reg;
}
ret = request_irq(spi->irq, ad7780_interrupt,
IRQF_TRIGGER_FALLING, spi_get_device_id(spi)->name, st);
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
if (ret)
goto error_free_gpio;
disable_irq(spi->irq);
ret = iio_device_register(indio_dev);
if (ret)
goto error_free_irq;
goto error_cleanup_buffer_and_trigger;
return 0;
error_free_irq:
free_irq(spi->irq, st);
error_cleanup_buffer_and_trigger:
ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_free_gpio:
gpio_free(st->pdata->gpio_pdrst);
gpio_free(pdata->gpio_pdrst);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
@ -272,14 +225,15 @@ static int __devinit ad7780_probe(struct spi_device *spi)
return ret;
}
static int ad7780_remove(struct spi_device *spi)
static int __devexit ad7780_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7780_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
free_irq(spi->irq, st);
gpio_free(st->pdata->gpio_pdrst);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
gpio_free(st->powerdown_gpio);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);

View File

@ -1,5 +1,5 @@
/*
* AD7792/AD7793 SPI ADC driver
* AD7785/AD7792/AD7793/AD7794/AD7795 SPI ADC driver
*
* Copyright 2011-2012 Analog Devices Inc.
*
@ -24,6 +24,7 @@
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/adc/ad_sigma_delta.h>
#include "ad7793.h"
@ -36,198 +37,65 @@
*/
struct ad7793_chip_info {
struct iio_chan_spec channel[7];
const struct iio_chan_spec *channels;
unsigned int num_channels;
};
struct ad7793_state {
struct spi_device *spi;
struct iio_trigger *trig;
const struct ad7793_chip_info *chip_info;
struct regulator *reg;
struct ad7793_platform_data *pdata;
wait_queue_head_t wq_data_avail;
bool done;
bool irq_dis;
u16 int_vref_mv;
u16 mode;
u16 conf;
u32 scale_avail[8][2];
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
u8 data[4] ____cacheline_aligned;
struct ad_sigma_delta sd;
};
enum ad7793_supported_device_ids {
ID_AD7785,
ID_AD7792,
ID_AD7793,
ID_AD7794,
ID_AD7795,
};
static int __ad7793_write_reg(struct ad7793_state *st, bool locked,
bool cs_change, unsigned char reg,
unsigned size, unsigned val)
static struct ad7793_state *ad_sigma_delta_to_ad7793(struct ad_sigma_delta *sd)
{
u8 *data = st->data;
struct spi_transfer t = {
.tx_buf = data,
.len = size + 1,
.cs_change = cs_change,
};
struct spi_message m;
data[0] = AD7793_COMM_WRITE | AD7793_COMM_ADDR(reg);
switch (size) {
case 3:
data[1] = val >> 16;
data[2] = val >> 8;
data[3] = val;
break;
case 2:
data[1] = val >> 8;
data[2] = val;
break;
case 1:
data[1] = val;
break;
default:
return -EINVAL;
}
spi_message_init(&m);
spi_message_add_tail(&t, &m);
if (locked)
return spi_sync_locked(st->spi, &m);
else
return spi_sync(st->spi, &m);
return container_of(sd, struct ad7793_state, sd);
}
static int ad7793_write_reg(struct ad7793_state *st,
unsigned reg, unsigned size, unsigned val)
static int ad7793_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
{
return __ad7793_write_reg(st, false, false, reg, size, val);
struct ad7793_state *st = ad_sigma_delta_to_ad7793(sd);
st->conf &= ~AD7793_CONF_CHAN_MASK;
st->conf |= AD7793_CONF_CHAN(channel);
return ad_sd_write_reg(&st->sd, AD7793_REG_CONF, 2, st->conf);
}
static int __ad7793_read_reg(struct ad7793_state *st, bool locked,
bool cs_change, unsigned char reg,
int *val, unsigned size)
static int ad7793_set_mode(struct ad_sigma_delta *sd,
enum ad_sigma_delta_mode mode)
{
u8 *data = st->data;
int ret;
struct spi_transfer t[] = {
{
.tx_buf = data,
.len = 1,
}, {
.rx_buf = data,
.len = size,
.cs_change = cs_change,
},
};
struct spi_message m;
struct ad7793_state *st = ad_sigma_delta_to_ad7793(sd);
data[0] = AD7793_COMM_READ | AD7793_COMM_ADDR(reg);
st->mode &= ~AD7793_MODE_SEL_MASK;
st->mode |= AD7793_MODE_SEL(mode);
spi_message_init(&m);
spi_message_add_tail(&t[0], &m);
spi_message_add_tail(&t[1], &m);
if (locked)
ret = spi_sync_locked(st->spi, &m);
else
ret = spi_sync(st->spi, &m);
if (ret < 0)
return ret;
switch (size) {
case 3:
*val = data[0] << 16 | data[1] << 8 | data[2];
break;
case 2:
*val = data[0] << 8 | data[1];
break;
case 1:
*val = data[0];
break;
default:
return -EINVAL;
}
return 0;
return ad_sd_write_reg(&st->sd, AD7793_REG_MODE, 2, st->mode);
}
static int ad7793_read_reg(struct ad7793_state *st,
unsigned reg, int *val, unsigned size)
{
return __ad7793_read_reg(st, 0, 0, reg, val, size);
}
static const struct ad_sigma_delta_info ad7793_sigma_delta_info = {
.set_channel = ad7793_set_channel,
.set_mode = ad7793_set_mode,
.has_registers = true,
.addr_shift = 3,
.read_mask = BIT(6),
};
static int ad7793_read(struct ad7793_state *st, unsigned ch,
unsigned len, int *val)
{
int ret;
st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch);
st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
AD7793_MODE_SEL(AD7793_MODE_SINGLE);
ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
spi_bus_lock(st->spi->master);
st->done = false;
ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
if (ret < 0)
goto out;
st->irq_dis = false;
enable_irq(st->spi->irq);
wait_event_interruptible(st->wq_data_avail, st->done);
ret = __ad7793_read_reg(st, 1, 0, AD7793_REG_DATA, val, len);
out:
spi_bus_unlock(st->spi->master);
return ret;
}
static int ad7793_calibrate(struct ad7793_state *st, unsigned mode, unsigned ch)
{
int ret;
st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch);
st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(mode);
ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
spi_bus_lock(st->spi->master);
st->done = false;
ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
if (ret < 0)
goto out;
st->irq_dis = false;
enable_irq(st->spi->irq);
wait_event_interruptible(st->wq_data_avail, st->done);
st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
AD7793_MODE_SEL(AD7793_MODE_IDLE);
ret = __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
out:
spi_bus_unlock(st->spi->master);
return ret;
}
static const u8 ad7793_calib_arr[6][2] = {
static const struct ad_sd_calib_data ad7793_calib_arr[6] = {
{AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN1P_AIN1M},
{AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN1P_AIN1M},
{AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN2P_AIN2M},
@ -238,59 +106,49 @@ static const u8 ad7793_calib_arr[6][2] = {
static int ad7793_calibrate_all(struct ad7793_state *st)
{
int i, ret;
for (i = 0; i < ARRAY_SIZE(ad7793_calib_arr); i++) {
ret = ad7793_calibrate(st, ad7793_calib_arr[i][0],
ad7793_calib_arr[i][1]);
if (ret)
goto out;
}
return 0;
out:
dev_err(&st->spi->dev, "Calibration failed\n");
return ret;
return ad_sd_calibrate_all(&st->sd, ad7793_calib_arr,
ARRAY_SIZE(ad7793_calib_arr));
}
static int ad7793_setup(struct ad7793_state *st)
static int ad7793_setup(struct iio_dev *indio_dev,
const struct ad7793_platform_data *pdata)
{
struct ad7793_state *st = iio_priv(indio_dev);
int i, ret = -1;
unsigned long long scale_uv;
u32 id;
/* reset the serial interface */
ret = spi_write(st->spi, (u8 *)&ret, sizeof(ret));
ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret));
if (ret < 0)
goto out;
msleep(1); /* Wait for at least 500us */
/* write/read test for device presence */
ret = ad7793_read_reg(st, AD7793_REG_ID, &id, 1);
ret = ad_sd_read_reg(&st->sd, AD7793_REG_ID, 1, &id);
if (ret)
goto out;
id &= AD7793_ID_MASK;
if (!((id == AD7792_ID) || (id == AD7793_ID))) {
dev_err(&st->spi->dev, "device ID query failed\n");
if (!((id == AD7792_ID) || (id == AD7793_ID) || (id == AD7795_ID))) {
dev_err(&st->sd.spi->dev, "device ID query failed\n");
goto out;
}
st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) |
AD7793_MODE_SEL(AD7793_MODE_IDLE);
st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1);
st->mode = pdata->mode;
st->conf = pdata->conf;
ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode);
ret = ad7793_set_mode(&st->sd, AD_SD_MODE_IDLE);
if (ret)
goto out;
ret = ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
ret = ad7793_set_channel(&st->sd, 0);
if (ret)
goto out;
ret = ad7793_write_reg(st, AD7793_REG_IO,
sizeof(st->pdata->io), st->pdata->io);
ret = ad_sd_write_reg(&st->sd, AD7793_REG_IO,
sizeof(pdata->io), pdata->io);
if (ret)
goto out;
@ -301,7 +159,7 @@ static int ad7793_setup(struct ad7793_state *st)
/* Populate available ADC input ranges */
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) {
scale_uv = ((u64)st->int_vref_mv * 100000000)
>> (st->chip_info->channel[0].scan_type.realbits -
>> (st->chip_info->channels[0].scan_type.realbits -
(!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1));
scale_uv >>= i;
@ -311,184 +169,10 @@ static int ad7793_setup(struct ad7793_state *st)
return 0;
out:
dev_err(&st->spi->dev, "setup failed\n");
dev_err(&st->sd.spi->dev, "setup failed\n");
return ret;
}
static int ad7793_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7793_state *st = iio_priv(indio_dev);
unsigned channel;
int ret;
if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
ret = iio_sw_buffer_preenable(indio_dev);
if (ret < 0)
return ret;
channel = find_first_bit(indio_dev->active_scan_mask,
indio_dev->masklength);
st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
AD7793_MODE_SEL(AD7793_MODE_CONT);
st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) |
AD7793_CONF_CHAN(indio_dev->channels[channel].address);
ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
spi_bus_lock(st->spi->master);
__ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
st->irq_dis = false;
enable_irq(st->spi->irq);
return 0;
}
static int ad7793_ring_postdisable(struct iio_dev *indio_dev)
{
struct ad7793_state *st = iio_priv(indio_dev);
st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
AD7793_MODE_SEL(AD7793_MODE_IDLE);
st->done = false;
wait_event_interruptible(st->wq_data_avail, st->done);
if (!st->irq_dis)
disable_irq_nosync(st->spi->irq);
__ad7793_write_reg(st, 1, 0, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
return spi_bus_unlock(st->spi->master);
}
/**
* ad7793_trigger_handler() bh of trigger launched polling to ring buffer
**/
static irqreturn_t ad7793_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct iio_buffer *ring = indio_dev->buffer;
struct ad7793_state *st = iio_priv(indio_dev);
s64 dat64[2];
s32 *dat32 = (s32 *)dat64;
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
__ad7793_read_reg(st, 1, 1, AD7793_REG_DATA,
dat32,
indio_dev->channels[0].scan_type.realbits/8);
/* Guaranteed to be aligned with 8 byte boundary */
if (indio_dev->scan_timestamp)
dat64[1] = pf->timestamp;
ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
st->irq_dis = false;
enable_irq(st->spi->irq);
return IRQ_HANDLED;
}
static const struct iio_buffer_setup_ops ad7793_ring_setup_ops = {
.preenable = &ad7793_ring_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
.postdisable = &ad7793_ring_postdisable,
.validate_scan_mask = &iio_validate_scan_mask_onehot,
};
static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
&ad7793_trigger_handler, &ad7793_ring_setup_ops);
}
static void ad7793_ring_cleanup(struct iio_dev *indio_dev)
{
iio_triggered_buffer_cleanup(indio_dev);
}
/**
* ad7793_data_rdy_trig_poll() the event handler for the data rdy trig
**/
static irqreturn_t ad7793_data_rdy_trig_poll(int irq, void *private)
{
struct ad7793_state *st = iio_priv(private);
st->done = true;
wake_up_interruptible(&st->wq_data_avail);
disable_irq_nosync(irq);
st->irq_dis = true;
iio_trigger_poll(st->trig, iio_get_time_ns());
return IRQ_HANDLED;
}
static struct iio_trigger_ops ad7793_trigger_ops = {
.owner = THIS_MODULE,
};
static int ad7793_probe_trigger(struct iio_dev *indio_dev)
{
struct ad7793_state *st = iio_priv(indio_dev);
int ret;
st->trig = iio_trigger_alloc("%s-dev%d",
spi_get_device_id(st->spi)->name,
indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
}
st->trig->ops = &ad7793_trigger_ops;
ret = request_irq(st->spi->irq,
ad7793_data_rdy_trig_poll,
IRQF_TRIGGER_LOW,
spi_get_device_id(st->spi)->name,
indio_dev);
if (ret)
goto error_free_trig;
disable_irq_nosync(st->spi->irq);
st->irq_dis = true;
st->trig->dev.parent = &st->spi->dev;
st->trig->private_data = indio_dev;
ret = iio_trigger_register(st->trig);
/* select default trigger */
indio_dev->trig = st->trig;
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(st->spi->irq, indio_dev);
error_free_trig:
iio_trigger_free(st->trig);
error_ret:
return ret;
}
static void ad7793_remove_trigger(struct iio_dev *indio_dev)
{
struct ad7793_state *st = iio_priv(indio_dev);
iio_trigger_unregister(st->trig);
free_irq(st->spi->irq, indio_dev);
iio_trigger_free(st->trig);
}
static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19,
17, 16, 12, 10, 8, 6, 4};
@ -531,7 +215,7 @@ static ssize_t ad7793_write_frequency(struct device *dev,
mutex_lock(&indio_dev->mlock);
st->mode &= ~AD7793_MODE_RATE(-1);
st->mode |= AD7793_MODE_RATE(i);
ad7793_write_reg(st, AD7793_REG_MODE,
ad_sd_write_reg(&st->sd, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
mutex_unlock(&indio_dev->mlock);
ret = 0;
@ -585,26 +269,16 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7793_state *st = iio_priv(indio_dev);
int ret, smpl = 0;
int ret;
unsigned long long scale_uv;
bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR);
switch (m) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
else
ret = ad7793_read(st, chan->address,
chan->scan_type.realbits / 8, &smpl);
mutex_unlock(&indio_dev->mlock);
ret = ad_sigma_delta_single_conversion(indio_dev, chan, val);
if (ret < 0)
return ret;
*val = (smpl >> chan->scan_type.shift) &
((1 << (chan->scan_type.realbits)) - 1);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@ -675,17 +349,18 @@ static int ad7793_write_raw(struct iio_dev *indio_dev,
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
if (val2 == st->scale_avail[i][1]) {
ret = 0;
tmp = st->conf;
st->conf &= ~AD7793_CONF_GAIN(-1);
st->conf |= AD7793_CONF_GAIN(i);
if (tmp != st->conf) {
ad7793_write_reg(st, AD7793_REG_CONF,
sizeof(st->conf),
st->conf);
ad7793_calibrate_all(st);
}
ret = 0;
if (tmp == st->conf)
break;
ad_sd_write_reg(&st->sd, AD7793_REG_CONF,
sizeof(st->conf), st->conf);
ad7793_calibrate_all(st);
break;
}
break;
default:
@ -696,15 +371,6 @@ static int ad7793_write_raw(struct iio_dev *indio_dev,
return ret;
}
static int ad7793_validate_trigger(struct iio_dev *indio_dev,
struct iio_trigger *trig)
{
if (indio_dev->trig != trig)
return -EINVAL;
return 0;
}
static int ad7793_write_raw_get_fmt(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask)
@ -717,172 +383,67 @@ static const struct iio_info ad7793_info = {
.write_raw = &ad7793_write_raw,
.write_raw_get_fmt = &ad7793_write_raw_get_fmt,
.attrs = &ad7793_attribute_group,
.validate_trigger = ad7793_validate_trigger,
.validate_trigger = ad_sd_validate_trigger,
.driver_module = THIS_MODULE,
};
#define DECLARE_AD7793_CHANNELS(_name, _b, _sb, _s) \
const struct iio_chan_spec _name##_channels[] = { \
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \
AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \
AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \
AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \
AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \
AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \
IIO_CHAN_SOFT_TIMESTAMP(6), \
}
#define DECLARE_AD7795_CHANNELS(_name, _b, _sb) \
const struct iio_chan_spec _name##_channels[] = { \
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \
AD_SD_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
AD_SD_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \
AD_SD_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
IIO_CHAN_SOFT_TIMESTAMP(9), \
}
static DECLARE_AD7793_CHANNELS(ad7785, 20, 32, 4);
static DECLARE_AD7793_CHANNELS(ad7792, 16, 32, 0);
static DECLARE_AD7793_CHANNELS(ad7793, 24, 32, 0);
static DECLARE_AD7795_CHANNELS(ad7794, 16, 32);
static DECLARE_AD7795_CHANNELS(ad7795, 24, 32);
static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
[ID_AD7793] = {
.channel[0] = {
.type = IIO_VOLTAGE,
.differential = 1,
.indexed = 1,
.channel = 0,
.channel2 = 0,
.address = AD7793_CH_AIN1P_AIN1M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 24, 32, 0)
},
.channel[1] = {
.type = IIO_VOLTAGE,
.differential = 1,
.indexed = 1,
.channel = 1,
.channel2 = 1,
.address = AD7793_CH_AIN2P_AIN2M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 24, 32, 0)
},
.channel[2] = {
.type = IIO_VOLTAGE,
.differential = 1,
.indexed = 1,
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN3P_AIN3M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 24, 32, 0)
},
.channel[3] = {
.type = IIO_VOLTAGE,
.differential = 1,
.extend_name = "shorted",
.indexed = 1,
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN1M_AIN1M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 24, 32, 0)
},
.channel[4] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
.address = AD7793_CH_TEMP,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 4,
.scan_type = IIO_ST('u', 24, 32, 0),
},
.channel[5] = {
.type = IIO_VOLTAGE,
.extend_name = "supply",
.indexed = 1,
.channel = 4,
.address = AD7793_CH_AVDD_MONITOR,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 5,
.scan_type = IIO_ST('u', 24, 32, 0),
},
.channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),
[ID_AD7785] = {
.channels = ad7785_channels,
.num_channels = ARRAY_SIZE(ad7785_channels),
},
[ID_AD7792] = {
.channel[0] = {
.type = IIO_VOLTAGE,
.differential = 1,
.indexed = 1,
.channel = 0,
.channel2 = 0,
.address = AD7793_CH_AIN1P_AIN1M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 16, 32, 0)
},
.channel[1] = {
.type = IIO_VOLTAGE,
.differential = 1,
.indexed = 1,
.channel = 1,
.channel2 = 1,
.address = AD7793_CH_AIN2P_AIN2M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 16, 32, 0)
},
.channel[2] = {
.type = IIO_VOLTAGE,
.differential = 1,
.indexed = 1,
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN3P_AIN3M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 16, 32, 0)
},
.channel[3] = {
.type = IIO_VOLTAGE,
.differential = 1,
.extend_name = "shorted",
.indexed = 1,
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN1M_AIN1M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 16, 32, 0)
},
.channel[4] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
.address = AD7793_CH_TEMP,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 4,
.scan_type = IIO_ST('u', 16, 32, 0),
},
.channel[5] = {
.type = IIO_VOLTAGE,
.extend_name = "supply",
.indexed = 1,
.channel = 4,
.address = AD7793_CH_AVDD_MONITOR,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 5,
.scan_type = IIO_ST('u', 16, 32, 0),
},
.channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),
.channels = ad7792_channels,
.num_channels = ARRAY_SIZE(ad7792_channels),
},
[ID_AD7793] = {
.channels = ad7793_channels,
.num_channels = ARRAY_SIZE(ad7793_channels),
},
[ID_AD7794] = {
.channels = ad7794_channels,
.num_channels = ARRAY_SIZE(ad7794_channels),
},
[ID_AD7795] = {
.channels = ad7795_channels,
.num_channels = ARRAY_SIZE(ad7795_channels),
},
};
static int __devinit ad7793_probe(struct spi_device *spi)
{
struct ad7793_platform_data *pdata = spi->dev.platform_data;
const struct ad7793_platform_data *pdata = spi->dev.platform_data;
struct ad7793_state *st;
struct iio_dev *indio_dev;
int ret, voltage_uv = 0;
@ -903,6 +464,8 @@ static int __devinit ad7793_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info);
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
@ -915,8 +478,6 @@ static int __devinit ad7793_probe(struct spi_device *spi)
st->chip_info =
&ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data];
st->pdata = pdata;
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
else if (voltage_uv)
@ -925,26 +486,19 @@ static int __devinit ad7793_probe(struct spi_device *spi)
st->int_vref_mv = 1170; /* Build-in ref */
spi_set_drvdata(spi, indio_dev);
st->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->channels = st->chip_info->channel;
indio_dev->num_channels = 7;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
indio_dev->info = &ad7793_info;
init_waitqueue_head(&st->wq_data_avail);
ret = ad7793_register_ring_funcs_and_init(indio_dev);
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
if (ret)
goto error_disable_reg;
ret = ad7793_probe_trigger(indio_dev);
if (ret)
goto error_unreg_ring;
ret = ad7793_setup(st);
ret = ad7793_setup(indio_dev, pdata);
if (ret)
goto error_remove_trigger;
@ -955,9 +509,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
return 0;
error_remove_trigger:
ad7793_remove_trigger(indio_dev);
error_unreg_ring:
ad7793_ring_cleanup(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
@ -970,14 +522,13 @@ static int __devinit ad7793_probe(struct spi_device *spi)
return ret;
}
static int ad7793_remove(struct spi_device *spi)
static int __devexit ad7793_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7793_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
ad7793_remove_trigger(indio_dev);
ad7793_ring_cleanup(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
@ -990,8 +541,11 @@ static int ad7793_remove(struct spi_device *spi)
}
static const struct spi_device_id ad7793_id[] = {
{"ad7785", ID_AD7785},
{"ad7792", ID_AD7792},
{"ad7793", ID_AD7793},
{"ad7794", ID_AD7794},
{"ad7795", ID_AD7795},
{}
};
MODULE_DEVICE_TABLE(spi, ad7793_id);
@ -1008,5 +562,5 @@ static struct spi_driver ad7793_driver = {
module_spi_driver(ad7793_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD7792/3 ADC");
MODULE_DESCRIPTION("Analog Devices AD7793 and simialr ADCs");
MODULE_LICENSE("GPL v2");

View File

@ -41,6 +41,7 @@
/* Mode Register Bit Designations (AD7793_REG_MODE) */
#define AD7793_MODE_SEL(x) (((x) & 0x7) << 13) /* Operation Mode Select */
#define AD7793_MODE_SEL_MASK (0x7 << 13) /* Operation Mode Select mask */
#define AD7793_MODE_CLKSRC(x) (((x) & 0x3) << 6) /* ADC Clock Source Select */
#define AD7793_MODE_RATE(x) ((x) & 0xF) /* Filter Update Rate Select */
@ -69,7 +70,8 @@
#define AD7793_CONF_GAIN(x) (((x) & 0x7) << 8) /* Gain Select */
#define AD7793_CONF_REFSEL (1 << 7) /* INT/EXT Reference Select */
#define AD7793_CONF_BUF (1 << 4) /* Buffered Mode Enable */
#define AD7793_CONF_CHAN(x) ((x) & 0x7) /* Channel select */
#define AD7793_CONF_CHAN(x) ((x) & 0xf) /* Channel select */
#define AD7793_CONF_CHAN_MASK 0xf /* Channel select mask */
#define AD7793_CH_AIN1P_AIN1M 0 /* AIN1(+) - AIN1(-) */
#define AD7793_CH_AIN2P_AIN2M 1 /* AIN2(+) - AIN2(-) */
@ -78,9 +80,15 @@
#define AD7793_CH_TEMP 6 /* Temp Sensor */
#define AD7793_CH_AVDD_MONITOR 7 /* AVDD Monitor */
#define AD7795_CH_AIN4P_AIN4M 4 /* AIN4(+) - AIN4(-) */
#define AD7795_CH_AIN5P_AIN5M 5 /* AIN5(+) - AIN5(-) */
#define AD7795_CH_AIN6P_AIN6M 6 /* AIN6(+) - AIN6(-) */
#define AD7795_CH_AIN1M_AIN1M 8 /* AIN1(-) - AIN1(-) */
/* ID Register Bit Designations (AD7793_REG_ID) */
#define AD7792_ID 0xA
#define AD7793_ID 0xB
#define AD7795_ID 0xF
#define AD7793_ID_MASK 0xF
/* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */

View File

@ -219,7 +219,7 @@ static int __devinit ad7887_probe(struct spi_device *spi)
return ret;
}
static int ad7887_remove(struct spi_device *spi)
static int __devexit ad7887_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7887_state *st = iio_priv(indio_dev);

View File

@ -1367,7 +1367,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
return ret;
}
static int max1363_remove(struct i2c_client *client)
static int __devexit max1363_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct max1363_state *st = iio_priv(indio_dev);
@ -1434,11 +1434,11 @@ static struct i2c_driver max1363_driver = {
.name = "max1363",
},
.probe = max1363_probe,
.remove = max1363_remove,
.remove = __devexit_p(max1363_remove),
.id_table = max1363_id,
};
module_i2c_driver(max1363_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("Maxim 1363 ADC");
MODULE_LICENSE("GPL v2");

View File

@ -330,36 +330,30 @@ static int __devinit spear_adc_probe(struct platform_device *pdev)
goto errout3;
}
ret = clk_prepare(info->clk);
if (ret) {
dev_err(dev, "failed preparing clock\n");
goto errout4;
}
ret = clk_enable(info->clk);
ret = clk_prepare_enable(info->clk);
if (ret) {
dev_err(dev, "failed enabling clock\n");
goto errout5;
goto errout4;
}
irq = platform_get_irq(pdev, 0);
if ((irq < 0) || (irq >= NR_IRQS)) {
dev_err(dev, "failed getting interrupt resource\n");
ret = -EINVAL;
goto errout6;
goto errout5;
}
ret = devm_request_irq(dev, irq, spear_adc_isr, 0, MOD_NAME, info);
if (ret < 0) {
dev_err(dev, "failed requesting interrupt\n");
goto errout6;
goto errout5;
}
if (of_property_read_u32(np, "sampling-frequency",
&info->sampling_freq)) {
dev_err(dev, "sampling-frequency missing in DT\n");
ret = -EINVAL;
goto errout6;
goto errout5;
}
/*
@ -389,16 +383,14 @@ static int __devinit spear_adc_probe(struct platform_device *pdev)
ret = iio_device_register(iodev);
if (ret)
goto errout6;
goto errout5;
dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
return 0;
errout6:
clk_disable(info->clk);
errout5:
clk_unprepare(info->clk);
clk_disable_unprepare(info->clk);
errout4:
clk_put(info->clk);
errout3:
@ -416,8 +408,7 @@ static int __devexit spear_adc_remove(struct platform_device *pdev)
iio_device_unregister(iodev);
platform_set_drvdata(pdev, NULL);
clk_disable(info->clk);
clk_unprepare(info->clk);
clk_disable_unprepare(info->clk);
clk_put(info->clk);
iounmap(info->adc_base_spear6xx);
iio_device_free(iodev);

View File

@ -184,7 +184,7 @@ static int __devinit adis16060_r_probe(struct spi_device *spi)
}
/* fixme, confirm ordering in this function */
static int adis16060_r_remove(struct spi_device *spi)
static int __devexit adis16060_r_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
iio_device_free(spi_get_drvdata(spi));
@ -210,7 +210,7 @@ static int __devinit adis16060_w_probe(struct spi_device *spi)
return ret;
}
static int adis16060_w_remove(struct spi_device *spi)
static int __devexit adis16060_w_remove(struct spi_device *spi)
{
return 0;
}

View File

@ -177,7 +177,7 @@ static int __devinit adis16080_probe(struct spi_device *spi)
}
/* fixme, confirm ordering in this function */
static int adis16080_remove(struct spi_device *spi)
static int __devexit adis16080_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
iio_device_free(spi_get_drvdata(spi));

View File

@ -154,7 +154,7 @@ static int __devinit adis16130_probe(struct spi_device *spi)
}
/* fixme, confirm ordering in this function */
static int adis16130_remove(struct spi_device *spi)
static int __devexit adis16130_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
iio_device_free(spi_get_drvdata(spi));

View File

@ -698,7 +698,7 @@ static int __devinit adis16260_probe(struct spi_device *spi)
return ret;
}
static int adis16260_remove(struct spi_device *spi)
static int __devexit adis16260_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -409,7 +409,7 @@ static int __devinit adxrs450_probe(struct spi_device *spi)
return ret;
}
static int adxrs450_remove(struct spi_device *spi)
static int __devexit adxrs450_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
iio_device_free(spi_get_drvdata(spi));

View File

@ -216,6 +216,6 @@ static __exit void iio_dummy_evgen_exit(void)
}
module_exit(iio_dummy_evgen_exit);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("IIO dummy driver");
MODULE_LICENSE("GPL v2");

View File

@ -217,6 +217,6 @@ static struct platform_driver __refdata iio_hwmon_driver = {
module_platform_driver(iio_hwmon_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("IIO to hwmon driver");
MODULE_LICENSE("GPL v2");

View File

@ -558,6 +558,6 @@ static __exit void iio_dummy_exit(void)
}
module_exit(iio_dummy_exit);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("IIO dummy driver");
MODULE_LICENSE("GPL v2");

View File

@ -5,7 +5,7 @@
* 3d 2.5gauss magnetometers via SPI
*
* Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
* Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
*
* Loosely based upon lis3l02dq.h
*

View File

@ -5,7 +5,7 @@
* 3d Magnetometers via SPI
*
* Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
* Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
* Copyright (c) 2011 Analog Devices Inc.
*
* This program is free software; you can redistribute it and/or modify
@ -1204,7 +1204,7 @@ static int __devinit adis16400_probe(struct spi_device *spi)
}
/* fixme, confirm ordering in this function */
static int adis16400_remove(struct spi_device *spi)
static int __devexit adis16400_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -805,7 +805,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
return err;
}
static int tsl2563_remove(struct i2c_client *client)
static int __devexit tsl2563_remove(struct i2c_client *client)
{
struct tsl2563_chip *chip = i2c_get_clientdata(client);
struct iio_dev *indio_dev = iio_priv_to_dev(chip);

View File

@ -1,6 +1,6 @@
/* Copyright (C) 2010 Texas Instruments
Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
Acknowledgement: Jonathan Cameron <jic23@cam.ac.uk> for valuable inputs.
Acknowledgement: Jonathan Cameron <jic23@kernel.org> for valuable inputs.
Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>.

View File

@ -553,7 +553,7 @@ static int __devinit ade7753_probe(struct spi_device *spi)
}
/* fixme, confirm ordering in this function */
static int ade7753_remove(struct spi_device *spi)
static int __devexit ade7753_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -575,7 +575,7 @@ static int __devinit ade7754_probe(struct spi_device *spi)
}
/* fixme, confirm ordering in this function */
static int ade7754_remove(struct spi_device *spi)
static int __devexit ade7754_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -962,7 +962,7 @@ static int __devinit ade7758_probe(struct spi_device *spi)
return ret;
}
static int ade7758_remove(struct spi_device *spi)
static int __devexit ade7758_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ade7758_state *st = iio_priv(indio_dev);

View File

@ -497,7 +497,7 @@ static int __devinit ade7759_probe(struct spi_device *spi)
}
/* fixme, confirm ordering in this function */
static int ade7759_remove(struct spi_device *spi)
static int __devexit ade7759_remove(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev = spi_get_drvdata(spi);

View File

@ -330,7 +330,7 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi)
return 0;
}
static int ade7854_spi_remove(struct spi_device *spi)
static int __devexit ade7854_spi_remove(struct spi_device *spi)
{
ade7854_remove(spi_get_drvdata(spi));

View File

@ -5,7 +5,7 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* Copyright (c) 2009 Jonathan Cameron <jic23@cam.ac.uk>
* Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org>
*
*/

View File

@ -51,7 +51,7 @@ static const struct iio_trigger_ops iio_gpio_trigger_ops = {
.owner = THIS_MODULE,
};
static int iio_gpio_trigger_probe(struct platform_device *pdev)
static int __devinit iio_gpio_trigger_probe(struct platform_device *pdev)
{
struct iio_gpio_trigger_info *trig_info;
struct iio_trigger *trig, *trig2;
@ -130,7 +130,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev)
return ret;
}
static int iio_gpio_trigger_remove(struct platform_device *pdev)
static int __devexit iio_gpio_trigger_remove(struct platform_device *pdev)
{
struct iio_trigger *trig, *trig2;
struct iio_gpio_trigger_info *trig_info;
@ -153,7 +153,7 @@ static int iio_gpio_trigger_remove(struct platform_device *pdev)
static struct platform_driver iio_gpio_trigger_driver = {
.probe = iio_gpio_trigger_probe,
.remove = iio_gpio_trigger_remove,
.remove = __devexit_p(iio_gpio_trigger_remove),
.driver = {
.name = "iio_gpio_trigger",
.owner = THIS_MODULE,
@ -162,6 +162,6 @@ static struct platform_driver iio_gpio_trigger_driver = {
module_platform_driver(iio_gpio_trigger_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("Example gpio trigger for the iio subsystem");
MODULE_LICENSE("GPL v2");

View File

@ -101,7 +101,7 @@ static const struct iio_trigger_ops iio_prtc_trigger_ops = {
.set_trigger_state = &iio_trig_periodic_rtc_set_state,
};
static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
static int __devinit iio_trig_periodic_rtc_probe(struct platform_device *dev)
{
char **pdata = dev->dev.platform_data;
struct iio_prtc_trigger_info *trig_info;
@ -167,7 +167,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
return ret;
}
static int iio_trig_periodic_rtc_remove(struct platform_device *dev)
static int __devexit iio_trig_periodic_rtc_remove(struct platform_device *dev)
{
struct iio_trigger *trig, *trig2;
struct iio_prtc_trigger_info *trig_info;
@ -188,7 +188,7 @@ static int iio_trig_periodic_rtc_remove(struct platform_device *dev)
static struct platform_driver iio_trig_periodic_rtc_driver = {
.probe = iio_trig_periodic_rtc_probe,
.remove = iio_trig_periodic_rtc_remove,
.remove = __devexit_p(iio_trig_periodic_rtc_remove),
.driver = {
.name = "iio_prtc_trigger",
.owner = THIS_MODULE,
@ -197,6 +197,6 @@ static struct platform_driver iio_trig_periodic_rtc_driver = {
module_platform_driver(iio_trig_periodic_rtc_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("Periodic realtime clock trigger for the iio subsystem");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,173 @@
/*
* Support code for Analog Devices Sigma-Delta ADCs
*
* Copyright 2012 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#ifndef __AD_SIGMA_DELTA_H__
#define __AD_SIGMA_DELTA_H__
enum ad_sigma_delta_mode {
AD_SD_MODE_CONTINUOUS = 0,
AD_SD_MODE_SINGLE = 1,
AD_SD_MODE_IDLE = 2,
AD_SD_MODE_POWERDOWN = 3,
};
/**
* struct ad_sigma_delta_calib_data - Calibration data for Sigma Delta devices
* @mode: Calibration mode.
* @channel: Calibration channel.
*/
struct ad_sd_calib_data {
unsigned int mode;
unsigned int channel;
};
struct ad_sigma_delta;
struct iio_dev;
/**
* struct ad_sigma_delta_info - Sigma Delta driver specific callbacks and options
* @set_channel: Will be called to select the current channel, may be NULL.
* @set_mode: Will be called to select the current mode, may be NULL.
* @postprocess_sample: Is called for each sampled data word, can be used to
* modify or drop the sample data, it, may be NULL.
* @has_registers: true if the device has writable and readable registers, false
* if there is just one read-only sample data shift register.
* @addr_shift: Shift of the register address in the communications register.
* @read_mask: Mask for the communications register having the read bit set.
*/
struct ad_sigma_delta_info {
int (*set_channel)(struct ad_sigma_delta *, unsigned int channel);
int (*set_mode)(struct ad_sigma_delta *, enum ad_sigma_delta_mode mode);
int (*postprocess_sample)(struct ad_sigma_delta *, unsigned int raw_sample);
bool has_registers;
unsigned int addr_shift;
unsigned int read_mask;
};
/**
* struct ad_sigma_delta - Sigma Delta device struct
* @spi: The spi device associated with the Sigma Delta device.
* @trig: The IIO trigger associated with the Sigma Delta device.
*
* Most of the fields are private to the sigma delta library code and should not
* be accessed by individual drivers.
*/
struct ad_sigma_delta {
struct spi_device *spi;
struct iio_trigger *trig;
/* private: */
struct completion completion;
bool irq_dis;
bool bus_locked;
uint8_t comm;
const struct ad_sigma_delta_info *info;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
uint8_t data[4] ____cacheline_aligned;
};
static inline int ad_sigma_delta_set_channel(struct ad_sigma_delta *sd,
unsigned int channel)
{
if (sd->info->set_channel)
return sd->info->set_channel(sd, channel);
return 0;
}
static inline int ad_sigma_delta_set_mode(struct ad_sigma_delta *sd,
unsigned int mode)
{
if (sd->info->set_mode)
return sd->info->set_mode(sd, mode);
return 0;
}
static inline int ad_sigma_delta_postprocess_sample(struct ad_sigma_delta *sd,
unsigned int raw_sample)
{
if (sd->info->postprocess_sample)
return sd->info->postprocess_sample(sd, raw_sample);
return 0;
}
void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm);
int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
unsigned int size, unsigned int val);
int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
unsigned int size, unsigned int *val);
int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, int *val);
int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
const struct ad_sd_calib_data *cd, unsigned int n);
int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
struct spi_device *spi, const struct ad_sigma_delta_info *info);
int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev);
void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev);
int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig);
#define __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift, _extend_name, _type) \
{ \
.type = (_type), \
.differential = (_channel2 == -1 ? 0 : 1), \
.indexed = 1, \
.channel = (_channel1), \
.channel2 = (_channel2), \
.address = (_address), \
.extend_name = (_extend_name), \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
.scan_index = (_si), \
.scan_type = { \
.sign = 'u', \
.realbits = (_bits), \
.storagebits = (_storagebits), \
.shift = (_shift), \
.endianness = IIO_BE, \
}, \
}
#define AD_SD_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift) \
__AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift, NULL, IIO_VOLTAGE)
#define AD_SD_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
_storagebits, _shift) \
__AD_SD_CHANNEL(_si, _channel, _channel, _address, _bits, \
_storagebits, _shift, "shorted", IIO_VOLTAGE)
#define AD_SD_CHANNEL(_si, _channel, _address, _bits, \
_storagebits, _shift) \
__AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
_storagebits, _shift, NULL, IIO_VOLTAGE)
#define AD_SD_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
__AD_SD_CHANNEL(_si, 0, -1, _address, _bits, \
_storagebits, _shift, NULL, IIO_TEMP)
#define AD_SD_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
_shift) \
__AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
_storagebits, _shift, "supply", IIO_VOLTAGE)
#endif

View File

@ -8,7 +8,7 @@
* the Free Software Foundation.
*/
#ifndef _IIO_INKERN_CONSUMER_H_
#define _IIO_INKERN_CONSUMER_H
#define _IIO_INKERN_CONSUMER_H_
#include <linux/iio/types.h>
struct iio_dev;

View File

@ -164,7 +164,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
* IIO_ENUM() - Initialize enum extended channel attribute
* @_name: Attribute name
* @_shared: Whether the attribute is shared between all channels
* @_e: Pointer to a iio_enum struct
* @_e: Pointer to an iio_enum struct
*
* This should usually be used together with IIO_ENUM_AVAILABLE()
*/
@ -180,9 +180,9 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
/**
* IIO_ENUM_AVAILABLE() - Initialize enum available extended channel attribute
* @_name: Attribute name ("_available" will be appended to the name)
* @_e: Pointer to a iio_enum struct
* @_e: Pointer to an iio_enum struct
*
* Creates a read only attribute which list all the available enum items in a
* Creates a read only attribute which lists all the available enum items in a
* space separated list. This should usually be used together with IIO_ENUM()
*/
#define IIO_ENUM_AVAILABLE(_name, _e) \
@ -229,6 +229,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
* @indexed: Specify the channel has a numerical index. If not,
* the channel index number will be suppressed for sysfs
* attributes but not for event codes.
* @output: Channel is output.
* @differential: Channel is differential.
*/
struct iio_chan_spec {
@ -312,6 +313,9 @@ struct iio_dev;
* Meaning is event dependent.
* @validate_trigger: function to validate the trigger when the
* current trigger gets changed.
* @update_scan_mode: function to configure device and scan buffer when
* channels have changed
* @debugfs_reg_access: function to read or write register value of device
**/
struct iio_info {
struct module *driver_module;
@ -367,10 +371,10 @@ struct iio_info {
* scan mask is valid for the device.
*/
struct iio_buffer_setup_ops {
int (*preenable)(struct iio_dev *);
int (*postenable)(struct iio_dev *);
int (*predisable)(struct iio_dev *);
int (*postdisable)(struct iio_dev *);
int (*preenable)(struct iio_dev *);
int (*postenable)(struct iio_dev *);
int (*predisable)(struct iio_dev *);
int (*postdisable)(struct iio_dev *);
bool (*validate_scan_mask)(struct iio_dev *indio_dev,
const unsigned long *scan_mask);
};
@ -516,6 +520,31 @@ static inline struct iio_dev *iio_device_get(struct iio_dev *indio_dev)
return indio_dev ? dev_to_iio_dev(get_device(&indio_dev->dev)) : NULL;
}
/**
* iio_device_set_drvdata() - Set device driver data
* @indio_dev: IIO device structure
* @data: Driver specific data
*
* Allows to attach an arbitrary pointer to an IIO device, which can later be
* retrieved by iio_device_get_drvdata().
*/
static inline void iio_device_set_drvdata(struct iio_dev *indio_dev, void *data)
{
dev_set_drvdata(&indio_dev->dev, data);
}
/**
* iio_device_get_drvdata() - Get device driver data
* @indio_dev: IIO device structure
*
* Returns the data previously set with iio_device_set_drvdata()
*/
static inline void *iio_device_get_drvdata(struct iio_dev *indio_dev)
{
return dev_get_drvdata(&indio_dev->dev);
}
/* Can we make this smaller? */
#define IIO_ALIGN L1_CACHE_BYTES
/**

View File

@ -1,3 +1,5 @@
#ifndef __LINUX_IIO_KFIFO_BUF_H__
#define __LINUX_IIO_KFIFO_BUF_H__
#include <linux/kfifo.h>
#include <linux/iio/iio.h>
@ -6,3 +8,4 @@
struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev);
void iio_kfifo_free(struct iio_buffer *r);
#endif

View File

@ -8,6 +8,9 @@
* the Free Software Foundation.
*/
#ifndef __LINUX_IIO_MACHINE_H__
#define __LINUX_IIO_MACHINE_H__
/**
* struct iio_map - description of link between consumer and device channels
* @adc_channel_label: Label used to identify the channel on the provider.
@ -22,3 +25,5 @@ struct iio_map {
const char *consumer_dev_name;
const char *consumer_channel;
};
#endif

View File

@ -29,7 +29,7 @@ struct iio_subirq {
* instances of a given device.
**/
struct iio_trigger_ops {
struct module *owner;
struct module *owner;
int (*set_trigger_state)(struct iio_trigger *trig, bool state);
int (*try_reenable)(struct iio_trigger *trig);
int (*validate_device)(struct iio_trigger *trig,
@ -39,7 +39,7 @@ struct iio_trigger_ops {
/**
* struct iio_trigger - industrial I/O trigger device
*
* @ops: [DRIVER] operations structure
* @id: [INTERN] unique id number
* @name: [DRIVER] unique name
* @dev: [DRIVER] associated device (if relevant)
@ -76,19 +76,19 @@ struct iio_trigger {
static inline struct iio_trigger *to_iio_trigger(struct device *d)
{
return container_of(d, struct iio_trigger, dev);
};
}
static inline void iio_trigger_put(struct iio_trigger *trig)
{
module_put(trig->ops->owner);
put_device(&trig->dev);
};
}
static inline void iio_trigger_get(struct iio_trigger *trig)
{
get_device(&trig->dev);
__module_get(trig->ops->owner);
};
}
/**
* iio_trigger_register() - register a trigger with the IIO core
@ -104,7 +104,8 @@ void iio_trigger_unregister(struct iio_trigger *trig_info);
/**
* iio_trigger_poll() - called on a trigger occurring
* @trig: trigger which occurred
* @trig: trigger which occurred
* @time: timestamp when trigger occurred
*
* Typically called in relevant hardware interrupt handler.
**/

View File

@ -7,6 +7,15 @@
* the Free Software Foundation.
*/
#ifndef __LINUX_IIO_TRIGGER_CONSUMER_H__
#define __LINUX_IIO_TRIGGER_CONSUMER_H__
#include <linux/interrupt.h>
#include <linux/types.h>
struct iio_dev;
struct iio_trigger;
/**
* struct iio_poll_func - poll function pair
*
@ -50,3 +59,5 @@ void iio_trigger_notify_done(struct iio_trigger *trig);
*/
int iio_triggered_buffer_postenable(struct iio_dev *indio_dev);
int iio_triggered_buffer_predisable(struct iio_dev *indio_dev);
#endif