diff options
author | Lee Jones <lee.jones@linaro.org> | 2014-01-21 03:26:55 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2014-01-21 03:26:55 -0500 |
commit | 28b4c2948fe005da0f70d492f59593f862b3f773 (patch) | |
tree | f45d67d4dd230bdfffdb9fa93eea32913bf14c96 /drivers/mfd | |
parent | 09fd19da0074b86030a00303522b2ba63a4399b7 (diff) | |
parent | 7ca6740cd1cd410828a01151a044b51910d06eff (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.c | 71 |
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 | ||
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)); |