aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-12-10 22:26:26 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-12-12 16:07:28 -0500
commit70c8f01a357ac74d223a632659787396fef1e649 (patch)
treeaff7db7fdcc8bdb3fe74f6313c2b8701cfdc9d0b
parent5b46ac3a7723636082ec6234289517ca5b9c65af (diff)
sh-pfc: Support GPIO to IRQ mapping specified IRQ resources
On non-DT platforms IRQ controllers associated with the GPIOs have a fixed IRQ base value known at compile time. The sh-pfc driver translates GPIO number to IRQ numbers using a hardcoded table. This mechanism breaks on DT platforms, as the IRQ base values are dynamic in that case. Fix this by specifying IRQs associated with GPIOs in IRQ resources, populated automatically from the device tree. When IRQ resources are specified the driver requires one IRQ resource per GPIO able to generate an interrupt, and uses the translation table to compute the IRQ resource offset instead of the IRQ number. Cc: devicetree@vger.kernel.org Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Acked-by: Magnus Damm <damm@opensource.se> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt14
-rw-r--r--drivers/pinctrl/sh-pfc/core.c69
-rw-r--r--drivers/pinctrl/sh-pfc/core.h2
-rw-r--r--drivers/pinctrl/sh-pfc/gpio.c14
4 files changed, 82 insertions, 17 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
index d5dac7b843a9..35d2e1f186f0 100644
--- a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
@@ -26,6 +26,11 @@ Optional properties:
26 - #gpio-range-cells: Mandatory when the PFC doesn't handle GPIO, forbidden 26 - #gpio-range-cells: Mandatory when the PFC doesn't handle GPIO, forbidden
27 otherwise. Should be 3. 27 otherwise. Should be 3.
28 28
29 - interrupts-extended: Specify the interrupts associated with external
30 IRQ pins. This property is mandatory when the PFC handles GPIOs and
31 forbidden otherwise. When specified, it must contain one interrupt per
32 external IRQ, sorted by external IRQ number.
33
29The PFC node also acts as a container for pin configuration nodes. Please refer 34The PFC node also acts as a container for pin configuration nodes. Please refer
30to pinctrl-bindings.txt in this directory for the definition of the term "pin 35to pinctrl-bindings.txt in this directory for the definition of the term "pin
31configuration node" and for the common pinctrl bindings used by client devices. 36configuration node" and for the common pinctrl bindings used by client devices.
@@ -103,6 +108,15 @@ Example 1: SH73A0 (SH-Mobile AG5) pin controller node
103 <0xe605801c 0x1c>; 108 <0xe605801c 0x1c>;
104 gpio-controller; 109 gpio-controller;
105 #gpio-cells = <2>; 110 #gpio-cells = <2>;
111 interrupts-extended =
112 <&irqpin0 0 0>, <&irqpin0 1 0>, <&irqpin0 2 0>, <&irqpin0 3 0>,
113 <&irqpin0 4 0>, <&irqpin0 5 0>, <&irqpin0 6 0>, <&irqpin0 7 0>,
114 <&irqpin1 0 0>, <&irqpin1 1 0>, <&irqpin1 2 0>, <&irqpin1 3 0>,
115 <&irqpin1 4 0>, <&irqpin1 5 0>, <&irqpin1 6 0>, <&irqpin1 7 0>,
116 <&irqpin2 0 0>, <&irqpin2 1 0>, <&irqpin2 2 0>, <&irqpin2 3 0>,
117 <&irqpin2 4 0>, <&irqpin2 5 0>, <&irqpin2 6 0>, <&irqpin2 7 0>,
118 <&irqpin3 0 0>, <&irqpin3 1 0>, <&irqpin3 2 0>, <&irqpin3 3 0>,
119 <&irqpin3 4 0>, <&irqpin3 5 0>, <&irqpin3 6 0>, <&irqpin3 7 0>;
106 }; 120 };
107 121
108Example 2: A GPIO LED node that references a GPIO 122Example 2: A GPIO LED node that references a GPIO
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index 7831f078a5ef..b9b464d0578c 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -26,30 +26,67 @@
26 26
27#include "core.h" 27#include "core.h"
28 28
29static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev) 29static int sh_pfc_map_resources(struct sh_pfc *pfc,
30 struct platform_device *pdev)
30{ 31{
32 unsigned int num_windows = 0;
33 unsigned int num_irqs = 0;
34 struct sh_pfc_window *windows;
35 unsigned int *irqs = NULL;
31 struct resource *res; 36 struct resource *res;
32 unsigned int k; 37 unsigned int i;
38
39 /* Count the MEM and IRQ resources. */
40 for (i = 0; i < pdev->num_resources; ++i) {
41 switch (resource_type(&pdev->resource[i])) {
42 case IORESOURCE_MEM:
43 num_windows++;
44 break;
45
46 case IORESOURCE_IRQ:
47 num_irqs++;
48 break;
49 }
50 }
33 51
34 if (pdev->num_resources == 0) 52 if (num_windows == 0)
35 return -EINVAL; 53 return -EINVAL;
36 54
37 pfc->windows = devm_kzalloc(pfc->dev, pdev->num_resources * 55 /* Allocate memory windows and IRQs arrays. */
38 sizeof(*pfc->windows), GFP_NOWAIT); 56 windows = devm_kzalloc(pfc->dev, num_windows * sizeof(*windows),
39 if (!pfc->windows) 57 GFP_KERNEL);
58 if (windows == NULL)
40 return -ENOMEM; 59 return -ENOMEM;
41 60
42 pfc->num_windows = pdev->num_resources; 61 pfc->num_windows = num_windows;
62 pfc->windows = windows;
43 63
44 for (k = 0, res = pdev->resource; k < pdev->num_resources; k++, res++) { 64 if (num_irqs) {
45 WARN_ON(resource_type(res) != IORESOURCE_MEM); 65 irqs = devm_kzalloc(pfc->dev, num_irqs * sizeof(*irqs),
46 pfc->windows[k].phys = res->start; 66 GFP_KERNEL);
47 pfc->windows[k].size = resource_size(res); 67 if (irqs == NULL)
48 pfc->windows[k].virt =
49 devm_ioremap_nocache(pfc->dev, res->start,
50 resource_size(res));
51 if (!pfc->windows[k].virt)
52 return -ENOMEM; 68 return -ENOMEM;
69
70 pfc->num_irqs = num_irqs;
71 pfc->irqs = irqs;
72 }
73
74 /* Fill them. */
75 for (i = 0, res = pdev->resource; i < pdev->num_resources; i++, res++) {
76 switch (resource_type(res)) {
77 case IORESOURCE_MEM:
78 windows->phys = res->start;
79 windows->size = resource_size(res);
80 windows->virt = devm_ioremap_resource(pfc->dev, res);
81 if (IS_ERR(windows->virt))
82 return -ENOMEM;
83 windows++;
84 break;
85
86 case IORESOURCE_IRQ:
87 *irqs++ = res->start;
88 break;
89 }
53 } 90 }
54 91
55 return 0; 92 return 0;
@@ -482,7 +519,7 @@ static int sh_pfc_probe(struct platform_device *pdev)
482 pfc->info = info; 519 pfc->info = info;
483 pfc->dev = &pdev->dev; 520 pfc->dev = &pdev->dev;
484 521
485 ret = sh_pfc_ioremap(pfc, pdev); 522 ret = sh_pfc_map_resources(pfc, pdev);
486 if (unlikely(ret < 0)) 523 if (unlikely(ret < 0))
487 return ret; 524 return ret;
488 525
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
index a83b7472e674..b7b0e6ccf305 100644
--- a/drivers/pinctrl/sh-pfc/core.h
+++ b/drivers/pinctrl/sh-pfc/core.h
@@ -38,6 +38,8 @@ struct sh_pfc {
38 38
39 unsigned int num_windows; 39 unsigned int num_windows;
40 struct sh_pfc_window *windows; 40 struct sh_pfc_window *windows;
41 unsigned int num_irqs;
42 unsigned int *irqs;
41 43
42 struct sh_pfc_pin_range *ranges; 44 struct sh_pfc_pin_range *ranges;
43 unsigned int nr_ranges; 45 unsigned int nr_ranges;
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c
index 6a21349fb116..63480815e1af 100644
--- a/drivers/pinctrl/sh-pfc/gpio.c
+++ b/drivers/pinctrl/sh-pfc/gpio.c
@@ -211,11 +211,17 @@ static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset)
211 211
212 for (k = 0; gpios[k] >= 0; k++) { 212 for (k = 0; gpios[k] >= 0; k++) {
213 if (gpios[k] == offset) 213 if (gpios[k] == offset)
214 return pfc->info->gpio_irq[i].irq; 214 goto found;
215 } 215 }
216 } 216 }
217 217
218 return -ENOSYS; 218 return -ENOSYS;
219
220found:
221 if (pfc->num_irqs)
222 return pfc->irqs[i];
223 else
224 return pfc->info->gpio_irq[i].irq;
219} 225}
220 226
221static int gpio_pin_setup(struct sh_pfc_chip *chip) 227static int gpio_pin_setup(struct sh_pfc_chip *chip)
@@ -357,6 +363,12 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
357 if (i == pfc->num_windows) 363 if (i == pfc->num_windows)
358 return 0; 364 return 0;
359 365
366 /* If we have IRQ resources make sure their number is correct. */
367 if (pfc->num_irqs && pfc->num_irqs != pfc->info->gpio_irq_size) {
368 dev_err(pfc->dev, "invalid number of IRQ resources\n");
369 return -EINVAL;
370 }
371
360 /* Register the real GPIOs chip. */ 372 /* Register the real GPIOs chip. */
361 chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]); 373 chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]);
362 if (IS_ERR(chip)) 374 if (IS_ERR(chip))