Skip to content

Commit

Permalink
gpio-rcar: Add DT support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Laurent Pinchart authored and Simon Horman committed Jun 12, 2013
1 parent 5fcf4a3 commit 159f8a0
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 10 deletions.
52 changes: 52 additions & 0 deletions Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
* Renesas R-Car GPIO Controller

Required Properties:

- compatible: should be one of the following.
- "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller.
- "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller.
- "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller.
- "renesas,gpio-rcar": for generic R-Car GPIO controller.

- reg: Base address and length of each memory resource used by the GPIO
controller hardware module.

- interrupt-parent: phandle of the parent interrupt controller.
- interrupts: Interrupt specifier for the controllers interrupt.

- gpio-controller: Marks the device node as a gpio controller.
- #gpio-cells: Should be 2. The first cell is the GPIO number and the second
cell is used to specify optional parameters as bit flags. Only the GPIO
active low flag (bit 0) is currently supported.
- gpio-ranges: Range of pins managed by the GPIO controller as a 4-cells
tuple using the following syntax.

<[phandle of the pin controller node]
0
[index of the first pin]
[number of pins]>

Please refer to gpio.txt in this directory for details of the common GPIO
bindings used by client devices.

Example: R8A7779 (R-Car H1) GPIO controller nodes

gpio0: gpio@ffc40000 {
compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
reg = <0xffc40000 0x2c>;
interrupt-parent = <&gic>;
interrupts = <0 141 0x4>;
#gpio-cells = <2>;
gpio-controller;
gpio-ranges = <&pfc 0 0 32>;
};
...
gpio6: gpio@ffc46000 {
compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
reg = <0xffc46000 0x2c>;
interrupt-parent = <&gic>;
interrupts = <0 147 0x4>;
#gpio-cells = <2>;
gpio-controller;
gpio-ranges = <&pfc 0 192 9>;
};
66 changes: 56 additions & 10 deletions drivers/gpio/gpio-rcar.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct gpio_rcar_priv {
#define FILONOFF 0x28
#define BOTHEDGE 0x4c

#define RCAR_MAX_GPIO_PER_BANK 32

static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs)
{
return ioread32(p->base + offs);
Expand Down Expand Up @@ -274,9 +276,39 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = {
.map = gpio_rcar_irq_domain_map,
};

static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)
{
struct gpio_rcar_config *pdata = p->pdev->dev.platform_data;
#ifdef CONFIG_OF
struct device_node *np = p->pdev->dev.of_node;
struct of_phandle_args args;
int ret;
#endif

if (pdata)
p->config = *pdata;
#ifdef CONFIG_OF
else if (np) {
ret = of_parse_phandle_with_args(np, "gpio-ranges",
"#gpio-range-cells", 0, &args);
p->config.number_of_pins = ret == 0 && args.args_count == 3
? args.args[2]
: RCAR_MAX_GPIO_PER_BANK;
p->config.gpio_base = -1;
}
#endif

if (p->config.number_of_pins == 0 ||
p->config.number_of_pins > RCAR_MAX_GPIO_PER_BANK) {
dev_warn(&p->pdev->dev,
"Invalid number of gpio lines %u, using %u\n",
p->config.number_of_pins, RCAR_MAX_GPIO_PER_BANK);
p->config.number_of_pins = RCAR_MAX_GPIO_PER_BANK;
}
}

static int gpio_rcar_probe(struct platform_device *pdev)
{
struct gpio_rcar_config *pdata = pdev->dev.platform_data;
struct gpio_rcar_priv *p;
struct resource *io, *irq;
struct gpio_chip *gpio_chip;
Expand All @@ -291,14 +323,14 @@ static int gpio_rcar_probe(struct platform_device *pdev)
goto err0;
}

/* deal with driver instance configuration */
if (pdata)
p->config = *pdata;

p->pdev = pdev;
platform_set_drvdata(pdev, p);
spin_lock_init(&p->lock);

/* Get device configuration from DT node or platform data. */
gpio_rcar_parse_pdata(p);

platform_set_drvdata(pdev, p);

io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

Expand All @@ -325,6 +357,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
gpio_chip->set = gpio_rcar_set;
gpio_chip->to_irq = gpio_rcar_to_irq;
gpio_chip->label = name;
gpio_chip->dev = &pdev->dev;
gpio_chip->owner = THIS_MODULE;
gpio_chip->base = p->config.gpio_base;
gpio_chip->ngpio = p->config.number_of_pins;
Expand Down Expand Up @@ -371,10 +404,12 @@ static int gpio_rcar_probe(struct platform_device *pdev)
p->config.irq_base, ret);
}

ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0,
gpio_chip->base, gpio_chip->ngpio);
if (ret < 0)
dev_warn(&pdev->dev, "failed to add pin range\n");
if (p->config.pctl_name) {
ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0,
gpio_chip->base, gpio_chip->ngpio);
if (ret < 0)
dev_warn(&pdev->dev, "failed to add pin range\n");
}

return 0;

Expand All @@ -397,11 +432,22 @@ static int gpio_rcar_remove(struct platform_device *pdev)
return 0;
}

#ifdef CONFIG_OF
static const struct of_device_id gpio_rcar_of_table[] = {
{
.compatible = "renesas,gpio-rcar",
},
};

MODULE_DEVICE_TABLE(of, gpio_rcar_of_table);
#endif

static struct platform_driver gpio_rcar_device_driver = {
.probe = gpio_rcar_probe,
.remove = gpio_rcar_remove,
.driver = {
.name = "gpio_rcar",
.of_match_table = of_match_ptr(gpio_rcar_of_table),
}
};

Expand Down

0 comments on commit 159f8a0

Please sign in to comment.