Commit b13bc8dd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'staging-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging tree patches from Greg Kroah-Hartman:
 "Here's the big staging tree merge for the 3.6-rc1 merge window.

  There are some patches in here outside of drivers/staging/, notibly
  the iio code (which is still stradeling the staging / not staging
  boundry), the pstore code, and the tracing code.  All of these have
  gotten acks from the various subsystem maintainers to be included in
  this tree.  The pstore and tracing patches are related, and are coming
  here as they replace one of the android staging drivers.

  Otherwise, the normal staging mess.  Lots of cleanups and a few new
  drivers (some iio drivers, and the large csr wireless driver
  abomination.)

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

Fixed up trivial conflicts in drivers/staging/comedi/drivers/s626.h and
drivers/staging/gdm72xx/netlink_k.c

* tag 'staging-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1108 commits)
  staging: csr: delete a bunch of unused library functions
  staging: csr: remove csr_utf16.c
  staging: csr: remove csr_pmem.h
  staging: csr: remove CsrPmemAlloc
  staging: csr: remove CsrPmemFree()
  staging: csr: remove CsrMemAllocDma()
  staging: csr: remove CsrMemCalloc()
  staging: csr: remove CsrMemAlloc()
  staging: csr: remove CsrMemFree() and CsrMemFreeDma()
  staging: csr: remove csr_util.h
  staging: csr: remove CsrOffSetOf()
  stating: csr: remove unneeded #includes in csr_util.c
  staging: csr: make CsrUInt16ToHex static
  staging: csr: remove CsrMemCpy()
  staging: csr: remove CsrStrLen()
  staging: csr: remove CsrVsnprintf()
  staging: csr: remove CsrStrDup
  staging: csr: remove CsrStrChr()
  staging: csr: remove CsrStrNCmp
  staging: csr: remove CsrStrCmp
  ...
parents 9fc37779 419e9266
......@@ -40,9 +40,9 @@ Contact: linux-iio@vger.kernel.org
Description:
Some devices have internal clocks. This parameter sets the
resulting sampling frequency. In many devices this
parameter has an effect on input filters etc rather than
parameter has an effect on input filters etc. rather than
simply controlling when the input is sampled. As this
effects datardy triggers, hardware buffers and the sysfs
effects data ready triggers, hardware buffers and the sysfs
direct access interfaces, it may be found in any of the
relevant directories. If it effects all of the above
then it is to be found in the base device directory.
......@@ -74,7 +74,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_raw
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no bias removal etc) voltage measurement from
Raw (unscaled no bias removal etc.) voltage measurement from
channel Y. In special cases where the channel does not
correspond to externally available input one of the named
versions may be used. The number must always be specified and
......@@ -118,11 +118,11 @@ What: /sys/bus/iio/devices/iio:deviceX/in_temp_z_raw
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no bias removal etc) temperature measurement.
Raw (unscaled no bias removal etc.) temperature measurement.
If an axis is specified it generally means that the temperature
sensor is associated with one part of a compound device (e.g.
a gyroscope axis). Units after application of scale and offset
are milli degrees Celsuis.
are milli degrees Celsius.
What: /sys/bus/iio/devices/iio:deviceX/in_tempX_input
KernelVersion: 2.6.38
......@@ -148,10 +148,9 @@ KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
Angular velocity about axis x, y or z (may be arbitrarily
assigned) Data converted by application of offset then scale to
radians per second. Has all the equivalent parameters as
per voltageY. Units after application of scale and offset are
radians per second.
assigned). Has all the equivalent parameters as per voltageY.
Units after application of scale and offset are radians per
second.
What: /sys/bus/iio/devices/iio:deviceX/in_incli_x_raw
What: /sys/bus/iio/devices/iio:deviceX/in_incli_y_raw
......@@ -161,7 +160,7 @@ Contact: linux-iio@vger.kernel.org
Description:
Inclination raw reading about axis x, y or z (may be
arbitrarily assigned). Data converted by application of offset
and scale to Degrees.
and scale to degrees.
What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_raw
What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_raw
......@@ -203,7 +202,7 @@ Contact: linux-iio@vger.kernel.org
Description:
If known for a device, offset to be added to <type>[Y]_raw prior
to scaling by <type>[Y]_scale in order to obtain value in the
<type> units as specified in <type>[y]_raw documentation.
<type> units as specified in <type>[Y]_raw documentation.
Not present if the offset is always 0 or unknown. If Y or
axis <x|y|z> is not present, then the offset applies to all
in channels of <type>.
......@@ -249,7 +248,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
Hardware applied calibration offset. (assumed to fix production
Hardware applied calibration offset (assumed to fix production
inaccuracies).
What /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale
......@@ -266,7 +265,7 @@ what /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
Hardware applied calibration scale factor. (assumed to fix
Hardware applied calibration scale factor (assumed to fix
production inaccuracies). If shared across all channels,
<type>_calibscale is used.
......@@ -276,10 +275,10 @@ What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available
What: /sys/.../iio:deviceX/out_voltageX_scale_available
What: /sys/.../iio:deviceX/out_altvoltageX_scale_available
What: /sys/.../iio:deviceX/in_capacitance_scale_available
KernelVersion: 2.635
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
If a discrete set of scale values are available, they
If a discrete set of scale values is available, they
are listed in this attribute.
What /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain
......@@ -330,9 +329,11 @@ Contact: linux-iio@vger.kernel.org
Description:
Specifies the output powerdown mode.
DAC output stage is disconnected from the amplifier and
1kohm_to_gnd: connected to ground via an 1kOhm resistor
100kohm_to_gnd: connected to ground via an 100kOhm resistor
three_state: left floating
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
100kohm_to_gnd: connected to ground via an 100kOhm resistor,
three_state: left floating.
For a list of available output power down options read
outX_powerdown_mode_available. If Y is not present the
mode is shared across all outputs.
......@@ -355,9 +356,10 @@ KernelVersion: 2.6.38
Contact: linux-iio@vger.kernel.org
Description:
Writing 1 causes output Y to enter the power down mode specified
by the corresponding outY_powerdown_mode. Clearing returns to
normal operation. Y may be suppressed if all outputs are
controlled together.
by the corresponding outY_powerdown_mode. DAC output stage is
disconnected from the amplifier. Clearing returns to normal
operation. Y may be suppressed if all outputs are controlled
together.
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency
KernelVersion: 3.4.0
......@@ -421,12 +423,12 @@ Description:
different values, but the device can only enable both thresholds
or neither.
Note the driver will assume the last p events requested are
to be enabled where p is however many it supports (which may
vary depending on the exact set requested. So if you want to be
to be enabled where p is how many it supports (which may vary
depending on the exact set requested. So if you want to be
sure you have set what you think you have, check the contents of
these attributes after everything is configured. Drivers may
have to buffer any parameters so that they are consistent when
a given event type is enabled a future point (and not those for
a given event type is enabled at a future point (and not those for
whatever event was previously enabled).
What: /sys/.../iio:deviceX/events/in_accel_x_roc_rising_en
......@@ -702,7 +704,7 @@ 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-in_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
KernelVersion: 2.6.37
......@@ -723,7 +725,7 @@ Description:
the buffer output value appropriately. The storagebits value
also specifies the data alignment. So s48/64>>2 will be a
signed 48 bit integer stored in a 64 bit location aligned to
a a64 bit boundary. To obtain the clean value, shift right 2
a 64 bit boundary. To obtain the clean value, shift right 2
and apply a mask to zero the top 16 bits of the result.
For other storage combinations this attribute will be extended
appropriately.
......
What: /sys/bus/iio/devices/iio:deviceX/pll2_feedback_clk_present
What: /sys/bus/iio/devices/iio:deviceX/pll2_reference_clk_present
What: /sys/bus/iio/devices/iio:deviceX/pll1_reference_clk_a_present
What: /sys/bus/iio/devices/iio:deviceX/pll1_reference_clk_b_present
What: /sys/bus/iio/devices/iio:deviceX/pll1_reference_clk_test_present
What: /sys/bus/iio/devices/iio:deviceX/vcxo_clk_present
KernelVersion: 3.4.0
Contact: linux-iio@vger.kernel.org
Description:
Reading returns either '1' or '0'.
'1' means that the clock in question is present.
'0' means that the clock is missing.
What: /sys/bus/iio/devices/iio:deviceX/pllY_locked
KernelVersion: 3.4.0
Contact: linux-iio@vger.kernel.org
Description:
Reading returns either '1' or '0'. '1' means that the
pllY is locked.
What: /sys/bus/iio/devices/iio:deviceX/store_eeprom
KernelVersion: 3.4.0
Contact: linux-iio@vger.kernel.org
Description:
Writing '1' stores the current device configuration into
on-chip EEPROM. After power-up or chip reset the device will
automatically load the saved configuration.
What: /sys/bus/iio/devices/iio:deviceX/sync_dividers
KernelVersion: 3.4.0
Contact: linux-iio@vger.kernel.org
Description:
Writing '1' triggers the clock distribution synchronization
functionality. All dividers are reset and the channels start
with their predefined phase offsets (out_altvoltageY_phase).
Writing this file has the effect as driving the external
/SYNC pin low.
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency_resolution
KernelVersion: 3.4.0
Contact: linux-iio@vger.kernel.org
Description:
Stores channel Y frequency resolution/channel spacing in Hz.
The value given directly influences the MODULUS used by
the fractional-N PLL. It is assumed that the algorithm
that is used to compute the various dividers, is able to
generate proper values for multiples of channel spacing.
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_refin_frequency
KernelVersion: 3.4.0
Contact: linux-iio@vger.kernel.org
Description:
Sets channel Y REFin frequency in Hz. In some clock chained
applications, the reference frequency used by the PLL may
change during runtime. This attribute allows the user to
adjust the reference frequency accordingly.
The value written has no effect until out_altvoltageY_frequency
is updated. Consider to use out_altvoltageY_powerdown to power
down the PLL and it's RFOut buffers during REFin changes.
What: /sys/.../events/in_illuminance0_thresh_either_en
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Event generated when channel passes one of the four thresholds
in each direction (rising|falling) and a zone change occurs.
The corresponding light zone can be read from
in_illuminance0_zone.
What: /sys/.../events/in_illuminance0_threshY_hysteresis
Date: May 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Get the hysteresis for thresholds Y, that is,
threshY_hysteresis = threshY_raising - threshY_falling
What: /sys/.../events/illuminance_threshY_falling_value
What: /sys/.../events/illuminance_threshY_raising_value
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Specifies the value of threshold that the device is comparing
against for the events enabled by
in_illuminance0_thresh_either_en (0..255), where Y in 0..3.
Note that threshY_falling must be less than or equal to
threshY_raising.
These thresholds correspond to the eight zone-boundary
registers (boundaryY_{low,high}) and define the five light
zones.
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_zone
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Get the current light zone (0..4) as defined by the
in_illuminance0_threshY_{falling,rising} thresholds.
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw
Date: May 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Get output current for channel Y (0..255), that is,
out_currentY_currentZ_raw, where Z is the current zone.
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_currentZ_raw
Date: May 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the output current for channel out_currentY when in zone
Z (0..255), where Y in 0..2 and Z in 0..4.
These values correspond to the ALS-mapper target registers for
ALS-mapper Y + 1.
......@@ -40,6 +40,12 @@ corrupt, but usually it is restorable.
Setting the ramoops parameters can be done in 2 different manners:
1. Use the module parameters (which have the names of the variables described
as before).
For quick debugging, you can also reserve parts of memory during boot
and then use the reserved memory for ramoops. For example, assuming a machine
with > 128 MB of memory, the following kernel command line will tell the
kernel to use only the first 128 MB of memory, and place ECC-protected ramoops
region at 128 MB boundary:
"mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1"
2. Use a platform device and set the platform data. The parameters can then
be set through that platform data. An example of doing that is:
......@@ -70,6 +76,14 @@ if (ret) {
return ret;
}
You can specify either RAM memory or peripheral devices' memory. However, when
specifying RAM, be sure to reserve the memory by issuing memblock_reserve()
very early in the architecture code, e.g.:
#include <linux/memblock.h>
memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size);
3. Dump format
The data dump begins with a header, currently defined as "====" followed by a
......@@ -80,3 +94,28 @@ timestamp and a new line. The dump then continues with the actual data.
The dump data can be read from the pstore filesystem. The format for these
files is "dmesg-ramoops-N", where N is the record number in memory. To delete
a stored record from RAM, simply unlink the respective pstore file.
5. Persistent function tracing
Persistent function tracing might be useful for debugging software or hardware
related hangs. The functions call chain log is stored in a "ftrace-ramoops"
file. Here is an example of usage:
# mount -t debugfs debugfs /sys/kernel/debug/
# cd /sys/kernel/debug/tracing
# echo function > current_tracer
# echo 1 > options/func_pstore
# reboot -f
[...]
# mount -t pstore pstore /mnt/
# tail /mnt/ftrace-ramoops
0 ffffffff8101ea64 ffffffff8101bcda native_apic_mem_read <- disconnect_bsp_APIC+0x6a/0xc0
0 ffffffff8101ea44 ffffffff8101bcf6 native_apic_mem_write <- disconnect_bsp_APIC+0x86/0xc0
0 ffffffff81020084 ffffffff8101a4b5 hpet_disable <- native_machine_shutdown+0x75/0x90
0 ffffffff81005f94 ffffffff8101a4bb iommu_shutdown_noop <- native_machine_shutdown+0x7b/0x90
0 ffffffff8101a6a1 ffffffff8101a437 native_machine_emergency_restart <- native_machine_restart+0x37/0x40
0 ffffffff811f9876 ffffffff8101a73a acpi_reboot <- native_machine_emergency_restart+0xaa/0x1e0
0 ffffffff8101a514 ffffffff8101a772 mach_reboot_fixups <- native_machine_emergency_restart+0xe2/0x1e0
0 ffffffff811d9c54 ffffffff8101a7a0 __const_udelay <- native_machine_emergency_restart+0x110/0x1e0
0 ffffffff811d9c34 ffffffff811d9c80 __delay <- __const_udelay+0x30/0x40
0 ffffffff811d9d14 ffffffff811d9c3f delay_tsc <- __delay+0xf/0x20
......@@ -29,6 +29,13 @@ config IIO_KFIFO_BUF
no buffer events so it is up to userspace to work out how
often to read from the buffer.
config IIO_TRIGGERED_BUFFER
tristate
select IIO_TRIGGER
select IIO_KFIFO_BUF
help
Provides helper functions for setting up triggered buffers.
endif # IIO_BUFFER
config IIO_TRIGGER
......@@ -49,5 +56,8 @@ config IIO_CONSUMERS_PER_TRIGGER
source "drivers/iio/adc/Kconfig"
source "drivers/iio/amplifiers/Kconfig"
source "drivers/iio/light/Kconfig"
source "drivers/iio/frequency/Kconfig"
source "drivers/iio/dac/Kconfig"
endif # IIO
......@@ -7,7 +7,11 @@ industrialio-y := industrialio-core.o industrialio-event.o inkern.o
industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
obj-y += adc/
obj-y += amplifiers/
obj-y += light/
obj-y += frequency/
obj-y += dac/
......@@ -3,12 +3,21 @@
#
menu "Analog to digital converters"
config AD7266
tristate "Analog Devices AD7265/AD7266 ADC driver"
depends on SPI_MASTER
select IIO_BUFFER
select IIO_TRIGGER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Analog Devices AD7265 and AD7266
ADCs.
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91
select IIO_BUFFER
select IIO_KFIFO_BUF
select IIO_TRIGGER
select IIO_TRIGGERED_BUFFER
select SYSFS
help
Say yes here to build support for Atmel AT91 ADC.
......
......@@ -2,4 +2,5 @@
# Makefile for IIO ADC drivers
#
obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
This diff is collapsed.
......@@ -26,9 +26,9 @@
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <mach/at91_adc.h>
......@@ -318,58 +318,15 @@ static void at91_adc_trigger_remove(struct iio_dev *idev)
}
}
static const struct iio_buffer_setup_ops at91_adc_buffer_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
};
static int at91_adc_buffer_init(struct iio_dev *idev)
{
int ret;
idev->buffer = iio_kfifo_allocate(idev);
if (!idev->buffer) {
ret = -ENOMEM;
goto error_ret;
}
idev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&at91_adc_trigger_handler,
IRQF_ONESHOT,
idev,
"%s-consumer%d",
idev->name,
idev->id);
if (idev->pollfunc == NULL) {
ret = -ENOMEM;
goto error_pollfunc;
}
idev->setup_ops = &at91_adc_buffer_ops;
idev->modes |= INDIO_BUFFER_TRIGGERED;
ret = iio_buffer_register(idev,
idev->channels,
idev->num_channels);
if (ret)
goto error_register;
return 0;
error_register:
iio_dealloc_pollfunc(idev->pollfunc);
error_pollfunc:
iio_kfifo_free(idev->buffer);
error_ret:
return ret;
return iio_triggered_buffer_setup(idev, &iio_pollfunc_store_time,
&at91_adc_trigger_handler, NULL);
}
static void at91_adc_buffer_remove(struct iio_dev *idev)
{
iio_buffer_unregister(idev);
iio_dealloc_pollfunc(idev->pollfunc);
iio_kfifo_free(idev->buffer);
iio_triggered_buffer_cleanup(idev);
}
static int at91_adc_read_raw(struct iio_dev *idev,
......@@ -392,9 +349,11 @@ static int at91_adc_read_raw(struct iio_dev *idev,
st->done,
msecs_to_jiffies(1000));
if (ret == 0)
return -ETIMEDOUT;
else if (ret < 0)
ret = -ETIMEDOUT;
if (ret < 0) {
mutex_unlock(&st->lock);
return ret;
}
*val = st->last_value;
......
......@@ -4,12 +4,12 @@
menu "Digital to analog converters"
config AD5064
tristate "Analog Devices AD5064/64-1/65/44/45/24/25, AD5628/48/66/68 DAC driver"
depends on SPI
tristate "Analog Devices AD5064 and similar multi-channel DAC driver"
depends on (SPI_MASTER || I2C)
help
Say yes here to build support for Analog Devices AD5024, AD5025, AD5044,
AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, AD5666, AD5668 Digital
to Analog Converter.
AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668,
AD5669R Digital to Analog Converter.
To compile this driver as a module, choose M here: the
module will be called ad5064.
......@@ -59,9 +59,9 @@ config AD5446
tristate "Analog Devices AD5446 and similar single channel DACs driver"
depends on SPI
help
Say yes here to build support for Analog Devices AD5444, AD5446,
AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, AD5611, AD5620,
AD5621, AD5640, AD5660, AD5662 DACs.
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.
To compile this driver as a module, choose M here: the
module will be called ad5446.
......@@ -118,4 +118,15 @@ config MAX517
This driver can also be built as a module. If so, the module
will be called max517.
config MCP4725
tristate "MCP4725 DAC driver"
depends on I2C
---help---
Say Y here if you want to build a driver for the Microchip
MCP 4725 12-bit digital-to-analog converter (DAC) with I2C
interface.
To compile this driver as a module, choose M here: the module
will be called mcp4725.
endmenu
......@@ -13,3 +13,4 @@ obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MCP4725) += mcp4725.o
......@@ -18,7 +18,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "dac.h"
#define AD5360_CMD(x) ((x) << 22)
#define AD5360_ADDR(x) ((x) << 16)
......
......@@ -20,8 +20,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "dac.h"
#define AD5380_REG_DATA(x) (((x) << 2) | 3)
#define AD5380_REG_OFFSET(x) (((x) << 2) | 2)
......@@ -81,103 +79,18 @@ enum ad5380_type {
ID_AD5392_5,
};
#define AD5380_CHANNEL(_bits) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
.scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)) \
}
static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
[ID_AD5380_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 40,
.int_vref = 1250000,
},
[ID_AD5380_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 40,
.int_vref = 2500000,
},
[ID_AD5381_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 1250000,
},
[ID_AD5381_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 2500000,
},
[ID_AD5382_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 32,
.int_vref = 1250000,
},
[ID_AD5382_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 32,
.int_vref = 2500000,
},
[ID_AD5383_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 32,
.int_vref = 1250000,
},
[ID_AD5383_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 32,
.int_vref = 2500000,
},
[ID_AD5390_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 16,
.int_vref = 1250000,
},
[ID_AD5390_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 16,
.int_vref = 2500000,
},
[ID_AD5391_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 1250000,
},
[ID_AD5391_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 2500000,
},
[ID_AD5392_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 8,
.int_vref = 1250000,
},
[ID_AD5392_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 8,
.int_vref = 2500000,
},
};
static ssize_t ad5380_read_dac_powerdown(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t ad5380_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5380_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->pwr_down);
}
static ssize_t ad5380_write_dac_powerdown(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5380_state *st = iio_priv(indio_dev);
bool pwr_down;
int ret;
......@@ -200,20 +113,14 @@ static ssize_t ad5380_write_dac_powerdown(struct device *dev,
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(out_voltage_powerdown,
S_IRUGO | S_IWUSR,
ad5380_read_dac_powerdown,
ad5380_write_dac_powerdown, 0);
static const char ad5380_powerdown_modes[][15] = {
[0] = "100kohm_to_gnd",
[1] = "three_state",
static const char * const ad5380_powerdown_modes[] = {
"100kohm_to_gnd",
"three_state",
};
static ssize_t ad5380_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
static int ad5380_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5380_state *st = iio_priv(indio_dev);
unsigned int mode;
int ret;
......@@ -224,49 +131,27 @@ static ssize_t ad5380_read_powerdown_mode(struct device *dev,
mode = (mode >> AD5380_CTRL_PWR_DOWN_MODE_OFFSET) & 1;
return sprintf(buf, "%s\n", ad5380_powerdown_modes[mode]);
return mode;
}
static ssize_t ad5380_write_powerdown_mode(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
static int ad5380_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int mode)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5380_state *st = iio_priv(indio_dev);
unsigned int i;
int ret;
for (i = 0; i < ARRAY_SIZE(ad5380_powerdown_modes); ++i) {
if (sysfs_streq(buf, ad5380_powerdown_modes[i]))
break;
}
if (i == ARRAY_SIZE(ad5380_powerdown_modes))
return -EINVAL;
ret = regmap_update_bits(st->regmap, AD5380_REG_SF_CTRL,
1 << AD5380_CTRL_PWR_DOWN_MODE_OFFSET,
i << AD5380_CTRL_PWR_DOWN_MODE_OFFSET);
mode << AD5380_CTRL_PWR_DOWN_MODE_OFFSET);
return ret ? ret : len;
return ret;
}
static IIO_DEVICE_ATTR(out_voltage_powerdown_mode,
S_IRUGO | S_IWUSR,
ad5380_read_powerdown_mode,
ad5380_write_powerdown_mode, 0);
static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"100kohm_to_gnd three_state");
static struct attribute *ad5380_attributes[] = {
&iio_dev_attr_out_voltage_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ad5380_attribute_group = {
.attrs = ad5380_attributes,
static const struct iio_enum ad5380_powerdown_mode_enum = {
.items = ad5380_powerdown_modes,
.num_items = ARRAY_SIZE(ad5380_powerdown_modes),
.get = ad5380_get_powerdown_mode,
.set = ad5380_set_powerdown_mode,
};
static unsigned int ad5380_info_to_reg(struct iio_chan_spec const *chan,
......@@ -354,10 +239,105 @@ static int ad5380_read_raw(struct iio_dev *indio_dev,
static const struct iio_info ad5380_info = {
.read_raw = ad5380_read_raw,
.write_raw = ad5380_write_raw,
.attrs = &ad5380_attribute_group,
.driver_module = THIS_MODULE,
};
static struct iio_chan_spec_ext_info ad5380_ext_info[] = {
{
.name = "powerdown",
.read = ad5380_read_dac_powerdown,
.write = ad5380_write_dac_powerdown,
},
IIO_ENUM("powerdown_mode", true, &ad5380_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum),
{ },
};
#define AD5380_CHANNEL(_bits) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
.scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)), \
.ext_info = ad5380_ext_info, \
}
static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
[ID_AD5380_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 40,
.int_vref = 1250000,
},
[ID_AD5380_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 40,
.int_vref = 2500000,
},
[ID_AD5381_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 1250000,
},
[ID_AD5381_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 2500000,
},
[ID_AD5382_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 32,
.int_vref = 1250000,
},
[ID_AD5382_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 32,
.int_vref = 2500000,
},
[ID_AD5383_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 32,
.int_vref = 1250000,
},
[ID_AD5383_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 32,
.int_vref = 2500000,
},
[ID_AD5390_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 16,
.int_vref = 1250000,
},
[ID_AD5390_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 16,
.int_vref = 2500000,
},
[ID_AD5391_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 1250000,
},
[ID_AD5391_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 2500000,
},
[ID_AD5392_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 8,
.int_vref = 1250000,
},
[ID_AD5392_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 8,
.int_vref = 2500000,
},
};
static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev)
{
struct ad5380_state *st = iio_priv(indio_dev);
......@@ -393,7 +373,7 @@ static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap,
if (indio_dev == NULL) {
dev_err(dev, "Failed to allocate iio device\n");
ret = -ENOMEM;
goto error_regmap_exit;
goto error_out;
}
st = iio_priv(indio_dev);
......@@ -456,8 +436,7 @@ static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap,
kfree(indio_dev->channels);
error_free:
iio_device_free(indio_dev);
error_regmap_exit:
regmap_exit(regmap);
error_out:
return ret;
}
......@@ -476,7 +455,6 @@ static int __devexit ad5380_remove(struct device *dev)
regulator_put(st->vref_reg);
}
regmap_exit(st->regmap);
iio_device_free(indio_dev);
return 0;
......@@ -505,7 +483,7 @@ static int __devinit ad5380_spi_probe(struct spi_device *spi)
const struct spi_device_id *id = spi_get_device_id(spi);
struct regmap *regmap;
regmap = regmap_init_spi(spi, &ad5380_regmap_config);
regmap = devm_regmap_init_spi(spi, &ad5380_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
......@@ -579,7 +557,7 @@ static int __devinit ad5380_i2c_probe(struct i2c_client *i2c,
{
struct regmap *regmap;
regmap = regmap_init_i2c(i2c, &ad5380_regmap_config);
regmap = devm_regmap_init_i2c(i2c, &ad5380_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
......
......@@ -19,8 +19,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include "dac.h"
#include "ad5421.h"
#include <linux/iio/dac/ad5421.h>
#define AD5421_REG_DAC_DATA 0x1
......
......@@ -20,7 +20,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "dac.h"
#include "ad5446.h"
......@@ -42,47 +41,34 @@ static int ad5660_write(struct ad5446_state *st, unsigned val)
}
static const char * const ad5446_powerdown_modes[] = {
"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"
"1kohm_to_gnd", "100kohm_to_gnd", "three_state"
};
static ssize_t ad5446_read_powerdown_mode_available(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
return sprintf(buf, "%s %s %s\n", ad5446_powerdown_modes[1],
ad5446_powerdown_modes[2], ad5446_powerdown_modes[3]);
}
static ssize_t ad5446_write_powerdown_mode(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
const char *buf, size_t len)
static int ad5446_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int mode)
{
struct ad5446_state *st = iio_priv(indio_dev);
int i;
for (i = 1; i < ARRAY_SIZE(ad5446_powerdown_modes); i++) {
if (sysfs_streq(buf, ad5446_powerdown_modes[i])) {
st->pwr_down_mode = i;
break;
}
}
if (i == ARRAY_SIZE(ad5446_powerdown_modes))
return -EINVAL;
st->pwr_down_mode = mode + 1;
return len;
return 0;
}
static ssize_t ad5446_read_powerdown_mode(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
char *buf)
static int ad5446_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct ad5446_state *st = iio_priv(indio_dev);
return sprintf(buf, "%s\n", ad5446_powerdown_modes[st->pwr_down_mode]);
return st->pwr_down_mode - 1;
}
static const struct iio_enum ad5446_powerdown_mode_enum = {
.items = ad5446_powerdown_modes,
.num_items = ARRAY_SIZE(ad5446_powerdown_modes),
.get = ad5446_get_powerdown_mode,
.set = ad5446_set_powerdown_mode,
};
static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
......@@ -129,15 +115,9 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = {
.name = "powerdown",
.read = ad5446_read_dac_powerdown,
.write = ad5446_write_dac_powerdown,
}, {
.name = "powerdown_mode",
.read = ad5446_read_powerdown_mode,
.write = ad5446_write_powerdown_mode,
}, {
.name = "powerdown_mode_available",
.shared = true,
.read = ad5446_read_powerdown_mode_available,
},
IIO_ENUM("powerdown_mode", false, &ad5446_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum),
{ },
};
......@@ -167,6 +147,14 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
.channel = AD5446_CHANNEL(14, 16, 0),
.write = ad5446_write,
},
[ID_AD5450] = {
.channel = AD5446_CHANNEL(8, 16, 6),
.write = ad5446_write,
},
[ID_AD5451] = {
.channel = AD5446_CHANNEL(10, 16, 4),
.write = ad5446_write,
},
[ID_AD5541A] = {
.channel = AD5446_CHANNEL(16, 16, 0),
.write = ad5446_write,
......@@ -321,6 +309,8 @@ static int __devinit ad5446_probe(struct spi_device *spi)
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)
......@@ -364,6 +354,10 @@ static int ad5446_remove(struct spi_device *spi)
static const struct spi_device_id ad5446_id[] = {
{"ad5444", ID_AD5444},
{"ad5446", ID_AD5446},
{"ad5450", ID_AD5450},
{"ad5451", ID_AD5451},
{"ad5452", ID_AD5444}, /* ad5452 is compatible to the ad5444 */
{"ad5453", ID_AD5446}, /* ad5453 is compatible to the ad5446 */
{"ad5512a", ID_AD5512A},
{"ad5541a", ID_AD5541A},
{"ad5542a", ID_AD5541A}, /* ad5541a and ad5542a are compatible */
......
......@@ -71,6 +71,8 @@ struct ad5446_chip_info {
enum ad5446_supported_device_ids {
ID_AD5444,
ID_AD5446,
ID_AD5450,
ID_AD5451,
ID_AD5541A,
ID_AD5512A,
ID_AD5553,
......
......@@ -19,25 +19,51 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include "dac.h"
#include "ad5504.h"
#include <linux/iio/dac/ad5504.h>
#define AD5505_BITS 12
#define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1)
#define AD5504_CMD_READ (1 << 15)
#define AD5504_CMD_WRITE (0 << 15)
#define AD5504_ADDR(addr) ((addr) << 12)
/* Registers */
#define AD5504_ADDR_NOOP 0
#define AD5504_ADDR_DAC(x) ((x) + 1)
#define AD5504_ADDR_ALL_DAC 5
#define AD5504_ADDR_CTRL 7
/* Control Register */
#define AD5504_DAC_PWR(ch) ((ch) << 2)
#define AD5504_DAC_PWRDWN_MODE(mode) ((mode) << 6)
#define AD5504_DAC_PWRDN_20K 0
#define AD5504_DAC_PWRDN_3STATE 1
/**
* struct ad5446_state - driver instance specific data
* @us: spi_device
* @reg: supply regulator
* @vref_mv: actual reference voltage used
* @pwr_down_mask power down mask
* @pwr_down_mode current power down mode
*/
#define AD5504_CHANNEL(_chan) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = AD5504_ADDR_DAC(_chan), \
.scan_type = IIO_ST('u', 12, 16, 0), \
}
struct ad5504_state {
struct spi_device *spi;
struct regulator *reg;
unsigned short vref_mv;
unsigned pwr_down_mask;
unsigned pwr_down_mode;
};
static const struct iio_chan_spec ad5504_channels[] = {
AD5504_CHANNEL(0),
AD5504_CHANNEL(1),
AD5504_CHANNEL(2),
AD5504_CHANNEL(3),
/**
* ad5504_supported_device_ids:
*/
enum ad5504_supported_device_ids {
ID_AD5504,
ID_AD5501,
};
static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val)
......@@ -122,67 +148,61 @@ static int ad5504_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
static ssize_t ad5504_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
static const char * const ad5504_powerdown_modes[] = {
"20kohm_to_gnd",
"three_state",
};
static int ad5504_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5504_state *st = iio_priv(indio_dev);
const char mode[][14] = {"20kohm_to_gnd", "three_state"};
return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
return st->pwr_down_mode;
}
static ssize_t ad5504_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static int ad5504_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int mode)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5504_state *st = iio_priv(indio_dev);
int ret;
if (sysfs_streq(buf, "20kohm_to_gnd"))
st->pwr_down_mode = AD5504_DAC_PWRDN_20K;
else if (sysfs_streq(buf, "three_state"))
st->pwr_down_mode = AD5504_DAC_PWRDN_3STATE;
else
ret = -EINVAL;
st->pwr_down_mode = mode;
return ret ? ret : len;
return 0;
}
static ssize_t ad5504_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
static const struct iio_enum ad5504_powerdown_mode_enum = {
.items = ad5504_powerdown_modes,
.num_items = ARRAY_SIZE(ad5504_powerdown_modes),
.get = ad5504_get_powerdown_mode,
.set = ad5504_set_powerdown_mode,
};
static ssize_t ad5504_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5504_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
return sprintf(buf, "%d\n",
!(st->pwr_down_mask & (1 << this_attr->address)));
!(st->pwr_down_mask & (1 << chan->channel)));
}
static ssize_t ad5504_write_dac_powerdown(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
long readin;
bool pwr_down;
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5504_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = strict_strtol(buf, 10, &readin);
ret = strtobool(buf, &pwr_down);
if (ret)
return ret;
if (readin == 0)
st->pwr_down_mask |= (1 << this_attr->address);
else if (readin == 1)
st->pwr_down_mask &= ~(1 << this_attr->address);
if (pwr_down)
st->pwr_down_mask |= (1 << chan->channel);
else
ret = -EINVAL;
st->pwr_down_mask &= ~(1 << chan->channel);
ret = ad5504_spi_write(st->spi, AD5504_ADDR_CTRL,
AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) |
......@@ -194,50 +214,6 @@ static ssize_t ad5504_write_dac_powerdown(struct device *dev,
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
S_IWUSR, ad5504_read_powerdown_mode,
ad5504_write_powerdown_mode, 0);
static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"20kohm_to_gnd three_state");
#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \
IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
S_IRUGO | S_IWUSR, _show, _store, _addr)
static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5504_read_dac_powerdown,
ad5504_write_dac_powerdown, 0);
static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5504_read_dac_powerdown,
ad5504_write_dac_powerdown, 1);
static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5504_read_dac_powerdown,
ad5504_write_dac_powerdown, 2);
static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown,
ad5504_write_dac_powerdown, 3);
static struct attribute *ad5504_attributes[] = {
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ad5504_attribute_group = {
.attrs = ad5504_attributes,
};
static struct attribute *ad5501_attributes[] = {
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ad5501_attribute_group = {
.attrs = ad5501_attributes,
};
static IIO_CONST_ATTR(temp0_thresh_rising_value, "110000");
static IIO_CONST_ATTR(temp0_thresh_rising_en, "1");
......@@ -267,17 +243,38 @@ static irqreturn_t ad5504_event_handler(int irq, void *private)
static const struct iio_info ad5504_info = {
.write_raw = ad5504_write_raw,
.read_raw = ad5504_read_raw,
.attrs = &ad5504_attribute_group,
.event_attrs = &ad5504_ev_attribute_group,
.driver_module = THIS_MODULE,
};
static const struct iio_info ad5501_info = {
.write_raw = ad5504_write_raw,
.read_raw = ad5504_read_raw,
.attrs = &ad5501_attribute_group,
.event_attrs = &ad5504_ev_attribute_group,
.driver_module = THIS_MODULE,
static const struct iio_chan_spec_ext_info ad5504_ext_info[] = {
{
.name = "powerdown",
.read = ad5504_read_dac_powerdown,
.write = ad5504_write_dac_powerdown,
},
IIO_ENUM("powerdown_mode", true, &ad5504_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum),
{ },
};
#define AD5504_CHANNEL(_chan) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = AD5504_ADDR_DAC(_chan), \
.scan_type = IIO_ST('u', 12, 16, 0), \
.ext_info = ad5504_ext_info, \
}
static const struct iio_chan_spec ad5504_channels[] = {
AD5504_CHANNEL(0),
AD5504_CHANNEL(1),
AD5504_CHANNEL(2),
AD5504_CHANNEL(3),
};
static int __devinit ad5504_probe(struct spi_device *spi)
......@@ -315,13 +312,11 @@ static int __devinit ad5504_probe(struct spi_device *spi)
st->spi = spi;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(st->spi)->name;
if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) {
indio_dev->info = &ad5501_info;
indio_dev->info = &ad5504_info;
if (spi_get_device_id(st->spi)->driver_data == ID_AD5501)
indio_dev->num_channels = 1;
} else {
indio_dev->info = &ad5504_info;
else
indio_dev->num_channels = 4;
}
indio_dev->channels = ad5504_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
......@@ -343,7 +338,8 @@ static int __devinit ad5504_probe(struct spi_device *spi)
return 0;
error_free_irq:
free_irq(spi->irq, indio_dev);
if (spi->irq)
free_irq(spi->irq, indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
......
......@@ -18,58 +18,8 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "dac.h"
#include "ad5624r.h"
#define AD5624R_CHANNEL(_chan, _bits) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = (_chan), \
.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \
}
#define DECLARE_AD5624R_CHANNELS(_name, _bits) \
const struct iio_chan_spec _name##_channels[] = { \
AD5624R_CHANNEL(0, _bits), \
AD5624R_CHANNEL(1, _bits), \
AD5624R_CHANNEL(2, _bits), \
AD5624R_CHANNEL(3, _bits), \
}
static DECLARE_AD5624R_CHANNELS(ad5624r, 12);
static DECLARE_AD5624R_CHANNELS(ad5644r, 14);
static DECLARE_AD5624R_CHANNELS(ad5664r, 16);
static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
[ID_AD5624R3] = {
.channels = ad5624r_channels,
.int_vref_mv = 1250,
},
[ID_AD5624R5] = {
.channels = ad5624r_channels,
.int_vref_mv = 2500,
},
[ID_AD5644R3] = {
.channels = ad5644r_channels,
.int_vref_mv = 1250,
},
[ID_AD5644R5] = {
.channels = ad5644r_channels,
.int_vref_mv = 2500,
},
[ID_AD5664R3] = {
.channels = ad5664r_channels,
.int_vref_mv = 1250,
},
[ID_AD5664R5] = {
.channels = ad5664r_channels,
.int_vref_mv = 2500,
},
};
#include "ad5624r.h"
static int ad5624r_spi_write(struct spi_device *spi,
u8 cmd, u8 addr, u16 val, u8 len)
......@@ -138,69 +88,62 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
static ssize_t ad5624r_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
static const char * const ad5624r_powerdown_modes[] = {
"1kohm_to_gnd",
"100kohm_to_gnd",
"three_state"
};
static int ad5624r_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
return st->pwr_down_mode;
}
static ssize_t ad5624r_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static int ad5624r_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int mode)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
int ret;
if (sysfs_streq(buf, "1kohm_to_gnd"))
st->pwr_down_mode = AD5624R_LDAC_PWRDN_1K;
else if (sysfs_streq(buf, "100kohm_to_gnd"))
st->pwr_down_mode = AD5624R_LDAC_PWRDN_100K;
else if (sysfs_streq(buf, "three_state"))
st->pwr_down_mode = AD5624R_LDAC_PWRDN_3STATE;
else
ret = -EINVAL;
st->pwr_down_mode = mode;
return ret ? ret : len;
return 0;
}
static ssize_t ad5624r_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
static const struct iio_enum ad5624r_powerdown_mode_enum = {
.items = ad5624r_powerdown_modes,
.num_items = ARRAY_SIZE(ad5624r_powerdown_modes),
.get = ad5624r_get_powerdown_mode,
.set = ad5624r_set_powerdown_mode,
};
static ssize_t ad5624r_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
return sprintf(buf, "%d\n",
!!(st->pwr_down_mask & (1 << this_attr->address)));
!!(st->pwr_down_mask & (1 << chan->channel)));
}
static ssize_t ad5624r_write_dac_powerdown(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static ssize_t ad5624r_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
long readin;
bool pwr_down;
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = strict_strtol(buf, 10, &readin);
ret = strtobool(buf, &pwr_down);
if (ret)
return ret;
if (readin == 1)
st->pwr_down_mask |= (1 << this_attr->address);
else if (!readin)
st->pwr_down_mask &= ~(1 << this_attr->address);
if (pwr_down)
st->pwr_down_mask |= (1 << chan->channel);
else
ret = -EINVAL;
st->pwr_down_mask &= ~(1 << chan->channel);
ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0,
(st->pwr_down_mode << 4) |
......@@ -209,47 +152,74 @@ static ssize_t ad5624r_write_dac_powerdown(struct device *dev,
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
S_IWUSR, ad5624r_read_powerdown_mode,
ad5624r_write_powerdown_mode, 0);
static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"1kohm_to_gnd 100kohm_to_gnd three_state");
#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \
IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
S_IRUGO | S_IWUSR, _show, _store, _addr)
static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5624r_read_dac_powerdown,
ad5624r_write_dac_powerdown, 0);
static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5624r_read_dac_powerdown,
ad5624r_write_dac_powerdown, 1);
static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5624r_read_dac_powerdown,
ad5624r_write_dac_powerdown, 2);
static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown,
ad5624r_write_dac_powerdown, 3);
static struct attribute *ad5624r_attributes[] = {
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ad5624r_attribute_group = {
.attrs = ad5624r_attributes,
};
static const struct iio_info ad5624r_info = {
.write_raw = ad5624r_write_raw,
.read_raw = ad5624r_read_raw,
.attrs = &ad5624r_attribute_group,
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = {
{
.name = "powerdown",
.read = ad5624r_read_dac_powerdown,
.write = ad5624r_write_dac_powerdown,
},
IIO_ENUM("powerdown_mode", true, &ad5624r_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum),
{ },
};
#define AD5624R_CHANNEL(_chan, _bits) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = (_chan), \
.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \
.ext_info = ad5624r_ext_info, \
}
#define DECLARE_AD5624R_CHANNELS(_name, _bits) \
const struct iio_chan_spec _name##_channels[] = { \
AD5624R_CHANNEL(0, _bits), \
AD5624R_CHANNEL(1, _bits), \
AD5624R_CHANNEL(2, _bits), \
AD5624R_CHANNEL(3, _bits), \
}
static DECLARE_AD5624R_CHANNELS(ad5624r, 12);
static DECLARE_AD5624R_CHANNELS(ad5644r, 14);
static DECLARE_AD5624R_CHANNELS(ad5664r, 16);
static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
[ID_AD5624R3] = {
.channels = ad5624r_channels,
.int_vref_mv = 1250,
},
[ID_AD5624R5] = {
.channels = ad5624r_channels,
.int_vref_mv = 2500,
},
[ID_AD5644R3] = {
.channels = ad5644r_channels,
.int_vref_mv = 1250,
},
[ID_AD5644R5] = {
.channels = ad5644r_channels,
.int_vref_mv = 2500,
},
[ID_AD5664R3] = {
.channels = ad5664r_channels,
.int_vref_mv = 1250,
},
[ID_AD5664R5] = {
.channels = ad5664r_channels,
.int_vref_mv = 2500,
},
};
static int __devinit ad5624r_probe(struct spi_device *spi)
{
struct ad5624r_state *st;
......
......@@ -18,7 +18,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "dac.h"
#define AD5686_DAC_CHANNELS 4
......@@ -93,40 +92,6 @@ enum ad5686_supported_device_ids {
ID_AD5685,
ID_AD5686,
};
#define AD5868_CHANNEL(chan, bits, shift) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = chan, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = AD5686_ADDR_DAC(chan), \
.scan_type = IIO_ST('u', bits, 16, shift) \
}
static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
[ID_AD5684] = {
.channel[0] = AD5868_CHANNEL(0, 12, 4),
.channel[1] = AD5868_CHANNEL(1, 12, 4),
.channel[2] = AD5868_CHANNEL(2, 12, 4),
.channel[3] = AD5868_CHANNEL(3, 12, 4),
.int_vref_mv = 2500,
},
[ID_AD5685] = {
.channel[0] = AD5868_CHANNEL(0, 14, 2),
.channel[1] = AD5868_CHANNEL(1, 14, 2),
.channel[2] = AD5868_CHANNEL(2, 14, 2),
.channel[3] = AD5868_CHANNEL(3, 14, 2),
.int_vref_mv = 2500,
},
[ID_AD5686] = {
.channel[0] = AD5868_CHANNEL(0, 16, 0),
.channel[1] = AD5868_CHANNEL(1, 16, 0),
.channel[2] = AD5868_CHANNEL(2, 16, 0),
.channel[3] = AD5868_CHANNEL(3, 16, 0),
.int_vref_mv = 2500,
},
};
static int ad5686_spi_write(struct ad5686_state *st,
u8 cmd, u8 addr, u16 val, u8 shift)
{
......@@ -170,73 +135,63 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
return be32_to_cpu(st->data[2].d32);
}
static ssize_t ad5686_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
static const char * const ad5686_powerdown_modes[] = {
"1kohm_to_gnd",
"100kohm_to_gnd",
"three_state"
};
static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5686_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
return sprintf(buf, "%s\n", mode[(st->pwr_down_mode >>
(this_attr->address * 2)) & 0x3]);
return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1;
}
static ssize_t ad5686_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int mode)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5686_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned mode;
if (sysfs_streq(buf, "1kohm_to_gnd"))
mode = AD5686_LDAC_PWRDN_1K;
else if (sysfs_streq(buf, "100kohm_to_gnd"))
mode = AD5686_LDAC_PWRDN_100K;
else if (sysfs_streq(buf, "three_state"))
mode = AD5686_LDAC_PWRDN_3STATE;
else
return -EINVAL;
st->pwr_down_mode &= ~(0x3 << (this_attr->address * 2));
st->pwr_down_mode |= (mode << (this_attr->address * 2));
st->pwr_down_mode &= ~(0x3 << (chan->channel * 2));
st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2));
return len;
return 0;
}
static ssize_t ad5686_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
static const struct iio_enum ad5686_powerdown_mode_enum = {
.items = ad5686_powerdown_modes,
.num_items = ARRAY_SIZE(ad5686_powerdown_modes),
.get = ad5686_get_powerdown_mode,
.set = ad5686_set_powerdown_mode,
};
static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5686_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
return sprintf(buf, "%d\n", !!(st->pwr_down_mask &
(0x3 << (this_attr->address * 2))));
(0x3 << (chan->channel * 2))));
}
static ssize_t ad5686_write_dac_powerdown(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
bool readin;
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5686_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = strtobool(buf, &readin);
if (ret)
return ret;
if (readin == true)
st->pwr_down_mask |= (0x3 << (this_attr->address * 2));
st->pwr_down_mask |= (0x3 << (chan->channel * 2));
else
st->pwr_down_mask &= ~(0x3 << (this_attr->address * 2));
st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
ret = ad5686_spi_write(st, AD5686_CMD_POWERDOWN_DAC, 0,
st->pwr_down_mask & st->pwr_down_mode, 0);
......@@ -244,48 +199,6 @@ static ssize_t ad5686_write_dac_powerdown(struct device *dev,
return ret ? ret : len;
}
static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"1kohm_to_gnd 100kohm_to_gnd three_state");
#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_num) \
IIO_DEVICE_ATTR(out_voltage##_num##_powerdown_mode, \
S_IRUGO | S_IWUSR, \
ad5686_read_powerdown_mode, \
ad5686_write_powerdown_mode, _num)
static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0);
static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1);
static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2);
static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3);
#define IIO_DEV_ATTR_DAC_POWERDOWN(_num) \
IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
S_IRUGO | S_IWUSR, \
ad5686_read_dac_powerdown, \
ad5686_write_dac_powerdown, _num)
static IIO_DEV_ATTR_DAC_POWERDOWN(0);
static IIO_DEV_ATTR_DAC_POWERDOWN(1);
static IIO_DEV_ATTR_DAC_POWERDOWN(2);
static IIO_DEV_ATTR_DAC_POWERDOWN(3);
static struct attribute *ad5686_attributes[] = {
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage0_powerdown_mode.dev_attr.attr,
&iio_dev_attr_out_voltage1_powerdown_mode.dev_attr.attr,
&iio_dev_attr_out_voltage2_powerdown_mode.dev_attr.attr,
&iio_dev_attr_out_voltage3_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ad5686_attribute_group = {
.attrs = ad5686_attributes,
};
static int ad5686_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
......@@ -349,10 +262,57 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
static const struct iio_info ad5686_info = {
.read_raw = ad5686_read_raw,
.write_raw = ad5686_write_raw,
.attrs = &ad5686_attribute_group,
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec_ext_info ad5686_ext_info[] = {
{
.name = "powerdown",
.read = ad5686_read_dac_powerdown,
.write = ad5686_write_dac_powerdown,
},
IIO_ENUM("powerdown_mode", false, &ad5686_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum),
{ },
};
#define AD5868_CHANNEL(chan, bits, shift) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = chan, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = AD5686_ADDR_DAC(chan), \
.scan_type = IIO_ST('u', bits, 16, shift), \
.ext_info = ad5686_ext_info, \
}
static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
[ID_AD5684] = {
.channel[0] = AD5868_CHANNEL(0, 12, 4),
.channel[1] = AD5868_CHANNEL(1, 12, 4),
.channel[2] = AD5868_CHANNEL(2, 12, 4),
.channel[3] = AD5868_CHANNEL(3, 12, 4),
.int_vref_mv = 2500,
},
[ID_AD5685] = {
.channel[0] = AD5868_CHANNEL(0, 14, 2),
.channel[1] = AD5868_CHANNEL(1, 14, 2),
.channel[2] = AD5868_CHANNEL(2, 14, 2),
.channel[3] = AD5868_CHANNEL(3, 14, 2),
.int_vref_mv = 2500,
},
[ID_AD5686] = {
.channel[0] = AD5868_CHANNEL(0, 16, 0),
.channel[1] = AD5868_CHANNEL(1, 16, 0),
.channel[2] = AD5868_CHANNEL(2, 16, 0),
.channel[3] = AD5868_CHANNEL(3, 16, 0),
.int_vref_mv = 2500,
},
};
static int __devinit ad5686_probe(struct spi_device *spi)
{
struct ad5686_state *st;
......@@ -385,6 +345,9 @@ static int __devinit ad5686_probe(struct spi_device *spi)
st->spi = spi;
/* Set all the power down mode for all channels to 1K pulldown */
st->pwr_down_mode = 0x55;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad5686_info;
......
......@@ -18,7 +18,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "dac.h"
#define AD5764_REG_SF_NOP 0x0
#define AD5764_REG_SF_CONFIG 0x1
......
......@@ -19,8 +19,90 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "dac.h"
#include "ad5791.h"
#include <linux/iio/dac/ad5791.h>
#define AD5791_RES_MASK(x) ((1 << (x)) - 1)
#define AD5791_DAC_MASK AD5791_RES_MASK(20)
#define AD5791_DAC_MSB (1 << 19)
#define AD5791_CMD_READ (1 << 23)
#define AD5791_CMD_WRITE (0 << 23)
#define AD5791_ADDR(addr) ((addr) << 20)
/* Registers */
#define AD5791_ADDR_NOOP 0
#define AD5791_ADDR_DAC0 1
#define AD5791_ADDR_CTRL 2
#define AD5791_ADDR_CLRCODE 3
#define AD5791_ADDR_SW_CTRL 4
/* Control Register */
#define AD5791_CTRL_RBUF (1 << 1)
#define AD5791_CTRL_OPGND (1 << 2)
#define AD5791_CTRL_DACTRI (1 << 3)
#define AD5791_CTRL_BIN2SC (1 << 4)
#define AD5791_CTRL_SDODIS (1 << 5)
#define AD5761_CTRL_LINCOMP(x) ((x) << 6)
#define AD5791_LINCOMP_0_10 0
#define AD5791_LINCOMP_10_12 1
#define AD5791_LINCOMP_12_16 2
#define AD5791_LINCOMP_16_19 3
#define AD5791_LINCOMP_19_20 12
#define AD5780_LINCOMP_0_10 0
#define AD5780_LINCOMP_10_20 12
/* Software Control Register */
#define AD5791_SWCTRL_LDAC (1 << 0)
#define AD5791_SWCTRL_CLR (1 << 1)
#define AD5791_SWCTRL_RESET (1 << 2)
#define AD5791_DAC_PWRDN_6K 0
#define AD5791_DAC_PWRDN_3STATE 1
/**
* struct ad5791_chip_info - chip specific information
* @get_lin_comp: function pointer to the device specific function
*/
struct ad5791_chip_info {
int (*get_lin_comp) (unsigned int span);
};
/**
* struct ad5791_state - driver instance specific data
* @us: spi_device
* @reg_vdd: positive supply regulator
* @reg_vss: negative supply regulator
* @chip_info: chip model specific constants
* @vref_mv: actual reference voltage used
* @vref_neg_mv: voltage of the negative supply
* @pwr_down_mode current power down mode
*/
struct ad5791_state {
struct spi_device *spi;
struct regulator *reg_vdd;
struct regulator *reg_vss;
const struct ad5791_chip_info *chip_info;
unsigned short vref_mv;
unsigned int vref_neg_mv;
unsigned ctrl;
unsigned pwr_down_mode;
bool pwr_down;
};
/**
* ad5791_supported_device_ids:
*/
enum ad5791_supported_device_ids {
ID_AD5760,
ID_AD5780,
ID_AD5781,
ID_AD5791,
};
static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val)
{
......@@ -72,119 +154,71 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
return ret;
}
#define AD5791_CHAN(bits, shift) { \
.type = IIO_VOLTAGE, \
.output = 1, \
.indexed = 1, \
.address = AD5791_ADDR_DAC0, \
.channel = 0, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
.scan_type = IIO_ST('u', bits, 24, shift) \
}
static const struct iio_chan_spec ad5791_channels[] = {
[ID_AD5760] = AD5791_CHAN(16, 4),
[ID_AD5780] = AD5791_CHAN(18, 2),
[ID_AD5781] = AD5791_CHAN(18, 2),
[ID_AD5791] = AD5791_CHAN(20, 0)
static const char * const ad5791_powerdown_modes[] = {
"6kohm_to_gnd",
"three_state",
};
static ssize_t ad5791_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
static int ad5791_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5791_state *st = iio_priv(indio_dev);
const char mode[][14] = {"6kohm_to_gnd", "three_state"};
return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
return st->pwr_down_mode;
}
static ssize_t ad5791_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static int ad5791_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int mode)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5791_state *st = iio_priv(indio_dev);
int ret;
if (sysfs_streq(buf, "6kohm_to_gnd"))
st->pwr_down_mode = AD5791_DAC_PWRDN_6K;
else if (sysfs_streq(buf, "three_state"))
st->pwr_down_mode = AD5791_DAC_PWRDN_3STATE;
else
ret = -EINVAL;
st->pwr_down_mode = mode;
return ret ? ret : len;
return 0;
}
static ssize_t ad5791_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
static const struct iio_enum ad5791_powerdown_mode_enum = {
.items = ad5791_powerdown_modes,
.num_items = ARRAY_SIZE(ad5791_powerdown_modes),
.get = ad5791_get_powerdown_mode,
.set = ad5791_set_powerdown_mode,
};
static ssize_t ad5791_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5791_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->pwr_down);
}
static ssize_t ad5791_write_dac_powerdown(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
long readin;
bool pwr_down;
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5791_state *st = iio_priv(indio_dev);
ret = strict_strtol(buf, 10, &readin);
ret = strtobool(buf, &pwr_down);
if (ret)
return ret;
if (readin == 0) {
st->pwr_down = false;
if (!pwr_down) {
st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
} else if (readin == 1) {
st->pwr_down = true;
} else {
if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K)
st->ctrl |= AD5791_CTRL_OPGND;
else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE)
st->ctrl |= AD5791_CTRL_DACTRI;
} else
ret = -EINVAL;
}
st->pwr_down = pwr_down;
ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl);
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
S_IWUSR, ad5791_read_powerdown_mode,
ad5791_write_powerdown_mode, 0);
static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"6kohm_to_gnd three_state");
#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \
IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
S_IRUGO | S_IWUSR, _show, _store, _addr)
static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5791_read_dac_powerdown,
ad5791_write_dac_powerdown, 0);
static struct attribute *ad5791_attributes[] = {
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ad5791_attribute_group = {
.attrs = ad5791_attributes,
};
static int ad5791_get_lin_comp(unsigned int span)
{
if (span <= 10000)
......@@ -254,6 +288,37 @@ static int ad5791_read_raw(struct iio_dev *indio_dev,
};
static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
{
.name = "powerdown",
.shared = true,
.read = ad5791_read_dac_powerdown,
.write = ad5791_write_dac_powerdown,
},
IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum),
{ },
};
#define AD5791_CHAN(bits, shift) { \
.type = IIO_VOLTAGE, \
.output = 1, \
.indexed = 1, \
.address = AD5791_ADDR_DAC0, \
.channel = 0, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
.scan_type = IIO_ST('u', bits, 24, shift), \
.ext_info = ad5791_ext_info, \
}
static const struct iio_chan_spec ad5791_channels[] = {
[ID_AD5760] = AD5791_CHAN(16, 4),
[ID_AD5780] = AD5791_CHAN(18, 2),
[ID_AD5781] = AD5791_CHAN(18, 2),
[ID_AD5791] = AD5791_CHAN(20, 0)
};
static int ad5791_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
......@@ -278,7 +343,6 @@ static int ad5791_write_raw(struct iio_dev *indio_dev,
static const struct iio_info ad5791_info = {
.read_raw = &ad5791_read_raw,
.write_raw = &ad5791_write_raw,
.attrs = &ad5791_attribute_group,
.driver_module = THIS_MODULE,
};
......
......@@ -27,9 +27,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include "dac.h"
#include "max517.h"
#include <linux/iio/dac/max517.h>
#define MAX517_DRV_NAME "max517"
......@@ -45,7 +43,6 @@ enum max517_device_ids {
};
struct max517_data {
struct iio_dev *indio_dev;
struct i2c_client *client;
unsigned short vref_mv[2];
};
......@@ -55,129 +52,67 @@ struct max517_data {
* bit 1: channel 2
* (this way, it's possible to set both channels at once)
*/
static ssize_t max517_set_value(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count, int channel)
static int max517_set_value(struct iio_dev *indio_dev,
long val, int channel)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct max517_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
u8 outbuf[4]; /* 1x or 2x command + value */
int outbuf_size = 0;
u8 outbuf[2];
int res;
long val;
res = strict_strtol(buf, 10, &val);
if (res)
return res;
if (val < 0 || val > 255)
return -EINVAL;
if (channel & 1) {
outbuf[outbuf_size++] = COMMAND_CHANNEL0;
outbuf[outbuf_size++] = val;
}
if (channel & 2) {
outbuf[outbuf_size++] = COMMAND_CHANNEL1;
outbuf[outbuf_size++] = val;
}
/*
* At this point, there are always 1 or 2 two-byte commands in
* outbuf. With 2 commands, the device can set two outputs
* simultaneously, latching the values upon the end of the I2C
* transfer.
*/
outbuf[0] = channel;
outbuf[1] = val;
res = i2c_master_send(client, outbuf, outbuf_size);
res = i2c_master_send(client, outbuf, 2);
if (res < 0)
return res;
return count;
}
static ssize_t max517_set_value_1(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return max517_set_value(dev, attr, buf, count, 1);
}
static IIO_DEV_ATTR_OUT_RAW(1, max517_set_value_1, 0);
static ssize_t max517_set_value_2(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return max517_set_value(dev, attr, buf, count, 2);
}
static IIO_DEV_ATTR_OUT_RAW(2, max517_set_value_2, 1);
static ssize_t max517_set_value_both(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return max517_set_value(dev, attr, buf, count, 3);
else if (res != 2)
return -EIO;
else
return 0;
}
static IIO_DEVICE_ATTR_NAMED(out_voltage1and2_raw,
out_voltage1&2_raw, S_IWUSR, NULL,
max517_set_value_both, -1);
static ssize_t max517_show_scale(struct device *dev,
struct device_attribute *attr,
char *buf, int channel)
static int max517_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long m)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct max517_data *data = iio_priv(indio_dev);
/* Corresponds to Vref / 2^(bits) */
unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8;
return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
unsigned int scale_uv;
switch (m) {
case IIO_CHAN_INFO_SCALE:
/* Corresponds to Vref / 2^(bits) */
scale_uv = (data->vref_mv[chan->channel] * 1000) >> 8;
*val = scale_uv / 1000000;
*val2 = scale_uv % 1000000;
return IIO_VAL_INT_PLUS_MICRO;
default:
break;
}
return -EINVAL;
}
static ssize_t max517_show_scale1(struct device *dev,
struct device_attribute *attr,
char *buf)
static int max517_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long mask)
{
return max517_show_scale(dev, attr, buf, 1);
}
static IIO_DEVICE_ATTR(out_voltage1_scale, S_IRUGO,
max517_show_scale1, NULL, 0);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = max517_set_value(indio_dev, val, chan->channel);
break;
default:
ret = -EINVAL;
break;
}
static ssize_t max517_show_scale2(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return max517_show_scale(dev, attr, buf, 2);
return ret;
}
static IIO_DEVICE_ATTR(out_voltage2_scale, S_IRUGO,
max517_show_scale2, NULL, 0);
/* On MAX517 variant, we have one output */
static struct attribute *max517_attributes[] = {
&iio_dev_attr_out_voltage1_raw.dev_attr.attr,
&iio_dev_attr_out_voltage1_scale.dev_attr.attr,
NULL
};
static struct attribute_group max517_attribute_group = {
.attrs = max517_attributes,
};
/* On MAX518 and MAX519 variant, we have two outputs */
static struct attribute *max518_attributes[] = {
&iio_dev_attr_out_voltage1_raw.dev_attr.attr,
&iio_dev_attr_out_voltage1_scale.dev_attr.attr,
&iio_dev_attr_out_voltage2_raw.dev_attr.attr,
&iio_dev_attr_out_voltage2_scale.dev_attr.attr,
&iio_dev_attr_out_voltage1and2_raw.dev_attr.attr,
NULL
};
static struct attribute_group max518_attribute_group = {
.attrs = max518_attributes,
};
#ifdef CONFIG_PM_SLEEP
static int max517_suspend(struct device *dev)
......@@ -201,16 +136,27 @@ static SIMPLE_DEV_PM_OPS(max517_pm_ops, max517_suspend, max517_resume);
#endif
static const struct iio_info max517_info = {
.attrs = &max517_attribute_group,
.read_raw = max517_read_raw,
.write_raw = max517_write_raw,
.driver_module = THIS_MODULE,
};
static const struct iio_info max518_info = {
.attrs = &max518_attribute_group,
.driver_module = THIS_MODULE,
#define MAX517_CHANNEL(chan) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (chan), \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.scan_type = IIO_ST('u', 8, 8, 0), \
}
static const struct iio_chan_spec max517_channels[] = {
MAX517_CHANNEL(0),
MAX517_CHANNEL(1)
};
static int max517_probe(struct i2c_client *client,
static int __devinit max517_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max517_data *data;
......@@ -230,12 +176,14 @@ static int max517_probe(struct i2c_client *client,
/* establish that the iio_dev is a child of the i2c device */
indio_dev->dev.parent = &client->dev;
/* reduced attribute set for MAX517 */
/* reduced channel set for MAX517 */
if (id->driver_data == ID_MAX517)
indio_dev->info = &max517_info;
indio_dev->num_channels = 1;
else
indio_dev->info = &max518_info;
indio_dev->num_channels = 2;
indio_dev->channels = max517_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &max517_info;
/*
* Reference voltage on MAX518 and default is 5V, else take vref_mv
......@@ -262,7 +210,7 @@ static int max517_probe(struct i2c_client *client,
return err;
}
static int max517_remove(struct i2c_client *client)
static int __devexit max517_remove(struct i2c_client *client)
{
iio_device_unregister(i2c_get_clientdata(client));
iio_device_free(i2c_get_clientdata(client));
......@@ -284,7 +232,7 @@ static struct i2c_driver max517_driver = {
.pm = MAX517_PM_OPS,
},
.probe = max517_probe,
.remove = max517_remove,
.remove = __devexit_p(max517_remove),
.id_table = max517_id,
};
module_i2c_driver(max517_driver);
......
/*
* mcp4725.c - Support for Microchip MCP4725
*
* Copyright (C) 2012 Peter Meerwald <pmeerw@pmeerw.net>
*
* Based on max517 by Roland Stigge <stigge@antcom.de>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* driver for the Microchip I2C 12-bit digital-to-analog converter (DAC)
* (7-bit I2C slave address 0x60, the three LSBs can be configured in
* hardware)
*
* writing the DAC value to EEPROM is not supported
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/dac/mcp4725.h>
#define MCP4725_DRV_NAME "mcp4725"
struct mcp4725_data {
struct i2c_client *client;
u16 vref_mv;
u16 dac_value;
};
#ifdef CONFIG_PM_SLEEP
static int mcp4725_suspend(struct device *dev)
{
u8 outbuf[2];
outbuf[0] = 0x3 << 4; /* power-down bits, 500 kOhm resistor */
outbuf[1] = 0;
return i2c_master_send(to_i2c_client(dev), outbuf, 2);
}
static int mcp4725_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct mcp4725_data *data = iio_priv(indio_dev);
u8 outbuf[2];
/* restore previous DAC value */
outbuf[0] = (data->dac_value >> 8) & 0xf;
outbuf[1] = data->dac_value & 0xff;
return i2c_master_send(to_i2c_client(dev), outbuf, 2);
}
static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume);
#define MCP4725_PM_OPS (&mcp4725_pm_ops)
#else
#define MCP4725_PM_OPS NULL
#endif
static const struct iio_chan_spec mcp4725_channel = {
.type = IIO_VOLTAGE,
.indexed = 1,
.output = 1,
.channel = 0,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_type = IIO_ST('u', 12, 16, 0),
};
static int mcp4725_set_value(struct iio_dev *indio_dev, int val)
{
struct mcp4725_data *data = iio_priv(indio_dev);
u8 outbuf[2];
int ret;
if (val >= (1 << 12) || val < 0)
return -EINVAL;
outbuf[0] = (val >> 8) & 0xf;
outbuf[1] = val & 0xff;
ret = i2c_master_send(data->client, outbuf, 2);
if (ret < 0)
return ret;
else if (ret != 2)
return -EIO;
else
return 0;
}
static int mcp4725_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct mcp4725_data *data = iio_priv(indio_dev);
unsigned long scale_uv;
switch (mask) {
case IIO_CHAN_INFO_RAW:
*val = data->dac_value;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (data->vref_mv * 1000) >> 12;
*val = scale_uv / 1000000;
*val2 = scale_uv % 1000000;
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int mcp4725_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct mcp4725_data *data = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = mcp4725_set_value(indio_dev, val);
data->dac_value = val;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static const struct iio_info mcp4725_info = {
.read_raw = mcp4725_read_raw,
.write_raw = mcp4725_write_raw,
.driver_module = THIS_MODULE,
};
static int __devinit mcp4725_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mcp4725_data *data;
struct iio_dev *indio_dev;
struct mcp4725_platform_data *platform_data = client->dev.platform_data;
u8 inbuf[3];
int err;
if (!platform_data || !platform_data->vref_mv) {
dev_err(&client->dev, "invalid platform data");
err = -EINVAL;
goto exit;
}
indio_dev = iio_device_alloc(sizeof(*data));
if (indio_dev == NULL) {
err = -ENOMEM;
goto exit;
}
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
indio_dev->dev.parent = &client->dev;
indio_dev->info = &mcp4725_info;
indio_dev->channels = &mcp4725_channel;
indio_dev->num_channels = 1;
indio_dev->modes = INDIO_DIRECT_MODE;
data->vref_mv = platform_data->vref_mv;
/* read current DAC value */
err = i2c_master_recv(client, inbuf, 3);
if (err < 0) {
dev_err(&client->dev, "failed to read DAC value");
goto exit_free_device;
}
data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
err = iio_device_register(indio_dev);
if (err)
goto exit_free_device;
dev_info(&client->dev, "MCP4725 DAC registered\n");
return 0;
exit_free_device:
iio_device_free(indio_dev);
exit:
return err;
}
static int __devexit mcp4725_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
iio_device_free(indio_dev);
return 0;
}
static const struct i2c_device_id mcp4725_id[] = {
{ "mcp4725", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp4725_id);
static struct i2c_driver mcp4725_driver = {
.driver = {
.name = MCP4725_DRV_NAME,
.pm = MCP4725_PM_OPS,
},
.probe = mcp4725_probe,
.remove = __devexit_p(mcp4725_remove),
.id_table = mcp4725_id,
};
module_i2c_driver(mcp4725_driver);
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
MODULE_DESCRIPTION("MCP4725 12-bit DAC");
MODULE_LICENSE("GPL");
#
# Frequency
# Direct Digital Synthesis drivers (DDS)
# Clock Distribution device drivers
# Phase-Locked Loop (PLL) frequency synthesizers
#
menu "Frequency Synthesizers DDS/PLL"
menu "Clock Generator/Distribution"
config AD9523
tristate "Analog Devices AD9523 Low Jitter Clock Generator"
depends on SPI
help
Say yes here to build support for Analog Devices AD9523 Low Jitter
Clock Generator. The driver provides direct access via sysfs.
To compile this driver as a module, choose M here: the
module will be called ad9523.
endmenu
#
# Phase-Locked Loop (PLL) frequency synthesizers
#
menu "Phase-Locked Loop (PLL) frequency synthesizers"
config ADF4350
tristate "Analog Devices ADF4350/ADF4351 Wideband Synthesizers"
depends on SPI
help
Say yes here to build support for Analog Devices ADF4350/ADF4351
Wideband Synthesizers. The driver provides direct access via sysfs.
To compile this driver as a module, choose M here: the
module will be called adf4350.
endmenu
endmenu
#
# Makefile iio/frequency
#
obj-$(CONFIG_AD9523) += ad9523.o
obj-$(CONFIG_ADF4350) += adf4350.o
This diff is collapsed.
This diff is collapsed.
......@@ -285,11 +285,14 @@ int iio_buffer_register(struct iio_dev *indio_dev,
if (channels) {
/* new magic */
for (i = 0; i < num_channels; i++) {
if (channels[i].scan_index < 0)
continue;
/* Establish necessary mask length */
if (channels[i].scan_index >
(int)indio_dev->masklength - 1)
indio_dev->masklength
= indio_dev->channels[i].scan_index + 1;
= channels[i].scan_index + 1;
ret = iio_buffer_add_channel_sysfs(indio_dev,
&channels[i]);
......@@ -553,6 +556,10 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
buffer->scan_mask);
else
indio_dev->active_scan_mask = buffer->scan_mask;
if (indio_dev->active_scan_mask == NULL)
return -EINVAL;
iio_update_demux(indio_dev);
if (indio_dev->info->update_scan_mode)
......@@ -563,6 +570,31 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
}
EXPORT_SYMBOL(iio_sw_buffer_preenable);
/**
* iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
* @indio_dev: the iio device
* @mask: scan mask to be checked
*
* Return true if exactly one bit is set in the scan mask, false otherwise. It
* can be used for devices where only one channel can be active for sampling at
* a time.
*/
bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
const unsigned long *mask)
{
return bitmap_weight(mask, indio_dev->masklength) == 1;
}
EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
const unsigned long *mask)
{
if (!indio_dev->setup_ops->validate_scan_mask)
return true;
return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask);
}
/**
* iio_scan_mask_set() - set particular bit in the scan mask
* @buffer: the buffer whose scan mask we are interested in
......@@ -582,27 +614,31 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
return -ENOMEM;
if (!indio_dev->masklength) {
WARN_ON("trying to set scanmask prior to registering buffer\n");
kfree(trialmask);
return -EINVAL;
goto err_invalid_mask;
}
bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
set_bit(bit, trialmask);
if (!iio_validate_scan_mask(indio_dev, trialmask))
goto err_invalid_mask;
if (indio_dev->available_scan_masks) {
mask = iio_scan_mask_match(indio_dev->available_scan_masks,
indio_dev->masklength,
trialmask);
if (!mask) {
kfree(trialmask);
return -EINVAL;
}
if (!mask)
goto err_invalid_mask;
}
bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength);
kfree(trialmask);
return 0;
};
err_invalid_mask:
kfree(trialmask);
return -EINVAL;
}
EXPORT_SYMBOL_GPL(iio_scan_mask_set);
int iio_scan_mask_query(struct iio_dev *indio_dev,
......
......@@ -64,14 +64,21 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_TIMESTAMP] = "timestamp",
[IIO_CAPACITANCE] = "capacitance",
[IIO_ALTVOLTAGE] = "altvoltage",
[IIO_CCT] = "cct",
};
static const char * const iio_modifier_names[] = {
[IIO_MOD_X] = "x",
[IIO_MOD_Y] = "y",
[IIO_MOD_Z] = "z",
[IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
[IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
[IIO_MOD_LIGHT_BOTH] = "both",
[IIO_MOD_LIGHT_IR] = "ir",
[IIO_MOD_LIGHT_CLEAR] = "clear",
[IIO_MOD_LIGHT_RED] = "red",
[IIO_MOD_LIGHT_GREEN] = "green",
[IIO_MOD_LIGHT_BLUE] = "blue",
};
/* relies on pairs of these shared then separate */
......@@ -289,6 +296,69 @@ static ssize_t iio_write_channel_ext_info(struct device *dev,
this_attr->c, buf, len);
}
ssize_t iio_enum_available_read(struct iio_dev *indio_dev,
uintptr_t priv, const struct iio_chan_spec *chan, char *buf)
{
const struct iio_enum *e = (const struct iio_enum *)priv;
unsigned int i;
size_t len = 0;
if (!e->num_items)
return 0;
for (i = 0; i < e->num_items; ++i)
len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]);
/* replace last space with a newline */
buf[len - 1] = '\n';
return len;
}
EXPORT_SYMBOL_GPL(iio_enum_available_read);
ssize_t iio_enum_read(struct iio_dev *indio_dev,
uintptr_t priv, const struct iio_chan_spec *chan, char *buf)
{
const struct iio_enum *e = (const struct iio_enum *)priv;
int i;
if (!e->get)
return -EINVAL;
i = e->get(indio_dev, chan);
if (i < 0)
return i;
else if (i >= e->num_items)
return -EINVAL;
return sprintf(buf, "%s\n", e->items[i]);
}
EXPORT_SYMBOL_GPL(iio_enum_read);
ssize_t iio_enum_write(struct iio_dev *indio_dev,
uintptr_t priv, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
const struct iio_enum *e = (const struct iio_enum *)priv;
unsigned int i;
int ret;
if (!e->set)
return -EINVAL;
for (i = 0; i < e->num_items; i++) {
if (sysfs_streq(buf, e->items[i]))
break;
}
if (i == e->num_items)
return -EINVAL;
ret = e->set(indio_dev, chan, i);
return ret ? ret : len;
}
EXPORT_SYMBOL_GPL(iio_enum_write);
static ssize_t iio_read_channel_info(struct device *dev,
struct device_attribute *attr,
char *buf)
......
......@@ -345,7 +345,6 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
{
int j, ret, attrcount = 0;
INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
/* Dynically created from the channels array */
for (j = 0; j < indio_dev->num_channels; j++) {
ret = iio_device_add_event_sysfs(indio_dev,
......@@ -396,6 +395,8 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
goto error_ret;
}
INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
iio_setup_ev_int(indio_dev->event_interface);
if (indio_dev->info->event_attrs != NULL) {
attr = indio_dev->info->event_attrs->attrs;
......
......@@ -45,31 +45,25 @@ static ssize_t iio_trigger_read_name(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_trigger *trig = dev_get_drvdata(dev);
struct iio_trigger *trig = to_iio_trigger(dev);
return sprintf(buf, "%s\n", trig->name);
}
static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
/**
* iio_trigger_register_sysfs() - create a device for this trigger
* @trig_info: the trigger
*
* Also adds any control attribute registered by the trigger driver
**/
static int iio_trigger_register_sysfs(struct iio_trigger *trig_info)
{
return sysfs_add_file_to_group(&trig_info->dev.kobj,
&dev_attr_name.attr,
NULL);
}
static struct attribute *iio_trig_dev_attrs[] = {
&dev_attr_name.attr,
NULL,
};
static void iio_trigger_unregister_sysfs(struct iio_trigger *trig_info)
{
sysfs_remove_file_from_group(&trig_info->dev.kobj,
&dev_attr_name.attr,
NULL);
}
static struct attribute_group iio_trig_attr_group = {
.attrs = iio_trig_dev_attrs,
};
static const struct attribute_group *iio_trig_attr_groups[] = {
&iio_trig_attr_group,
NULL
};
int iio_trigger_register(struct iio_trigger *trig_info)
{
......@@ -88,10 +82,6 @@ int iio_trigger_register(struct iio_trigger *trig_info)
if (ret)
goto error_unregister_id;
ret = iio_trigger_register_sysfs(trig_info);
if (ret)
goto error_device_del;
/* Add to list of available triggers held by the IIO core */
mutex_lock(&iio_trigger_list_lock);
list_add_tail(&trig_info->list, &iio_trigger_list);
......@@ -99,8 +89,6 @@ int iio_trigger_register(struct iio_trigger *trig_info)
return 0;
error_device_del:
device_del(&trig_info->dev);
error_unregister_id:
ida_simple_remove(&iio_trigger_ida, trig_info->id);
error_ret:
......@@ -114,7 +102,6 @@ void iio_trigger_unregister(struct iio_trigger *trig_info)
list_del(&trig_info->list);
mutex_unlock(&iio_trigger_list_lock);
iio_trigger_unregister_sysfs(trig_info);
ida_simple_remove(&iio_trigger_ida, trig_info->id);
/* Possible issue in here */
device_unregister(&trig_info->dev);
......@@ -234,7 +221,7 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
return ret;
}
static int iio_trigger_dettach_poll_func(struct iio_trigger *trig,
static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
struct iio_poll_func *pf)
{
int ret = 0;
......@@ -406,6 +393,7 @@ static void iio_trig_release(struct device *device)
static struct device_type iio_trig_type = {
.release = iio_trig_release,
.groups = iio_trig_attr_groups,
};
static void iio_trig_subirqmask(struct irq_data *d)
......@@ -436,7 +424,6 @@ struct iio_trigger *iio_trigger_alloc(const char *fmt, ...)
trig->dev.type = &iio_trig_type;
trig->dev.bus = &iio_bus_type;
device_initialize(&trig->dev);
dev_set_drvdata(&trig->dev, (void *)trig);
mutex_init(&trig->pool_lock);
trig->subirq_base
......@@ -503,7 +490,7 @@ EXPORT_SYMBOL(iio_triggered_buffer_postenable);
int iio_triggered_buffer_predisable(struct iio_dev *indio_dev)
{
return iio_trigger_dettach_poll_func(indio_dev->trig,
return iio_trigger_detach_poll_func(indio_dev->trig,
indio_dev->pollfunc);
}
EXPORT_SYMBOL(iio_triggered_buffer_predisable);
This diff is collapsed.
This diff is collapsed.
#
# Light sensors
#
menu "Light sensors"
config ADJD_S311
tristate "ADJD-S311-CR999 digital color sensor"
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
depends on I2C
help
If you say yes here you get support for the Avago ADJD-S311-CR999
digital color light sensor.
This driver can also be built as a module. If so, the module
will be called adjd_s311.
config SENSORS_LM3533
tristate "LM3533 ambient light sensor"
depends on MFD_LM3533
help
If you say yes here you get support for the ambient light sensor
interface on National Semiconductor / TI LM3533 Lighting Power
chips.
The sensor interface can be used to control the LEDs and backlights
of the chip through defining five light zones and three sets of
corresponding output-current values.
The driver provides raw and mean adc readings along with the current
light zone through sysfs. A threshold event can be generated on zone
changes. The ALS-control output values can be set per zone for the
three current output channels.
config VCNL4000
tristate "VCNL4000 combined ALS and proximity sensor"
depends on I2C
help
Say Y here if you want to build a driver for the Vishay VCNL4000
combined ambient light and proximity sensor.
To compile this driver as a module, choose M here: the
module will be called vcnl4000.
endmenu
#
# Makefile for IIO Light sensors
#
obj-$(CONFIG_ADJD_S311) += adjd_s311.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
File mode changed from 100755 to 100644
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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