drivers/irqchip/irq-aspeed-vic.c
Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-aspeed-vic.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/irqchip/irq-aspeed-vic.c- Extension
.c- Size
- 5852 bytes
- Lines
- 222
- 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/export.hlinux/init.hlinux/list.hlinux/io.hlinux/irq.hlinux/irqchip.hlinux/irqchip/chained_irq.hlinux/irqdomain.hlinux/of.hlinux/of_address.hlinux/of_irq.hlinux/syscore_ops.hlinux/device.hlinux/slab.hasm/exception.hasm/irq.h
Detected Declarations
struct aspeed_vicfunction vic_init_hwfunction avic_handle_irqfunction avic_ack_irqfunction avic_mask_irqfunction avic_unmask_irqfunction avic_mask_ack_irqfunction avic_mapfunction avic_of_init
Annotated Snippet
struct aspeed_vic {
void __iomem *base;
u32 edge_sources[2];
struct irq_domain *dom;
};
static struct aspeed_vic *system_avic;
static void vic_init_hw(struct aspeed_vic *vic)
{
u32 sense;
/* Disable all interrupts */
writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR);
writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR + 4);
/* Make sure no soft trigger is on */
writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR);
writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR + 4);
/* Set everything to be IRQ */
writel(0, vic->base + AVIC_INT_SELECT);
writel(0, vic->base + AVIC_INT_SELECT + 4);
/* Some interrupts have a programmable high/low level trigger
* (4 GPIO direct inputs), for now we assume this was configured
* by firmware. We read which ones are edge now.
*/
sense = readl(vic->base + AVIC_INT_SENSE);
vic->edge_sources[0] = ~sense;
sense = readl(vic->base + AVIC_INT_SENSE + 4);
vic->edge_sources[1] = ~sense;
/* Clear edge detection latches */
writel(0xffffffff, vic->base + AVIC_EDGE_CLR);
writel(0xffffffff, vic->base + AVIC_EDGE_CLR + 4);
}
static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
{
struct aspeed_vic *vic = system_avic;
u32 stat, irq;
for (;;) {
irq = 0;
stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS);
if (!stat) {
stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS + 4);
irq = 32;
}
if (stat == 0)
break;
irq += ffs(stat) - 1;
generic_handle_domain_irq(vic->dom, irq);
}
}
static void avic_ack_irq(struct irq_data *d)
{
struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
unsigned int sidx = d->hwirq >> 5;
unsigned int sbit = 1u << (d->hwirq & 0x1f);
/* Clear edge latch for edge interrupts, nop for level */
if (vic->edge_sources[sidx] & sbit)
writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
}
static void avic_mask_irq(struct irq_data *d)
{
struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
unsigned int sidx = d->hwirq >> 5;
unsigned int sbit = 1u << (d->hwirq & 0x1f);
writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
}
static void avic_unmask_irq(struct irq_data *d)
{
struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
unsigned int sidx = d->hwirq >> 5;
unsigned int sbit = 1u << (d->hwirq & 0x1f);
writel(sbit, vic->base + AVIC_INT_ENABLE + sidx * 4);
}
/* For level irq, faster than going through a nop "ack" and mask */
static void avic_mask_ack_irq(struct irq_data *d)
{
struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
unsigned int sidx = d->hwirq >> 5;
Annotation
- Immediate include surface: `linux/export.h`, `linux/init.h`, `linux/list.h`, `linux/io.h`, `linux/irq.h`, `linux/irqchip.h`, `linux/irqchip/chained_irq.h`, `linux/irqdomain.h`.
- Detected declarations: `struct aspeed_vic`, `function vic_init_hw`, `function avic_handle_irq`, `function avic_ack_irq`, `function avic_mask_irq`, `function avic_unmask_irq`, `function avic_mask_ack_irq`, `function avic_map`, `function avic_of_init`.
- Atlas domain: Driver Families / drivers/irqchip.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.