drivers/irqchip/irq-imx-mu-msi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-imx-mu-msi.c
Extension
.c
Size
10940 bytes
Lines
441
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 imx_mu_dcfg {
	enum imx_mu_type type;
	u32     xTR;            /* Transmit Register0 */
	u32     xRR;            /* Receive Register0 */
	u32     xSR[IMX_MU_xSR_MAX];         /* Status Registers */
	u32     xCR[IMX_MU_xCR_MAX];         /* Control Registers */
};

struct imx_mu_msi {
	raw_spinlock_t			lock;
	struct irq_domain		*msi_domain;
	void __iomem			*regs;
	phys_addr_t			msiir_addr;
	const struct imx_mu_dcfg	*cfg;
	unsigned long			used;
	struct clk			*clk;
};

static void imx_mu_write(struct imx_mu_msi *msi_data, u32 val, u32 offs)
{
	iowrite32(val, msi_data->regs + offs);
}

static u32 imx_mu_read(struct imx_mu_msi *msi_data, u32 offs)
{
	return ioread32(msi_data->regs + offs);
}

static u32 imx_mu_xcr_rmw(struct imx_mu_msi *msi_data, enum imx_mu_xcr type, u32 set, u32 clr)
{
	unsigned long flags;
	u32 val;

	raw_spin_lock_irqsave(&msi_data->lock, flags);
	val = imx_mu_read(msi_data, msi_data->cfg->xCR[type]);
	val &= ~clr;
	val |= set;
	imx_mu_write(msi_data, val, msi_data->cfg->xCR[type]);
	raw_spin_unlock_irqrestore(&msi_data->lock, flags);

	return val;
}

static void imx_mu_msi_parent_mask_irq(struct irq_data *data)
{
	struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(data);

	imx_mu_xcr_rmw(msi_data, IMX_MU_RCR, 0, IMX_MU_xCR_RIEn(msi_data, data->hwirq));
}

static void imx_mu_msi_parent_unmask_irq(struct irq_data *data)
{
	struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(data);

	imx_mu_xcr_rmw(msi_data, IMX_MU_RCR, IMX_MU_xCR_RIEn(msi_data, data->hwirq), 0);
}

static void imx_mu_msi_parent_ack_irq(struct irq_data *data)
{
	struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(data);

	imx_mu_read(msi_data, msi_data->cfg->xRR + data->hwirq * 4);
}

static void imx_mu_msi_parent_compose_msg(struct irq_data *data,
					  struct msi_msg *msg)
{
	struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(data);
	u64 addr = msi_data->msiir_addr + 4 * data->hwirq;

	msg->address_hi = upper_32_bits(addr);
	msg->address_lo = lower_32_bits(addr);
	msg->data = data->hwirq;
}

static int imx_mu_msi_parent_set_affinity(struct irq_data *irq_data,
				   const struct cpumask *mask, bool force)
{
	return -EINVAL;
}

static struct irq_chip imx_mu_msi_parent_chip = {
	.name		= "MU",
	.irq_mask	= imx_mu_msi_parent_mask_irq,
	.irq_unmask	= imx_mu_msi_parent_unmask_irq,
	.irq_ack	= imx_mu_msi_parent_ack_irq,
	.irq_compose_msi_msg	= imx_mu_msi_parent_compose_msg,
	.irq_set_affinity = imx_mu_msi_parent_set_affinity,
};

Annotation

Implementation Notes