]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ARM: at91: gpio add DT support
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Mon, 17 Oct 2011 13:09:39 +0000 (21:09 +0800)
committerJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Thu, 24 Nov 2011 19:30:18 +0000 (03:30 +0800)
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Documentation/devicetree/bindings/gpio/gpio_at91.txt [new file with mode: 0644]
arch/arm/boot/dts/at91sam9g20.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/mach-at91/gpio.c

diff --git a/Documentation/devicetree/bindings/gpio/gpio_at91.txt b/Documentation/devicetree/bindings/gpio/gpio_at91.txt
new file mode 100644 (file)
index 0000000..e6dafdf
--- /dev/null
@@ -0,0 +1,9 @@
+Atmel AT91 GPIO controller
+
+Required properties:
+ - compatible : "atmel,at91rm9200-gpio"
+ - interrupts : Should be the port interrupt shared by all 32 pins.
+ - #gpio-cells : Should be two.  The first cell is the pin number and
+  the second cell is used to specify optional parameters (currently
+  unused).
+ - gpio-controller : Marks the device node as a GPIO controller.
index 410ae6e8f53569f236fe360d58a0f4e256adeeae..477f1692705ac301ee811984bcd45eb13da5c773 100644 (file)
@@ -23,6 +23,9 @@
                serial4 = &usart3;
                serial5 = &usart4;
                serial6 = &usart5;
+               gpio0 = &pioA;
+               gpio1 = &pioB;
+               gpio2 = &pioC;
        };
        cpus {
                cpu@0 {
                                interrupts = <1>;
                        };
 
+                       pioA: gpio@fffff400 {
+                               compatible = "atmel,at91rm9200-gpio";
+                               reg = < 0xfffff400 0x200 >;
+                               interrupts = <2>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+
+                       pioB: gpio@fffff600 {
+                               compatible = "atmel,at91rm9200-gpio";
+                               reg = < 0xfffff600 0x200 >;
+                               interrupts = <3>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+
+                       pioC: gpio@fffff800 {
+                               compatible = "atmel,at91rm9200-gpio";
+                               reg = < 0xfffff800 0x200 >;
+                               interrupts = <4>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
index a09b102cc3aed8244b13226fc7e3973a230853fa..0dd7c1105bbe986d31730a2d5e4c1e0d746ee00b 100644 (file)
                serial2 = &usart1;
                serial3 = &usart2;
                serial4 = &usart3;
+               gpio0 = &pioA;
+               gpio1 = &pioB;
+               gpio2 = &pioC;
+               gpio3 = &pioD;
+               gpio4 = &pioE;
        };
        cpus {
                cpu@0 {
                                interrupts = <21>;
                        };
 
+                       pioA: gpio@fffff200 {
+                               compatible = "atmel,at91rm9200-gpio";
+                               reg = < 0xfffff200 0x200 >;
+                               interrupts = <2>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+
+                       pioB: gpio@fffff400 {
+                               compatible = "atmel,at91rm9200-gpio";
+                               reg = < 0xfffff400 0x200 >;
+                               interrupts = <3>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+
+                       pioC: gpio@fffff600 {
+                               compatible = "atmel,at91rm9200-gpio";
+                               reg = < 0xfffff600 0x200 >;
+                               interrupts = <4>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+
+                       pioD: gpio@fffff800 {
+                               compatible = "atmel,at91rm9200-gpio";
+                               reg = < 0xfffff800 0x200 >;
+                               interrupts = <5>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+
+                       pioE: gpio@fffffa00 {
+                               compatible = "atmel,at91rm9200-gpio";
+                               reg = < 0xfffffa00 0x200 >;
+                               interrupts = <5>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+
                        dbgu: serial@ffffee00 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
index 74d6783eeabbb976c4261d299fcfe11b70d83984..63d25574675cd9db9fa5513674182aff71b5b5a7 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <mach/hardware.h>
 #include <mach/at91_pio.h>
@@ -600,6 +602,97 @@ static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
        }
 }
 
+#ifdef CONFIG_OF_GPIO
+static void __init of_at91_gpio_init_one(struct device_node *np)
+{
+       int i;
+       struct at91_gpio_chip *at91_gpio;
+       const unsigned int *intspec;
+
+       if (!np)
+               return;
+
+       i = of_alias_get_id(np, "gpio");
+       if (i >= MAX_GPIO_BANKS) {
+               pr_err("at91_gpio, failed id(%d) > MAX_GPIO_BANKS(%d), ignoring.\n", i, MAX_GPIO_BANKS);
+               return;
+       }
+
+       at91_gpio = &gpio_chip[i];
+       at91_gpio->chip.base = i * 32;
+
+       at91_gpio->regbase = of_iomap(np, 0);
+       if (!at91_gpio->regbase) {
+               pr_err("at91_gpio.%d, failed to map registers, ignoring.\n", i);
+               return;
+       }
+
+       /* Get the interrupts property */
+       intspec = of_get_property(np, "interrupts", NULL);
+       BUG_ON(!intspec);
+       at91_gpio->id = be32_to_cpup(intspec);
+
+       at91_gpio->clock = clk_get_sys(NULL, at91_gpio->chip.label);
+       if (!at91_gpio->clock) {
+               pr_err("at91_gpio.%d, failed to get clock, ignoring.\n", i);
+               return;
+       }
+
+       /* enable PIO controller's clock */
+       clk_enable(at91_gpio->clock);
+
+       at91_gpio->chip.of_node = np;
+       gpio_banks = max(gpio_banks, i + 1);
+}
+
+static int __init of_at91_gpio_init(void)
+{
+       struct device_node *np = NULL;
+
+       gpio_banks = 0;
+
+       /*
+        * This isn't ideal, but it gets things hooked up until this
+        * driver is converted into a platform_device
+        */
+       do {
+               np = of_find_compatible_node(np, NULL, "atmel,at91rm9200-gpio");
+
+               of_at91_gpio_init_one(np);
+       } while (np);
+
+       return gpio_banks > 0 ? 0 : -EINVAL;
+}
+#else
+static int __init of_at91_gpio_init(void)
+{
+       return -EINVAL;
+}
+#endif
+
+static void __init at91_gpio_init_one(int i, u32 regbase, int id)
+{
+       struct at91_gpio_chip *at91_gpio = &gpio_chip[i];
+
+       at91_gpio->chip.base = i * 32;
+       at91_gpio->id = id;
+
+       at91_gpio->regbase = ioremap(regbase, 512);
+       if (!at91_gpio->regbase) {
+               pr_err("at91_gpio.%d, failed to map registers, ignoring.\n", i);
+               return;
+       }
+
+       at91_gpio->clock = clk_get_sys(NULL, at91_gpio->chip.label);
+       if (!at91_gpio->clock) {
+               pr_err("at91_gpio.%d, failed to get clock, ignoring.\n", i);
+               return;
+       }
+
+       /* enable PIO controller's clock */
+       clk_enable(at91_gpio->clock);
+}
+
 /*
  * Called from the processor-specific init to enable GPIO pin support.
  */
@@ -610,28 +703,17 @@ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
 
        BUG_ON(nr_banks > MAX_GPIO_BANKS);
 
-       gpio_banks = nr_banks;
-
-       for (i = 0; i < nr_banks; i++) {
-               at91_gpio = &gpio_chip[i];
+       if (!of_at91_gpio_init())
+               goto fixup;
 
-               at91_gpio->id = data[i].id;
-               at91_gpio->chip.base = i * 32;
-
-               at91_gpio->regbase = ioremap(data[i].regbase, 512);
-               if (!at91_gpio->regbase) {
-                       pr_err("at91_gpio.%d, failed to map registers, ignoring.\n", i);
-                       continue;
-               }
+       gpio_banks = nr_banks;
 
-               at91_gpio->clock = clk_get_sys(NULL, at91_gpio->chip.label);
-               if (!at91_gpio->clock) {
-                       pr_err("at91_gpio.%d, failed to get clock, ignoring.\n", i);
-                       continue;
-               }
+       for (i = 0; i < nr_banks; i++)
+               at91_gpio_init_one(i, data[i].regbase, data[i].id);
 
-               /* enable PIO controller's clock */
-               clk_enable(at91_gpio->clock);
+fixup:
+       for (i = 0; i < gpio_banks; i++) {
+               at91_gpio = &gpio_chip[i];
 
                /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
                if (last && last->id == at91_gpio->id)