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

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
...@@ -101,6 +101,7 @@ struct its_node { ...@@ -101,6 +101,7 @@ struct its_node {
u32 ite_size; u32 ite_size;
u32 device_ids; u32 device_ids;
int numa_node; int numa_node;
bool is_v4;
}; };
#define ITS_ITT_ALIGN SZ_256 #define ITS_ITT_ALIGN SZ_256
...@@ -133,6 +134,14 @@ static DEFINE_SPINLOCK(its_lock); ...@@ -133,6 +134,14 @@ static DEFINE_SPINLOCK(its_lock);
static struct rdists *gic_rdists; static struct rdists *gic_rdists;
static struct irq_domain *its_parent; 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() (raw_cpu_ptr(gic_rdists->rdist))
#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) #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) ...@@ -1679,13 +1688,51 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
return 0; 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, static int __init its_probe_one(struct resource *res,
struct fwnode_handle *handle, int numa_node) struct fwnode_handle *handle, int numa_node)
{ {
struct its_node *its; struct its_node *its;
void __iomem *its_base; void __iomem *its_base;
u32 val; u32 val, ctlr;
u64 baser, tmp; u64 baser, tmp, typer;
int err; int err;
its_base = ioremap(res->start, resource_size(res)); its_base = ioremap(res->start, resource_size(res));
...@@ -1718,9 +1765,24 @@ static int __init its_probe_one(struct resource *res, ...@@ -1718,9 +1765,24 @@ static int __init its_probe_one(struct resource *res,
raw_spin_lock_init(&its->lock); raw_spin_lock_init(&its->lock);
INIT_LIST_HEAD(&its->entry); INIT_LIST_HEAD(&its->entry);
INIT_LIST_HEAD(&its->its_device_list); INIT_LIST_HEAD(&its->its_device_list);
typer = gic_read_typer(its_base + GITS_TYPER);
its->base = its_base; its->base = its_base;
its->phys_base = res->start; 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->numa_node = numa_node;
its->cmd_base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, its->cmd_base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
...@@ -1767,7 +1829,8 @@ static int __init its_probe_one(struct resource *res, ...@@ -1767,7 +1829,8 @@ static int __init its_probe_one(struct resource *res,
} }
gits_write_cwriter(0, its->base + GITS_CWRITER); 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); err = its_init_domain(handle, its);
if (err) if (err)
......
...@@ -235,15 +235,20 @@ ...@@ -235,15 +235,20 @@
#define GITS_TRANSLATER 0x10040 #define GITS_TRANSLATER 0x10040
#define GITS_CTLR_ENABLE (1U << 0) #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_CTLR_QUIESCENT (1U << 31)
#define GITS_TYPER_PLPIS (1UL << 0) #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_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_IDBITS_SHIFT 8
#define GITS_TYPER_DEVBITS_SHIFT 13 #define GITS_TYPER_DEVBITS_SHIFT 13
#define GITS_TYPER_DEVBITS(r) ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1) #define GITS_TYPER_DEVBITS(r) ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
#define GITS_TYPER_PTA (1UL << 19) #define GITS_TYPER_PTA (1UL << 19)
#define GITS_TYPER_HWCOLLCNT_SHIFT 24 #define GITS_TYPER_HWCOLLCNT_SHIFT 24
#define GITS_TYPER_VMOVP (1ULL << 37)
#define GITS_IIDR_REV_SHIFT 12 #define GITS_IIDR_REV_SHIFT 12
#define GITS_IIDR_REV_MASK (0xf << GITS_IIDR_REV_SHIFT) #define GITS_IIDR_REV_MASK (0xf << GITS_IIDR_REV_SHIFT)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment