diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2013-05-21 07:40:06 -0400 |
---|---|---|
committer | Simon Horman <horms+renesas@verge.net.au> | 2013-06-12 08:48:09 -0400 |
commit | 159f8a0209aff155af7f6fcdedd4a4484dd19c23 (patch) | |
tree | 2c3081a053077cceffb1c1651b977846043d1e5f | |
parent | 5fcf4a3c3a5bc08bf72a50ef1332501a3c1b96bb (diff) |
gpio-rcar: Add DT support
Add DT bindings for the gpio-rcar driver and read the device
configuration from the DT node at probe time if available.
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-rw-r--r-- | Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt | 52 | ||||
-rw-r--r-- | drivers/gpio/gpio-rcar.c | 66 |
2 files changed, 108 insertions, 10 deletions
diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt new file mode 100644 index 000000000000..46d76a004246 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt | |||
@@ -0,0 +1,52 @@ | |||
1 | * Renesas R-Car GPIO Controller | ||
2 | |||
3 | Required Properties: | ||
4 | |||
5 | - compatible: should be one of the following. | ||
6 | - "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller. | ||
7 | - "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller. | ||
8 | - "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller. | ||
9 | - "renesas,gpio-rcar": for generic R-Car GPIO controller. | ||
10 | |||
11 | - reg: Base address and length of each memory resource used by the GPIO | ||
12 | controller hardware module. | ||
13 | |||
14 | - interrupt-parent: phandle of the parent interrupt controller. | ||
15 | - interrupts: Interrupt specifier for the controllers interrupt. | ||
16 | |||
17 | - gpio-controller: Marks the device node as a gpio controller. | ||
18 | - #gpio-cells: Should be 2. The first cell is the GPIO number and the second | ||
19 | cell is used to specify optional parameters as bit flags. Only the GPIO | ||
20 | active low flag (bit 0) is currently supported. | ||
21 | - gpio-ranges: Range of pins managed by the GPIO controller as a 4-cells | ||
22 | tuple using the following syntax. | ||
23 | |||
24 | <[phandle of the pin controller node] | ||
25 | 0 | ||
26 | [index of the first pin] | ||
27 | [number of pins]> | ||
28 | |||
29 | Please refer to gpio.txt in this directory for details of the common GPIO | ||
30 | bindings used by client devices. | ||
31 | |||
32 | Example: R8A7779 (R-Car H1) GPIO controller nodes | ||
33 | |||
34 | gpio0: gpio@ffc40000 { | ||
35 | compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar"; | ||
36 | reg = <0xffc40000 0x2c>; | ||
37 | interrupt-parent = <&gic>; | ||
38 | interrupts = <0 141 0x4>; | ||
39 | #gpio-cells = <2>; | ||
40 | gpio-controller; | ||
41 | gpio-ranges = <&pfc 0 0 32>; | ||
42 | }; | ||
43 | ... | ||
44 | gpio6: gpio@ffc46000 { | ||
45 | compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar"; | ||
46 | reg = <0xffc46000 0x2c>; | ||
47 | interrupt-parent = <&gic>; | ||
48 | interrupts = <0 147 0x4>; | ||
49 | #gpio-cells = <2>; | ||
50 | gpio-controller; | ||
51 | gpio-ranges = <&pfc 0 192 9>; | ||
52 | }; | ||
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d173d56dbb8c..5a693dd0ac7a 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c | |||
@@ -51,6 +51,8 @@ struct gpio_rcar_priv { | |||
51 | #define FILONOFF 0x28 | 51 | #define FILONOFF 0x28 |
52 | #define BOTHEDGE 0x4c | 52 | #define BOTHEDGE 0x4c |
53 | 53 | ||
54 | #define RCAR_MAX_GPIO_PER_BANK 32 | ||
55 | |||
54 | static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs) | 56 | static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs) |
55 | { | 57 | { |
56 | return ioread32(p->base + offs); | 58 | return ioread32(p->base + offs); |
@@ -274,9 +276,39 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = { | |||
274 | .map = gpio_rcar_irq_domain_map, | 276 | .map = gpio_rcar_irq_domain_map, |
275 | }; | 277 | }; |
276 | 278 | ||
279 | static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) | ||
280 | { | ||
281 | struct gpio_rcar_config *pdata = p->pdev->dev.platform_data; | ||
282 | #ifdef CONFIG_OF | ||
283 | struct device_node *np = p->pdev->dev.of_node; | ||
284 | struct of_phandle_args args; | ||
285 | int ret; | ||
286 | #endif | ||
287 | |||
288 | if (pdata) | ||
289 | p->config = *pdata; | ||
290 | #ifdef CONFIG_OF | ||
291 | else if (np) { | ||
292 | ret = of_parse_phandle_with_args(np, "gpio-ranges", | ||
293 | "#gpio-range-cells", 0, &args); | ||
294 | p->config.number_of_pins = ret == 0 && args.args_count == 3 | ||
295 | ? args.args[2] | ||
296 | : RCAR_MAX_GPIO_PER_BANK; | ||
297 | p->config.gpio_base = -1; | ||
298 | } | ||
299 | #endif | ||
300 | |||
301 | if (p->config.number_of_pins == 0 || | ||
302 | p->config.number_of_pins > RCAR_MAX_GPIO_PER_BANK) { | ||
303 | dev_warn(&p->pdev->dev, | ||
304 | "Invalid number of gpio lines %u, using %u\n", | ||
305 | p->config.number_of_pins, RCAR_MAX_GPIO_PER_BANK); | ||
306 | p->config.number_of_pins = RCAR_MAX_GPIO_PER_BANK; | ||
307 | } | ||
308 | } | ||
309 | |||
277 | static int gpio_rcar_probe(struct platform_device *pdev) | 310 | static int gpio_rcar_probe(struct platform_device *pdev) |
278 | { | 311 | { |
279 | struct gpio_rcar_config *pdata = pdev->dev.platform_data; | ||
280 | struct gpio_rcar_priv *p; | 312 | struct gpio_rcar_priv *p; |
281 | struct resource *io, *irq; | 313 | struct resource *io, *irq; |
282 | struct gpio_chip *gpio_chip; | 314 | struct gpio_chip *gpio_chip; |
@@ -291,14 +323,14 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
291 | goto err0; | 323 | goto err0; |
292 | } | 324 | } |
293 | 325 | ||
294 | /* deal with driver instance configuration */ | ||
295 | if (pdata) | ||
296 | p->config = *pdata; | ||
297 | |||
298 | p->pdev = pdev; | 326 | p->pdev = pdev; |
299 | platform_set_drvdata(pdev, p); | ||
300 | spin_lock_init(&p->lock); | 327 | spin_lock_init(&p->lock); |
301 | 328 | ||
329 | /* Get device configuration from DT node or platform data. */ | ||
330 | gpio_rcar_parse_pdata(p); | ||
331 | |||
332 | platform_set_drvdata(pdev, p); | ||
333 | |||
302 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 334 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
303 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 335 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
304 | 336 | ||
@@ -325,6 +357,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
325 | gpio_chip->set = gpio_rcar_set; | 357 | gpio_chip->set = gpio_rcar_set; |
326 | gpio_chip->to_irq = gpio_rcar_to_irq; | 358 | gpio_chip->to_irq = gpio_rcar_to_irq; |
327 | gpio_chip->label = name; | 359 | gpio_chip->label = name; |
360 | gpio_chip->dev = &pdev->dev; | ||
328 | gpio_chip->owner = THIS_MODULE; | 361 | gpio_chip->owner = THIS_MODULE; |
329 | gpio_chip->base = p->config.gpio_base; | 362 | gpio_chip->base = p->config.gpio_base; |
330 | gpio_chip->ngpio = p->config.number_of_pins; | 363 | gpio_chip->ngpio = p->config.number_of_pins; |
@@ -371,10 +404,12 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
371 | p->config.irq_base, ret); | 404 | p->config.irq_base, ret); |
372 | } | 405 | } |
373 | 406 | ||
374 | ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0, | 407 | if (p->config.pctl_name) { |
375 | gpio_chip->base, gpio_chip->ngpio); | 408 | ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0, |
376 | if (ret < 0) | 409 | gpio_chip->base, gpio_chip->ngpio); |
377 | dev_warn(&pdev->dev, "failed to add pin range\n"); | 410 | if (ret < 0) |
411 | dev_warn(&pdev->dev, "failed to add pin range\n"); | ||
412 | } | ||
378 | 413 | ||
379 | return 0; | 414 | return 0; |
380 | 415 | ||
@@ -397,11 +432,22 @@ static int gpio_rcar_remove(struct platform_device *pdev) | |||
397 | return 0; | 432 | return 0; |
398 | } | 433 | } |
399 | 434 | ||
435 | #ifdef CONFIG_OF | ||
436 | static const struct of_device_id gpio_rcar_of_table[] = { | ||
437 | { | ||
438 | .compatible = "renesas,gpio-rcar", | ||
439 | }, | ||
440 | }; | ||
441 | |||
442 | MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); | ||
443 | #endif | ||
444 | |||
400 | static struct platform_driver gpio_rcar_device_driver = { | 445 | static struct platform_driver gpio_rcar_device_driver = { |
401 | .probe = gpio_rcar_probe, | 446 | .probe = gpio_rcar_probe, |
402 | .remove = gpio_rcar_remove, | 447 | .remove = gpio_rcar_remove, |
403 | .driver = { | 448 | .driver = { |
404 | .name = "gpio_rcar", | 449 | .name = "gpio_rcar", |
450 | .of_match_table = of_match_ptr(gpio_rcar_of_table), | ||
405 | } | 451 | } |
406 | }; | 452 | }; |
407 | 453 | ||