drivers/irqchip/irq-owl-sirq.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-owl-sirq.c
Extension
.c
Size
9027 bytes
Lines
360
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 owl_sirq_params {
	/* INTC_EXTCTL reg shared for all three SIRQ lines */
	bool reg_shared;
	/* INTC_EXTCTL reg offsets relative to controller base address */
	u16 reg_offset[NUM_SIRQ];
};

struct owl_sirq_chip_data {
	const struct owl_sirq_params	*params;
	void __iomem			*base;
	raw_spinlock_t			lock;
	u32				ext_irqs[NUM_SIRQ];
};

/* S500 & S700 SoCs */
static const struct owl_sirq_params owl_sirq_s500_params = {
	.reg_shared = true,
	.reg_offset = { 0, 0, 0 },
};

/* S900 SoC */
static const struct owl_sirq_params owl_sirq_s900_params = {
	.reg_shared = false,
	.reg_offset = { INTC_EXTCTL0, INTC_EXTCTL1, INTC_EXTCTL2 },
};

static u32 owl_field_get(u32 val, u32 index)
{
	switch (index) {
	case 0:
		return FIELD_GET(INTC_EXTCTL_SIRQ0_MASK, val);
	case 1:
		return FIELD_GET(INTC_EXTCTL_SIRQ1_MASK, val);
	case 2:
	default:
		return FIELD_GET(INTC_EXTCTL_SIRQ2_MASK, val);
	}
}

static u32 owl_field_prep(u32 val, u32 index)
{
	switch (index) {
	case 0:
		return FIELD_PREP(INTC_EXTCTL_SIRQ0_MASK, val);
	case 1:
		return FIELD_PREP(INTC_EXTCTL_SIRQ1_MASK, val);
	case 2:
	default:
		return FIELD_PREP(INTC_EXTCTL_SIRQ2_MASK, val);
	}
}

static u32 owl_sirq_read_extctl(struct owl_sirq_chip_data *data, u32 index)
{
	u32 val;

	val = readl_relaxed(data->base + data->params->reg_offset[index]);
	if (data->params->reg_shared)
		val = owl_field_get(val, index);

	return val;
}

static void owl_sirq_write_extctl(struct owl_sirq_chip_data *data,
				  u32 extctl, u32 index)
{
	u32 val;

	if (data->params->reg_shared) {
		val = readl_relaxed(data->base + data->params->reg_offset[index]);
		val &= ~owl_field_prep(0xff, index);
		extctl = owl_field_prep(extctl, index) | val;
	}

	writel_relaxed(extctl, data->base + data->params->reg_offset[index]);
}

static void owl_sirq_clear_set_extctl(struct owl_sirq_chip_data *d,
				      u32 clear, u32 set, u32 index)
{
	unsigned long flags;
	u32 val;

	raw_spin_lock_irqsave(&d->lock, flags);
	val = owl_sirq_read_extctl(d, index);
	val &= ~clear;
	val |= set;
	owl_sirq_write_extctl(d, val, index);
	raw_spin_unlock_irqrestore(&d->lock, flags);
}

Annotation

Implementation Notes