drivers/irqchip/irq-mst-intc.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-mst-intc.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-mst-intc.c
Extension
.c
Size
7340 bytes
Lines
296
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 mst_intc_chip_data {
	raw_spinlock_t	lock;
	unsigned int	irq_start, nr_irqs;
	void __iomem	*base;
	bool		no_eoi;
#ifdef CONFIG_PM_SLEEP
	struct list_head entry;
	u16 saved_polarity_conf[DIV_ROUND_UP(MST_INTC_MAX_IRQS, 16)];
#endif
};

static void mst_set_irq(struct irq_data *d, u32 offset)
{
	irq_hw_number_t hwirq = irqd_to_hwirq(d);
	struct mst_intc_chip_data *cd = irq_data_get_irq_chip_data(d);
	u16 val, mask;
	unsigned long flags;

	mask = 1 << (hwirq % 16);
	offset += (hwirq / 16) * 4;

	raw_spin_lock_irqsave(&cd->lock, flags);
	val = readw_relaxed(cd->base + offset) | mask;
	writew_relaxed(val, cd->base + offset);
	raw_spin_unlock_irqrestore(&cd->lock, flags);
}

static void mst_clear_irq(struct irq_data *d, u32 offset)
{
	irq_hw_number_t hwirq = irqd_to_hwirq(d);
	struct mst_intc_chip_data *cd = irq_data_get_irq_chip_data(d);
	u16 val, mask;
	unsigned long flags;

	mask = 1 << (hwirq % 16);
	offset += (hwirq / 16) * 4;

	raw_spin_lock_irqsave(&cd->lock, flags);
	val = readw_relaxed(cd->base + offset) & ~mask;
	writew_relaxed(val, cd->base + offset);
	raw_spin_unlock_irqrestore(&cd->lock, flags);
}

static void mst_intc_mask_irq(struct irq_data *d)
{
	mst_set_irq(d, INTC_MASK);
	irq_chip_mask_parent(d);
}

static void mst_intc_unmask_irq(struct irq_data *d)
{
	mst_clear_irq(d, INTC_MASK);
	irq_chip_unmask_parent(d);
}

static void mst_intc_eoi_irq(struct irq_data *d)
{
	struct mst_intc_chip_data *cd = irq_data_get_irq_chip_data(d);

	if (!cd->no_eoi)
		mst_set_irq(d, INTC_EOI);

	irq_chip_eoi_parent(d);
}

static int mst_irq_chip_set_type(struct irq_data *data, unsigned int type)
{
	switch (type) {
	case IRQ_TYPE_LEVEL_LOW:
	case IRQ_TYPE_EDGE_FALLING:
		mst_set_irq(data, INTC_REV_POLARITY);
		break;
	case IRQ_TYPE_LEVEL_HIGH:
	case IRQ_TYPE_EDGE_RISING:
		mst_clear_irq(data, INTC_REV_POLARITY);
		break;
	default:
		return -EINVAL;
	}

	return irq_chip_set_type_parent(data, IRQ_TYPE_LEVEL_HIGH);
}

static struct irq_chip mst_intc_chip = {
	.name			= "mst-intc",
	.irq_mask		= mst_intc_mask_irq,
	.irq_unmask		= mst_intc_unmask_irq,
	.irq_eoi		= mst_intc_eoi_irq,
	.irq_get_irqchip_state	= irq_chip_get_parent_state,
	.irq_set_irqchip_state	= irq_chip_set_parent_state,

Annotation

Implementation Notes