drivers/irqchip/irq-renesas-rzg2l.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-renesas-rzg2l.c
Extension
.c
Size
26955 bytes
Lines
953
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 rzg2l_irqc_reg_cache {
	u32	nitsr;
	u32	iitsr;
	u32	inttsel;
	u32	titsr[2];
};

/**
 * struct rzg2l_hw_info - Interrupt Control Unit controller hardware info structure.
 * @tssel_lut:		TINT lookup table
 * @irq_count:		Number of IRQC interrupts
 * @tint_start:		Start of TINT interrupts
 * @num_irq:		Total Number of interrupts
 * @shared_irq_cnt:	Number of shared interrupts
 */
struct rzg2l_hw_info {
	const u8	*tssel_lut;
	unsigned int	irq_count;
	unsigned int	tint_start;
	unsigned int	num_irq;
	unsigned int	shared_irq_cnt;
};

/**
 * struct rzg2l_irqc_priv - IRQ controller private data structure
 * @base:	Controller's base address
 * @irq_chip:	Pointer to struct irq_chip for irq
 * @tint_chip:	Pointer to struct irq_chip for tint
 * @fwspec:	IRQ firmware specific data
 * @lock:	Lock to serialize access to hardware registers
 * @info:	Hardware specific data
 * @cache:	Registers cache for suspend/resume
 * @used_irqs:	Bitmap to manage the shared interrupts
 */
static struct rzg2l_irqc_priv {
	void __iomem			*base;
	const struct irq_chip		*irq_chip;
	const struct irq_chip		*tint_chip;
	struct irq_fwspec		*fwspec;
	raw_spinlock_t			lock;
	struct rzg2l_hw_info		info;
	struct rzg2l_irqc_reg_cache	cache;
	DECLARE_BITMAP(used_irqs, IRQC_SHARED_IRQ_COUNT);
} *rzg2l_irqc_data;

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

static void rzg2l_clear_nmi_int(struct rzg2l_irqc_priv *priv)
{
	u32 bit = BIT(NSCR_NSTAT);
	u32 reg;

	/*
	 * No locking required as the register is not shared
	 * with other interrupts.
	 *
	 * Writing is allowed only when NSTAT is 1
	 */
	reg = readl_relaxed(priv->base + NSCR);
	if (reg & bit) {
		writel_relaxed(reg & ~bit, priv->base + NSCR);
		/*
		 * Enforce that the posted write is flushed to prevent that the
		 * just handled interrupt is raised again.
		 */
		readl_relaxed(priv->base + NSCR);
	}
}

static void rzg2l_clear_irq_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq)
{
	unsigned int hw_irq = hwirq - IRQC_IRQ_START;
	u32 bit = BIT(hw_irq);
	u32 iitsr, iscr;

	iscr = readl_relaxed(priv->base + ISCR);
	iitsr = readl_relaxed(priv->base + IITSR);

	/*
	 * ISCR can only be cleared if the type is falling-edge, rising-edge or
	 * falling/rising-edge.
	 */
	if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq))) {
		writel_relaxed(iscr & ~bit, priv->base + ISCR);
		/*
		 * Enforce that the posted write is flushed to prevent that the
		 * just handled interrupt is raised again.

Annotation

Implementation Notes