aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYun Wu <wuyun.wu@huawei.com>2015-03-06 11:37:50 -0500
committerJason Cooper <jason@lakedaemon.net>2015-03-08 00:34:58 -0500
commit4559fbb3a9b1bde46afc739fa6c300826acdc19c (patch)
treeb2d257b5b9de9e1f5c70bfa76566aeff5ce2320b
parent7cb991164a46992a499ecdc77b17f8ac94bdb75f (diff)
irqchip: gicv3-its: Support safe initialization
It's unsafe to change the configurations of an activated ITS directly since this will lead to unpredictable results. This patch guarantees the ITSes being initialized are quiescent. Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Yun Wu <wuyun.wu@huawei.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Link: https://lkml.kernel.org/r/1425659870-11832-12-git-send-email-marc.zyngier@arm.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 826da706be4b..596b0a9eee99 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1320,6 +1320,34 @@ static const struct irq_domain_ops its_domain_ops = {
1320 .deactivate = its_irq_domain_deactivate, 1320 .deactivate = its_irq_domain_deactivate,
1321}; 1321};
1322 1322
1323static int its_force_quiescent(void __iomem *base)
1324{
1325 u32 count = 1000000; /* 1s */
1326 u32 val;
1327
1328 val = readl_relaxed(base + GITS_CTLR);
1329 if (val & GITS_CTLR_QUIESCENT)
1330 return 0;
1331
1332 /* Disable the generation of all interrupts to this ITS */
1333 val &= ~GITS_CTLR_ENABLE;
1334 writel_relaxed(val, base + GITS_CTLR);
1335
1336 /* Poll GITS_CTLR and wait until ITS becomes quiescent */
1337 while (1) {
1338 val = readl_relaxed(base + GITS_CTLR);
1339 if (val & GITS_CTLR_QUIESCENT)
1340 return 0;
1341
1342 count--;
1343 if (!count)
1344 return -EBUSY;
1345
1346 cpu_relax();
1347 udelay(1);
1348 }
1349}
1350
1323static int its_probe(struct device_node *node, struct irq_domain *parent) 1351static int its_probe(struct device_node *node, struct irq_domain *parent)
1324{ 1352{
1325 struct resource res; 1353 struct resource res;
@@ -1348,6 +1376,13 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
1348 goto out_unmap; 1376 goto out_unmap;
1349 } 1377 }
1350 1378
1379 err = its_force_quiescent(its_base);
1380 if (err) {
1381 pr_warn("%s: failed to quiesce, giving up\n",
1382 node->full_name);
1383 goto out_unmap;
1384 }
1385
1351 pr_info("ITS: %s\n", node->full_name); 1386 pr_info("ITS: %s\n", node->full_name);
1352 1387
1353 its = kzalloc(sizeof(*its), GFP_KERNEL); 1388 its = kzalloc(sizeof(*its), GFP_KERNEL);