Lines Matching +full:twl4030 +full:- +full:madc
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * twl4030-irq.c - TWL4030/TPS659x0 irq support
5 * Copyright (C) 2005-2006 Texas Instruments, Inc.
25 #include "twl-core.h"
28 * TWL4030 IRQ handling has two stages in hardware, and thus in software.
31 * SIH modules are more traditional IRQ components, which support per-IRQ
38 * We set up IRQs starting at a platform-specified base, always starting
69 /* SIR ignored -- set interrupt, for testing only */
107 /* sih_modules_twl4030 is used both in twl4030 and twl5030 */
116 /* Note: *all* of these IRQs default to no-trigger */
141 /* Note: most of these IRQs default to no-trigger */
153 .name = "madc",
154 SIH_INITIALIZER(MADC, 4)
176 /* Note: *all* of these IRQs default to no-trigger */
200 /* Note: most of these IRQs default to no-trigger */
212 .name = "madc",
213 SIH_INITIALIZER(MADC, 4)
249 /* Note: most of these IRQs default to no-trigger */
266 /*----------------------------------------------------------------------*/
271 * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt.
272 * This is a chained interrupt, so there is no desc->action method for it.
273 * Now we need to query the interrupt controller in the twl4030 to determine
287 pr_warn("twl4030: I2C error %d reading PIH ISR\n", ret); in handle_twl4030_pih()
303 /*----------------------------------------------------------------------*/
323 return -EINVAL; in twl4030_init_sih_modules()
331 /* skip USB -- it's funky */ in twl4030_init_sih_modules()
332 if (!sih->bytes_ixr) in twl4030_init_sih_modules()
336 if (sih->irq_lines <= line) in twl4030_init_sih_modules()
339 status = twl_i2c_write(sih->module, buf, in twl4030_init_sih_modules()
340 sih->mask[line].imr_offset, sih->bytes_ixr); in twl4030_init_sih_modules()
342 pr_err("twl4030: err %d initializing %s %s\n", in twl4030_init_sih_modules()
343 status, sih->name, "IMR"); in twl4030_init_sih_modules()
347 * set Clear-On-Read (COR) bit. in twl4030_init_sih_modules()
350 * inverted: for MADC, COR=1 means "clear on write". in twl4030_init_sih_modules()
353 if (sih->set_cor) { in twl4030_init_sih_modules()
354 status = twl_i2c_write_u8(sih->module, in twl4030_init_sih_modules()
356 sih->control_offset); in twl4030_init_sih_modules()
358 pr_err("twl4030: err %d initializing %s %s\n", in twl4030_init_sih_modules()
359 status, sih->name, "SIH_CTRL"); in twl4030_init_sih_modules()
369 if (!sih->bytes_ixr) in twl4030_init_sih_modules()
373 if (sih->irq_lines <= line) in twl4030_init_sih_modules()
383 status = twl_i2c_read(sih->module, rxbuf, in twl4030_init_sih_modules()
384 sih->mask[line].isr_offset, sih->bytes_ixr); in twl4030_init_sih_modules()
386 pr_warn("twl4030: err %d initializing %s %s\n", in twl4030_init_sih_modules()
387 status, sih->name, "ISR"); in twl4030_init_sih_modules()
389 if (!sih->set_cor) { in twl4030_init_sih_modules()
390 status = twl_i2c_write(sih->module, buf, in twl4030_init_sih_modules()
391 sih->mask[line].isr_offset, in twl4030_init_sih_modules()
392 sih->bytes_ixr); in twl4030_init_sih_modules()
394 pr_warn("twl4030: write failed: %d\n", in twl4030_init_sih_modules()
412 /*----------------------------------------------------------------------*/
427 /*----------------------------------------------------------------------*/
433 * completion, potentially including some re-ordering, of these requests.
440 agent->imr |= BIT(data->irq - agent->irq_base); in twl4030_sih_mask()
441 agent->imr_change_pending = true; in twl4030_sih_mask()
448 agent->imr &= ~BIT(data->irq - agent->irq_base); in twl4030_sih_unmask()
449 agent->imr_change_pending = true; in twl4030_sih_unmask()
457 return -EINVAL; in twl4030_sih_set_type()
460 agent->edge_change |= BIT(data->irq - agent->irq_base); in twl4030_sih_set_type()
469 mutex_lock(&agent->irq_lock); in twl4030_sih_bus_lock()
475 const struct sih *sih = agent->sih; in twl4030_sih_bus_sync_unlock()
478 if (agent->imr_change_pending) { in twl4030_sih_bus_sync_unlock()
485 imr.word = cpu_to_le32(agent->imr); in twl4030_sih_bus_sync_unlock()
486 agent->imr_change_pending = false; in twl4030_sih_bus_sync_unlock()
489 status = twl_i2c_write(sih->module, imr.bytes, in twl4030_sih_bus_sync_unlock()
490 sih->mask[irq_line].imr_offset, in twl4030_sih_bus_sync_unlock()
491 sih->bytes_ixr); in twl4030_sih_bus_sync_unlock()
493 pr_err("twl4030: %s, %s --> %d\n", __func__, in twl4030_sih_bus_sync_unlock()
497 if (agent->edge_change) { in twl4030_sih_bus_sync_unlock()
501 edge_change = agent->edge_change; in twl4030_sih_bus_sync_unlock()
502 agent->edge_change = 0; in twl4030_sih_bus_sync_unlock()
510 status = twl_i2c_read(sih->module, bytes, in twl4030_sih_bus_sync_unlock()
511 sih->edr_offset, sih->bytes_edr); in twl4030_sih_bus_sync_unlock()
513 pr_err("twl4030: %s, %s --> %d\n", __func__, in twl4030_sih_bus_sync_unlock()
520 int i = fls(edge_change) - 1; in twl4030_sih_bus_sync_unlock()
527 type = irq_get_trigger_type(i + agent->irq_base); in twl4030_sih_bus_sync_unlock()
537 status = twl_i2c_write(sih->module, bytes, in twl4030_sih_bus_sync_unlock()
538 sih->edr_offset, sih->bytes_edr); in twl4030_sih_bus_sync_unlock()
540 pr_err("twl4030: %s, %s --> %d\n", __func__, in twl4030_sih_bus_sync_unlock()
544 mutex_unlock(&agent->irq_lock); in twl4030_sih_bus_sync_unlock()
548 .name = "twl4030",
557 /*----------------------------------------------------------------------*/
567 /* FIXME need retry-on-error ... */ in sih_read_isr()
570 status = twl_i2c_read(sih->module, isr.bytes, in sih_read_isr()
571 sih->mask[irq_line].isr_offset, sih->bytes_ixr); in sih_read_isr()
583 const struct sih *sih = agent->sih; in handle_twl4030_sih()
586 /* reading ISR acks the IRQs, using clear-on-read mode */ in handle_twl4030_sih()
590 pr_err("twl4030: %s SIH, read ISR error %d\n", in handle_twl4030_sih()
591 sih->name, isr); in handle_twl4030_sih()
598 irq--; in handle_twl4030_sih()
601 if (irq < sih->bits) in handle_twl4030_sih()
602 handle_nested_irq(agent->irq_base + irq); in handle_twl4030_sih()
604 pr_err("twl4030: %s SIH, invalid ISR bit %d\n", in handle_twl4030_sih()
605 sih->name, irq); in handle_twl4030_sih()
617 int status = -EINVAL; in twl4030_sih_setup()
619 /* only support modules with standard clear-on-read for now */ in twl4030_sih_setup()
622 if (sih->module == module && sih->set_cor) { in twl4030_sih_setup()
635 return -ENOMEM; in twl4030_sih_setup()
637 agent->irq_base = irq_base; in twl4030_sih_setup()
638 agent->sih = sih; in twl4030_sih_setup()
639 agent->imr = ~0; in twl4030_sih_setup()
640 mutex_init(&agent->irq_lock); in twl4030_sih_setup()
642 for (i = 0; i < sih->bits; i++) { in twl4030_sih_setup()
655 agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name); in twl4030_sih_setup()
658 agent->irq_name ?: sih->name, NULL); in twl4030_sih_setup()
660 dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name, in twl4030_sih_setup()
661 irq, irq_base, irq_base + i - 1); in twl4030_sih_setup()
668 /*----------------------------------------------------------------------*/
678 struct device_node *node = dev->of_node; in twl4030_init_irq()
687 irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); in twl4030_init_irq()
699 * Mask and clear all TWL4030 interrupts since initially we do in twl4030_init_irq()
700 * not have any TWL4030 module interrupt handlers present in twl4030_init_irq()
713 twl4030_irq_chip.name = "twl4030"; in twl4030_init_irq()
730 dev_err(dev, "sih_setup PWR INT --> %d\n", status); in twl4030_init_irq()
734 /* install an irq handler to demultiplex the TWL4030 interrupt */ in twl4030_init_irq()
737 "TWL4030-PIH", NULL); in twl4030_init_irq()
760 pr_err("twl4030: can't yet clean up IRQs?\n"); in twl4030_exit_irq()
761 return -ENOSYS; in twl4030_exit_irq()