Commit 3dfa576b authored by Marc Zyngier's avatar Marc Zyngier
Browse files

irqchip/gic-v3-its: Add probing for VLPI properties



Add the probing code for the ITS VLPI support. This includes
configuring the ITS number if not supporting the single VMOVP
command feature.

Reviewed-by: default avatarEric Auger <eric.auger@redhat.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent a13b0404
Loading
Loading
Loading
Loading
+67 −4
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ struct its_node {
	u32			ite_size;
	u32			device_ids;
	int			numa_node;
	bool			is_v4;
};

#define ITS_ITT_ALIGN		SZ_256
@@ -133,6 +134,14 @@ static DEFINE_SPINLOCK(its_lock);
static struct rdists *gic_rdists;
static struct irq_domain *its_parent;

/*
 * We have a maximum number of 16 ITSs in the whole system if we're
 * using the ITSList mechanism
 */
#define ITS_LIST_MAX		16

static unsigned long its_list_map;

#define gic_data_rdist()		(raw_cpu_ptr(gic_rdists->rdist))
#define gic_data_rdist_rd_base()	(gic_data_rdist()->rd_base)

@@ -1679,13 +1688,51 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
	return 0;
}

static int __init its_compute_its_list_map(struct resource *res,
					   void __iomem *its_base)
{
	int its_number;
	u32 ctlr;

	/*
	 * This is assumed to be done early enough that we're
	 * guaranteed to be single-threaded, hence no
	 * locking. Should this change, we should address
	 * this.
	 */
	its_number = find_first_zero_bit(&its_list_map, ITS_LIST_MAX);
	if (its_number >= ITS_LIST_MAX) {
		pr_err("ITS@%pa: No ITSList entry available!\n",
		       &res->start);
		return -EINVAL;
	}

	ctlr = readl_relaxed(its_base + GITS_CTLR);
	ctlr &= ~GITS_CTLR_ITS_NUMBER;
	ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT;
	writel_relaxed(ctlr, its_base + GITS_CTLR);
	ctlr = readl_relaxed(its_base + GITS_CTLR);
	if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) {
		its_number = ctlr & GITS_CTLR_ITS_NUMBER;
		its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT;
	}

	if (test_and_set_bit(its_number, &its_list_map)) {
		pr_err("ITS@%pa: Duplicate ITSList entry %d\n",
		       &res->start, its_number);
		return -EINVAL;
	}

	return its_number;
}

static int __init its_probe_one(struct resource *res,
				struct fwnode_handle *handle, int numa_node)
{
	struct its_node *its;
	void __iomem *its_base;
	u32 val;
	u64 baser, tmp;
	u32 val, ctlr;
	u64 baser, tmp, typer;
	int err;

	its_base = ioremap(res->start, resource_size(res));
@@ -1718,9 +1765,24 @@ static int __init its_probe_one(struct resource *res,
	raw_spin_lock_init(&its->lock);
	INIT_LIST_HEAD(&its->entry);
	INIT_LIST_HEAD(&its->its_device_list);
	typer = gic_read_typer(its_base + GITS_TYPER);
	its->base = its_base;
	its->phys_base = res->start;
	its->ite_size = ((gic_read_typer(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
	its->ite_size = GITS_TYPER_ITT_ENTRY_SIZE(typer);
	its->is_v4 = !!(typer & GITS_TYPER_VLPIS);
	if (its->is_v4) {
		if (!(typer & GITS_TYPER_VMOVP)) {
			err = its_compute_its_list_map(res, its_base);
			if (err < 0)
				goto out_free_its;

			pr_info("ITS@%pa: Using ITS number %d\n",
				&res->start, err);
		} else {
			pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
		}
	}

	its->numa_node = numa_node;

	its->cmd_base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
@@ -1767,7 +1829,8 @@ static int __init its_probe_one(struct resource *res,
	}

	gits_write_cwriter(0, its->base + GITS_CWRITER);
	writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
	ctlr = readl_relaxed(its->base + GITS_CTLR);
	writel_relaxed(ctlr | GITS_CTLR_ENABLE, its->base + GITS_CTLR);

	err = its_init_domain(handle, its);
	if (err)
+5 −0
Original line number Diff line number Diff line
@@ -235,15 +235,20 @@
#define GITS_TRANSLATER			0x10040

#define GITS_CTLR_ENABLE		(1U << 0)
#define	GITS_CTLR_ITS_NUMBER_SHIFT	4
#define	GITS_CTLR_ITS_NUMBER		(0xFU << GITS_CTLR_ITS_NUMBER_SHIFT)
#define GITS_CTLR_QUIESCENT		(1U << 31)

#define GITS_TYPER_PLPIS		(1UL << 0)
#define GITS_TYPER_VLPIS		(1UL << 1)
#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
#define GITS_TYPER_ITT_ENTRY_SIZE(r)	((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
#define GITS_TYPER_IDBITS_SHIFT		8
#define GITS_TYPER_DEVBITS_SHIFT	13
#define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
#define GITS_TYPER_PTA			(1UL << 19)
#define GITS_TYPER_HWCOLLCNT_SHIFT	24
#define GITS_TYPER_VMOVP		(1ULL << 37)

#define GITS_IIDR_REV_SHIFT		12
#define GITS_IIDR_REV_MASK		(0xf << GITS_IIDR_REV_SHIFT)