|
@@ -75,7 +75,7 @@ struct its_node {
|
|
|
raw_spinlock_t lock;
|
|
|
struct list_head entry;
|
|
|
void __iomem *base;
|
|
|
- unsigned long phys_base;
|
|
|
+ phys_addr_t phys_base;
|
|
|
struct its_cmd_block *cmd_base;
|
|
|
struct its_cmd_block *cmd_write;
|
|
|
struct its_baser tables[GITS_BASER_NR_REGS];
|
|
@@ -115,6 +115,7 @@ struct its_device {
|
|
|
static LIST_HEAD(its_nodes);
|
|
|
static DEFINE_SPINLOCK(its_lock);
|
|
|
static struct rdists *gic_rdists;
|
|
|
+static struct irq_domain *its_parent;
|
|
|
|
|
|
#define gic_data_rdist() (raw_cpu_ptr(gic_rdists->rdist))
|
|
|
#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
|
|
@@ -1614,8 +1615,7 @@ static void its_enable_quirks(struct its_node *its)
|
|
|
gic_enable_quirks(iidr, its_quirks, its);
|
|
|
}
|
|
|
|
|
|
-static int its_init_domain(struct device_node *node, struct its_node *its,
|
|
|
- struct irq_domain *parent)
|
|
|
+static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
|
|
|
{
|
|
|
struct irq_domain *inner_domain;
|
|
|
struct msi_domain_info *info;
|
|
@@ -1624,13 +1624,13 @@ static int its_init_domain(struct device_node *node, struct its_node *its,
|
|
|
if (!info)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- inner_domain = irq_domain_add_tree(node, &its_domain_ops, its);
|
|
|
+ inner_domain = irq_domain_create_tree(handle, &its_domain_ops, its);
|
|
|
if (!inner_domain) {
|
|
|
kfree(info);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- inner_domain->parent = parent;
|
|
|
+ inner_domain->parent = its_parent;
|
|
|
inner_domain->bus_token = DOMAIN_BUS_NEXUS;
|
|
|
info->ops = &its_msi_domain_ops;
|
|
|
info->data = its;
|
|
@@ -1639,43 +1639,35 @@ static int its_init_domain(struct device_node *node, struct its_node *its,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int __init its_probe(struct device_node *node,
|
|
|
- struct irq_domain *parent)
|
|
|
+static int __init its_probe_one(struct resource *res,
|
|
|
+ struct fwnode_handle *handle, int numa_node)
|
|
|
{
|
|
|
- struct resource res;
|
|
|
struct its_node *its;
|
|
|
void __iomem *its_base;
|
|
|
u32 val;
|
|
|
u64 baser, tmp;
|
|
|
int err;
|
|
|
|
|
|
- err = of_address_to_resource(node, 0, &res);
|
|
|
- if (err) {
|
|
|
- pr_warn("%s: no regs?\n", node->full_name);
|
|
|
- return -ENXIO;
|
|
|
- }
|
|
|
-
|
|
|
- its_base = ioremap(res.start, resource_size(&res));
|
|
|
+ its_base = ioremap(res->start, resource_size(res));
|
|
|
if (!its_base) {
|
|
|
- pr_warn("%s: unable to map registers\n", node->full_name);
|
|
|
+ pr_warn("ITS@%pa: Unable to map ITS registers\n", &res->start);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
val = readl_relaxed(its_base + GITS_PIDR2) & GIC_PIDR2_ARCH_MASK;
|
|
|
if (val != 0x30 && val != 0x40) {
|
|
|
- pr_warn("%s: no ITS detected, giving up\n", node->full_name);
|
|
|
+ pr_warn("ITS@%pa: No ITS detected, giving up\n", &res->start);
|
|
|
err = -ENODEV;
|
|
|
goto out_unmap;
|
|
|
}
|
|
|
|
|
|
err = its_force_quiescent(its_base);
|
|
|
if (err) {
|
|
|
- pr_warn("%s: failed to quiesce, giving up\n",
|
|
|
- node->full_name);
|
|
|
+ pr_warn("ITS@%pa: Failed to quiesce, giving up\n", &res->start);
|
|
|
goto out_unmap;
|
|
|
}
|
|
|
|
|
|
- pr_info("ITS: %s\n", node->full_name);
|
|
|
+ pr_info("ITS %pR\n", res);
|
|
|
|
|
|
its = kzalloc(sizeof(*its), GFP_KERNEL);
|
|
|
if (!its) {
|
|
@@ -1687,9 +1679,9 @@ static int __init its_probe(struct device_node *node,
|
|
|
INIT_LIST_HEAD(&its->entry);
|
|
|
INIT_LIST_HEAD(&its->its_device_list);
|
|
|
its->base = its_base;
|
|
|
- its->phys_base = res.start;
|
|
|
+ its->phys_base = res->start;
|
|
|
its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
|
|
|
- its->numa_node = of_node_to_nid(node);
|
|
|
+ its->numa_node = numa_node;
|
|
|
|
|
|
its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
|
|
|
if (!its->cmd_base) {
|
|
@@ -1736,7 +1728,7 @@ static int __init its_probe(struct device_node *node,
|
|
|
writeq_relaxed(0, its->base + GITS_CWRITER);
|
|
|
writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
|
|
|
|
|
|
- err = its_init_domain(node, its, parent);
|
|
|
+ err = its_init_domain(handle, its);
|
|
|
if (err)
|
|
|
goto out_free_tables;
|
|
|
|
|
@@ -1754,7 +1746,7 @@ out_free_its:
|
|
|
kfree(its);
|
|
|
out_unmap:
|
|
|
iounmap(its_base);
|
|
|
- pr_err("ITS: failed probing %s (%d)\n", node->full_name, err);
|
|
|
+ pr_err("ITS@%pa: failed probing (%d)\n", &res->start, err);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1782,10 +1774,10 @@ static struct of_device_id its_device_id[] = {
|
|
|
{},
|
|
|
};
|
|
|
|
|
|
-int __init its_init(struct device_node *node, struct rdists *rdists,
|
|
|
- struct irq_domain *parent_domain)
|
|
|
+static int __init its_of_probe(struct device_node *node)
|
|
|
{
|
|
|
struct device_node *np;
|
|
|
+ struct resource res;
|
|
|
|
|
|
for (np = of_find_matching_node(node, its_device_id); np;
|
|
|
np = of_find_matching_node(np, its_device_id)) {
|
|
@@ -1795,8 +1787,27 @@ int __init its_init(struct device_node *node, struct rdists *rdists,
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- its_probe(np, parent_domain);
|
|
|
+ if (of_address_to_resource(np, 0, &res)) {
|
|
|
+ pr_warn("%s: no regs?\n", np->full_name);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ its_probe_one(&res, &np->fwnode, of_node_to_nid(np));
|
|
|
}
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
|
|
|
+ struct irq_domain *parent_domain)
|
|
|
+{
|
|
|
+ struct device_node *of_node;
|
|
|
+
|
|
|
+ its_parent = parent_domain;
|
|
|
+ of_node = to_of_node(handle);
|
|
|
+ if (of_node)
|
|
|
+ its_of_probe(of_node);
|
|
|
+ else
|
|
|
+ return -ENODEV;
|
|
|
|
|
|
if (list_empty(&its_nodes)) {
|
|
|
pr_warn("ITS: No ITS available, not enabling LPIs\n");
|