Third IIO new drivers and cleanups series for 3.15.

New driver
 * Xilinx XADC driver -  This has been ready for a while but was awaiting
   a device tree ack (or as it turns out 3+ weeks).
 
 Cleanup
 * Drop some unreachable code from mag3110 highlighted by smatch.
 
 Fix
 * vf610 - introduced this cycle - put a possible negative error code
   into an unsigned long. Another smatch find - this one promoted by
   guilt that Dan was busy fixing all our messups.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJTGMrfAAoJEFSFNJnE9BaILFsP/iW3NlfWdk1JvdERTpvh4eRW
 zhhvje+ekn5zR5fwyOlpf7PgDW485sCQ6smVmkjiGvHVGK428Bg19NE2qGAEkaCu
 dlj0NhKDUWEy7yTixcuP9rPGOd7NFc5qsKfbHlMo9bHNdoKlo0KXOaY9vU8APNAC
 0fKyioOqQkcRqejO/4E5GH4uquoDF3e+kPk2vlMBGuxlBeQf3t1Va7j7bP601ln2
 YAd+P19s2H33Ujxvholyxad6wyM88W+sglJvM3rLvluGWXsQrnJWQPgD+RMjfvOT
 QOiyoA+dGuZogT7R3g22Ai6OmaxlXxKBXhutgfZ08VvOaJA0ZVyONvOYjdqQ+F/a
 UTg6WzkcVJSQdpbErHUEpR4p0n0Q/Whq7KAb1KGNkoe9cIiYGNcmHIg7+MsMtbZi
 GOGmEry4325ghBUULBfVNzUpQfGNHejw4f9gmngilU2lA7JHeyDUFNKWOKShUWMt
 nUUm41YsvI3Tj34+740UtldvZrpcvQ9lz6AFDh/xe3MnyLr68xwzc975x9PRr6L8
 ZGCAbYeGBzVWDKM2Gri1uF0hVobEB58BsRmViPM4Bwqr8Y3bThSpl68wLYaLw9+d
 xXu/c+VqyPeubtMKHqSEWJH2NraKo1GFkfQCe2MsnKHTnKfykMQeOKlne21/UCpA
 mZ/daW65ZngKkI1I1552
 =OSqU
 -----END PGP SIGNATURE-----

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

Jonathan writes:

Third IIO new drivers and cleanups series for 3.15.

New driver
* Xilinx XADC driver -  This has been ready for a while but was awaiting
  a device tree ack (or as it turns out 3+ weeks).

Cleanup
* Drop some unreachable code from mag3110 highlighted by smatch.

Fix
* vf610 - introduced this cycle - put a possible negative error code
  into an unsigned long. Another smatch find - this one promoted by
  guilt that Dan was busy fixing all our messups.
This commit is contained in:
Greg Kroah-Hartman 2014-03-06 11:33:04 -08:00
commit d62994701b
8 changed files with 1925 additions and 2 deletions

View file

@ -0,0 +1,113 @@
Xilinx XADC device driver
This binding document describes the bindings for both of them since the
bindings are very similar. The Xilinx XADC is a ADC that can be found in the
series 7 FPGAs from Xilinx. The XADC has a DRP interface for communication.
Currently two different frontends for the DRP interface exist. One that is only
available on the ZYNQ family as a hardmacro in the SoC portion of the ZYNQ. The
other one is available on all series 7 platforms and is a softmacro with a AXI
interface. This binding document describes the bindings for both of them since
the bindings are very similar.
Required properties:
- compatible: Should be one of
* "xlnx,zynq-xadc-1.00.a": When using the ZYNQ device
configuration interface to interface to the XADC hardmacro.
* "xlnx,axi-xadc-1.00.a": When using the axi-xadc pcore to
interface to the XADC hardmacro.
- reg: Address and length of the register set for the device
- interrupts: Interrupt for the XADC control interface.
- clocks: When using the ZYNQ this must be the ZYNQ PCAP clock,
when using the AXI-XADC pcore this must be the clock that provides the
clock to the AXI bus interface of the core.
Optional properties:
- interrupt-parent: phandle to the parent interrupt controller
- xlnx,external-mux:
* "none": No external multiplexer is used, this is the default
if the property is omitted.
* "single": External multiplexer mode is used with one
multiplexer.
* "dual": External multiplexer mode is used with two
multiplexers for simultaneous sampling.
- xlnx,external-mux-channel: Configures which pair of pins is used to
sample data in external mux mode.
Valid values for single external multiplexer mode are:
0: VP/VN
1: VAUXP[0]/VAUXN[0]
2: VAUXP[1]/VAUXN[1]
...
16: VAUXP[15]/VAUXN[15]
Valid values for dual external multiplexer mode are:
1: VAUXP[0]/VAUXN[0] - VAUXP[8]/VAUXN[8]
2: VAUXP[1]/VAUXN[1] - VAUXP[9]/VAUXN[9]
...
8: VAUXP[7]/VAUXN[7] - VAUXP[15]/VAUXN[15]
This property needs to be present if the device is configured for
external multiplexer mode (either single or dual). If the device is
not using external multiplexer mode the property is ignored.
- xnlx,channels: List of external channels that are connected to the ADC
Required properties:
* #address-cells: Should be 1.
* #size-cells: Should be 0.
The child nodes of this node represent the external channels which are
connected to the ADC. If the property is no present no external
channels will be assumed to be connected.
Each child node represents one channel and has the following
properties:
Required properties:
* reg: Pair of pins the the channel is connected to.
0: VP/VN
1: VAUXP[0]/VAUXN[0]
2: VAUXP[1]/VAUXN[1]
...
16: VAUXP[15]/VAUXN[15]
Note each channel number should only be used at most
once.
Optional properties:
* xlnx,bipolar: If set the channel is used in bipolar
mode.
Examples:
xadc@f8007100 {
compatible = "xlnx,zynq-xadc-1.00.a";
reg = <0xf8007100 0x20>;
interrupts = <0 7 4>;
interrupt-parent = <&gic>;
clocks = <&pcap_clk>;
xlnx,channels {
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
};
channel@1 {
reg = <1>;
};
channel@8 {
reg = <8>;
};
};
};
xadc@43200000 {
compatible = "xlnx,axi-xadc-1.00.a";
reg = <0x43200000 0x1000>;
interrupts = <0 53 4>;
interrupt-parent = <&gic>;
clocks = <&fpga1_clk>;
xlnx,channels {
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
xlnx,bipolar;
};
};
};

View file

@ -214,4 +214,17 @@ config VIPERBOARD_ADC
Say yes here to access the ADC part of the Nano River
Technologies Viperboard.
config XILINX_XADC
tristate "Xilinx XADC driver"
depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
depends on HAS_IOMEM
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to have support for the Xilinx XADC. The driver does support
both the ZYNQ interface to the XADC as well as the AXI-XADC interface.
The driver can also be build as a module. If so, the module will be called
xilinx-xadc.
endmenu

View file

@ -23,3 +23,5 @@ obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
obj-$(CONFIG_VF610_ADC) += vf610_adc.o
obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o
obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o

View file

@ -447,7 +447,7 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
{
struct vf610_adc *info = iio_priv(indio_dev);
unsigned int hc_cfg;
unsigned long ret;
long ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,254 @@
/*
* Xilinx XADC driver
*
* Copyright 2013 Analog Devices Inc.
* Author: Lars-Peter Clauen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/kernel.h>
#include "xilinx-xadc.h"
static const struct iio_chan_spec *xadc_event_to_channel(
struct iio_dev *indio_dev, unsigned int event)
{
switch (event) {
case XADC_THRESHOLD_OT_MAX:
case XADC_THRESHOLD_TEMP_MAX:
return &indio_dev->channels[0];
case XADC_THRESHOLD_VCCINT_MAX:
case XADC_THRESHOLD_VCCAUX_MAX:
return &indio_dev->channels[event];
default:
return &indio_dev->channels[event-1];
}
}
static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event)
{
const struct iio_chan_spec *chan;
unsigned int offset;
/* Temperature threshold error, we don't handle this yet */
if (event == 0)
return;
if (event < 4)
offset = event;
else
offset = event + 4;
chan = xadc_event_to_channel(indio_dev, event);
if (chan->type == IIO_TEMP) {
/*
* The temperature channel only supports over-temperature
* events.
*/
iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
iio_get_time_ns());
} else {
/*
* For other channels we don't know whether it is a upper or
* lower threshold event. Userspace will have to check the
* channel value if it wants to know.
*/
iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER),
iio_get_time_ns());
}
}
void xadc_handle_events(struct iio_dev *indio_dev, unsigned long events)
{
unsigned int i;
for_each_set_bit(i, &events, 8)
xadc_handle_event(indio_dev, i);
}
static unsigned xadc_get_threshold_offset(const struct iio_chan_spec *chan,
enum iio_event_direction dir)
{
unsigned int offset;
if (chan->type == IIO_TEMP) {
offset = XADC_THRESHOLD_OT_MAX;
} else {
if (chan->channel < 2)
offset = chan->channel + 1;
else
offset = chan->channel + 6;
}
if (dir == IIO_EV_DIR_FALLING)
offset += 4;
return offset;
}
static unsigned int xadc_get_alarm_mask(const struct iio_chan_spec *chan)
{
if (chan->type == IIO_TEMP) {
return XADC_ALARM_OT_MASK;
} else {
switch (chan->channel) {
case 0:
return XADC_ALARM_VCCINT_MASK;
case 1:
return XADC_ALARM_VCCAUX_MASK;
case 2:
return XADC_ALARM_VCCBRAM_MASK;
case 3:
return XADC_ALARM_VCCPINT_MASK;
case 4:
return XADC_ALARM_VCCPAUX_MASK;
case 5:
return XADC_ALARM_VCCODDR_MASK;
default:
/* We will never get here */
return 0;
}
}
}
int xadc_read_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir)
{
struct xadc *xadc = iio_priv(indio_dev);
return (bool)(xadc->alarm_mask & xadc_get_alarm_mask(chan));
}
int xadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, int state)
{
unsigned int alarm = xadc_get_alarm_mask(chan);
struct xadc *xadc = iio_priv(indio_dev);
uint16_t cfg, old_cfg;
int ret;
mutex_lock(&xadc->mutex);
if (state)
xadc->alarm_mask |= alarm;
else
xadc->alarm_mask &= ~alarm;
xadc->ops->update_alarm(xadc, xadc->alarm_mask);
ret = _xadc_read_adc_reg(xadc, XADC_REG_CONF1, &cfg);
if (ret)
goto err_out;
old_cfg = cfg;
cfg |= XADC_CONF1_ALARM_MASK;
cfg &= ~((xadc->alarm_mask & 0xf0) << 4); /* bram, pint, paux, ddr */
cfg &= ~((xadc->alarm_mask & 0x08) >> 3); /* ot */
cfg &= ~((xadc->alarm_mask & 0x07) << 1); /* temp, vccint, vccaux */
if (old_cfg != cfg)
ret = _xadc_write_adc_reg(xadc, XADC_REG_CONF1, cfg);
err_out:
mutex_unlock(&xadc->mutex);
return ret;
}
/* Register value is msb aligned, the lower 4 bits are ignored */
#define XADC_THRESHOLD_VALUE_SHIFT 4
int xadc_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
int *val, int *val2)
{
unsigned int offset = xadc_get_threshold_offset(chan, dir);
struct xadc *xadc = iio_priv(indio_dev);
switch (info) {
case IIO_EV_INFO_VALUE:
*val = xadc->threshold[offset];
break;
case IIO_EV_INFO_HYSTERESIS:
*val = xadc->temp_hysteresis;
break;
default:
return -EINVAL;
}
*val >>= XADC_THRESHOLD_VALUE_SHIFT;
return IIO_VAL_INT;
}
int xadc_write_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
int val, int val2)
{
unsigned int offset = xadc_get_threshold_offset(chan, dir);
struct xadc *xadc = iio_priv(indio_dev);
int ret = 0;
val <<= XADC_THRESHOLD_VALUE_SHIFT;
if (val < 0 || val > 0xffff)
return -EINVAL;
mutex_lock(&xadc->mutex);
switch (info) {
case IIO_EV_INFO_VALUE:
xadc->threshold[offset] = val;
break;
case IIO_EV_INFO_HYSTERESIS:
xadc->temp_hysteresis = val;
break;
default:
mutex_unlock(&xadc->mutex);
return -EINVAL;
}
if (chan->type == IIO_TEMP) {
/*
* According to the datasheet we need to set the lower 4 bits to
* 0x3, otherwise 125 degree celsius will be used as the
* threshold.
*/
val |= 0x3;
/*
* Since we store the hysteresis as relative (to the threshold)
* value, but the hardware expects an absolute value we need to
* recalcualte this value whenever the hysteresis or the
* threshold changes.
*/
if (xadc->threshold[offset] < xadc->temp_hysteresis)
xadc->threshold[offset + 4] = 0;
else
xadc->threshold[offset + 4] = xadc->threshold[offset] -
xadc->temp_hysteresis;
ret = _xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(offset + 4),
xadc->threshold[offset + 4]);
if (ret)
goto out_unlock;
}
if (info == IIO_EV_INFO_VALUE)
ret = _xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(offset), val);
out_unlock:
mutex_unlock(&xadc->mutex);
return ret;
}

View file

@ -0,0 +1,209 @@
/*
* Xilinx XADC driver
*
* Copyright 2013 Analog Devices Inc.
* Author: Lars-Peter Clauen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#ifndef __IIO_XILINX_XADC__
#define __IIO_XILINX_XADC__
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
struct iio_dev;
struct clk;
struct xadc_ops;
struct platform_device;
void xadc_handle_events(struct iio_dev *indio_dev, unsigned long events);
int xadc_read_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir);
int xadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, int state);
int xadc_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
int *val, int *val2);
int xadc_write_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
int val, int val2);
enum xadc_external_mux_mode {
XADC_EXTERNAL_MUX_NONE,
XADC_EXTERNAL_MUX_SINGLE,
XADC_EXTERNAL_MUX_DUAL,
};
struct xadc {
void __iomem *base;
struct clk *clk;
const struct xadc_ops *ops;
uint16_t threshold[16];
uint16_t temp_hysteresis;
unsigned int alarm_mask;
uint16_t *data;
struct iio_trigger *trigger;
struct iio_trigger *convst_trigger;
struct iio_trigger *samplerate_trigger;
enum xadc_external_mux_mode external_mux_mode;
unsigned int zynq_alarm;
unsigned int zynq_masked_alarm;
unsigned int zynq_intmask;
struct delayed_work zynq_unmask_work;
struct mutex mutex;
spinlock_t lock;
struct completion completion;
};
struct xadc_ops {
int (*read)(struct xadc *, unsigned int, uint16_t *);
int (*write)(struct xadc *, unsigned int, uint16_t);
int (*setup)(struct platform_device *pdev, struct iio_dev *indio_dev,
int irq);
void (*update_alarm)(struct xadc *, unsigned int);
unsigned long (*get_dclk_rate)(struct xadc *);
irqreturn_t (*interrupt_handler)(int, void *);
irqreturn_t (*threaded_interrupt_handler)(int, void *);
unsigned int flags;
};
static inline int _xadc_read_adc_reg(struct xadc *xadc, unsigned int reg,
uint16_t *val)
{
lockdep_assert_held(&xadc->mutex);
return xadc->ops->read(xadc, reg, val);
}
static inline int _xadc_write_adc_reg(struct xadc *xadc, unsigned int reg,
uint16_t val)
{
lockdep_assert_held(&xadc->mutex);
return xadc->ops->write(xadc, reg, val);
}
static inline int xadc_read_adc_reg(struct xadc *xadc, unsigned int reg,
uint16_t *val)
{
int ret;
mutex_lock(&xadc->mutex);
ret = _xadc_read_adc_reg(xadc, reg, val);
mutex_unlock(&xadc->mutex);
return ret;
}
static inline int xadc_write_adc_reg(struct xadc *xadc, unsigned int reg,
uint16_t val)
{
int ret;
mutex_lock(&xadc->mutex);
ret = _xadc_write_adc_reg(xadc, reg, val);
mutex_unlock(&xadc->mutex);
return ret;
}
/* XADC hardmacro register definitions */
#define XADC_REG_TEMP 0x00
#define XADC_REG_VCCINT 0x01
#define XADC_REG_VCCAUX 0x02
#define XADC_REG_VPVN 0x03
#define XADC_REG_VREFP 0x04
#define XADC_REG_VREFN 0x05
#define XADC_REG_VCCBRAM 0x06
#define XADC_REG_VCCPINT 0x0d
#define XADC_REG_VCCPAUX 0x0e
#define XADC_REG_VCCO_DDR 0x0f
#define XADC_REG_VAUX(x) (0x10 + (x))
#define XADC_REG_MAX_TEMP 0x20
#define XADC_REG_MAX_VCCINT 0x21
#define XADC_REG_MAX_VCCAUX 0x22
#define XADC_REG_MAX_VCCBRAM 0x23
#define XADC_REG_MIN_TEMP 0x24
#define XADC_REG_MIN_VCCINT 0x25
#define XADC_REG_MIN_VCCAUX 0x26
#define XADC_REG_MIN_VCCBRAM 0x27
#define XADC_REG_MAX_VCCPINT 0x28
#define XADC_REG_MAX_VCCPAUX 0x29
#define XADC_REG_MAX_VCCO_DDR 0x2a
#define XADC_REG_MIN_VCCPINT 0x2b
#define XADC_REG_MIN_VCCPAUX 0x2c
#define XADC_REG_MIN_VCCO_DDR 0x2d
#define XADC_REG_CONF0 0x40
#define XADC_REG_CONF1 0x41
#define XADC_REG_CONF2 0x42
#define XADC_REG_SEQ(x) (0x48 + (x))
#define XADC_REG_INPUT_MODE(x) (0x4c + (x))
#define XADC_REG_THRESHOLD(x) (0x50 + (x))
#define XADC_REG_FLAG 0x3f
#define XADC_CONF0_EC BIT(9)
#define XADC_CONF0_ACQ BIT(8)
#define XADC_CONF0_MUX BIT(11)
#define XADC_CONF0_CHAN(x) (x)
#define XADC_CONF1_SEQ_MASK (0xf << 12)
#define XADC_CONF1_SEQ_DEFAULT (0 << 12)
#define XADC_CONF1_SEQ_SINGLE_PASS (1 << 12)
#define XADC_CONF1_SEQ_CONTINUOUS (2 << 12)
#define XADC_CONF1_SEQ_SINGLE_CHANNEL (3 << 12)
#define XADC_CONF1_SEQ_SIMULTANEOUS (4 << 12)
#define XADC_CONF1_SEQ_INDEPENDENT (8 << 12)
#define XADC_CONF1_ALARM_MASK 0x0f0f
#define XADC_CONF2_DIV_MASK 0xff00
#define XADC_CONF2_DIV_OFFSET 8
#define XADC_CONF2_PD_MASK (0x3 << 4)
#define XADC_CONF2_PD_NONE (0x0 << 4)
#define XADC_CONF2_PD_ADC_B (0x2 << 4)
#define XADC_CONF2_PD_BOTH (0x3 << 4)
#define XADC_ALARM_TEMP_MASK BIT(0)
#define XADC_ALARM_VCCINT_MASK BIT(1)
#define XADC_ALARM_VCCAUX_MASK BIT(2)
#define XADC_ALARM_OT_MASK BIT(3)
#define XADC_ALARM_VCCBRAM_MASK BIT(4)
#define XADC_ALARM_VCCPINT_MASK BIT(5)
#define XADC_ALARM_VCCPAUX_MASK BIT(6)
#define XADC_ALARM_VCCODDR_MASK BIT(7)
#define XADC_THRESHOLD_TEMP_MAX 0x0
#define XADC_THRESHOLD_VCCINT_MAX 0x1
#define XADC_THRESHOLD_VCCAUX_MAX 0x2
#define XADC_THRESHOLD_OT_MAX 0x3
#define XADC_THRESHOLD_TEMP_MIN 0x4
#define XADC_THRESHOLD_VCCINT_MIN 0x5
#define XADC_THRESHOLD_VCCAUX_MIN 0x6
#define XADC_THRESHOLD_OT_MIN 0x7
#define XADC_THRESHOLD_VCCBRAM_MAX 0x8
#define XADC_THRESHOLD_VCCPINT_MAX 0x9
#define XADC_THRESHOLD_VCCPAUX_MAX 0xa
#define XADC_THRESHOLD_VCCODDR_MAX 0xb
#define XADC_THRESHOLD_VCCBRAM_MIN 0xc
#define XADC_THRESHOLD_VCCPINT_MIN 0xd
#define XADC_THRESHOLD_VCCPAUX_MIN 0xe
#define XADC_THRESHOLD_VCCODDR_MIN 0xf
#endif

View file

@ -194,7 +194,6 @@ static int mag3110_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
*val = mag3110_samp_freq[i][0];