diff options
-rw-r--r-- | drivers/iio/adc/ti_am335x_adc.c | 68 | ||||
-rw-r--r-- | drivers/input/touchscreen/ti_am335x_tsc.c | 4 | ||||
-rw-r--r-- | drivers/mfd/ti_am335x_tscadc.c | 71 | ||||
-rw-r--r-- | include/linux/mfd/ti_am335x_tscadc.h | 8 |
4 files changed, 117 insertions, 34 deletions
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index d4d748214e4b..31e786e3999b 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 | ||
63 | static 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 | |||
63 | static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) | 81 | static 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]; |
@@ -181,7 +199,7 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev) | |||
181 | enb |= (get_adc_step_bit(adc_dev, bit) << 1); | 199 | enb |= (get_adc_step_bit(adc_dev, bit) << 1); |
182 | adc_dev->buffer_en_ch_steps = enb; | 200 | adc_dev->buffer_en_ch_steps = enb; |
183 | 201 | ||
184 | am335x_tsc_se_set(adc_dev->mfd_tscadc, enb); | 202 | am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb); |
185 | 203 | ||
186 | tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES | 204 | tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES |
187 | | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW); | 205 | | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW); |
@@ -199,6 +217,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev) | |||
199 | tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | | 217 | tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | |
200 | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); | 218 | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); |
201 | am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps); | 219 | am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps); |
220 | adc_dev->buffer_en_ch_steps = 0; | ||
202 | 221 | ||
203 | /* Flush FIFO of leftover data in the time it takes to disable adc */ | 222 | /* Flush FIFO of leftover data in the time it takes to disable adc */ |
204 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | 223 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); |
@@ -328,34 +347,43 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, | |||
328 | unsigned int fifo1count, read, stepid; | 347 | unsigned int fifo1count, read, stepid; |
329 | bool found = false; | 348 | bool found = false; |
330 | u32 step_en; | 349 | u32 step_en; |
331 | unsigned long timeout = jiffies + usecs_to_jiffies | 350 | unsigned long timeout; |
332 | (IDLE_TIMEOUT * adc_dev->channels); | ||
333 | 351 | ||
334 | if (iio_buffer_enabled(indio_dev)) | 352 | if (iio_buffer_enabled(indio_dev)) |
335 | return -EBUSY; | 353 | return -EBUSY; |
336 | 354 | ||
337 | step_en = get_adc_step_mask(adc_dev); | 355 | step_en = get_adc_chan_step_mask(adc_dev, chan); |
338 | am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); | 356 | if (!step_en) |
357 | return -EINVAL; | ||
358 | |||
359 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | ||
360 | while (fifo1count--) | ||
361 | tiadc_readl(adc_dev, REG_FIFO1); | ||
362 | |||
363 | am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en); | ||
339 | 364 | ||
340 | /* Wait for ADC sequencer to complete sampling */ | 365 | timeout = jiffies + usecs_to_jiffies |
341 | while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) { | 366 | (IDLE_TIMEOUT * adc_dev->channels); |
342 | if (time_after(jiffies, timeout)) | 367 | /* Wait for Fifo threshold interrupt */ |
368 | while (1) { | ||
369 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | ||
370 | if (fifo1count) | ||
371 | break; | ||
372 | |||
373 | if (time_after(jiffies, timeout)) { | ||
374 | am335x_tsc_se_adc_done(adc_dev->mfd_tscadc); | ||
343 | return -EAGAIN; | 375 | return -EAGAIN; |
344 | } | 376 | } |
377 | } | ||
345 | map_val = chan->channel + TOTAL_CHANNELS; | 378 | map_val = chan->channel + TOTAL_CHANNELS; |
346 | 379 | ||
347 | /* | 380 | /* |
348 | * When the sub-system is first enabled, | 381 | * We check the complete FIFO. We programmed just one entry but in case |
349 | * the sequencer will always start with the | 382 | * something went wrong we left empty handed (-EAGAIN previously) and |
350 | * lowest step (1) and continue until step (16). | 383 | * then the value apeared somehow in the FIFO we would have two entries. |
351 | * For ex: If we have enabled 4 ADC channels and | 384 | * Therefore we read every item and keep only the latest version of the |
352 | * currently use only 1 out of them, the | 385 | * requested channel. |
353 | * sequencer still configures all the 4 steps, | ||
354 | * leading to 3 unwanted data. | ||
355 | * Hence we need to flush out this data. | ||
356 | */ | 386 | */ |
357 | |||
358 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | ||
359 | for (i = 0; i < fifo1count; i++) { | 387 | for (i = 0; i < fifo1count; i++) { |
360 | read = tiadc_readl(adc_dev, REG_FIFO1); | 388 | read = tiadc_readl(adc_dev, REG_FIFO1); |
361 | stepid = read & FIFOREAD_CHNLID_MASK; | 389 | stepid = read & FIFOREAD_CHNLID_MASK; |
@@ -367,6 +395,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, | |||
367 | *val = (u16) read; | 395 | *val = (u16) read; |
368 | } | 396 | } |
369 | } | 397 | } |
398 | am335x_tsc_se_adc_done(adc_dev->mfd_tscadc); | ||
370 | 399 | ||
371 | if (found == false) | 400 | if (found == false) |
372 | return -EBUSY; | 401 | return -EBUSY; |
@@ -494,7 +523,8 @@ static int tiadc_resume(struct device *dev) | |||
494 | tiadc_writel(adc_dev, REG_CTRL, restore); | 523 | tiadc_writel(adc_dev, REG_CTRL, restore); |
495 | 524 | ||
496 | tiadc_step_config(indio_dev); | 525 | tiadc_step_config(indio_dev); |
497 | 526 | am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, | |
527 | adc_dev->buffer_en_ch_steps); | ||
498 | return 0; | 528 | return 0; |
499 | } | 529 | } |
500 | 530 | ||
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 68beadaabceb..2ca5a7bee04e 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c | |||
@@ -198,7 +198,7 @@ static void titsc_step_config(struct titsc *ts_dev) | |||
198 | /* The steps1 … end and bit 0 for TS_Charge */ | 198 | /* The steps1 … end and bit 0 for TS_Charge */ |
199 | stepenable = (1 << (end_step + 2)) - 1; | 199 | stepenable = (1 << (end_step + 2)) - 1; |
200 | ts_dev->step_mask = stepenable; | 200 | ts_dev->step_mask = stepenable; |
201 | am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask); | 201 | am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask); |
202 | } | 202 | } |
203 | 203 | ||
204 | static void titsc_read_coordinates(struct titsc *ts_dev, | 204 | static void titsc_read_coordinates(struct titsc *ts_dev, |
@@ -322,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev) | |||
322 | 322 | ||
323 | if (irqclr) { | 323 | if (irqclr) { |
324 | titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); | 324 | titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); |
325 | am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask); | 325 | am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask); |
326 | return IRQ_HANDLED; | 326 | return IRQ_HANDLED; |
327 | } | 327 | } |
328 | return IRQ_NONE; | 328 | return IRQ_NONE; |
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 88718abfb9ba..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,32 +49,79 @@ static const struct regmap_config tscadc_regmap_config = { | |||
48 | .val_bits = 32, | 49 | .val_bits = 32, |
49 | }; | 50 | }; |
50 | 51 | ||
51 | void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc) | 52 | void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) |
52 | { | 53 | { |
53 | tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); | 54 | unsigned long flags; |
55 | |||
56 | spin_lock_irqsave(&tsadc->reg_lock, flags); | ||
57 | tsadc->reg_se_cache = val; | ||
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); | ||
64 | } | ||
65 | EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache); | ||
66 | |||
67 | static 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 | |||
97 | void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) | ||
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); | ||
54 | } | 104 | } |
55 | EXPORT_SYMBOL_GPL(am335x_tsc_se_update); | 105 | EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); |
56 | 106 | ||
57 | void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val) | 107 | void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc) |
58 | { | 108 | { |
59 | unsigned long flags; | 109 | unsigned long flags; |
60 | 110 | ||
61 | spin_lock_irqsave(&tsadc->reg_lock, flags); | 111 | spin_lock_irqsave(&tsadc->reg_lock, flags); |
62 | tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE); | 112 | tsadc->adc_in_use = false; |
63 | tsadc->reg_se_cache |= val; | 113 | tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); |
64 | am335x_tsc_se_update(tsadc); | ||
65 | spin_unlock_irqrestore(&tsadc->reg_lock, flags); | 114 | spin_unlock_irqrestore(&tsadc->reg_lock, flags); |
66 | } | 115 | } |
67 | EXPORT_SYMBOL_GPL(am335x_tsc_se_set); | 116 | EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done); |
68 | 117 | ||
69 | void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) | 118 | void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) |
70 | { | 119 | { |
71 | unsigned long flags; | 120 | unsigned long flags; |
72 | 121 | ||
73 | spin_lock_irqsave(&tsadc->reg_lock, flags); | 122 | spin_lock_irqsave(&tsadc->reg_lock, flags); |
74 | tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE); | ||
75 | tsadc->reg_se_cache &= ~val; | 123 | tsadc->reg_se_cache &= ~val; |
76 | am335x_tsc_se_update(tsadc); | 124 | tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); |
77 | spin_unlock_irqrestore(&tsadc->reg_lock, flags); | 125 | spin_unlock_irqrestore(&tsadc->reg_lock, flags); |
78 | } | 126 | } |
79 | EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); | 127 | EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); |
@@ -181,6 +229,8 @@ static int ti_tscadc_probe(struct platform_device *pdev) | |||
181 | } | 229 | } |
182 | 230 | ||
183 | spin_lock_init(&tscadc->reg_lock); | 231 | spin_lock_init(&tscadc->reg_lock); |
232 | init_waitqueue_head(&tscadc->reg_se_wait); | ||
233 | |||
184 | pm_runtime_enable(&pdev->dev); | 234 | pm_runtime_enable(&pdev->dev); |
185 | pm_runtime_get_sync(&pdev->dev); | 235 | pm_runtime_get_sync(&pdev->dev); |
186 | 236 | ||
@@ -302,7 +352,6 @@ static int tscadc_resume(struct device *dev) | |||
302 | 352 | ||
303 | if (tscadc_dev->tsc_cell != -1) | 353 | if (tscadc_dev->tsc_cell != -1) |
304 | tscadc_idle_config(tscadc_dev); | 354 | tscadc_idle_config(tscadc_dev); |
305 | am335x_tsc_se_update(tscadc_dev); | ||
306 | restore = tscadc_readl(tscadc_dev, REG_CTRL); | 355 | restore = tscadc_readl(tscadc_dev, REG_CTRL); |
307 | tscadc_writel(tscadc_dev, REG_CTRL, | 356 | tscadc_writel(tscadc_dev, REG_CTRL, |
308 | (restore | CNTRLREG_TSCSSENB)); | 357 | (restore | CNTRLREG_TSCSSENB)); |
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index d498d98f0c2c..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 | ||
@@ -176,8 +179,9 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p) | |||
176 | return *tscadc_dev; | 179 | return *tscadc_dev; |
177 | } | 180 | } |
178 | 181 | ||
179 | void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc); | 182 | void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val); |
180 | void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val); | 183 | void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val); |
181 | void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val); | 184 | void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val); |
185 | void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc); | ||
182 | 186 | ||
183 | #endif | 187 | #endif |