mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 16:29:05 +00:00
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: Eric Auger <eric.auger@redhat.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
a13b040408
commit
3dfa576bfb
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user