Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cefe8a32 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'iio-fixes-for-3.11b' of...

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.
parents 02073798 b1451e54
Loading
Loading
Loading
Loading
+22 −8
Original line number Diff line number Diff line
@@ -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;
+22 −12
Original line number Diff line number Diff line
@@ -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);
+2 −1
Original line number Diff line number Diff line
@@ -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;
+16 −0
Original line number Diff line number Diff line
@@ -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 {