Second round of IIO fixes for the 3.11 cycle.

1) Fix a long term race in the IIO trigger handling.
    This only effects cases where a single trigger is in use
    by multiple devices.
 2) ti_am335x fix an issue with incorrect data due to reading before
    the sequencer is finished.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.20 (GNU/Linux)
 
 iQIcBAABAgAGBQJR/oKnAAoJEFSFNJnE9BaItqYP/0V7a+3mVr2mCGq0McyUmY+P
 jQJ6+jg6Vv0RKajOKadv150qgQwrmCwE2Zgev8dmdrTajd/Ww0PiowUgmDSmacnE
 L+Tl5YDCG2arcZs6QiuccSTbssH/U8JOraFkKtlAw3dObWzMagg5eFHOXmnduHEp
 aY5O0v0eLySF1/1HaVkPFZ6zvWQnUh9ylnijqgZTT2JtUifuy2oR4Ib806G3ObU/
 gUJFN+FbUgbSKSy5GeBVWGEAG5YS8Io6GcWtCI5gzIlwfOoL6G0cCSueuTqD1/WZ
 R2uHi9irjNTmdysOlONvXRiKyZqPIFY2Th8DsfbrI5y5cm/hAXM0LeZLGmEosqKM
 qYqdA3AIVCaVRguyqtwO4q5t/taPS+D08TfnpiKr75JfB4BO6w9fm6RLSxeBtzoQ
 dAQhW/T4qooefDfe/x8Ol7AElVV5vNkJ82U2zoIOhWIcAHIFdUNGFI3Y4EAirEsh
 aFFQRaHCInwWtIEISlEvHWc3e1LbMXQajHuSU6UKvOrcI4d9NJSGDzNb6xyRIKSb
 zxeC8fxKLeJAtXj9iUrBBBn41cx5DZueGJzsuCtCUvApi/jujXWrxfDK0DaAodZ3
 6anolfW59YfWuEaXDBa0Y041qG4NI/fOZbrd43sY+9Bg6ZlGq2jss0u9rvI2Xtn7
 xhg2F75nFKKnv7JF7cRZ
 =U1lS
 -----END PGP SIGNATURE-----

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

Jonathan writes:

Second round of IIO fixes for the 3.11 cycle.

1) Fix a long term race in the IIO trigger handling.
   This only effects cases where a single trigger is in use
   by multiple devices.
2) ti_am335x fix an issue with incorrect data due to reading before
   the sequencer is finished.
This commit is contained in:
Greg Kroah-Hartman 2013-08-05 14:04:24 +08:00
commit cefe8a32f2
4 changed files with 62 additions and 21 deletions

View File

@ -60,7 +60,6 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
{
unsigned int stepconfig;
int i, steps;
u32 step_en;
/*
* There are 16 configurable steps and 8 analog input
@ -86,8 +85,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
adc_dev->channel_step[i] = steps;
steps++;
}
step_en = get_adc_step_mask(adc_dev);
am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
}
static const char * const chan_name_ain[] = {
@ -142,10 +140,22 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
int i;
unsigned int fifo1count, read;
int i, map_val;
unsigned int fifo1count, read, stepid;
u32 step = UINT_MAX;
bool found = false;
u32 step_en;
unsigned long timeout = jiffies + usecs_to_jiffies
(IDLE_TIMEOUT * adc_dev->channels);
step_en = get_adc_step_mask(adc_dev);
am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
/* Wait for ADC sequencer to complete sampling */
while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
if (time_after(jiffies, timeout))
return -EAGAIN;
}
map_val = chan->channel + TOTAL_CHANNELS;
/*
* When the sub-system is first enabled,
@ -170,12 +180,16 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
for (i = 0; i < fifo1count; i++) {
read = tiadc_readl(adc_dev, REG_FIFO1);
if (read >> 16 == step) {
*val = read & 0xfff;
stepid = read & FIFOREAD_CHNLID_MASK;
stepid = stepid >> 0x10;
if (stepid == map_val) {
read = read & FIFOREAD_DATA_MASK;
found = true;
*val = read;
}
}
am335x_tsc_se_update(adc_dev->mfd_tscadc);
if (found == false)
return -EBUSY;
return IIO_VAL_INT;

View File

@ -127,11 +127,16 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name,
void iio_trigger_poll(struct iio_trigger *trig, s64 time)
{
int i;
if (!trig->use_count)
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
if (trig->subirqs[i].enabled) {
trig->use_count++;
if (!atomic_read(&trig->use_count)) {
atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
if (trig->subirqs[i].enabled)
generic_handle_irq(trig->subirq_base + i);
else
iio_trigger_notify_done(trig);
}
}
}
EXPORT_SYMBOL(iio_trigger_poll);
@ -146,19 +151,24 @@ EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll);
void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time)
{
int i;
if (!trig->use_count)
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
if (trig->subirqs[i].enabled) {
trig->use_count++;
if (!atomic_read(&trig->use_count)) {
atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
if (trig->subirqs[i].enabled)
handle_nested_irq(trig->subirq_base + i);
else
iio_trigger_notify_done(trig);
}
}
}
EXPORT_SYMBOL(iio_trigger_poll_chained);
void iio_trigger_notify_done(struct iio_trigger *trig)
{
trig->use_count--;
if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable)
if (atomic_dec_and_test(&trig->use_count) && trig->ops &&
trig->ops->try_reenable)
if (trig->ops->try_reenable(trig))
/* Missed an interrupt so launch new poll now */
iio_trigger_poll(trig, 0);

View File

@ -8,6 +8,7 @@
*/
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/atomic.h>
#ifndef _IIO_TRIGGER_H_
#define _IIO_TRIGGER_H_
@ -61,7 +62,7 @@ struct iio_trigger {
struct list_head list;
struct list_head alloc_list;
int use_count;
atomic_t use_count;
struct irq_chip subirq_chip;
int subirq_base;

View File

@ -113,11 +113,27 @@
#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
#define CNTRLREG_TSCENB BIT(7)
/* FIFO READ Register */
#define FIFOREAD_DATA_MASK (0xfff << 0)
#define FIFOREAD_CHNLID_MASK (0xf << 16)
/* Sequencer Status */
#define SEQ_STATUS BIT(5)
#define ADC_CLK 3000000
#define MAX_CLK_DIV 7
#define TOTAL_STEPS 16
#define TOTAL_CHANNELS 8
/*
* ADC runs at 3MHz, and it takes
* 15 cycles to latch one data output.
* Hence the idle time for ADC to
* process one sample data would be
* around 5 micro seconds.
*/
#define IDLE_TIMEOUT 5 /* microsec */
#define TSCADC_CELLS 2
struct ti_tscadc_dev {