drivers/irqchip/irq-vt8500.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-vt8500.c
Extension
.c
Size
6202 bytes
Lines
252
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 vt8500_irq_data {
	void __iomem 		*base;		/* IO Memory base address */
	struct irq_domain	*domain;	/* Domain for this controller */
};

/* Primary interrupt controller data */
static struct vt8500_irq_data *primary_intc;

static void vt8500_irq_ack(struct irq_data *d)
{
	struct vt8500_irq_data *priv = d->domain->host_data;
	void __iomem *base = priv->base;
	void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4);
	u32 status = (1 << (d->hwirq & 0x1f));

	writel(status, stat_reg);
}

static void vt8500_irq_mask(struct irq_data *d)
{
	struct vt8500_irq_data *priv = d->domain->host_data;
	void __iomem *base = priv->base;
	u8 dctr;

	dctr = readb(base + VT8500_ICDC + d->hwirq);
	dctr &= ~VT8500_INT_ENABLE;
	writeb(dctr, base + VT8500_ICDC + d->hwirq);
}

static void vt8500_irq_unmask(struct irq_data *d)
{
	struct vt8500_irq_data *priv = d->domain->host_data;
	void __iomem *base = priv->base;
	u8 dctr;

	dctr = readb(base + VT8500_ICDC + d->hwirq);
	dctr |= VT8500_INT_ENABLE;
	writeb(dctr, base + VT8500_ICDC + d->hwirq);
}

static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
	struct vt8500_irq_data *priv = d->domain->host_data;
	void __iomem *base = priv->base;
	u8 dctr;

	dctr = readb(base + VT8500_ICDC + d->hwirq);
	dctr &= ~VT8500_EDGE;

	switch (flow_type) {
	case IRQF_TRIGGER_LOW:
		return -EINVAL;
	case IRQF_TRIGGER_HIGH:
		dctr |= VT8500_TRIGGER_HIGH;
		irq_set_handler_locked(d, handle_level_irq);
		break;
	case IRQF_TRIGGER_FALLING:
		dctr |= VT8500_TRIGGER_FALLING;
		irq_set_handler_locked(d, handle_edge_irq);
		break;
	case IRQF_TRIGGER_RISING:
		dctr |= VT8500_TRIGGER_RISING;
		irq_set_handler_locked(d, handle_edge_irq);
		break;
	}
	writeb(dctr, base + VT8500_ICDC + d->hwirq);

	return 0;
}

static struct irq_chip vt8500_irq_chip = {
	.name		= "vt8500",
	.irq_ack	= vt8500_irq_ack,
	.irq_mask	= vt8500_irq_mask,
	.irq_unmask	= vt8500_irq_unmask,
	.irq_set_type	= vt8500_irq_set_type,
};

static void __init vt8500_init_irq_hw(void __iomem *base)
{
	u32 i;

	/* Enable rotating priority for IRQ */
	writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
	writel(0x00, base + VT8500_ICPC_FIQ);

	/* Disable all interrupts and route them to IRQ */
	for (i = 0; i < 64; i++)
		writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i);
}

Annotation

Implementation Notes