drivers/irqchip/irq-ti-sci-intr.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-ti-sci-intr.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-ti-sci-intr.c
Extension
.c
Size
9130 bytes
Lines
325
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 ti_sci_intr_irq_domain {
	const struct ti_sci_handle *sci;
	struct ti_sci_resource *out_irqs;
	struct device *dev;
	u32 ti_sci_id;
	u32 type;
};

static struct irq_chip ti_sci_intr_irq_chip = {
	.name			= "INTR",
	.irq_eoi		= irq_chip_eoi_parent,
	.irq_mask		= irq_chip_mask_parent,
	.irq_unmask		= irq_chip_unmask_parent,
	.irq_set_type		= irq_chip_set_type_parent,
	.irq_retrigger		= irq_chip_retrigger_hierarchy,
	.irq_set_affinity	= irq_chip_set_affinity_parent,
};

/**
 * ti_sci_intr_irq_domain_translate() - Retrieve hwirq and type from
 *					IRQ firmware specific handler.
 * @domain:	Pointer to IRQ domain
 * @fwspec:	Pointer to IRQ specific firmware structure
 * @hwirq:	IRQ number identified by hardware
 * @type:	IRQ type
 *
 * Return 0 if all went ok else appropriate error.
 */
static int ti_sci_intr_irq_domain_translate(struct irq_domain *domain,
					    struct irq_fwspec *fwspec,
					    unsigned long *hwirq,
					    unsigned int *type)
{
	struct ti_sci_intr_irq_domain *intr = domain->host_data;

	if (intr->type) {
		/* Global interrupt-type */
		if (fwspec->param_count != 1)
			return -EINVAL;

		*hwirq = fwspec->param[0];
		*type = intr->type;
	} else {
		/* Per-Line interrupt-type */
		if (fwspec->param_count != 2)
			return -EINVAL;

		*hwirq = fwspec->param[0];
		*type = fwspec->param[1];
	}
	return 0;
}

/**
 * ti_sci_intr_xlate_irq() - Translate hwirq to parent's hwirq.
 * @intr:	IRQ domain corresponding to Interrupt Router
 * @irq:	Hardware irq corresponding to the above irq domain
 *
 * Return parent irq number if translation is available else -ENOENT.
 */
static int ti_sci_intr_xlate_irq(struct ti_sci_intr_irq_domain *intr, u32 irq)
{
	struct device_node *np = dev_of_node(intr->dev);
	u32 base, pbase, size, len;
	const __be32 *range;

	range = of_get_property(np, "ti,interrupt-ranges", &len);
	if (!range)
		return irq;

	for (len /= sizeof(*range); len >= 3; len -= 3) {
		base = be32_to_cpu(*range++);
		pbase = be32_to_cpu(*range++);
		size = be32_to_cpu(*range++);

		if (base <= irq && irq < base + size)
			return irq - base + pbase;
	}

	return -ENOENT;
}

/**
 * ti_sci_intr_irq_domain_free() - Free the specified IRQs from the domain.
 * @domain:	Domain to which the irqs belong
 * @virq:	Linux virtual IRQ to be freed.
 * @nr_irqs:	Number of continuous irqs to be freed
 */
static void ti_sci_intr_irq_domain_free(struct irq_domain *domain,
					unsigned int virq, unsigned int nr_irqs)

Annotation

Implementation Notes