drivers/irqchip/irq-loongson-pch-pic.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-loongson-pch-pic.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-loongson-pch-pic.c
Extension
.c
Size
11650 bytes
Lines
478
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 pch_pic {
	void __iomem		*base;
	struct irq_domain	*pic_domain;
	u32			ht_vec_base;
	raw_spinlock_t		pic_lock;
	u32			vec_count;
	u32			gsi_base;
	u32			saved_vec_en[PIC_REG_COUNT];
	u32			saved_vec_pol[PIC_REG_COUNT];
	u32			saved_vec_edge[PIC_REG_COUNT];
	u8			table[PIC_COUNT];
	int			inuse;
};

static struct pch_pic *pch_pic_priv[MAX_IO_PICS];

struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];

static inline u8 hwirq_to_bit(struct pch_pic *priv, int hirq)
{
	return priv->table[hirq];
}

static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit)
{
	u32 reg;
	void __iomem *addr = priv->base + offset + PIC_REG_IDX(bit) * 4;

	raw_spin_lock(&priv->pic_lock);
	reg = readl(addr);
	reg |= BIT(PIC_REG_BIT(bit));
	writel(reg, addr);
	raw_spin_unlock(&priv->pic_lock);
}

static void pch_pic_bitclr(struct pch_pic *priv, int offset, int bit)
{
	u32 reg;
	void __iomem *addr = priv->base + offset + PIC_REG_IDX(bit) * 4;

	raw_spin_lock(&priv->pic_lock);
	reg = readl(addr);
	reg &= ~BIT(PIC_REG_BIT(bit));
	writel(reg, addr);
	raw_spin_unlock(&priv->pic_lock);
}

static void pch_pic_mask_irq(struct irq_data *d)
{
	struct pch_pic *priv = irq_data_get_irq_chip_data(d);

	pch_pic_bitset(priv, PCH_PIC_MASK, hwirq_to_bit(priv, d->hwirq));
	irq_chip_mask_parent(d);
}

static void pch_pic_unmask_irq(struct irq_data *d)
{
	struct pch_pic *priv = irq_data_get_irq_chip_data(d);
	int bit = hwirq_to_bit(priv, d->hwirq);

	writel(BIT(PIC_REG_BIT(bit)),
			priv->base + PCH_PIC_CLR + PIC_REG_IDX(bit) * 4);

	irq_chip_unmask_parent(d);
	pch_pic_bitclr(priv, PCH_PIC_MASK, bit);
}

static int pch_pic_set_type(struct irq_data *d, unsigned int type)
{
	struct pch_pic *priv = irq_data_get_irq_chip_data(d);
	int bit = hwirq_to_bit(priv, d->hwirq);
	int ret = 0;

	switch (type) {
	case IRQ_TYPE_EDGE_RISING:
		pch_pic_bitset(priv, PCH_PIC_EDGE, bit);
		pch_pic_bitclr(priv, PCH_PIC_POL, bit);
		irq_set_handler_locked(d, handle_edge_irq);
		break;
	case IRQ_TYPE_EDGE_FALLING:
		pch_pic_bitset(priv, PCH_PIC_EDGE, bit);
		pch_pic_bitset(priv, PCH_PIC_POL, bit);
		irq_set_handler_locked(d, handle_edge_irq);
		break;
	case IRQ_TYPE_LEVEL_HIGH:
		pch_pic_bitclr(priv, PCH_PIC_EDGE, bit);
		pch_pic_bitclr(priv, PCH_PIC_POL, bit);
		irq_set_handler_locked(d, handle_level_irq);
		break;
	case IRQ_TYPE_LEVEL_LOW:

Annotation

Implementation Notes