drivers/irqchip/irq-xilinx-intc.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-xilinx-intc.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-xilinx-intc.c
Extension
.c
Size
6475 bytes
Lines
251
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 xintc_irq_chip {
	void		__iomem *base;
	struct		irq_domain *root_domain;
	u32		intr_mask;
	u32		nr_irq;
};

static struct xintc_irq_chip *primary_intc;

static void xintc_write(struct xintc_irq_chip *irqc, int reg, u32 data)
{
	if (static_branch_unlikely(&xintc_is_be))
		iowrite32be(data, irqc->base + reg);
	else
		iowrite32(data, irqc->base + reg);
}

static u32 xintc_read(struct xintc_irq_chip *irqc, int reg)
{
	if (static_branch_unlikely(&xintc_is_be))
		return ioread32be(irqc->base + reg);
	else
		return ioread32(irqc->base + reg);
}

static void intc_enable_or_unmask(struct irq_data *d)
{
	struct xintc_irq_chip *irqc = irq_data_get_irq_chip_data(d);
	unsigned long mask = BIT(d->hwirq);

	pr_debug("irq-xilinx: enable_or_unmask: %ld\n", d->hwirq);

	/* ack level irqs because they can't be acked during
	 * ack function since the handle_level_irq function
	 * acks the irq before calling the interrupt handler
	 */
	if (irqd_is_level_type(d))
		xintc_write(irqc, IAR, mask);

	xintc_write(irqc, SIE, mask);
}

static void intc_disable_or_mask(struct irq_data *d)
{
	struct xintc_irq_chip *irqc = irq_data_get_irq_chip_data(d);

	pr_debug("irq-xilinx: disable: %ld\n", d->hwirq);
	xintc_write(irqc, CIE, BIT(d->hwirq));
}

static void intc_ack(struct irq_data *d)
{
	struct xintc_irq_chip *irqc = irq_data_get_irq_chip_data(d);

	pr_debug("irq-xilinx: ack: %ld\n", d->hwirq);
	xintc_write(irqc, IAR, BIT(d->hwirq));
}

static void intc_mask_ack(struct irq_data *d)
{
	struct xintc_irq_chip *irqc = irq_data_get_irq_chip_data(d);
	unsigned long mask = BIT(d->hwirq);

	pr_debug("irq-xilinx: disable_and_ack: %ld\n", d->hwirq);
	xintc_write(irqc, CIE, mask);
	xintc_write(irqc, IAR, mask);
}

static struct irq_chip intc_dev = {
	.name = "Xilinx INTC",
	.irq_unmask = intc_enable_or_unmask,
	.irq_mask = intc_disable_or_mask,
	.irq_ack = intc_ack,
	.irq_mask_ack = intc_mask_ack,
};

static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
	struct xintc_irq_chip *irqc = d->host_data;

	if (irqc->intr_mask & BIT(hw)) {
		irq_set_chip_and_handler_name(irq, &intc_dev,
					      handle_edge_irq, "edge");
		irq_clear_status_flags(irq, IRQ_LEVEL);
	} else {
		irq_set_chip_and_handler_name(irq, &intc_dev,
					      handle_level_irq, "level");
		irq_set_status_flags(irq, IRQ_LEVEL);
	}
	irq_set_chip_data(irq, irqc);

Annotation

Implementation Notes