aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-03-24 19:05:58 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-04-08 09:20:58 -0400
commit3092f8050eccce8463afe771f0910634a433e24b (patch)
tree5b178d5527cffdf65bd2d7d045b8b3d4da6d7855 /drivers/mfd
parentf8a0941f1bbdbaa68441142675986501b48da8f5 (diff)
mfd: arizona: Allow GPIO to be specified for IRQ line
If a GPIO is specified for the chip IRQ line then request it. This improves support for systems that do not put pins into input mode when used as interrupts. Also use this GPIO when the primary IRQ is in edge triggered mode to detect if we have handled pending interrupts in order to improve robustness. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/arizona-irq.c66
1 files changed, 53 insertions, 13 deletions
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index aa25468d24aa..f761cc119c01 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -94,6 +94,7 @@ static irqreturn_t arizona_ctrlif_err(int irq, void *data)
94static irqreturn_t arizona_irq_thread(int irq, void *data) 94static irqreturn_t arizona_irq_thread(int irq, void *data)
95{ 95{
96 struct arizona *arizona = data; 96 struct arizona *arizona = data;
97 bool poll;
97 unsigned int val; 98 unsigned int val;
98 int ret; 99 int ret;
99 100
@@ -103,20 +104,39 @@ static irqreturn_t arizona_irq_thread(int irq, void *data)
103 return IRQ_NONE; 104 return IRQ_NONE;
104 } 105 }
105 106
106 /* Always handle the AoD domain */ 107 do {
107 handle_nested_irq(irq_find_mapping(arizona->virq, 0)); 108 poll = false;
109
110 /* Always handle the AoD domain */
111 handle_nested_irq(irq_find_mapping(arizona->virq, 0));
112
113 /*
114 * Check if one of the main interrupts is asserted and only
115 * check that domain if it is.
116 */
117 ret = regmap_read(arizona->regmap, ARIZONA_IRQ_PIN_STATUS,
118 &val);
119 if (ret == 0 && val & ARIZONA_IRQ1_STS) {
120 handle_nested_irq(irq_find_mapping(arizona->virq, 1));
121 } else if (ret != 0) {
122 dev_err(arizona->dev,
123 "Failed to read main IRQ status: %d\n", ret);
124 }
108 125
109 /* 126 /*
110 * Check if one of the main interrupts is asserted and only 127 * Poll the IRQ pin status to see if we're really done
111 * check that domain if it is. 128 * if the interrupt controller can't do it for us.
112 */ 129 */
113 ret = regmap_read(arizona->regmap, ARIZONA_IRQ_PIN_STATUS, &val); 130 if (!arizona->pdata.irq_gpio) {
114 if (ret == 0 && val & ARIZONA_IRQ1_STS) { 131 break;
115 handle_nested_irq(irq_find_mapping(arizona->virq, 1)); 132 } else if (arizona->pdata.irq_flags & IRQF_TRIGGER_RISING &&
116 } else if (ret != 0) { 133 gpio_get_value_cansleep(arizona->pdata.irq_gpio)) {
117 dev_err(arizona->dev, "Failed to read main IRQ status: %d\n", 134 poll = true;
118 ret); 135 } else if (arizona->pdata.irq_flags & IRQF_TRIGGER_FALLING &&
119 } 136 !gpio_get_value_cansleep(arizona->pdata.irq_gpio)) {
137 poll = true;
138 }
139 } while (poll);
120 140
121 pm_runtime_mark_last_busy(arizona->dev); 141 pm_runtime_mark_last_busy(arizona->dev);
122 pm_runtime_put_autosuspend(arizona->dev); 142 pm_runtime_put_autosuspend(arizona->dev);
@@ -262,6 +282,26 @@ int arizona_irq_init(struct arizona *arizona)
262 } 282 }
263 } 283 }
264 284
285 /* Used to emulate edge trigger and to work around broken pinmux */
286 if (arizona->pdata.irq_gpio) {
287 if (gpio_to_irq(arizona->pdata.irq_gpio) != arizona->irq) {
288 dev_warn(arizona->dev, "IRQ %d is not GPIO %d (%d)\n",
289 arizona->irq, arizona->pdata.irq_gpio,
290 gpio_to_irq(arizona->pdata.irq_gpio));
291 arizona->irq = gpio_to_irq(arizona->pdata.irq_gpio);
292 }
293
294 ret = devm_gpio_request_one(arizona->dev,
295 arizona->pdata.irq_gpio,
296 GPIOF_IN, "arizona IRQ");
297 if (ret != 0) {
298 dev_err(arizona->dev,
299 "Failed to request IRQ GPIO %d:: %d\n",
300 arizona->pdata.irq_gpio, ret);
301 arizona->pdata.irq_gpio = 0;
302 }
303 }
304
265 ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread, 305 ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,
266 flags, "arizona", arizona); 306 flags, "arizona", arizona);
267 307