drivers/irqchip/irq-ls-extirq.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-ls-extirq.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-ls-extirq.c
Extension
.c
Size
5620 bytes
Lines
232
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 ls_extirq_data {
	void __iomem		*intpcr;
	raw_spinlock_t		lock;
	bool			big_endian;
	bool			is_ls1021a_or_ls1043a;
	u32			nirq;
	struct irq_fwspec	map[MAXIRQ];
};

static void ls_extirq_intpcr_rmw(struct ls_extirq_data *priv, u32 mask,
				 u32 value)
{
	u32 intpcr;

	/*
	 * Serialize concurrent calls to ls_extirq_set_type() from multiple
	 * IRQ descriptors, making sure the read-modify-write is atomic.
	 */
	raw_spin_lock(&priv->lock);

	if (priv->big_endian)
		intpcr = ioread32be(priv->intpcr);
	else
		intpcr = ioread32(priv->intpcr);

	intpcr &= ~mask;
	intpcr |= value;

	if (priv->big_endian)
		iowrite32be(intpcr, priv->intpcr);
	else
		iowrite32(intpcr, priv->intpcr);

	raw_spin_unlock(&priv->lock);
}

static int
ls_extirq_set_type(struct irq_data *data, unsigned int type)
{
	struct ls_extirq_data *priv = data->chip_data;
	irq_hw_number_t hwirq = data->hwirq;
	u32 value, mask;

	if (priv->is_ls1021a_or_ls1043a)
		mask = 1U << (31 - hwirq);
	else
		mask = 1U << hwirq;

	switch (type) {
	case IRQ_TYPE_LEVEL_LOW:
		type = IRQ_TYPE_LEVEL_HIGH;
		value = mask;
		break;
	case IRQ_TYPE_EDGE_FALLING:
		type = IRQ_TYPE_EDGE_RISING;
		value = mask;
		break;
	case IRQ_TYPE_LEVEL_HIGH:
	case IRQ_TYPE_EDGE_RISING:
		value = 0;
		break;
	default:
		return -EINVAL;
	}

	ls_extirq_intpcr_rmw(priv, mask, value);

	return irq_chip_set_type_parent(data, type);
}

static struct irq_chip ls_extirq_chip = {
	.name			= "ls-extirq",
	.irq_mask		= irq_chip_mask_parent,
	.irq_unmask		= irq_chip_unmask_parent,
	.irq_eoi		= irq_chip_eoi_parent,
	.irq_set_type		= ls_extirq_set_type,
	.irq_retrigger		= irq_chip_retrigger_hierarchy,
	.irq_set_affinity	= irq_chip_set_affinity_parent,
	.flags                  = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE,
};

static int
ls_extirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
		       unsigned int nr_irqs, void *arg)
{
	struct ls_extirq_data *priv = domain->host_data;
	struct irq_fwspec *fwspec = arg;
	irq_hw_number_t hwirq;

	if (fwspec->param_count != 2)

Annotation

Implementation Notes