drivers/irqchip/irq-imx-intmux.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-imx-intmux.c
Extension
.c
Size
10205 bytes
Lines
367
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 intmux_irqchip_data {
	u32			saved_reg;
	int			chanidx;
	int			irq;
	struct irq_domain	*domain;
};

struct intmux_data {
	raw_spinlock_t			lock;
	void __iomem			*regs;
	struct clk			*ipg_clk;
	int				channum;
	struct intmux_irqchip_data	irqchip_data[] __counted_by(channum);
};

static void imx_intmux_irq_mask(struct irq_data *d)
{
	struct intmux_irqchip_data *irqchip_data = d->chip_data;
	int idx = irqchip_data->chanidx;
	struct intmux_data *data = container_of(irqchip_data, struct intmux_data,
						irqchip_data[idx]);
	unsigned long flags;
	void __iomem *reg;
	u32 val;

	raw_spin_lock_irqsave(&data->lock, flags);
	reg = data->regs + CHANIER(idx);
	val = readl_relaxed(reg);
	/* disable the interrupt source of this channel */
	val &= ~BIT(d->hwirq);
	writel_relaxed(val, reg);
	raw_spin_unlock_irqrestore(&data->lock, flags);
}

static void imx_intmux_irq_unmask(struct irq_data *d)
{
	struct intmux_irqchip_data *irqchip_data = d->chip_data;
	int idx = irqchip_data->chanidx;
	struct intmux_data *data = container_of(irqchip_data, struct intmux_data,
						irqchip_data[idx]);
	unsigned long flags;
	void __iomem *reg;
	u32 val;

	raw_spin_lock_irqsave(&data->lock, flags);
	reg = data->regs + CHANIER(idx);
	val = readl_relaxed(reg);
	/* enable the interrupt source of this channel */
	val |= BIT(d->hwirq);
	writel_relaxed(val, reg);
	raw_spin_unlock_irqrestore(&data->lock, flags);
}

static struct irq_chip imx_intmux_irq_chip __ro_after_init = {
	.name		= "intmux",
	.irq_mask	= imx_intmux_irq_mask,
	.irq_unmask	= imx_intmux_irq_unmask,
};

static int imx_intmux_irq_map(struct irq_domain *h, unsigned int irq,
			      irq_hw_number_t hwirq)
{
	struct intmux_irqchip_data *data = h->host_data;

	irq_set_chip_data(irq, data);
	irq_set_chip_and_handler(irq, &imx_intmux_irq_chip, handle_level_irq);

	return 0;
}

static int imx_intmux_irq_xlate(struct irq_domain *d, struct device_node *node,
				const u32 *intspec, unsigned int intsize,
				unsigned long *out_hwirq, unsigned int *out_type)
{
	struct intmux_irqchip_data *irqchip_data = d->host_data;
	int idx = irqchip_data->chanidx;
	struct intmux_data *data = container_of(irqchip_data, struct intmux_data,
						irqchip_data[idx]);

	/*
	 * two cells needed in interrupt specifier:
	 * the 1st cell: hw interrupt number
	 * the 2nd cell: channel index
	 */
	if (WARN_ON(intsize != 2))
		return -EINVAL;

	if (WARN_ON(intspec[1] >= data->channum))
		return -EINVAL;

Annotation

Implementation Notes