Commit bad15f2c authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-3.11c' of...

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

Jonathan writes:

Third round of IIO new stuff, cleanups and staging graduations for the 3.11
cycle.

1) Add clock consumer support and device tree bindings to adf4350.
   The clock consumer part depends on a not so optional 'optional'
   implementation of clock_round_rate which is not present for pxa27x.
   It will be shortly and as no one actually uses this chip with that
   sub arch as far as we know, no need to delay the inclusion in the
   meantime. See
   http://lkml.indiana.edu/hypermail/linux/kernel/1306.1/00023.html
   for the brief discussion.  This may be the first non soc specific driver
   that makes use of that function.

2) AD7303 DAC new driver.

3) ADIS16130 minor fixes and improvements plus move out of staging.

4) AD7291 improvements to bring it inline with more recent drivers.

5) Update to the sysfs ABI doc to fix some out of date paths.
parents 4a8d1135 1df9d1d4
......@@ -690,45 +690,45 @@ Description:
Actually start the buffer capture up. Will start trigger
if first device and appropriate.
What: /sys/bus/iio/devices/iio:deviceX/buffer/scan_elements
What: /sys/bus/iio/devices/iio:deviceX/scan_elements
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Directory containing interfaces for elements that will be
captured for a single triggered sample set in the buffer.
What: /sys/.../buffer/scan_elements/in_accel_x_en
What: /sys/.../buffer/scan_elements/in_accel_y_en
What: /sys/.../buffer/scan_elements/in_accel_z_en
What: /sys/.../buffer/scan_elements/in_anglvel_x_en
What: /sys/.../buffer/scan_elements/in_anglvel_y_en
What: /sys/.../buffer/scan_elements/in_anglvel_z_en
What: /sys/.../buffer/scan_elements/in_magn_x_en
What: /sys/.../buffer/scan_elements/in_magn_y_en
What: /sys/.../buffer/scan_elements/in_magn_z_en
What: /sys/.../buffer/scan_elements/in_timestamp_en
What: /sys/.../buffer/scan_elements/in_voltageY_supply_en
What: /sys/.../buffer/scan_elements/in_voltageY_en
What: /sys/.../buffer/scan_elements/in_voltageY-voltageZ_en
What: /sys/.../buffer/scan_elements/in_incli_x_en
What: /sys/.../buffer/scan_elements/in_incli_y_en
What: /sys/.../buffer/scan_elements/in_pressureY_en
What: /sys/.../buffer/scan_elements/in_pressure_en
What: /sys/.../iio:deviceX/scan_elements/in_accel_x_en
What: /sys/.../iio:deviceX/scan_elements/in_accel_y_en
What: /sys/.../iio:deviceX/scan_elements/in_accel_z_en
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_x_en
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_y_en
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_x_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_y_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_z_en
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY-voltageZ_en
What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en
What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_en
What: /sys/.../iio:deviceX/scan_elements/in_pressure_en
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Scan element control for triggered data capture.
What: /sys/.../buffer/scan_elements/in_accel_type
What: /sys/.../buffer/scan_elements/in_anglvel_type
What: /sys/.../buffer/scan_elements/in_magn_type
What: /sys/.../buffer/scan_elements/in_incli_type
What: /sys/.../buffer/scan_elements/in_voltageY_type
What: /sys/.../buffer/scan_elements/in_voltage_type
What: /sys/.../buffer/scan_elements/in_voltageY_supply_type
What: /sys/.../buffer/scan_elements/in_timestamp_type
What: /sys/.../buffer/scan_elements/in_pressureY_type
What: /sys/.../buffer/scan_elements/in_pressure_type
What: /sys/.../iio:deviceX/scan_elements/in_accel_type
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_type
What: /sys/.../iio:deviceX/scan_elements/in_magn_type
What: /sys/.../iio:deviceX/scan_elements/in_incli_type
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_type
What: /sys/.../iio:deviceX/scan_elements/in_voltage_type
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_type
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type
What: /sys/.../iio:deviceX/scan_elements/in_pressure_type
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
......@@ -752,29 +752,29 @@ Description:
For other storage combinations this attribute will be extended
appropriately.
What: /sys/.../buffer/scan_elements/in_accel_type_available
What: /sys/.../iio:deviceX/scan_elements/in_accel_type_available
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
If the type parameter can take one of a small set of values,
this attribute lists them.
What: /sys/.../buffer/scan_elements/in_voltageY_index
What: /sys/.../buffer/scan_elements/in_voltageY_supply_index
What: /sys/.../buffer/scan_elements/in_accel_x_index
What: /sys/.../buffer/scan_elements/in_accel_y_index
What: /sys/.../buffer/scan_elements/in_accel_z_index
What: /sys/.../buffer/scan_elements/in_anglvel_x_index
What: /sys/.../buffer/scan_elements/in_anglvel_y_index
What: /sys/.../buffer/scan_elements/in_anglvel_z_index
What: /sys/.../buffer/scan_elements/in_magn_x_index
What: /sys/.../buffer/scan_elements/in_magn_y_index
What: /sys/.../buffer/scan_elements/in_magn_z_index
What: /sys/.../buffer/scan_elements/in_incli_x_index
What: /sys/.../buffer/scan_elements/in_incli_y_index
What: /sys/.../buffer/scan_elements/in_timestamp_index
What: /sys/.../buffer/scan_elements/in_pressureY_index
What: /sys/.../buffer/scan_elements/in_pressure_index
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_index
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_x_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_y_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_z_index
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_x_index
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_y_index
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_x_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_y_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_z_index
What: /sys/.../iio:deviceX/scan_elements/in_incli_x_index
What: /sys/.../iio:deviceX/scan_elements/in_incli_y_index
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_index
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_index
What: /sys/.../iio:deviceX/scan_elements/in_pressure_index
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
......
Analog Devices AD7303 DAC device driver
Required properties:
- compatible: Must be "adi,ad7303"
- reg: SPI chip select number for the device
- spi-max-frequency: Max SPI frequency to use (< 30000000)
- Vdd-supply: Phandle to the Vdd power supply
Optional properties:
- REF-supply: Phandle to the external reference voltage supply. This should
only be set if there is an external reference voltage connected to the REF
pin. If the property is not set Vdd/2 is used as the reference voltage.
Example:
ad7303@4 {
compatible = "adi,ad7303";
reg = <4>;
spi-max-frequency = <10000000>;
Vdd-supply = <&vdd_supply>;
adi,use-external-reference;
REF-supply = <&vref_supply>;
};
Analog Devices ADF4350/ADF4351 device driver
Required properties:
- compatible: Should be one of
* "adi,adf4350": When using the ADF4350 device
* "adi,adf4351": When using the ADF4351 device
- reg: SPI chip select numbert for the device
- spi-max-frequency: Max SPI frequency to use (< 20000000)
- clocks: From common clock binding. Clock is phandle to clock for
ADF435x Reference Clock (CLKIN).
Optional properties:
- gpios: GPIO Lock detect - If set with a valid phandle and GPIO number,
pll lock state is tested upon read.
- adi,channel-spacing: Channel spacing in Hz (influences MODULUS).
- adi,power-up-frequency: If set in Hz the PLL tunes to
the desired frequency on probe.
- adi,reference-div-factor: If set the driver skips dynamic calculation
and uses this default value instead.
- adi,reference-doubler-enable: Enables reference doubler.
- adi,reference-div2-enable: Enables reference divider.
- adi,phase-detector-polarity-positive-enable: Enables positive phase
detector polarity. Default = negative.
- adi,lock-detect-precision-6ns-enable: Enables 6ns lock detect precision.
Default = 10ns.
- adi,lock-detect-function-integer-n-enable: Enables lock detect
for integer-N mode. Default = factional-N mode.
- adi,charge-pump-current: Charge pump current in mA.
Default = 2500mA.
- adi,muxout-select: On chip multiplexer output selection.
Valid values for the multiplexer output are:
0: Three-State Output (default)
1: DVDD
2: DGND
3: R-Counter output
4: N-Divider output
5: Analog lock detect
6: Digital lock detect
- adi,low-spur-mode-enable: Enables low spur mode.
Default = Low noise mode.
- adi,cycle-slip-reduction-enable: Enables cycle slip reduction.
- adi,charge-cancellation-enable: Enabled charge pump
charge cancellation for integer-N modes.
- adi,anti-backlash-3ns-enable: Enables 3ns antibacklash pulse width
for integer-N modes.
- adi,band-select-clock-mode-high-enable: Enables faster band
selection logic.
- adi,12bit-clk-divider: Clock divider value used when
adi,12bit-clkdiv-mode != 0
- adi,clk-divider-mode:
Valid values for the clkdiv mode are:
0: Clock divider off (default)
1: Fast lock enable
2: Phase resync enable
- adi,aux-output-enable: Enables auxiliary RF output.
- adi,aux-output-fundamental-enable: Selects fundamental VCO output on
the auxiliary RF output. Default = Output of RF dividers.
- adi,mute-till-lock-enable: Enables Mute-Till-Lock-Detect function.
- adi,output-power: Output power selection.
Valid values for the power mode are:
0: -4dBm (default)
1: -1dBm
2: +2dBm
3: +5dBm
- adi,aux-output-power: Auxiliary output power selection.
Valid values for the power mode are:
0: -4dBm (default)
1: -1dBm
2: +2dBm
3: +5dBm
Example:
lo_pll0_rx_adf4351: adf4351-rx-lpc@4 {
compatible = "adi,adf4351";
reg = <4>;
spi-max-frequency = <10000000>;
clocks = <&clk0_ad9523 9>;
clock-names = "clkin";
adi,channel-spacing = <10000>;
adi,power-up-frequency = <2400000000>;
adi,phase-detector-polarity-positive-enable;
adi,charge-pump-current = <2500>;
adi,output-power = <3>;
adi,mute-till-lock-enable;
};
......@@ -130,6 +130,16 @@ config AD5686
To compile this driver as a module, choose M here: the
module will be called ad5686.
config AD7303
tristate "Analog Devices Analog Devices AD7303 DAC driver"
depends on SPI
help
Say yes here to build support for Analog Devices AD7303 Digital to Analog
Converters (DAC).
To compile this driver as module choose M here: the module will be called
ad7303.
config MAX517
tristate "Maxim MAX517/518/519 DAC driver"
depends on I2C
......
......@@ -14,5 +14,6 @@ obj-$(CONFIG_AD5755) += ad5755.o
obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MCP4725) += mcp4725.o
/*
* AD7303 Digital to analog converters driver
*
* Copyright 2013 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/platform_data/ad7303.h>
#define AD7303_CFG_EXTERNAL_VREF BIT(15)
#define AD7303_CFG_POWER_DOWN(ch) BIT(11 + (ch))
#define AD7303_CFG_ADDR_OFFSET 10
#define AD7303_CMD_UPDATE_DAC (0x3 << 8)
/**
* struct ad7303_state - driver instance specific data
* @spi: the device for this driver instance
* @config: cached config register value
* @dac_cache: current DAC raw value (chip does not support readback)
* @data: spi transfer buffer
*/
struct ad7303_state {
struct spi_device *spi;
uint16_t config;
uint8_t dac_cache[2];
struct regulator *vdd_reg;
struct regulator *vref_reg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be16 data ____cacheline_aligned;
};
static int ad7303_write(struct ad7303_state *st, unsigned int chan,
uint8_t val)
{
st->data = cpu_to_be16(AD7303_CMD_UPDATE_DAC |
(chan << AD7303_CFG_ADDR_OFFSET) |
st->config | val);
return spi_write(st->spi, &st->data, sizeof(st->data));
}
static ssize_t ad7303_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct ad7303_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", (bool)(st->config &
AD7303_CFG_POWER_DOWN(chan->channel)));
}
static ssize_t ad7303_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
struct ad7303_state *st = iio_priv(indio_dev);
bool pwr_down;
int ret;
ret = strtobool(buf, &pwr_down);
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
if (pwr_down)
st->config |= AD7303_CFG_POWER_DOWN(chan->channel);
else
st->config &= ~AD7303_CFG_POWER_DOWN(chan->channel);
/* There is no noop cmd which allows us to only update the powerdown
* mode, so just write one of the DAC channels again */
ad7303_write(st, chan->channel, st->dac_cache[chan->channel]);
mutex_unlock(&indio_dev->mlock);
return ret ? ret : len;
}
static int ad7303_get_vref(struct ad7303_state *st,
struct iio_chan_spec const *chan)
{
int ret;
if (st->config & AD7303_CFG_EXTERNAL_VREF)
return regulator_get_voltage(st->vref_reg);
ret = regulator_get_voltage(st->vdd_reg);
if (ret < 0)
return ret;
return ret / 2;
}
static int ad7303_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info)
{
struct ad7303_state *st = iio_priv(indio_dev);
int vref_uv;
switch (info) {
case IIO_CHAN_INFO_RAW:
*val = st->dac_cache[chan->channel];
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
vref_uv = ad7303_get_vref(st, chan);
if (vref_uv < 0)
return vref_uv;
*val = 2 * vref_uv / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
break;
}
return -EINVAL;
}
static int ad7303_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long mask)
{
struct ad7303_state *st = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
ret = ad7303_write(st, chan->address, val);
if (ret == 0)
st->dac_cache[chan->channel] = val;
mutex_unlock(&indio_dev->mlock);
break;
default:
ret = -EINVAL;
}
return ret;
}
static const struct iio_info ad7303_info = {
.read_raw = ad7303_read_raw,
.write_raw = ad7303_write_raw,
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec_ext_info ad7303_ext_info[] = {
{
.name = "powerdown",
.read = ad7303_read_dac_powerdown,
.write = ad7303_write_dac_powerdown,
},
{ },
};
#define AD7303_CHANNEL(chan) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (chan), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = (chan), \
.scan_type = { \
.sign = 'u', \
.realbits = '8', \
.storagebits = '8', \
.shift = '0', \
}, \
.ext_info = ad7303_ext_info, \
}
static const struct iio_chan_spec ad7303_channels[] = {
AD7303_CHANNEL(0),
AD7303_CHANNEL(1),
};
static int ad7303_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct iio_dev *indio_dev;
struct ad7303_state *st;
bool ext_ref;
int ret;
indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->vdd_reg = regulator_get(&spi->dev, "Vdd");
if (IS_ERR(st->vdd_reg)) {
ret = PTR_ERR(st->vdd_reg);
goto err_free;
}
ret = regulator_enable(st->vdd_reg);
if (ret)
goto err_put_vdd_reg;
if (spi->dev.of_node) {
ext_ref = of_property_read_bool(spi->dev.of_node,
"REF-supply");
} else {
struct ad7303_platform_data *pdata = spi->dev.platform_data;
if (pdata && pdata->use_external_ref)
ext_ref = true;
else
ext_ref = false;
}
if (ext_ref) {
st->vref_reg = regulator_get(&spi->dev, "REF");
if (IS_ERR(st->vref_reg))
goto err_disable_vdd_reg;
ret = regulator_enable(st->vref_reg);
if (ret)
goto err_put_vref_reg;
st->config |= AD7303_CFG_EXTERNAL_VREF;
}
indio_dev->dev.parent = &spi->dev;
indio_dev->name = id->name;
indio_dev->info = &ad7303_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ad7303_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7303_channels);
ret = iio_device_register(indio_dev);
if (ret)
goto err_disable_vref_reg;
return 0;
err_disable_vref_reg:
if (st->vref_reg)
regulator_disable(st->vref_reg);
err_put_vref_reg:
if (st->vref_reg)
regulator_put(st->vref_reg);
err_disable_vdd_reg:
regulator_disable(st->vdd_reg);
err_put_vdd_reg:
regulator_put(st->vdd_reg);
err_free:
iio_device_free(indio_dev);
return ret;
}
static int ad7303_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7303_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (st->vref_reg) {
regulator_disable(st->vref_reg);
regulator_put(st->vref_reg);
}
regulator_disable(st->vdd_reg);
regulator_put(st->vdd_reg);
iio_device_free(indio_dev);
return 0;
}
static const struct spi_device_id ad7303_spi_ids[] = {
{ "ad7303", 0 },
{}
};
MODULE_DEVICE_TABLE(spi, ad7303_spi_ids);
static struct spi_driver ad7303_driver = {
.driver = {
.name = "ad7303",
.owner = THIS_MODULE,
},
.probe = ad7303_probe,
.remove = ad7303_remove,
.id_table = ad7303_spi_ids,
};
module_spi_driver(ad7303_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Devices AD7303 DAC driver");
MODULE_LICENSE("GPL v2");
/*
* ADF4350/ADF4351 SPI Wideband Synthesizer driver
*
* Copyright 2012 Analog Devices Inc.
* Copyright 2012-2013 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
......@@ -17,6 +17,9 @@
#include <linux/gcd.h>
#include <linux/gpio.h>
#include <asm/div64.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......@@ -33,6 +36,7 @@ struct adf4350_state {
struct spi_device *spi;
struct regulator *reg;
struct adf4350_platform_data *pdata;
struct clk *clk;
unsigned long clkin;
unsigned long chspc; /* Channel Spacing */
unsigned long fpfd; /* Phase Frequency Detector */
......@@ -43,7 +47,7 @@ struct adf4350_state {
unsigned r4_rf_div_sel;
unsigned long regs[6];
unsigned long regs_hw[6];
unsigned long long freq_req;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
......@@ -52,7 +56,6 @@ struct adf4350_state {
};
static struct adf4350_platform_data default_pdata = {
.clkin = 122880000,
.channel_spacing = 10000,
.r2_user_settings = ADF4350_REG2_PD_POLARITY_POS |
ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500),
......@@ -235,6 +238,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
ADF4350_REG4_MUTE_TILL_LOCK_EN));
st->regs[ADF4350_REG5] = ADF4350_REG5_LD_PIN_MODE_DIGITAL;
st->freq_req = freq;
return adf4350_sync_config(st);
}
......@@ -246,6 +250,7 @@ static ssize_t adf4350_write(struct iio_dev *indio_dev,
{
struct adf4350_state *st = iio_priv(indio_dev);
unsigned long long readin;
unsigned long tmp;
int ret;
ret = kstrtoull(buf, 10, &readin);
......@@ -258,10 +263,23 @@ static ssize_t adf4350_write(struct iio_dev *indio_dev,
ret = adf4350_set_freq(st, readin);
break;
case ADF4350_FREQ_REFIN:
if (readin > ADF4350_MAX_FREQ_REFIN)
if (readin > ADF4350_MAX_FREQ_REFIN) {
ret = -EINVAL;
else
break;
}
if (st->clk) {
tmp = clk_round_rate(st->clk, readin);
if (tmp != readin) {
ret = -EINVAL;
break;
}
ret = clk_set_rate(st->clk, tmp);
if (ret < 0)
break;
}
st->clkin = readin;
ret = adf4350_set_freq(st, st->freq_req);
break;
case ADF4350_FREQ_RESOLUTION:
if (readin == 0)
......@@ -308,6 +326,9 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev,
}
break;
case ADF4350_FREQ_REFIN:
if (st->clk)
st->clkin = clk_get_rate(st->clk);
val = st->clkin;
break;
case ADF4350_FREQ_RESOLUTION:
......@@ -318,6 +339,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev,
break;
default:
ret = -EINVAL;
val = 0;
}
mutex_unlock(&indio_dev->mlock);
......@@ -355,19 +377,153 @@ static const struct iio_info adf4350_info = {
.driver_module = THIS_MODULE,
};
#ifdef CONFIG_OF
static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
{
struct device_node *np = dev->of_node;
struct adf4350_platform_data *pdata;
unsigned int tmp;
int ret;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(dev, "could not allocate memory for platform data\n");
return NULL;
}
strncpy(&pdata->name[0], np->name, SPI_NAME_SIZE - 1);
tmp = 10000;
of_property_read_u32(np, "adi,channel-spacing", &tmp);
pdata->channel_spacing = tmp;
tmp = 0;
of_property_read_u32(np, "adi,power-up-frequency", &tmp);
pdata->power_up_frequency = tmp;
tmp = 0;
of_property_read_u32(np, "adi,reference-div-factor", &tmp);
pdata->ref_div_factor = tmp;
ret = of_get_gpio(np, 0);
if (ret < 0)
pdata->gpio_lock_detect = -1;
else
pdata->gpio_lock_detect = ret;
pdata->ref_doubler_en = of_property_read_bool(np,
"adi,reference-doubler-enable");
pdata->ref_div2_en = of_property_read_bool(np,
"adi,reference-div2-enable");
/* r2_user_settings */
pdata->r2_user_settings = of_property_read_bool(np,
"adi,phase-detector-polarity-positive-enable") ?
ADF4350_REG2_PD_POLARITY_POS : 0;
pdata->r2_user_settings |= of_property_read_bool(np,
"adi,lock-detect-precision-6ns-enable") ?
ADF4350_REG2_LDP_6ns : 0;
pdata->r2_user_settings |= of_property_read_bool(np,
"adi,lock-detect-function-integer-n-enable") ?
ADF4350_REG2_LDF_INT_N : 0;
tmp = 2500;
of_property_read_u32(np, "adi,charge-pump-current", &tmp);
pdata->r2_user_settings |= ADF4350_REG2_CHARGE_PUMP_CURR_uA(tmp);
tmp = 0;
of_property_read_u32(np, "adi,muxout-select", &tmp);
pdata->r2_user_settings |= ADF4350_REG2_MUXOUT(tmp);
pdata->r2_user_settings |= of_property_read_bool(np,
"adi,low-spur-mode-enable") ?
ADF4350_REG2_NOISE_MODE(0x3) : 0;
/* r3_user_settings */
pdata->r3_user_settings = of_property_read_bool(np,
"adi,cycle-slip-reduction-enable") ?
ADF4350_REG3_12BIT_CSR_EN : 0;
pdata->r3_user_settings |= of_property_read_bool(np,
"adi,charge-cancellation-enable") ?
ADF4351_REG3_CHARGE_CANCELLATION_EN : 0;
pdata->r3_user_settings |= of_property_read_bool(np,
"adi,anti-backlash-3ns-enable") ?
ADF4351_REG3_ANTI_BACKLASH_3ns_EN : 0;
pdata->r3_user_settings |= of_property_read_bool(np,
"adi,band-select-clock-mode-high-enable") ?
ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH : 0;
tmp = 0;
of_property_read_u32(np, "adi,12bit-clk-divider", &tmp);
pdata->r3_user_settings |= ADF4350_REG3_12BIT_CLKDIV(tmp);
tmp = 0;
of_property_read_u32(np, "adi,clk-divider-mode", &tmp);
pdata->r3_user_settings |= ADF4350_REG3_12BIT_CLKDIV_MODE(tmp);
/* r4_user_settings */
pdata->r4_user_settings = of_property_read_bool(np,
"adi,aux-output-enable") ?
ADF4350_REG4_AUX_OUTPUT_EN : 0;
pdata->r4_user_settings |= of_property_read_bool(np,
"adi,aux-output-fundamental-enable") ?
ADF4350_REG4_AUX_OUTPUT_FUND : 0;
pdata->r4_user_settings |= of_property_read_bool(np,
"adi,mute-till-lock-enable") ?
ADF4350_REG4_MUTE_TILL_LOCK_EN : 0;
tmp = 0;
of_property_read_u32(np, "adi,output-power", &tmp);
pdata->r4_user_settings |= ADF4350_REG4_OUTPUT_PWR(tmp);
tmp = 0;
of_property_read_u32(np, "adi,aux-output-power", &tmp);
pdata->r4_user_settings |= ADF4350_REG4_AUX_OUTPUT_PWR(tmp);
return pdata;
}
#else
static
struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
{
return NULL;
}
#endif
static int adf4350_probe(struct spi_device *spi)
{
struct adf4350_platform_data *pdata = spi->dev.platform_data;
struct adf4350_platform_data *pdata;
struct iio_dev *indio_dev;
struct adf4350_state *st;
struct clk *clk = NULL;
int ret;
if (spi->dev.of_node) {
pdata = adf4350_parse_dt(&spi->dev);
if (pdata == NULL)
return -EINVAL;
} else {
pdata = spi->dev.platform_data;
}
if (!pdata) {
dev_warn(&spi->dev, "no platform data? using default\n");
pdata = &default_pdata;
}
if (!pdata->clkin) {
clk = clk_get(&spi->dev, "clkin");
if (IS_ERR(clk))
return -EPROBE_DEFER;
ret = clk_prepare_enable(clk);
if (ret < 0)
return ret;
}
indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
......@@ -395,7 +551,12 @@ static int adf4350_probe(struct spi_device *spi)
indio_dev->num_channels = 1;
st->chspc = pdata->channel_spacing;
if (clk) {
st->clk = clk;
st->clkin = clk_get_rate(clk);
} else {
st->clkin = pdata->clkin;
}
st->min_out_freq = spi_get_device_id(spi)->driver_data == 4351 ?
ADF4351_MIN_OUT_FREQ : ADF4350_MIN_OUT_FREQ;
......@@ -435,6 +596,8 @@ static int adf4350_probe(struct spi_device *spi)
if (!IS_ERR(st->reg))
regulator_put(st->reg);
if (clk)
clk_disable_unprepare(clk);
iio_device_free(indio_dev);
return ret;
......@@ -451,6 +614,9 @@ static int adf4350_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
if (st->clk)
clk_disable_unprepare(st->clk);
if (!IS_ERR(reg)) {
regulator_disable(reg);
regulator_put(reg);
......@@ -481,6 +647,6 @@ static struct spi_driver adf4350_driver = {
};
module_spi_driver(adf4350_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADF4350/ADF4351 PLL");
MODULE_LICENSE("GPL v2");
......@@ -10,6 +10,13 @@ config ADIS16080
Say yes here to build support for Analog Devices ADIS16080, ADIS16100 Yaw
Rate Gyroscope with SPI.
config ADIS16130
tristate "Analog Devices ADIS16130 High Precision Angular Rate Sensor driver"
depends on SPI
help
Say yes here to build support for Analog Devices ADIS16130 High Precision
Angular Rate Sensor driver.
config ADIS16136
tristate "Analog devices ADIS16136 and similar gyroscopes driver"
depends on SPI_MASTER
......
......@@ -3,6 +3,7 @@
#
obj-$(CONFIG_ADIS16080) += adis16080.o
obj-$(CONFIG_ADIS16130) += adis16130.o
obj-$(CONFIG_ADIS16136) += adis16136.o
obj-$(CONFIG_ADXRS450) += adxrs450.o
......
......@@ -6,18 +6,12 @@
* Licensed under the GPL-2 or later.
*/
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define ADIS16130_CON 0x0
#define ADIS16130_CON_RD (1 << 6)
......@@ -68,7 +62,6 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->us, &msg);
ret = spi_read(st->us, st->buf, 4);
if (ret == 0)
*val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3];
......@@ -85,6 +78,8 @@ static int adis16130_read_raw(struct iio_dev *indio_dev,
int ret;
u32 temp;
switch (mask) {
case IIO_CHAN_INFO_RAW:
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
ret = adis16130_spi_read(indio_dev, chan->address, &temp);
......@@ -93,6 +88,37 @@ static int adis16130_read_raw(struct iio_dev *indio_dev,
return ret;
*val = temp;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
/* 0 degree = 838860, 250 degree = 14260608 */
*val = 250;
*val2 = 336440817; /* RAD_TO_DEGREE(14260608 - 8388608) */
return IIO_VAL_FRACTIONAL;
case IIO_TEMP:
/* 0C = 8036283, 105C = 9516048 */
*val = 105000;
*val2 = 9516048 - 8036283;
return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
break;
case IIO_CHAN_INFO_OFFSET:
switch (chan->type) {
case IIO_ANGL_VEL:
*val = -8388608;
return IIO_VAL_INT;
case IIO_TEMP:
*val = -8036283;
return IIO_VAL_INT;
default:
return -EINVAL;
}
break;
}
return -EINVAL;
}
static const struct iio_chan_spec adis16130_channels[] = {
......@@ -100,13 +126,17 @@ static const struct iio_chan_spec adis16130_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.address = ADIS16130_RATEDATA,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.address = ADIS16130_TEMPDATA,
}
};
......@@ -153,7 +183,6 @@ static int adis16130_probe(struct spi_device *spi)
return ret;
}
/* fixme, confirm ordering in this function */
static int adis16130_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
......
......@@ -21,6 +21,8 @@
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include "ad7291.h"
/*
* Simplified handling
*
......@@ -39,33 +41,9 @@
#define AD7291_VOLTAGE 0x01
#define AD7291_T_SENSE 0x02
#define AD7291_T_AVERAGE 0x03
#define AD7291_CH0_DATA_HIGH 0x04
#define AD7291_CH0_DATA_LOW 0x05
#define AD7291_CH0_HYST 0x06
#define AD7291_CH1_DATA_HIGH 0x07
#define AD7291_CH1_DATA_LOW 0x08
#define AD7291_CH1_HYST 0x09
#define AD7291_CH2_DATA_HIGH 0x0A
#define AD7291_CH2_DATA_LOW 0x0B
#define AD7291_CH2_HYST 0x0C
#define AD7291_CH3_DATA_HIGH 0x0D
#define AD7291_CH3_DATA_LOW 0x0E
#define AD7291_CH3_HYST 0x0F
#define AD7291_CH4_DATA_HIGH 0x10
#define AD7291_CH4_DATA_LOW 0x11
#define AD7291_CH4_HYST 0x12
#define AD7291_CH5_DATA_HIGH 0x13
#define AD7291_CH5_DATA_LOW 0x14
#define AD7291_CH5_HYST 0x15
#define AD7291_CH6_DATA_HIGH 0x16
#define AD7291_CH6_DATA_LOW 0x17
#define AD7291_CH6_HYST 0x18
#define AD7291_CH7_DATA_HIGH 0x19
#define AD7291_CH7_DATA_LOW 0x1A
#define AD7291_CH7_HYST 0x2B
#define AD7291_T_SENSE_HIGH 0x1C
#define AD7291_T_SENSE_LOW 0x1D
#define AD7291_T_SENSE_HYST 0x1E
#define AD7291_DATA_HIGH(x) ((x) * 3 + 0x4)
#define AD7291_DATA_LOW(x) ((x) * 3 + 0x5)
#define AD7291_HYST(x) ((x) * 3 + 0x6)
#define AD7291_VOLTAGE_ALERT_STATUS 0x1F
#define AD7291_T_ALERT_STATUS 0x20
......@@ -100,7 +78,6 @@
struct ad7291_chip_info {
struct i2c_client *client;
struct regulator *reg;
u16 int_vref_mv;
u16 command;
u16 c_mask; /* Active voltage channels for events */
struct mutex state_lock;
......@@ -111,45 +88,22 @@ static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data)
struct i2c_client *client = chip->client;
int ret = 0;
ret = i2c_smbus_read_word_data(client, reg);
ret = i2c_smbus_read_word_swapped(client, reg);
if (ret < 0) {
dev_err(&client->dev, "I2C read error\n");
return ret;
}
*data = swab16((u16)ret);
*data = ret;
return 0;
}
static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data)
{
return i2c_smbus_write_word_data(chip->client, reg, swab16(data));
}
static ssize_t ad7291_store_reset(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7291_chip_info *chip = iio_priv(indio_dev);
return ad7291_i2c_write(chip, AD7291_COMMAND,
chip->command | AD7291_RESET);
return i2c_smbus_write_word_swapped(chip->client, reg, data);
}
static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, ad7291_store_reset, 0);
static struct attribute *ad7291_attributes[] = {
&iio_dev_attr_reset.dev_attr.attr,
NULL,
};
static const struct attribute_group ad7291_attribute_group = {
.attrs = ad7291_attributes,
};
static irqreturn_t ad7291_event_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
......@@ -255,31 +209,31 @@ static inline ssize_t ad7291_set_hyst(struct device *dev,
static IIO_DEVICE_ATTR(in_temp0_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst,
AD7291_T_SENSE_HYST);
AD7291_HYST(8));
static IIO_DEVICE_ATTR(in_voltage0_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_CH0_HYST);
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(0));
static IIO_DEVICE_ATTR(in_voltage1_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_CH1_HYST);
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(1));
static IIO_DEVICE_ATTR(in_voltage2_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_CH2_HYST);
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(2));
static IIO_DEVICE_ATTR(in_voltage3_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_CH3_HYST);
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(3));
static IIO_DEVICE_ATTR(in_voltage4_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_CH4_HYST);
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(4));
static IIO_DEVICE_ATTR(in_voltage5_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_CH5_HYST);
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(5));
static IIO_DEVICE_ATTR(in_voltage6_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_CH6_HYST);
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(6));
static IIO_DEVICE_ATTR(in_voltage7_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_CH7_HYST);
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(7));
static struct attribute *ad7291_event_attributes[] = {
&iio_dev_attr_in_temp0_thresh_both_hyst_raw.dev_attr.attr,
......@@ -294,53 +248,45 @@ static struct attribute *ad7291_event_attributes[] = {
NULL,
};
/* high / low */
static u8 ad7291_limit_regs[9][2] = {
{ AD7291_CH0_DATA_HIGH, AD7291_CH0_DATA_LOW },
{ AD7291_CH1_DATA_HIGH, AD7291_CH1_DATA_LOW },
{ AD7291_CH2_DATA_HIGH, AD7291_CH2_DATA_LOW },
{ AD7291_CH3_DATA_HIGH, AD7291_CH3_DATA_LOW }, /* FIXME: ? */
{ AD7291_CH4_DATA_HIGH, AD7291_CH4_DATA_LOW },
{ AD7291_CH5_DATA_HIGH, AD7291_CH5_DATA_LOW },
{ AD7291_CH6_DATA_HIGH, AD7291_CH6_DATA_LOW },
{ AD7291_CH7_DATA_HIGH, AD7291_CH7_DATA_LOW },
/* temp */
{ AD7291_T_SENSE_HIGH, AD7291_T_SENSE_LOW },
};
static unsigned int ad7291_threshold_reg(u64 event_code)
{
unsigned int offset;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
case IIO_VOLTAGE:
offset = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
break;
case IIO_TEMP:
offset = 8;
break;
default:
return 0;
}
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
return AD7291_DATA_LOW(offset);
else
return AD7291_DATA_HIGH(offset);
}
static int ad7291_read_event_value(struct iio_dev *indio_dev,
u64 event_code,
int *val)
{
struct ad7291_chip_info *chip = iio_priv(indio_dev);
int ret;
u8 reg;
u16 uval;
s16 signval;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
case IIO_VOLTAGE:
reg = ad7291_limit_regs[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)]
[!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
IIO_EV_DIR_RISING)];
ret = ad7291_i2c_read(chip, reg, &uval);
ret = ad7291_i2c_read(chip, ad7291_threshold_reg(event_code), &uval);
if (ret < 0)
return ret;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
case IIO_VOLTAGE:
*val = uval & AD7291_VALUE_MASK;
return 0;
case IIO_TEMP:
reg = ad7291_limit_regs[8]
[!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
IIO_EV_DIR_RISING)];
ret = ad7291_i2c_read(chip, reg, &signval);
if (ret < 0)
return ret;
signval = (s16)((signval & AD7291_VALUE_MASK) << 4) >> 4;
*val = signval;
*val = sign_extend32(uval, 11);
return 0;
default:
return -EINVAL;
......@@ -352,28 +298,21 @@ static int ad7291_write_event_value(struct iio_dev *indio_dev,
int val)
{
struct ad7291_chip_info *chip = iio_priv(indio_dev);
u8 reg;
s16 signval;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
case IIO_VOLTAGE:
if (val > AD7291_VALUE_MASK || val < 0)
return -EINVAL;
reg = ad7291_limit_regs[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)]
[!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
IIO_EV_DIR_RISING)];
return ad7291_i2c_write(chip, reg, val);
break;
case IIO_TEMP:
if (val > 2047 || val < -2048)
return -EINVAL;
reg = ad7291_limit_regs[8]
[!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
IIO_EV_DIR_RISING)];
signval = val;
return ad7291_i2c_write(chip, reg, *(u16 *)&signval);
break;
default:
return -EINVAL;
};
}
return ad7291_i2c_write(chip, ad7291_threshold_reg(event_code), val);
}
static int ad7291_read_event_config(struct iio_dev *indio_dev,
......@@ -456,9 +395,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
{
int ret;
struct ad7291_chip_info *chip = iio_priv(indio_dev);
unsigned int scale_uv;
u16 regval;
s16 signval;
switch (mask) {
case IIO_CHAN_INFO_RAW:
......@@ -479,44 +416,47 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
return ret;
}
/* Read voltage */
ret = i2c_smbus_read_word_data(chip->client,
ret = i2c_smbus_read_word_swapped(chip->client,
AD7291_VOLTAGE);
if (ret < 0) {
mutex_unlock(&chip->state_lock);
return ret;
}
*val = swab16((u16)ret) & AD7291_VALUE_MASK;
*val = ret & AD7291_VALUE_MASK;
mutex_unlock(&chip->state_lock);
return IIO_VAL_INT;
case IIO_TEMP:
/* Assumes tsense bit of command register always set */
ret = i2c_smbus_read_word_data(chip->client,
ret = i2c_smbus_read_word_swapped(chip->client,
AD7291_T_SENSE);
if (ret < 0)
return ret;
signval = (s16)((swab16((u16)ret) &
AD7291_VALUE_MASK) << 4) >> 4;
*val = signval;
*val = sign_extend32(ret, 11);
return IIO_VAL_INT;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_AVERAGE_RAW:
ret = i2c_smbus_read_word_data(chip->client,
ret = i2c_smbus_read_word_swapped(chip->client,
AD7291_T_AVERAGE);
if (ret < 0)
return ret;
signval = (s16)((swab16((u16)ret) &
AD7291_VALUE_MASK) << 4) >> 4;
*val = signval;
*val = sign_extend32(ret, 11);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
scale_uv = (chip->int_vref_mv * 1000) >> AD7291_BITS;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
if (chip->reg) {
int vref;
vref = regulator_get_voltage(chip->reg);
if (vref < 0)
return vref;
*val = vref / 1000;
} else {
*val = 2500;
}
*val2 = AD7291_BITS;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_TEMP:
/*
* One LSB of the ADC corresponds to 0.25 deg C.
......@@ -571,7 +511,6 @@ static struct attribute_group ad7291_event_attribute_group = {
};
static const struct iio_info ad7291_info = {
.attrs = &ad7291_attribute_group,
.read_raw = &ad7291_read_raw,
.read_event_config = &ad7291_read_event_config,
.write_event_config = &ad7291_write_event_config,
......@@ -583,9 +522,10 @@ static const struct iio_info ad7291_info = {
static int ad7291_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ad7291_platform_data *pdata = client->dev.platform_data;
struct ad7291_chip_info *chip;
struct iio_dev *indio_dev;
int ret = 0, voltage_uv = 0;
int ret = 0;
indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
......@@ -594,12 +534,14 @@ static int ad7291_probe(struct i2c_client *client,
}
chip = iio_priv(indio_dev);
chip->reg = regulator_get(&client->dev, "vcc");
if (!IS_ERR(chip->reg)) {
if (pdata && pdata->use_external_ref) {
chip->reg = regulator_get(&client->dev, "vref");
if (IS_ERR(chip->reg))
goto error_free;
ret = regulator_enable(chip->reg);
if (ret)
goto error_put_reg;
voltage_uv = regulator_get_voltage(chip->reg);
}
mutex_init(&chip->state_lock);
......@@ -612,12 +554,8 @@ static int ad7291_probe(struct i2c_client *client,
AD7291_T_SENSE_MASK | /* Tsense always enabled */
AD7291_ALERT_POLARITY; /* set irq polarity low level */
if (voltage_uv) {
chip->int_vref_mv = voltage_uv / 1000;
if (pdata && pdata->use_external_ref)
chip->command |= AD7291_EXT_REF;
} else {
chip->int_vref_mv = 2500; /* Build-in ref */
}
indio_dev->name = id->name;
indio_dev->channels = ad7291_channels;
......@@ -654,21 +592,18 @@ static int ad7291_probe(struct i2c_client *client,
if (ret)
goto error_unreg_irq;
dev_info(&client->dev, "%s ADC registered.\n",
id->name);
return 0;
error_unreg_irq:
if (client->irq)
free_irq(client->irq, indio_dev);
error_disable_reg:
if (!IS_ERR(chip->reg))
if (chip->reg)
regulator_disable(chip->reg);
error_put_reg:
if (!IS_ERR(chip->reg))
if (chip->reg)
regulator_put(chip->reg);
error_free:
iio_device_free(indio_dev);
error_ret:
return ret;
......@@ -684,7 +619,7 @@ static int ad7291_remove(struct i2c_client *client)
if (client->irq)
free_irq(client->irq, indio_dev);
if (!IS_ERR(chip->reg)) {
if (chip->reg) {
regulator_disable(chip->reg);
regulator_put(chip->reg);
}
......
#ifndef __IIO_AD7291_H__
#define __IIO_AD7291_H__
/**
* struct ad7291_platform_data - AD7291 platform data
* @use_external_ref: Whether to use an external or internal reference voltage
*/
struct ad7291_platform_data {
bool use_external_ref;
};
#endif
......@@ -10,13 +10,6 @@ config ADIS16060
Say yes here to build support for Analog Devices adis16060 wide bandwidth
yaw rate gyroscope with SPI.
config ADIS16130
tristate "Analog Devices ADIS16130 High Precision Angular Rate Sensor driver"
depends on SPI
help
Say yes here to build support for Analog Devices ADIS16130 High Precision
Angular Rate Sensor driver.
config ADIS16260
tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
depends on SPI
......
......@@ -5,8 +5,5 @@
adis16060-y := adis16060_core.o
obj-$(CONFIG_ADIS16060) += adis16060.o
adis16130-y := adis16130_core.o
obj-$(CONFIG_ADIS16130) += adis16130.o
adis16260-y := adis16260_core.o
obj-$(CONFIG_ADIS16260) += adis16260.o
/*
* Analog Devices AD7303 DAC driver
*
* Copyright 2013 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
#ifndef __IIO_ADC_AD7303_H__
#define __IIO_ADC_AD7303_H__
/**
* struct ad7303_platform_data - AD7303 platform data
* @use_external_ref: If set to true use an external voltage reference connected
* to the REF pin, otherwise use the internal reference derived from Vdd.
*/
struct ad7303_platform_data {
bool use_external_ref;
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment