forked from Minki/linux
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:
commit
cefe8a32f2
@ -60,7 +60,6 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
|
|||||||
{
|
{
|
||||||
unsigned int stepconfig;
|
unsigned int stepconfig;
|
||||||
int i, steps;
|
int i, steps;
|
||||||
u32 step_en;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are 16 configurable steps and 8 analog input
|
* 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;
|
adc_dev->channel_step[i] = steps;
|
||||||
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[] = {
|
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)
|
int *val, int *val2, long mask)
|
||||||
{
|
{
|
||||||
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
||||||
int i;
|
int i, map_val;
|
||||||
unsigned int fifo1count, read;
|
unsigned int fifo1count, read, stepid;
|
||||||
u32 step = UINT_MAX;
|
u32 step = UINT_MAX;
|
||||||
bool found = false;
|
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,
|
* 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);
|
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
||||||
for (i = 0; i < fifo1count; i++) {
|
for (i = 0; i < fifo1count; i++) {
|
||||||
read = tiadc_readl(adc_dev, REG_FIFO1);
|
read = tiadc_readl(adc_dev, REG_FIFO1);
|
||||||
if (read >> 16 == step) {
|
stepid = read & FIFOREAD_CHNLID_MASK;
|
||||||
*val = read & 0xfff;
|
stepid = stepid >> 0x10;
|
||||||
|
|
||||||
|
if (stepid == map_val) {
|
||||||
|
read = read & FIFOREAD_DATA_MASK;
|
||||||
found = true;
|
found = true;
|
||||||
|
*val = read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
am335x_tsc_se_update(adc_dev->mfd_tscadc);
|
|
||||||
if (found == false)
|
if (found == false)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
|
@ -127,12 +127,17 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name,
|
|||||||
void iio_trigger_poll(struct iio_trigger *trig, s64 time)
|
void iio_trigger_poll(struct iio_trigger *trig, s64 time)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (!trig->use_count)
|
|
||||||
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
|
if (!atomic_read(&trig->use_count)) {
|
||||||
if (trig->subirqs[i].enabled) {
|
atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
|
||||||
trig->use_count++;
|
|
||||||
|
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
|
||||||
|
if (trig->subirqs[i].enabled)
|
||||||
generic_handle_irq(trig->subirq_base + i);
|
generic_handle_irq(trig->subirq_base + i);
|
||||||
}
|
else
|
||||||
|
iio_trigger_notify_done(trig);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iio_trigger_poll);
|
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)
|
void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (!trig->use_count)
|
|
||||||
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
|
if (!atomic_read(&trig->use_count)) {
|
||||||
if (trig->subirqs[i].enabled) {
|
atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
|
||||||
trig->use_count++;
|
|
||||||
|
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
|
||||||
|
if (trig->subirqs[i].enabled)
|
||||||
handle_nested_irq(trig->subirq_base + i);
|
handle_nested_irq(trig->subirq_base + i);
|
||||||
}
|
else
|
||||||
|
iio_trigger_notify_done(trig);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iio_trigger_poll_chained);
|
EXPORT_SYMBOL(iio_trigger_poll_chained);
|
||||||
|
|
||||||
void iio_trigger_notify_done(struct iio_trigger *trig)
|
void iio_trigger_notify_done(struct iio_trigger *trig)
|
||||||
{
|
{
|
||||||
trig->use_count--;
|
if (atomic_dec_and_test(&trig->use_count) && trig->ops &&
|
||||||
if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable)
|
trig->ops->try_reenable)
|
||||||
if (trig->ops->try_reenable(trig))
|
if (trig->ops->try_reenable(trig))
|
||||||
/* Missed an interrupt so launch new poll now */
|
/* Missed an interrupt so launch new poll now */
|
||||||
iio_trigger_poll(trig, 0);
|
iio_trigger_poll(trig, 0);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/atomic.h>
|
||||||
|
|
||||||
#ifndef _IIO_TRIGGER_H_
|
#ifndef _IIO_TRIGGER_H_
|
||||||
#define _IIO_TRIGGER_H_
|
#define _IIO_TRIGGER_H_
|
||||||
@ -61,7 +62,7 @@ struct iio_trigger {
|
|||||||
|
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct list_head alloc_list;
|
struct list_head alloc_list;
|
||||||
int use_count;
|
atomic_t use_count;
|
||||||
|
|
||||||
struct irq_chip subirq_chip;
|
struct irq_chip subirq_chip;
|
||||||
int subirq_base;
|
int subirq_base;
|
||||||
|
@ -113,11 +113,27 @@
|
|||||||
#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
|
#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
|
||||||
#define CNTRLREG_TSCENB BIT(7)
|
#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 ADC_CLK 3000000
|
||||||
#define MAX_CLK_DIV 7
|
#define MAX_CLK_DIV 7
|
||||||
#define TOTAL_STEPS 16
|
#define TOTAL_STEPS 16
|
||||||
#define TOTAL_CHANNELS 8
|
#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
|
#define TSCADC_CELLS 2
|
||||||
|
|
||||||
struct ti_tscadc_dev {
|
struct ti_tscadc_dev {
|
||||||
|
Loading…
Reference in New Issue
Block a user