drivers/pinctrl/mediatek/mtk-eint.c

Source file repositories/reference/linux-study-clean/drivers/pinctrl/mediatek/mtk-eint.c

File Facts

System
Linux kernel
Corpus path
drivers/pinctrl/mediatek/mtk-eint.c
Extension
.c
Size
16448 bytes
Lines
628
Domain
Driver Families
Bucket
drivers/pinctrl
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

while (status) {
				shift = __ffs(status);
				status &= ~BIT(shift);
				mask = BIT(shift);
				eint_num = eint->pin_list[i][shift + j];

				/*
				 * If we get an interrupt on pin that was only required
				 * for wake (but no real interrupt requested), mask the
				 * interrupt (as would mtk_eint_resume do anyway later
				 * in the resume sequence).
				 */
				if (eint->wake_mask[i][port] & mask &&
				    !(eint->cur_mask[i][port] & mask)) {
					reg = mtk_eint_get_offset(eint, eint_num,
								  eint->regs->mask_set);
					writel_relaxed(mask, reg);
				}

				dual_edge = eint->pins[eint_num].dual_edge;
				if (dual_edge) {
					/*
					 * Clear soft-irq in case we raised it last
					 * time.
					 */
					reg = mtk_eint_get_offset(eint, eint_num,
								  eint->regs->soft_clr);
					writel(mask, reg);

					start_level =
					eint->gpio_xlate->get_gpio_state(eint->pctl,
									 eint_num);
				}

				generic_handle_domain_irq(eint->domain, eint_num);

				if (dual_edge) {
					curr_level = mtk_eint_flip_edge(eint, eint_num);

					/*
					 * If level changed, we might lost one edge
					 * interrupt, raised it through soft-irq.
					 */
					if (start_level != curr_level) {
						reg = mtk_eint_get_offset(eint, eint_num,
									  eint->regs->soft_set);
						writel(mask, reg);
					}
				}

				if (eint->pins[eint_num].debounce)
					mtk_eint_debounce_process(eint, eint_num);
			}
		}
	}
	chained_irq_exit(chip, desc);
}

int mtk_eint_do_suspend(struct mtk_eint *eint)
{
	mtk_eint_chip_write_mask(eint, eint->wake_mask);

	return 0;
}
EXPORT_SYMBOL_GPL(mtk_eint_do_suspend);

int mtk_eint_do_resume(struct mtk_eint *eint)
{
	mtk_eint_chip_write_mask(eint, eint->cur_mask);

	return 0;
}
EXPORT_SYMBOL_GPL(mtk_eint_do_resume);

int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
			  unsigned int debounce)
{
	int virq, eint_offset;
	unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask,
		     dbnc;
	unsigned int inst = eint->pins[eint_num].instance;
	unsigned int idx = eint->pins[eint_num].index;
	struct irq_data *d;

	if (!eint->hw->db_time)
		return -EOPNOTSUPP;

	virq = irq_find_mapping(eint->domain, eint_num);
	eint_offset = (idx % 4) * 8;
	d = irq_get_irq_data(virq);

Annotation

Implementation Notes