drivers/irqchip/irq-ast2700-intc0.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-ast2700-intc0.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-ast2700-intc0.c
Extension
.c
Size
16944 bytes
Lines
583
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

if (resolved) {
			resolved->start = output;
			resolved->count = 1;
			resolved->upstream = range.upstream;
			resolved->upstream.param[ASPEED_INTC_RANGES_COUNT] +=
				output - range.start;
		}

		return 0;
	}

	return -ENOENT;
}

static int resolve_parent_route_for_input(const struct aspeed_intc0 *intc0,
					  const struct fwnode_handle *parent, u32 input,
					  struct aspeed_intc_interrupt_range *resolved)
{
	int rc = -ENOENT;
	u32 c0o;

	if (input < INT_NUM) {
		static_assert(INTC0_ROUTE_NUM < INT_MAX, "Broken cast");
		for (size_t i = 0; rc == -ENOENT && i < INTC0_ROUTE_NUM; i++) {
			c0o = aspeed_intc0_routes[input / INTC0_IRQS_PER_BANK][i];
			if (c0o == AST2700_INTC_INVALID_ROUTE)
				continue;

			if (input < GIC_P2P_SPI_END)
				c0o += input % INTC0_IRQS_PER_BANK;

			rc = resolve_parent_range_for_output(intc0, parent, c0o, resolved);
			if (!rc)
				return (int)i;
		}
	} else if (input < (INT_NUM + INTM_NUM)) {
		c0o = aspeed_intc0_intm_routes[(input - INT_NUM) / INTM_IRQS_PER_BANK];
		c0o += ((input - INT_NUM) % INTM_IRQS_PER_BANK);
		return resolve_parent_range_for_output(intc0, parent, c0o, resolved);
	} else if (input < (INT_NUM + INTM_NUM + SWINT_NUM)) {
		c0o = input - SWINT_BASE + INTC0_SWINT_OUT_BASE;
		return resolve_parent_range_for_output(intc0, parent, c0o, resolved);
	} else {
		return -ENOENT;
	}

	return rc;
}

/**
 * aspeed_intc0_resolve_route - Determine the necessary interrupt output at intc1
 * @c0domain: The pointer to intc0's irq_domain
 * @nc1outs: The number of valid intc1 outputs available for the input
 * @c1outs: The array of available intc1 output indices for the input
 * @nc1ranges: The number of interrupt range entries for intc1
 * @c1ranges: The array of configured intc1 interrupt ranges
 * @resolved: The fully resolved range entry after applying the resolution
 *            algorithm
 *
 * Returns: The intc1 route index associated with the intc1 output identified in
 * @resolved on success. Otherwise, a negative errno value.
 *
 * The AST2700 interrupt architecture allows any peripheral interrupt source
 * to be routed to one of up to four processors running in the SoC. A processor
 * binding a driver for a peripheral that requests an interrupt is (without
 * further design and effort) the destination for the requested interrupt.
 *
 * Routing a peripheral interrupt to its destination processor requires
 * coordination between INTC0 on the CPU die and one or more INTC1 instances.
 * At least one INTC1 instance exists in the SoC on the IO-die, however up
 * to two more instances may be integrated via LTPI (LVDS Tunneling Protocol
 * & Interface).
 *
 * Between the multiple destinations, various route constraints, and the
 * devicetree binding design, some information that's needed at INTC1 instances
 * to route inbound interrupts correctly to the destination processor is only
 * available at INTC0.
 *
 * aspeed_intc0_resolve_route() is to be invoked by INTC1 driver instances to
 * perform the route resolution. The implementation in INTC0 allows INTC0 to
 * encapsulate the information used to perform route selection, and provides it
 * with an opportunity to apply policy as part of the selection process. Such
 * policy may, for instance, choose to de-prioritise some interrupts destined
 * for the PSP (Primary Service Processor) GIC.
 */
int aspeed_intc0_resolve_route(const struct irq_domain *c0domain, size_t nc1outs,
			       const u32 *c1outs, size_t nc1ranges,
			       const struct aspeed_intc_interrupt_range *c1ranges,
			       struct aspeed_intc_interrupt_range *resolved)
{

Annotation

Implementation Notes