On Wed, Jun 24, 2009 at 08:57:56AM +0100, Russell King - ARM Linux wrote: > On Wed, Jun 24, 2009 at 01:16:52PM +0530, Shilimkar, Santosh wrote: > > After digging a bit, the proposed twl_irq change would need some major > > changes. > > > > 1. All the T2(TWL)drivers ( rtc, madc, bci, gpio, keypad, usb, mmc)needs > > modification.Currently twl_irq fw implements kind of "twl4030_irq_chip" > > which allows all the T2 drivers to get virtual interrupt numbers and can > > make use of standard "request_irq" linux api. > > You can still use virtual interrupt numbers. All you're changing is > _how_ you're handling the interrupts internally. > > I'll see about creating a patch tomorrow. And here it is - I've only build-tested it so far. drivers/mfd/twl4030-irq.c | 55 ++++++++++++++++++-------------------------- 1 files changed, 23 insertions(+), 32 deletions(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index bae61b2..4bb1ea7 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -180,15 +180,9 @@ static struct completion irq_event; static int twl4030_irq_thread(void *data) { long irq = (long)data; - struct irq_desc *desc = irq_to_desc(irq); static unsigned i2c_errors; static const unsigned max_i2c_errors = 100; - if (!desc) { - pr_err("twl4030: Invalid IRQ: %ld\n", irq); - return -EINVAL; - } - current->flags |= PF_NOFREEZE; while (!kthread_should_stop()) { @@ -240,38 +234,25 @@ static int twl4030_irq_thread(void *data) } local_irq_enable(); - desc->chip->unmask(irq); + enable_irq(irq); } return 0; } /* - * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt. - * This is a chained interrupt, so there is no desc->action method for it. + * handle_twl4030_pih() is the handler for the main twl4030 interrupt. * Now we need to query the interrupt controller in the twl4030 to determine * which module is generating the interrupt request. However, we can't do i2c * transactions in interrupt context, so we must defer that work to a kernel * thread. All we do here is acknowledge and mask the interrupt and wakeup * the kernel thread. */ -static void handle_twl4030_pih(unsigned int irq, struct irq_desc *desc) -{ - /* Acknowledge, clear *AND* mask the interrupt... */ - desc->chip->ack(irq); - complete(&irq_event); -} - -static struct task_struct *start_twl4030_irq_thread(long irq) +static irqreturn_t handle_twl4030_pih(int irq, void *devid) { - struct task_struct *thread; - - init_completion(&irq_event); - thread = kthread_run(twl4030_irq_thread, (void *)irq, "twl4030-irq"); - if (!thread) - pr_err("twl4030: could not create irq %ld thread!\n", irq); - - return thread; + disable_irq_nosync(irq); + complete(devid); + return IRQ_HANDLED; } /*----------------------------------------------------------------------*/ @@ -734,18 +715,28 @@ int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) } /* install an irq handler to demultiplex the TWL4030 interrupt */ - task = start_twl4030_irq_thread(irq_num); - if (!task) { - pr_err("twl4030: irq thread FAIL\n"); - status = -ESRCH; - goto fail; + init_completion(&irq_event); + + status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED, + "TWL4030-PIH", &irq_event); + if (status < 0) { + pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status); + goto fail_rqirq; } - set_irq_data(irq_num, task); - set_irq_chained_handler(irq_num, handle_twl4030_pih); + task = kthread_run(twl4030_irq_thread, (void *)irq_num, "twl4030-irq"); + if (IS_ERR(task)) { + pr_err("twl4030: could not create irq %d thread!\n", irq_num); + status = PTR_ERR(task); + goto fail_kthread; + } return status; +fail_kthread: + free_irq(irq_num, &irq_event); +fail_rqirq: + /* clean up twl4030_sih_setup */ fail: for (i = irq_base; i < irq_end; i++) set_irq_chip_and_handler(i, NULL, NULL); -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html