aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2014-01-21 03:26:55 -0500
committerLee Jones <lee.jones@linaro.org>2014-01-21 03:26:55 -0500
commit28b4c2948fe005da0f70d492f59593f862b3f773 (patch)
treef45d67d4dd230bdfffdb9fa93eea32913bf14c96 /drivers/mfd
parent09fd19da0074b86030a00303522b2ba63a4399b7 (diff)
parent7ca6740cd1cd410828a01151a044b51910d06eff (diff)
Merge tag 'ib-iio-input-3.13-1' into for-mfd-next
Immutable branch for IIO and Input
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c71
1 files changed, 60 insertions, 11 deletions
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
51void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc) 52void 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}
65EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
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
97void 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}
55EXPORT_SYMBOL_GPL(am335x_tsc_se_update); 105EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
56 106
57void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val) 107void 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}
67EXPORT_SYMBOL_GPL(am335x_tsc_se_set); 116EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
68 117
69void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) 118void 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}
79EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); 127EXPORT_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));