drivers/irqchip/irq-renesas-rza1.c

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

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-renesas-rza1.c
Extension
.c
Size
6624 bytes
Lines
272
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 rza1_irqc_priv {
	struct device *dev;
	void __iomem *base;
	struct irq_chip chip;
	struct irq_domain *irq_domain;
	struct of_phandle_args map[IRQC_NUM_IRQ];
};

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

static void rza1_irqc_eoi(struct irq_data *d)
{
	struct rza1_irqc_priv *priv = irq_data_to_priv(d);
	u16 bit = BIT(irqd_to_hwirq(d));
	u16 tmp;

	tmp = readw_relaxed(priv->base + IRQRR);
	if (tmp & bit)
		writew_relaxed(GENMASK(IRQC_NUM_IRQ - 1, 0) & ~bit,
			       priv->base + IRQRR);

	irq_chip_eoi_parent(d);
}

static int rza1_irqc_set_type(struct irq_data *d, unsigned int type)
{
	struct rza1_irqc_priv *priv = irq_data_to_priv(d);
	unsigned int hw_irq = irqd_to_hwirq(d);
	u16 sense, tmp;

	switch (type & IRQ_TYPE_SENSE_MASK) {
	case IRQ_TYPE_LEVEL_LOW:
		sense = ICR1_IRQS_LEVEL_LOW;
		break;

	case IRQ_TYPE_EDGE_FALLING:
		sense = ICR1_IRQS_EDGE_FALLING;
		break;

	case IRQ_TYPE_EDGE_RISING:
		sense = ICR1_IRQS_EDGE_RISING;
		break;

	case IRQ_TYPE_EDGE_BOTH:
		sense = ICR1_IRQS_EDGE_BOTH;
		break;

	default:
		return -EINVAL;
	}

	tmp = readw_relaxed(priv->base + ICR1);
	tmp &= ~ICR1_IRQS_MASK(hw_irq);
	tmp |= ICR1_IRQS(hw_irq, sense);
	writew_relaxed(tmp, priv->base + ICR1);
	return 0;
}

static int rza1_irqc_alloc(struct irq_domain *domain, unsigned int virq,
			   unsigned int nr_irqs, void *arg)
{
	struct rza1_irqc_priv *priv = domain->host_data;
	struct irq_fwspec *fwspec = arg;
	unsigned int hwirq = fwspec->param[0];
	struct irq_fwspec spec;
	unsigned int i;
	int ret;

	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &priv->chip,
					    priv);
	if (ret)
		return ret;

	spec.fwnode = &priv->dev->of_node->fwnode;
	spec.param_count = priv->map[hwirq].args_count;
	for (i = 0; i < spec.param_count; i++)
		spec.param[i] = priv->map[hwirq].args[i];

	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &spec);
}

static int rza1_irqc_translate(struct irq_domain *domain,
			       struct irq_fwspec *fwspec, unsigned long *hwirq,
			       unsigned int *type)
{
	if (fwspec->param_count != 2 || fwspec->param[0] >= IRQC_NUM_IRQ)
		return -EINVAL;

Annotation

Implementation Notes