aboutsummaryrefslogtreecommitdiffstats
path: root/patches.renesas/0252-pinctrl-sh-pfc-Convert-to-platform_get_.patch
blob: 7626a0e37534ea48ff70279bb3d0bd16165ae3fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
From 1941ea8aac7287ea40ab9d1a266fe4e3206a84c9 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Thu, 25 Jun 2015 11:39:53 +0200
Subject: [PATCH 252/326] pinctrl: sh-pfc: Convert to platform_get_*()

If the pin function controller (which can be a GPIO controller) is
instantiated before the interrupt controllers, due to the ordering in
the DTS, the irq domains for the interrupt controllers referenced by its
"interrupts-extended" property cannot be found yet:

    irq: no irq domain found for /interrupt-controller@e61c0000 !

As the sh-pfc driver accesses the platform device's resources directly,
it cannot find the (optional) IRQ resources, and thinks no interrupts
are available. This may lead to failures later, when GPIOs are used as
interupts:

    gpio-keys keyboard: Unable to claim irq 0; error -22
    gpio-keys: probe of keyboard failed with error -22

To fix this, add support for deferred probing to sh-pfc, by converting
the driver from direct platform device resource access to using the
platform_get_resource() and platform_get_irq() helpers.

Note that while this fixes the root cause worked around by commit
e4ba0a9bddff3ba5 ("ARM: shmobile: r8a73a4: Move pfc node to work around
probe ordering bug"), I strongly recommend against reverting the
workaround now, as this would lead to lots of probe deferrals in drivers
relying on pinctrl. This may be reconsidered once the DT code starts
taking into account phandle dependencies during device instantation.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
(cherry picked from commit c7977ec4a33633c8e8d9267dd014356cf857351c)
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 drivers/pinctrl/sh-pfc/core.c | 46 ++++++++++++++++++++-----------------------
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index 865d235612c5..979623895904 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -29,24 +29,25 @@
 static int sh_pfc_map_resources(struct sh_pfc *pfc,
 				struct platform_device *pdev)
 {
-	unsigned int num_windows = 0;
-	unsigned int num_irqs = 0;
+	unsigned int num_windows, num_irqs;
 	struct sh_pfc_window *windows;
 	unsigned int *irqs = NULL;
 	struct resource *res;
 	unsigned int i;
+	int irq;
 
 	/* Count the MEM and IRQ resources. */
-	for (i = 0; i < pdev->num_resources; ++i) {
-		switch (resource_type(&pdev->resource[i])) {
-		case IORESOURCE_MEM:
-			num_windows++;
+	for (num_windows = 0;; num_windows++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, num_windows);
+		if (!res)
 			break;
-
-		case IORESOURCE_IRQ:
-			num_irqs++;
+	}
+	for (num_irqs = 0;; num_irqs++) {
+		irq = platform_get_irq(pdev, num_irqs);
+		if (irq == -EPROBE_DEFER)
+			return irq;
+		if (irq < 0)
 			break;
-		}
 	}
 
 	if (num_windows == 0)
@@ -72,22 +73,17 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc,
 	}
 
 	/* Fill them. */
-	for (i = 0, res = pdev->resource; i < pdev->num_resources; i++, res++) {
-		switch (resource_type(res)) {
-		case IORESOURCE_MEM:
-			windows->phys = res->start;
-			windows->size = resource_size(res);
-			windows->virt = devm_ioremap_resource(pfc->dev, res);
-			if (IS_ERR(windows->virt))
-				return -ENOMEM;
-			windows++;
-			break;
-
-		case IORESOURCE_IRQ:
-			*irqs++ = res->start;
-			break;
-		}
+	for (i = 0; i < num_windows; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		windows->phys = res->start;
+		windows->size = resource_size(res);
+		windows->virt = devm_ioremap_resource(pfc->dev, res);
+		if (IS_ERR(windows->virt))
+			return -ENOMEM;
+		windows++;
 	}
+	for (i = 0; i < num_irqs; i++)
+		*irqs++ = platform_get_irq(pdev, i);
 
 	return 0;
 }
-- 
2.6.2