aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-02-07 15:41:30 -0500
committerMatthew Garrett <mjg@redhat.com>2011-02-21 17:06:11 -0500
commit98401ae43413ac374c0eb8d6018b13495e08f948 (patch)
treeb389790651fb384b1fbef96789c3b0eb179ee99c /drivers/platform
parentd4b7de612d193e1c8fdeee9902e5a582e746dfe9 (diff)
platform-drivers: x86: pmic: Use request_irq instead of chained handler
There is no need to install a chained handler for this hardware. This is a plain x86 IOAPIC interrupt which is handled by the core code perfectly fine. There is nothing special about demultiplexing these gpio interrupts which justifies a custom hack. Replace it by a plain old interrupt handler installed with request_irq. That makes the code agnostic about the underlying primary interrupt hardware. The overhead for this is minimal, but it gives us the advantage of accounting, balancing and to detect interrupt storms. gpio interrupts are not really that performance critical. Patch fixups from akpm Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/intel_pmic_gpio.c50
1 files changed, 12 insertions, 38 deletions
diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c
index df244c83681d..61433d492862 100644
--- a/drivers/platform/x86/intel_pmic_gpio.c
+++ b/drivers/platform/x86/intel_pmic_gpio.c
@@ -74,19 +74,6 @@ struct pmic_gpio {
74 u32 trigger_type; 74 u32 trigger_type;
75}; 75};
76 76
77static void pmic_program_irqtype(int gpio, int type)
78{
79 if (type & IRQ_TYPE_EDGE_RISING)
80 intel_scu_ipc_update_register(GPIO0 + gpio, 0x20, 0x20);
81 else
82 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x20);
83
84 if (type & IRQ_TYPE_EDGE_FALLING)
85 intel_scu_ipc_update_register(GPIO0 + gpio, 0x10, 0x10);
86 else
87 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10);
88};
89
90static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 77static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
91{ 78{
92 if (offset > 8) { 79 if (offset > 8) {
@@ -179,26 +166,6 @@ static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
179 return pg->irq_base + offset; 166 return pg->irq_base + offset;
180} 167}
181 168
182static void pmic_bus_lock(struct irq_data *data)
183{
184 struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
185
186 mutex_lock(&pg->buslock);
187}
188
189static void pmic_bus_sync_unlock(struct irq_data *data)
190{
191 struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
192
193 if (pg->update_type) {
194 unsigned int gpio = pg->update_type & ~GPIO_UPDATE_TYPE;
195
196 pmic_program_irqtype(gpio, pg->trigger_type);
197 pg->update_type = 0;
198 }
199 mutex_unlock(&pg->buslock);
200}
201
202/* the gpiointr register is read-clear, so just do nothing. */ 169/* the gpiointr register is read-clear, so just do nothing. */
203static void pmic_irq_unmask(struct irq_data *data) { } 170static void pmic_irq_unmask(struct irq_data *data) { }
204 171
@@ -211,19 +178,21 @@ static struct irq_chip pmic_irqchip = {
211 .irq_set_type = pmic_irq_type, 178 .irq_set_type = pmic_irq_type,
212}; 179};
213 180
214static void pmic_irq_handler(unsigned irq, struct irq_desc *desc) 181static irqreturn_t pmic_irq_handler(int irq, void *data)
215{ 182{
216 struct pmic_gpio *pg = (struct pmic_gpio *)get_irq_data(irq); 183 struct pmic_gpio *pg = data;
217 u8 intsts = *((u8 *)pg->gpiointr + 4); 184 u8 intsts = *((u8 *)pg->gpiointr + 4);
218 int gpio; 185 int gpio;
186 irqreturn_t ret = IRQ_NONE;
219 187
220 for (gpio = 0; gpio < 8; gpio++) { 188 for (gpio = 0; gpio < 8; gpio++) {
221 if (intsts & (1 << gpio)) { 189 if (intsts & (1 << gpio)) {
222 pr_debug("pmic pin %d triggered\n", gpio); 190 pr_debug("pmic pin %d triggered\n", gpio);
223 generic_handle_irq(pg->irq_base + gpio); 191 generic_handle_irq(pg->irq_base + gpio);
192 ret = IRQ_HANDLED;
224 } 193 }
225 } 194 }
226 desc->chip->irq_eoi(get_irq_desc_chip_data(desc)); 195 return ret;
227} 196}
228 197
229static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev) 198static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
@@ -280,8 +249,13 @@ static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
280 printk(KERN_ERR "%s: Can not add pmic gpio chip.\n", __func__); 249 printk(KERN_ERR "%s: Can not add pmic gpio chip.\n", __func__);
281 goto err; 250 goto err;
282 } 251 }
283 set_irq_data(pg->irq, pg); 252
284 set_irq_chained_handler(pg->irq, pmic_irq_handler); 253 retval = request_irq(pg->irq, pmic_irq_handler, 0, "pmic", pg);
254 if (retval) {
255 printk(KERN_WARNING "pmic: Interrupt request failed\n");
256 goto err;
257 }
258
285 for (i = 0; i < 8; i++) { 259 for (i = 0; i < 8; i++) {
286 set_irq_chip_and_handler_name(i + pg->irq_base, &pmic_irqchip, 260 set_irq_chip_and_handler_name(i + pg->irq_base, &pmic_irqchip,
287 handle_simple_irq, "demux"); 261 handle_simple_irq, "demux");