drivers/irqchip/irq-imx-irqsteer.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-imx-irqsteer.c
Extension
.c
Size
9236 bytes
Lines
363
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 irqsteer_devtype_data {
	u32	quirks;
};

struct irqsteer_data {
	void __iomem				*regs;
	struct clk				*ipg_clk;
	int					irq[CHAN_MAX_OUTPUT_INT];
	int					irq_count;
	raw_spinlock_t				lock;
	int					reg_num;
	int					channel;
	struct irq_domain			*domain;
	u32					*saved_reg;
	struct device				*dev;
	const struct irqsteer_devtype_data	*devtype_data;
};

static const struct irqsteer_devtype_data imx_data = { };

static const struct irqsteer_devtype_data s32n79_data = {
	.quirks	= IRQSTEER_QUIRK_NO_CHANCTRL,
};

static bool irqsteer_has_chanctrl(const struct irqsteer_devtype_data *data)
{
	return !(data->quirks & IRQSTEER_QUIRK_NO_CHANCTRL);
}

static int imx_irqsteer_get_reg_index(struct irqsteer_data *data,
				      unsigned long irqnum)
{
	return (data->reg_num - irqnum / 32 - 1);
}

static void imx_irqsteer_irq_unmask(struct irq_data *d)
{
	struct irqsteer_data *data = d->chip_data;
	int idx = imx_irqsteer_get_reg_index(data, d->hwirq);
	unsigned long flags;
	u32 val;

	raw_spin_lock_irqsave(&data->lock, flags);
	val = readl_relaxed(data->regs + CHANMASK(idx, data->reg_num));
	val |= BIT(d->hwirq % 32);
	writel_relaxed(val, data->regs + CHANMASK(idx, data->reg_num));
	raw_spin_unlock_irqrestore(&data->lock, flags);
}

static void imx_irqsteer_irq_mask(struct irq_data *d)
{
	struct irqsteer_data *data = d->chip_data;
	int idx = imx_irqsteer_get_reg_index(data, d->hwirq);
	unsigned long flags;
	u32 val;

	raw_spin_lock_irqsave(&data->lock, flags);
	val = readl_relaxed(data->regs + CHANMASK(idx, data->reg_num));
	val &= ~BIT(d->hwirq % 32);
	writel_relaxed(val, data->regs + CHANMASK(idx, data->reg_num));
	raw_spin_unlock_irqrestore(&data->lock, flags);
}

static void imx_irqsteer_irq_bus_lock(struct irq_data *d)
{
	struct irqsteer_data *data = d->chip_data;

	pm_runtime_get_sync(data->dev);
}

static void imx_irqsteer_irq_bus_sync_unlock(struct irq_data *d)
{
	struct irqsteer_data *data = d->chip_data;

	pm_runtime_put_autosuspend(data->dev);
}

static const struct irq_chip imx_irqsteer_irq_chip = {
	.name			= "irqsteer",
	.irq_mask		= imx_irqsteer_irq_mask,
	.irq_unmask		= imx_irqsteer_irq_unmask,
	.irq_bus_lock		= imx_irqsteer_irq_bus_lock,
	.irq_bus_sync_unlock	= imx_irqsteer_irq_bus_sync_unlock,
};

static int imx_irqsteer_irq_map(struct irq_domain *h, unsigned int irq,
				irq_hw_number_t hwirq)
{
	irq_set_status_flags(irq, IRQ_LEVEL);
	irq_set_chip_data(irq, h->host_data);

Annotation

Implementation Notes