drivers/irqchip/qcom-pdc.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/qcom-pdc.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/qcom-pdc.c
Extension
.c
Size
11989 bytes
Lines
453
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 pdc_pin_region {
	u32 pin_base;
	u32 parent_base;
	u32 cnt;
};

#define pin_to_hwirq(r, p)	((r)->parent_base + (p) - (r)->pin_base)

static DEFINE_RAW_SPINLOCK(pdc_lock);
static void __iomem *pdc_base;
static void __iomem *pdc_prev_base;
static struct pdc_pin_region *pdc_region;
static int pdc_region_cnt;
static unsigned int pdc_version;
static bool pdc_x1e_quirk;

static void pdc_base_reg_write(void __iomem *base, int reg, u32 i, u32 val)
{
	writel_relaxed(val, base + reg + i * sizeof(u32));
}

static void pdc_reg_write(int reg, u32 i, u32 val)
{
	pdc_base_reg_write(pdc_base, reg, i, val);
}

static u32 pdc_reg_read(int reg, u32 i)
{
	return readl_relaxed(pdc_base + reg + i * sizeof(u32));
}

static void pdc_x1e_irq_enable_write(u32 bank, u32 enable)
{
	void __iomem *base;

	/* Remap the write access to work around a hardware bug on X1E */
	switch (bank) {
	case 0 ... 1:
		/* Use previous DRV (client) region and shift to bank 3-4 */
		base = pdc_prev_base;
		bank += 3;
		break;
	case 2 ... 4:
		/* Use our own region and shift to bank 0-2 */
		base = pdc_base;
		bank -= 2;
		break;
	case 5:
		/* No fixup required for bank 5 */
		base = pdc_base;
		break;
	default:
		WARN_ON(1);
		return;
	}

	pdc_base_reg_write(base, IRQ_ENABLE_BANK, bank, enable);
}

static void pdc_enable_intr_bank(int pin_out, bool on)
{
	unsigned long enable;
	u32 index, mask;

	index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out);
	mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out);

	enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
	__assign_bit(mask, &enable, on);

	if (pdc_x1e_quirk)
		pdc_x1e_irq_enable_write(index, enable);
	else
		pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
}

static void pdc_enable_intr_cfg(int pin_out, bool on)
{
	unsigned long enable = pdc_reg_read(IRQ_i_CFG, pin_out);

	__assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on);
	pdc_reg_write(IRQ_i_CFG, pin_out, enable);
}

static void __pdc_enable_intr(int pin_out, bool on)
{
	if (pdc_version < PDC_VERSION_3_2)
		pdc_enable_intr_bank(pin_out, on);
	else
		pdc_enable_intr_cfg(pin_out, on);

Annotation

Implementation Notes