drivers/irqchip/irq-renesas-rzv2h.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-renesas-rzv2h.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-renesas-rzv2h.c
Extension
.c
Size
27877 bytes
Lines
954
Domain
Driver Families
Bucket
drivers/irqchip
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 rzv2h_irqc_reg_cache {
	u32	nitsr;
	u32	iitsr;
	u32	titsr[2];
};

/**
 * struct rzv2h_hw_info - Interrupt Control Unit controller hardware info structure.
 * @tssel_lut:		TINT lookup table
 * @t_offs:		TINT offset
 * @max_tssel:		TSSEL max value
 * @field_width:	TSSR field width
 * @ecc_start:		Start index of ECC RAM interrupts
 * @ecc_end:		End index of ECC RAM interrupts
 */
struct rzv2h_hw_info {
	const u8	*tssel_lut;
	u16		t_offs;
	u8		max_tssel;
	u8		field_width;
	u8		ecc_start;
	u8		ecc_end;
};

/* DMAC */
#define ICU_DMAC_DkRQ_SEL_MASK			GENMASK(9, 0)

#define ICU_DMAC_DMAREQ_SHIFT(up)		((up) * 16)
#define ICU_DMAC_DMAREQ_MASK(up)		(ICU_DMAC_DkRQ_SEL_MASK \
						 << ICU_DMAC_DMAREQ_SHIFT(up))
#define ICU_DMAC_PREP_DMAREQ(sel, up)		(FIELD_PREP(ICU_DMAC_DkRQ_SEL_MASK, (sel)) \
						 << ICU_DMAC_DMAREQ_SHIFT(up))

/**
 * struct rzv2h_icu_priv - Interrupt Control Unit controller private data structure.
 * @base:	Controller's base address
 * @fwspec:	IRQ firmware specific data
 * @lock:	Lock to serialize access to hardware registers
 * @info:	Pointer to struct rzv2h_hw_info
 * @cache:	Registers cache for suspend/resume
 */
static struct rzv2h_icu_priv {
	void __iomem			*base;
	struct irq_fwspec		fwspec[ICU_NUM_IRQ];
	raw_spinlock_t			lock;
	const struct rzv2h_hw_info	*info;
	struct rzv2h_irqc_reg_cache	cache;
} *rzv2h_icu_data;

void rzv2h_icu_register_dma_req(struct platform_device *icu_dev, u8 dmac_index, u8 dmac_channel,
				u16 req_no)
{
	struct rzv2h_icu_priv *priv = platform_get_drvdata(icu_dev);
	u32 icu_dmksely, dmareq, dmareq_mask;
	u8 y, upper;

	y = dmac_channel / 2;
	upper = dmac_channel % 2;

	dmareq = ICU_DMAC_PREP_DMAREQ(req_no, upper);
	dmareq_mask = ICU_DMAC_DMAREQ_MASK(upper);

	guard(raw_spinlock_irqsave)(&priv->lock);

	icu_dmksely = readl(priv->base + ICU_DMkSELy(dmac_index, y));
	icu_dmksely = (icu_dmksely & ~dmareq_mask) | dmareq;
	writel(icu_dmksely, priv->base + ICU_DMkSELy(dmac_index, y));
}
EXPORT_SYMBOL_GPL(rzv2h_icu_register_dma_req);

static inline struct rzv2h_icu_priv *irq_data_to_priv(struct irq_data *data)
{
	return data->domain->host_data;
}

static void rzv2h_icu_tint_eoi(struct irq_data *d)
{
	struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
	unsigned int hw_irq = irqd_to_hwirq(d);
	unsigned int tintirq_nr;
	u32 bit;

	if (!irqd_is_level_type(d)) {
		tintirq_nr = hw_irq - ICU_TINT_START;
		bit = BIT(tintirq_nr);
		writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR);
	}

	irq_chip_eoi_parent(d);
}

Annotation

Implementation Notes