drivers/irqchip/irq-sg2042-msi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-sg2042-msi.c
Extension
.c
Size
9766 bytes
Lines
341
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 sg204x_msi_chip_info {
	const struct irq_chip		*irqchip;
	const struct msi_parent_ops	*parent_ops;
};

/**
 * struct sg204x_msi_chipdata - chip data for the SG204x MSI IRQ controller
 * @reg_clr:		clear reg, see TRM, 10.1.33, GP_INTR0_CLR
 * @doorbell_addr:	see TRM, 10.1.32, GP_INTR0_SET
 * @irq_first:		First vectors number that MSIs starts
 * @num_irqs:		Number of vectors for MSIs
 * @irq_type:		IRQ type for MSIs
 * @msi_map:		mapping for allocated MSI vectors.
 * @msi_map_lock:	Lock for msi_map
 * @chip_info:		chip specific infomations
 */
struct sg204x_msi_chipdata {
	void __iomem				*reg_clr;

	phys_addr_t				doorbell_addr;

	u32					irq_first;
	u32					num_irqs;
	unsigned int				irq_type;

	unsigned long				*msi_map;
	struct mutex				msi_map_lock;

	const struct sg204x_msi_chip_info	*chip_info;
};

static int sg204x_msi_allocate_hwirq(struct sg204x_msi_chipdata *data, int num_req)
{
	int first;

	guard(mutex)(&data->msi_map_lock);
	first = bitmap_find_free_region(data->msi_map, data->num_irqs,
					get_count_order(num_req));
	return first >= 0 ? first : -ENOSPC;
}

static void sg204x_msi_free_hwirq(struct sg204x_msi_chipdata *data, int hwirq, int num_req)
{
	guard(mutex)(&data->msi_map_lock);
	bitmap_release_region(data->msi_map, hwirq, get_count_order(num_req));
}

static void sg2042_msi_irq_ack(struct irq_data *d)
{
	struct sg204x_msi_chipdata *data  = irq_data_get_irq_chip_data(d);
	int bit_off = d->hwirq;

	writel(1 << bit_off, data->reg_clr);

	irq_chip_ack_parent(d);
}

static void sg2042_msi_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
{
	struct sg204x_msi_chipdata *data = irq_data_get_irq_chip_data(d);

	msg->address_hi = upper_32_bits(data->doorbell_addr);
	msg->address_lo = lower_32_bits(data->doorbell_addr);
	msg->data = 1 << d->hwirq;
}

static const struct irq_chip sg2042_msi_middle_irq_chip = {
	.name			= "SG2042 MSI",
	.irq_startup		= irq_chip_startup_parent,
	.irq_shutdown		= irq_chip_shutdown_parent,
	.irq_ack		= sg2042_msi_irq_ack,
	.irq_mask		= irq_chip_mask_parent,
	.irq_unmask		= irq_chip_unmask_parent,
#ifdef CONFIG_SMP
	.irq_set_affinity	= irq_chip_set_affinity_parent,
#endif
	.irq_compose_msi_msg	= sg2042_msi_irq_compose_msi_msg,
};

static void sg2044_msi_irq_ack(struct irq_data *d)
{
	struct sg204x_msi_chipdata *data = irq_data_get_irq_chip_data(d);

	writel(0, (u32 __iomem *)data->reg_clr + d->hwirq);
	irq_chip_ack_parent(d);
}

static void sg2044_msi_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
{
	struct sg204x_msi_chipdata *data = irq_data_get_irq_chip_data(d);

Annotation

Implementation Notes