static int __init gic_of_init()

in irq-mips-gic.c [688:820]


static int __init gic_of_init(struct device_node *node,
			      struct device_node *parent)
{
	unsigned int cpu_vec, i, gicconfig, v[2], num_ipis;
	unsigned long reserved;
	phys_addr_t gic_base;
	struct resource res;
	size_t gic_len;

	/* Find the first available CPU vector. */
	i = 0;
	reserved = (C_SW0 | C_SW1) >> __ffs(C_SW0);
	while (!of_property_read_u32_index(node, "mti,reserved-cpu-vectors",
					   i++, &cpu_vec))
		reserved |= BIT(cpu_vec);

	cpu_vec = find_first_zero_bit(&reserved, hweight_long(ST0_IM));
	if (cpu_vec == hweight_long(ST0_IM)) {
		pr_err("No CPU vectors available\n");
		return -ENODEV;
	}

	if (of_address_to_resource(node, 0, &res)) {
		/*
		 * Probe the CM for the GIC base address if not specified
		 * in the device-tree.
		 */
		if (mips_cm_present()) {
			gic_base = read_gcr_gic_base() &
				~CM_GCR_GIC_BASE_GICEN;
			gic_len = 0x20000;
			pr_warn("Using inherited base address %pa\n",
				&gic_base);
		} else {
			pr_err("Failed to get memory range\n");
			return -ENODEV;
		}
	} else {
		gic_base = res.start;
		gic_len = resource_size(&res);
	}

	if (mips_cm_present()) {
		write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN);
		/* Ensure GIC region is enabled before trying to access it */
		__sync();
	}

	mips_gic_base = ioremap(gic_base, gic_len);

	gicconfig = read_gic_config();
	gic_shared_intrs = FIELD_GET(GIC_CONFIG_NUMINTERRUPTS, gicconfig);
	gic_shared_intrs = (gic_shared_intrs + 1) * 8;

	if (cpu_has_veic) {
		/* Always use vector 1 in EIC mode */
		gic_cpu_pin = 0;
		timer_cpu_pin = gic_cpu_pin;
		set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET,
			       __gic_irq_dispatch);
	} else {
		gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET;
		irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec,
					gic_irq_dispatch);
		/*
		 * With the CMP implementation of SMP (deprecated), other CPUs
		 * are started by the bootloader and put into a timer based
		 * waiting poll loop. We must not re-route those CPU's local
		 * timer interrupts as the wait instruction will never finish,
		 * so just handle whatever CPU interrupt it is routed to by
		 * default.
		 *
		 * This workaround should be removed when CMP support is
		 * dropped.
		 */
		if (IS_ENABLED(CONFIG_MIPS_CMP) &&
		    gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) {
			timer_cpu_pin = read_gic_vl_timer_map() & GIC_MAP_PIN_MAP;
			irq_set_chained_handler(MIPS_CPU_IRQ_BASE +
						GIC_CPU_PIN_OFFSET +
						timer_cpu_pin,
						gic_irq_dispatch);
		} else {
			timer_cpu_pin = gic_cpu_pin;
		}
	}

	gic_irq_domain = irq_domain_add_simple(node, GIC_NUM_LOCAL_INTRS +
					       gic_shared_intrs, 0,
					       &gic_irq_domain_ops, NULL);
	if (!gic_irq_domain) {
		pr_err("Failed to add IRQ domain");
		return -ENXIO;
	}

	gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain,
						  IRQ_DOMAIN_FLAG_IPI_PER_CPU,
						  GIC_NUM_LOCAL_INTRS + gic_shared_intrs,
						  node, &gic_ipi_domain_ops, NULL);
	if (!gic_ipi_domain) {
		pr_err("Failed to add IPI domain");
		return -ENXIO;
	}

	irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI);

	if (node &&
	    !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) {
		bitmap_set(ipi_resrv, v[0], v[1]);
	} else {
		/*
		 * Reserve 2 interrupts per possible CPU/VP for use as IPIs,
		 * meeting the requirements of arch/mips SMP.
		 */
		num_ipis = 2 * num_possible_cpus();
		bitmap_set(ipi_resrv, gic_shared_intrs - num_ipis, num_ipis);
	}

	bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS);

	board_bind_eic_interrupt = &gic_bind_eic_interrupt;

	/* Setup defaults */
	for (i = 0; i < gic_shared_intrs; i++) {
		change_gic_pol(i, GIC_POL_ACTIVE_HIGH);
		change_gic_trig(i, GIC_TRIG_LEVEL);
		write_gic_rmask(i);
	}

	return cpuhp_setup_state(CPUHP_AP_IRQ_MIPS_GIC_STARTING,
				 "irqchip/mips/gic:starting",
				 gic_cpu_startup, NULL);
}