drivers/irqchip/irq-lan966x-oic.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-lan966x-oic.c
Extension
.c
Size
8188 bytes
Lines
275
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 lan966x_oic_chip_regs {
	int reg_off_ena_set;
	int reg_off_ena_clr;
	int reg_off_sticky;
	int reg_off_ident;
	int reg_off_map;
};

struct lan966x_oic_data {
	void __iomem	*regs;
	int		irq;
};

#define LAN966X_OIC_NR_IRQ 86

/* Interrupt sticky status */
#define LAN966X_OIC_INTR_STICKY		0x30
#define LAN966X_OIC_INTR_STICKY1	0x34
#define LAN966X_OIC_INTR_STICKY2	0x38

/* Interrupt enable */
#define LAN966X_OIC_INTR_ENA		0x48
#define LAN966X_OIC_INTR_ENA1		0x4c
#define LAN966X_OIC_INTR_ENA2		0x50

/* Atomic clear of interrupt enable */
#define LAN966X_OIC_INTR_ENA_CLR	0x54
#define LAN966X_OIC_INTR_ENA_CLR1	0x58
#define LAN966X_OIC_INTR_ENA_CLR2	0x5c

/* Atomic set of interrupt */
#define LAN966X_OIC_INTR_ENA_SET	0x60
#define LAN966X_OIC_INTR_ENA_SET1	0x64
#define LAN966X_OIC_INTR_ENA_SET2	0x68

/* Mapping of source to destination interrupts (_n = 0..8) */
#define LAN966X_OIC_DST_INTR_MAP(_n)	(0x78 + (_n) * 4)
#define LAN966X_OIC_DST_INTR_MAP1(_n)	(0x9c + (_n) * 4)
#define LAN966X_OIC_DST_INTR_MAP2(_n)	(0xc0 + (_n) * 4)

/* Currently active interrupt sources per destination (_n = 0..8) */
#define LAN966X_OIC_DST_INTR_IDENT(_n)	(0xe4 + (_n) * 4)
#define LAN966X_OIC_DST_INTR_IDENT1(_n)	(0x108 + (_n) * 4)
#define LAN966X_OIC_DST_INTR_IDENT2(_n)	(0x12c + (_n) * 4)

static unsigned int lan966x_oic_irq_startup(struct irq_data *data)
{
	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
	struct irq_chip_type *ct = irq_data_get_chip_type(data);
	struct lan966x_oic_chip_regs *chip_regs = gc->private;
	u32 map;

	scoped_guard (raw_spinlock, &gc->lock) {
		/* Map the source interrupt to the destination */
		map = irq_reg_readl(gc, chip_regs->reg_off_map);
		map |= data->mask;
		irq_reg_writel(gc, map, chip_regs->reg_off_map);
	}

	ct->chip.irq_ack(data);
	ct->chip.irq_unmask(data);

	return 0;
}

static void lan966x_oic_irq_shutdown(struct irq_data *data)
{
	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
	struct irq_chip_type *ct = irq_data_get_chip_type(data);
	struct lan966x_oic_chip_regs *chip_regs = gc->private;
	u32 map;

	ct->chip.irq_mask(data);

	guard(raw_spinlock)(&gc->lock);

	/* Unmap the interrupt */
	map = irq_reg_readl(gc, chip_regs->reg_off_map);
	map &= ~data->mask;
	irq_reg_writel(gc, map, chip_regs->reg_off_map);
}

static int lan966x_oic_irq_set_type(struct irq_data *data,
				    unsigned int flow_type)
{
	if (flow_type != IRQ_TYPE_LEVEL_HIGH) {
		pr_err("lan966x oic doesn't support flow type %d\n", flow_type);
		return -EINVAL;
	}

Annotation

Implementation Notes