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.
26 #include "twl-core.h"
29 * TWL4030 IRQ handling has two stages in hardware, and thus in software.
32 * SIH modules are more traditional IRQ components, which support per-IRQ
39 * We set up IRQs starting at a platform-specified base, always starting
70 /* SIR ignored -- set interrupt, for testing only */
108 /* sih_modules_twl4030 is used both in twl4030 and twl5030 */
117 /* Note: *all* of these IRQs default to no-trigger */
142 /* Note: most of these IRQs default to no-trigger */
154 .name = "madc",
155 SIH_INITIALIZER(MADC, 4)
177 /* Note: *all* of these IRQs default to no-trigger */
201 /* Note: most of these IRQs default to no-trigger */
213 .name = "madc",
214 SIH_INITIALIZER(MADC, 4)
250 /* Note: most of these IRQs default to no-trigger */
267 /*----------------------------------------------------------------------*/
272 * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt.
273 * This is a chained interrupt, so there is no desc->action method for it.
274 * Now we need to query the interrupt controller in the twl4030 to determine
288 pr_warn("twl4030: I2C error %d reading PIH ISR\n", ret); in handle_twl4030_pih()
304 /*----------------------------------------------------------------------*/
324 return -EINVAL; in twl4030_init_sih_modules()
332 /* skip USB -- it's funky */ in twl4030_init_sih_modules()
333 if (!sih->bytes_ixr) in twl4030_init_sih_modules()
337 if (sih->irq_lines <= line) in twl4030_init_sih_modules()
340 status = twl_i2c_write(sih->module, buf, in twl4030_init_sih_modules()
341 sih->mask[line].imr_offset, sih->bytes_ixr); in twl4030_init_sih_modules()
343 pr_err("twl4030: err %d initializing %s %s\n", in twl4030_init_sih_modules()
344 status, sih->name, "IMR"); in twl4030_init_sih_modules()
348 * set Clear-On-Read (COR) bit. in twl4030_init_sih_modules()
351 * inverted: for MADC, COR=1 means "clear on write". in twl4030_init_sih_modules()
354 if (sih->set_cor) { in twl4030_init_sih_modules()
355 status = twl_i2c_write_u8(sih->module, in twl4030_init_sih_modules()
357 sih->control_offset); in twl4030_init_sih_modules()
359 pr_err("twl4030: err %d initializing %s %s\n", in twl4030_init_sih_modules()
360 status, sih->name, "SIH_CTRL"); in twl4030_init_sih_modules()
370 if (!sih->bytes_ixr) in twl4030_init_sih_modules()
374 if (sih->irq_lines <= line) in twl4030_init_sih_modules()
384 status = twl_i2c_read(sih->module, rxbuf, in twl4030_init_sih_modules()
385 sih->mask[line].isr_offset, sih->bytes_ixr); in twl4030_init_sih_modules()
387 pr_warn("twl4030: err %d initializing %s %s\n", in twl4030_init_sih_modules()
388 status, sih->name, "ISR"); in twl4030_init_sih_modules()
390 if (!sih->set_cor) { in twl4030_init_sih_modules()
391 status = twl_i2c_write(sih->module, buf, in twl4030_init_sih_modules()
392 sih->mask[line].isr_offset, in twl4030_init_sih_modules()
393 sih->bytes_ixr); in twl4030_init_sih_modules()
395 pr_warn("twl4030: write failed: %d\n", in twl4030_init_sih_modules()
413 /*----------------------------------------------------------------------*/
428 /*----------------------------------------------------------------------*/
434 * completion, potentially including some re-ordering, of these requests.
441 agent->imr |= BIT(data->irq - agent->irq_base); in twl4030_sih_mask()
442 agent->imr_change_pending = true; in twl4030_sih_mask()
449 agent->imr &= ~BIT(data->irq - agent->irq_base); in twl4030_sih_unmask()
450 agent->imr_change_pending = true; in twl4030_sih_unmask()
458 return -EINVAL; in twl4030_sih_set_type()
461 agent->edge_change |= BIT(data->irq - agent->irq_base); in twl4030_sih_set_type()
470 mutex_lock(&agent->irq_lock); in twl4030_sih_bus_lock()
476 const struct sih *sih = agent->sih; in twl4030_sih_bus_sync_unlock()
479 if (agent->imr_change_pending) { in twl4030_sih_bus_sync_unlock()
486 imr.word = cpu_to_le32(agent->imr); in twl4030_sih_bus_sync_unlock()
487 agent->imr_change_pending = false; in twl4030_sih_bus_sync_unlock()
490 status = twl_i2c_write(sih->module, imr.bytes, in twl4030_sih_bus_sync_unlock()
491 sih->mask[irq_line].imr_offset, in twl4030_sih_bus_sync_unlock()
492 sih->bytes_ixr); in twl4030_sih_bus_sync_unlock()
494 pr_err("twl4030: %s, %s --> %d\n", __func__, in twl4030_sih_bus_sync_unlock()
498 if (agent->edge_change) { in twl4030_sih_bus_sync_unlock()
502 edge_change = agent->edge_change; in twl4030_sih_bus_sync_unlock()
503 agent->edge_change = 0; in twl4030_sih_bus_sync_unlock()
511 status = twl_i2c_read(sih->module, bytes, in twl4030_sih_bus_sync_unlock()
512 sih->edr_offset, sih->bytes_edr); in twl4030_sih_bus_sync_unlock()
514 pr_err("twl4030: %s, %s --> %d\n", __func__, in twl4030_sih_bus_sync_unlock()
521 int i = fls(edge_change) - 1; in twl4030_sih_bus_sync_unlock()
528 type = irq_get_trigger_type(i + agent->irq_base); in twl4030_sih_bus_sync_unlock()
538 status = twl_i2c_write(sih->module, bytes, in twl4030_sih_bus_sync_unlock()
539 sih->edr_offset, sih->bytes_edr); in twl4030_sih_bus_sync_unlock()
541 pr_err("twl4030: %s, %s --> %d\n", __func__, in twl4030_sih_bus_sync_unlock()
545 mutex_unlock(&agent->irq_lock); in twl4030_sih_bus_sync_unlock()
549 .name = "twl4030",
558 /*----------------------------------------------------------------------*/
568 /* FIXME need retry-on-error ... */ in sih_read_isr()
571 status = twl_i2c_read(sih->module, isr.bytes, in sih_read_isr()
572 sih->mask[irq_line].isr_offset, sih->bytes_ixr); in sih_read_isr()
584 const struct sih *sih = agent->sih; in handle_twl4030_sih()
587 /* reading ISR acks the IRQs, using clear-on-read mode */ in handle_twl4030_sih()
591 pr_err("twl4030: %s SIH, read ISR error %d\n", in handle_twl4030_sih()
592 sih->name, isr); in handle_twl4030_sih()
599 irq--; in handle_twl4030_sih()
602 if (irq < sih->bits) in handle_twl4030_sih()
603 handle_nested_irq(agent->irq_base + irq); in handle_twl4030_sih()
605 pr_err("twl4030: %s SIH, invalid ISR bit %d\n", in handle_twl4030_sih()
606 sih->name, irq); in handle_twl4030_sih()
618 int status = -EINVAL; in twl4030_sih_setup()
620 /* only support modules with standard clear-on-read for now */ in twl4030_sih_setup()
623 if (sih->module == module && sih->set_cor) { in twl4030_sih_setup()
636 return -ENOMEM; in twl4030_sih_setup()
638 agent->irq_base = irq_base; in twl4030_sih_setup()
639 agent->sih = sih; in twl4030_sih_setup()
640 agent->imr = ~0; in twl4030_sih_setup()
641 mutex_init(&agent->irq_lock); in twl4030_sih_setup()
643 for (i = 0; i < sih->bits; i++) { in twl4030_sih_setup()
656 agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name); in twl4030_sih_setup()
659 agent->irq_name ?: sih->name, NULL); in twl4030_sih_setup()
661 dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name, in twl4030_sih_setup()
662 irq, irq_base, irq_base + i - 1); in twl4030_sih_setup()
669 /*----------------------------------------------------------------------*/
679 struct device_node *node = dev->of_node; in twl4030_init_irq()
688 irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); in twl4030_init_irq()
700 * Mask and clear all TWL4030 interrupts since initially we do in twl4030_init_irq()
701 * not have any TWL4030 module interrupt handlers present in twl4030_init_irq()
714 twl4030_irq_chip.name = "twl4030"; in twl4030_init_irq()
731 dev_err(dev, "sih_setup PWR INT --> %d\n", status); in twl4030_init_irq()
735 /* install an irq handler to demultiplex the TWL4030 interrupt */ in twl4030_init_irq()
738 "TWL4030-PIH", NULL); in twl4030_init_irq()
761 pr_err("twl4030: can't yet clean up IRQs?\n"); in twl4030_exit_irq()