drivers/irqchip/irq-mchp-eic.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-mchp-eic.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-mchp-eic.c
Extension
.c
Size
6701 bytes
Lines
286
Domain
Driver Families
Bucket
drivers/irqchip
Inferred role
Driver Families: implementation source
Status
source 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

struct mchp_eic {
	void __iomem *base;
	struct clk *clk;
	struct irq_domain *domain;
	u32 irqs[MCHP_EIC_NIRQ];
	u32 scfg[MCHP_EIC_NIRQ];
	u32 wakeup_source;
};

static struct mchp_eic *eic;

static void mchp_eic_irq_mask(struct irq_data *d)
{
	unsigned int tmp;

	tmp = readl_relaxed(eic->base + MCHP_EIC_SCFG(d->hwirq));
	tmp &= ~MCHP_EIC_SCFG_EN;
	writel_relaxed(tmp, eic->base + MCHP_EIC_SCFG(d->hwirq));

	irq_chip_mask_parent(d);
}

static void mchp_eic_irq_unmask(struct irq_data *d)
{
	unsigned int tmp;

	tmp = readl_relaxed(eic->base + MCHP_EIC_SCFG(d->hwirq));
	tmp |= MCHP_EIC_SCFG_EN;
	writel_relaxed(tmp, eic->base + MCHP_EIC_SCFG(d->hwirq));

	irq_chip_unmask_parent(d);
}

static int mchp_eic_irq_set_type(struct irq_data *d, unsigned int type)
{
	unsigned int parent_irq_type;
	unsigned int tmp;

	tmp = readl_relaxed(eic->base + MCHP_EIC_SCFG(d->hwirq));
	tmp &= ~(MCHP_EIC_SCFG_POL | MCHP_EIC_SCFG_LVL);
	switch (type) {
	case IRQ_TYPE_LEVEL_HIGH:
		tmp |= MCHP_EIC_SCFG_POL | MCHP_EIC_SCFG_LVL;
		parent_irq_type = IRQ_TYPE_LEVEL_HIGH;
		break;
	case IRQ_TYPE_LEVEL_LOW:
		tmp |= MCHP_EIC_SCFG_LVL;
		parent_irq_type = IRQ_TYPE_LEVEL_HIGH;
		break;
	case IRQ_TYPE_EDGE_RISING:
		parent_irq_type = IRQ_TYPE_EDGE_RISING;
		break;
	case IRQ_TYPE_EDGE_FALLING:
		tmp |= MCHP_EIC_SCFG_POL;
		parent_irq_type = IRQ_TYPE_EDGE_RISING;
		break;
	default:
		return -EINVAL;
	}

	writel_relaxed(tmp, eic->base + MCHP_EIC_SCFG(d->hwirq));

	return irq_chip_set_type_parent(d, parent_irq_type);
}

static int mchp_eic_irq_set_wake(struct irq_data *d, unsigned int on)
{
	irq_set_irq_wake(eic->irqs[d->hwirq], on);
	if (on)
		eic->wakeup_source |= BIT(d->hwirq);
	else
		eic->wakeup_source &= ~BIT(d->hwirq);

	return 0;
}

static int mchp_eic_irq_suspend(void *data)
{
	unsigned int hwirq;

	for (hwirq = 0; hwirq < MCHP_EIC_NIRQ; hwirq++)
		eic->scfg[hwirq] = readl_relaxed(eic->base +
						 MCHP_EIC_SCFG(hwirq));

	if (!eic->wakeup_source)
		clk_disable_unprepare(eic->clk);

	return 0;
}

Annotation

Implementation Notes