aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2013-12-19 10:28:31 -0500
committerLee Jones <lee.jones@linaro.org>2014-01-07 03:45:00 -0500
commit7ca6740cd1cd410828a01151a044b51910d06eff (patch)
treee9527767fefbe621dfdeca70e0a310c818f9175d
parent3954b7bfc665fed878cabe57342bae34d2391478 (diff)
mfd: input: iio: ti_amm335x: Rework TSC/ADC synchronization
The ADC driver always programs all possible ADC values and discards them except for the value IIO asked for. On the am335x-evm the driver programs four values and it takes 500us to gather them. Reducing the number of conversations down to the (required) one also reduces the busy loop down to 125us. This leads to another error, namely the FIFOCOUNT register is sometimes (like one out of 10 attempts) not updated in time leading to EBUSY. The next read has the FIFOCOUNT register updated. Checking for the ADCSTAT register for being idle isn't a good choice either. The problem is that if TSC is used at the same time, the HW completes the conversation for ADC *and* before the driver noticed it, the HW begins to perform a TSC conversation and so the driver never seen the HW idle. The next time we would have two values in the FIFO but since the driver reads everything we always see the current one. So instead of polling for the IDLE bit in ADCStatus register, we should check the FIFOCOUNT register. It should be one instead of zero because we request one value. This change in turn leads to another error. Sometimes if TSC & ADC are used together the TSC starts generating interrupts even if nobody actually touched the touchscreen. The interrupts seem valid because TSC's FIFO is filled with values for each channel of the TSC. This condition stops after a few ADC reads but will occur again. Not good. On top of this (even without the changes I just mentioned) there is a ADC & TSC lockup condition which was reported to me by Jeff Lance including the following test case: A busy loop of "cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw" and a mug on touch screen. With this setup, the hardware will lockup after something between 20 minutes and it could take up to a couple of hours. During that lockup, the ADCSTAT register says 0x30 (or 0x70) which means STEP_ID = IDLE and FSM_BUSY = yes. That means the hardware says that it is idle and busy at the same time which is an invalid condition. For all this reasons I decided to rework this TSC/ADC part and add a handshake / synchronization here: First the ADC signals that it needs the HW and writes a 0 mask into the SE register. The HW (if active) will complete the current conversation and become idle. The TSC driver will gather the values from the FIFO (woken up by an interrupt) and won't "enable" another conversation. Instead it will wake up the ADC driver which is already waiting. The ADC driver will start "its" conversation and once it is done, it will enable the TSC steps so the TSC will work again. After this rework I haven't observed the lockup so far. Plus the busy loop has been reduced from 500us to 125us. The continues-read mode remains unchanged. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c64
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c63
-rw-r--r--include/linux/mfd/ti_am335x_tscadc.h4
3 files changed, 103 insertions, 28 deletions
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index e0dc2d0e7590..dff7343405e2 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -60,6 +60,24 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
60 return step_en; 60 return step_en;
61} 61}
62 62
63static u32 get_adc_chan_step_mask(struct tiadc_device *adc_dev,
64 struct iio_chan_spec const *chan)
65{
66 int i;
67
68 for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
69 if (chan->channel == adc_dev->channel_line[i]) {
70 u32 step;
71
72 step = adc_dev->channel_step[i];
73 /* +1 for the charger */
74 return 1 << (step + 1);
75 }
76 }
77 WARN_ON(1);
78 return 0;
79}
80
63static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) 81static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
64{ 82{
65 return 1 << adc_dev->channel_step[chan]; 83 return 1 << adc_dev->channel_step[chan];
@@ -326,34 +344,43 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
326 unsigned int fifo1count, read, stepid; 344 unsigned int fifo1count, read, stepid;
327 bool found = false; 345 bool found = false;
328 u32 step_en; 346 u32 step_en;
329 unsigned long timeout = jiffies + usecs_to_jiffies 347 unsigned long timeout;
330 (IDLE_TIMEOUT * adc_dev->channels);
331 348
332 if (iio_buffer_enabled(indio_dev)) 349 if (iio_buffer_enabled(indio_dev))
333 return -EBUSY; 350 return -EBUSY;
334 351
335 step_en = get_adc_step_mask(adc_dev); 352 step_en = get_adc_chan_step_mask(adc_dev, chan);
353 if (!step_en)
354 return -EINVAL;
355
356 fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
357 while (fifo1count--)
358 tiadc_readl(adc_dev, REG_FIFO1);
359
336 am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en); 360 am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en);
337 361
338 /* Wait for ADC sequencer to complete sampling */ 362 timeout = jiffies + usecs_to_jiffies
339 while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) { 363 (IDLE_TIMEOUT * adc_dev->channels);
340 if (time_after(jiffies, timeout)) 364 /* Wait for Fifo threshold interrupt */
365 while (1) {
366 fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
367 if (fifo1count)
368 break;
369
370 if (time_after(jiffies, timeout)) {
371 am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
341 return -EAGAIN; 372 return -EAGAIN;
373 }
342 } 374 }
343 map_val = chan->channel + TOTAL_CHANNELS; 375 map_val = chan->channel + TOTAL_CHANNELS;
344 376
345 /* 377 /*
346 * When the sub-system is first enabled, 378 * We check the complete FIFO. We programmed just one entry but in case
347 * the sequencer will always start with the 379 * something went wrong we left empty handed (-EAGAIN previously) and
348 * lowest step (1) and continue until step (16). 380 * then the value apeared somehow in the FIFO we would have two entries.
349 * For ex: If we have enabled 4 ADC channels and 381 * Therefore we read every item and keep only the latest version of the
350 * currently use only 1 out of them, the 382 * requested channel.
351 * sequencer still configures all the 4 steps,
352 * leading to 3 unwanted data.
353 * Hence we need to flush out this data.
354 */ 383 */
355
356 fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
357 for (i = 0; i < fifo1count; i++) { 384 for (i = 0; i < fifo1count; i++) {
358 read = tiadc_readl(adc_dev, REG_FIFO1); 385 read = tiadc_readl(adc_dev, REG_FIFO1);
359 stepid = read & FIFOREAD_CHNLID_MASK; 386 stepid = read & FIFOREAD_CHNLID_MASK;
@@ -365,6 +392,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
365 *val = (u16) read; 392 *val = (u16) read;
366 } 393 }
367 } 394 }
395 am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
368 396
369 if (found == false) 397 if (found == false)
370 return -EBUSY; 398 return -EBUSY;
@@ -492,8 +520,8 @@ static int tiadc_resume(struct device *dev)
492 tiadc_writel(adc_dev, REG_CTRL, restore); 520 tiadc_writel(adc_dev, REG_CTRL, restore);
493 521
494 tiadc_step_config(indio_dev); 522 tiadc_step_config(indio_dev);
495 am335x_tsc_se_set(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps); 523 am335x_tsc_se_set_cache(adc_dev->mfd_tscadc,
496 524 adc_dev->buffer_en_ch_steps);
497 return 0; 525 return 0;
498} 526}
499 527
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 157f5699a33c..d4e860413bb5 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -24,6 +24,7 @@
24#include <linux/pm_runtime.h> 24#include <linux/pm_runtime.h>
25#include <linux/of.h> 25#include <linux/of.h>
26#include <linux/of_device.h> 26#include <linux/of_device.h>
27#include <linux/sched.h>
27 28
28#include <linux/mfd/ti_am335x_tscadc.h> 29#include <linux/mfd/ti_am335x_tscadc.h>
29 30
@@ -48,31 +49,71 @@ static const struct regmap_config tscadc_regmap_config = {
48 .val_bits = 32, 49 .val_bits = 32,
49}; 50};
50 51
51static void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
52{
53 tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
54}
55
56void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) 52void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val)
57{ 53{
58 unsigned long flags; 54 unsigned long flags;
59 55
60 spin_lock_irqsave(&tsadc->reg_lock, flags); 56 spin_lock_irqsave(&tsadc->reg_lock, flags);
61 tsadc->reg_se_cache |= val; 57 tsadc->reg_se_cache = val;
62 am335x_tsc_se_update(tsadc); 58 if (tsadc->adc_waiting)
59 wake_up(&tsadc->reg_se_wait);
60 else if (!tsadc->adc_in_use)
61 tscadc_writel(tsadc, REG_SE, val);
62
63 spin_unlock_irqrestore(&tsadc->reg_lock, flags); 63 spin_unlock_irqrestore(&tsadc->reg_lock, flags);
64} 64}
65EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache); 65EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
66 66
67static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
68{
69 DEFINE_WAIT(wait);
70 u32 reg;
71
72 /*
73 * disable TSC steps so it does not run while the ADC is using it. If
74 * write 0 while it is running (it just started or was already running)
75 * then it completes all steps that were enabled and stops then.
76 */
77 tscadc_writel(tsadc, REG_SE, 0);
78 reg = tscadc_readl(tsadc, REG_ADCFSM);
79 if (reg & SEQ_STATUS) {
80 tsadc->adc_waiting = true;
81 prepare_to_wait(&tsadc->reg_se_wait, &wait,
82 TASK_UNINTERRUPTIBLE);
83 spin_unlock_irq(&tsadc->reg_lock);
84
85 schedule();
86
87 spin_lock_irq(&tsadc->reg_lock);
88 finish_wait(&tsadc->reg_se_wait, &wait);
89
90 reg = tscadc_readl(tsadc, REG_ADCFSM);
91 WARN_ON(reg & SEQ_STATUS);
92 tsadc->adc_waiting = false;
93 }
94 tsadc->adc_in_use = true;
95}
96
67void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) 97void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
68{ 98{
99 spin_lock_irq(&tsadc->reg_lock);
100 am335x_tscadc_need_adc(tsadc);
101
102 tscadc_writel(tsadc, REG_SE, val);
103 spin_unlock_irq(&tsadc->reg_lock);
104}
105EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
106
107void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc)
108{
69 unsigned long flags; 109 unsigned long flags;
70 110
71 spin_lock_irqsave(&tsadc->reg_lock, flags); 111 spin_lock_irqsave(&tsadc->reg_lock, flags);
72 tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache | val); 112 tsadc->adc_in_use = false;
113 tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
73 spin_unlock_irqrestore(&tsadc->reg_lock, flags); 114 spin_unlock_irqrestore(&tsadc->reg_lock, flags);
74} 115}
75EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); 116EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
76 117
77void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) 118void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
78{ 119{
@@ -80,7 +121,7 @@ void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
80 121
81 spin_lock_irqsave(&tsadc->reg_lock, flags); 122 spin_lock_irqsave(&tsadc->reg_lock, flags);
82 tsadc->reg_se_cache &= ~val; 123 tsadc->reg_se_cache &= ~val;
83 am335x_tsc_se_update(tsadc); 124 tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
84 spin_unlock_irqrestore(&tsadc->reg_lock, flags); 125 spin_unlock_irqrestore(&tsadc->reg_lock, flags);
85} 126}
86EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); 127EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
@@ -188,6 +229,8 @@ static int ti_tscadc_probe(struct platform_device *pdev)
188 } 229 }
189 230
190 spin_lock_init(&tscadc->reg_lock); 231 spin_lock_init(&tscadc->reg_lock);
232 init_waitqueue_head(&tscadc->reg_se_wait);
233
191 pm_runtime_enable(&pdev->dev); 234 pm_runtime_enable(&pdev->dev);
192 pm_runtime_get_sync(&pdev->dev); 235 pm_runtime_get_sync(&pdev->dev);
193 236
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 2fa9c0613da4..fb96c84dada5 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -159,6 +159,9 @@ struct ti_tscadc_dev {
159 int adc_cell; /* -1 if not used */ 159 int adc_cell; /* -1 if not used */
160 struct mfd_cell cells[TSCADC_CELLS]; 160 struct mfd_cell cells[TSCADC_CELLS];
161 u32 reg_se_cache; 161 u32 reg_se_cache;
162 bool adc_waiting;
163 bool adc_in_use;
164 wait_queue_head_t reg_se_wait;
162 spinlock_t reg_lock; 165 spinlock_t reg_lock;
163 unsigned int clk_div; 166 unsigned int clk_div;
164 167
@@ -179,5 +182,6 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
179void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val); 182void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val);
180void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val); 183void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val);
181void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val); 184void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
185void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc);
182 186
183#endif 187#endif