drivers/irqchip/irq-uniphier-aidet.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-uniphier-aidet.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-uniphier-aidet.c
Extension
.c
Size
6294 bytes
Lines
252
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 uniphier_aidet_priv {
	struct irq_domain *domain;
	void __iomem *reg_base;
	spinlock_t lock;
	u32 saved_vals[UNIPHIER_AIDET_NR_IRQS / 32];
};

static void uniphier_aidet_reg_update(struct uniphier_aidet_priv *priv,
				      unsigned int reg, u32 mask, u32 val)
{
	unsigned long flags;
	u32 tmp;

	spin_lock_irqsave(&priv->lock, flags);
	tmp = readl_relaxed(priv->reg_base + reg);
	tmp &= ~mask;
	tmp |= mask & val;
	writel_relaxed(tmp, priv->reg_base + reg);
	spin_unlock_irqrestore(&priv->lock, flags);
}

static void uniphier_aidet_detconf_update(struct uniphier_aidet_priv *priv,
					  unsigned long index, unsigned int val)
{
	unsigned int reg;
	u32 mask;

	reg = UNIPHIER_AIDET_DETCONF + index / 32 * 4;
	mask = BIT(index % 32);

	uniphier_aidet_reg_update(priv, reg, mask, val ? mask : 0);
}

static int uniphier_aidet_irq_set_type(struct irq_data *data, unsigned int type)
{
	struct uniphier_aidet_priv *priv = data->chip_data;
	unsigned int val;

	/* enable inverter for active low triggers */
	switch (type) {
	case IRQ_TYPE_EDGE_RISING:
	case IRQ_TYPE_LEVEL_HIGH:
		val = 0;
		break;
	case IRQ_TYPE_EDGE_FALLING:
		val = 1;
		type = IRQ_TYPE_EDGE_RISING;
		break;
	case IRQ_TYPE_LEVEL_LOW:
		val = 1;
		type = IRQ_TYPE_LEVEL_HIGH;
		break;
	default:
		return -EINVAL;
	}

	uniphier_aidet_detconf_update(priv, data->hwirq, val);

	return irq_chip_set_type_parent(data, type);
}

static struct irq_chip uniphier_aidet_irq_chip = {
	.name = "AIDET",
	.irq_mask = irq_chip_mask_parent,
	.irq_unmask = irq_chip_unmask_parent,
	.irq_eoi = irq_chip_eoi_parent,
	.irq_set_affinity = irq_chip_set_affinity_parent,
	.irq_set_type = uniphier_aidet_irq_set_type,
};

static int uniphier_aidet_domain_translate(struct irq_domain *domain,
					   struct irq_fwspec *fwspec,
					   unsigned long *out_hwirq,
					   unsigned int *out_type)
{
	if (WARN_ON(fwspec->param_count < 2))
		return -EINVAL;

	*out_hwirq = fwspec->param[0];
	*out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;

	return 0;
}

static int uniphier_aidet_domain_alloc(struct irq_domain *domain,
				       unsigned int virq, unsigned int nr_irqs,
				       void *arg)
{
	struct irq_fwspec parent_fwspec;
	irq_hw_number_t hwirq;

Annotation

Implementation Notes