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 /drivers/gpio | |
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>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-rcar.c | 66 |
1 files changed, 56 insertions, 10 deletions
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 | ||