Merge tag 'soc2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpio-samsung.c
index 19d6fc0229c3505d802e068553db8be4e5b1361e..7bb00448e13d2cd30140b06c9c1ca635708d9bbd 100644 (file)
@@ -452,12 +452,14 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
 };
 #endif
 
+#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
 static struct samsung_gpio_cfg exynos_gpio_cfg = {
        .set_pull       = exynos_gpio_setpull,
        .get_pull       = exynos_gpio_getpull,
        .set_config     = samsung_gpio_setcfg_4bit,
        .get_config     = samsung_gpio_getcfg_4bit,
 };
+#endif
 
 #if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
 static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
@@ -2123,8 +2125,8 @@ static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
  * uses the above macro and depends on the banks being listed in order here.
  */
 
-static struct samsung_gpio_chip exynos4_gpios_1[] = {
 #ifdef CONFIG_ARCH_EXYNOS4
+static struct samsung_gpio_chip exynos4_gpios_1[] = {
        {
                .chip   = {
                        .base   = EXYNOS4_GPA0(0),
@@ -2222,11 +2224,11 @@ static struct samsung_gpio_chip exynos4_gpios_1[] = {
                        .label  = "GPF3",
                },
        },
-#endif
 };
+#endif
 
-static struct samsung_gpio_chip exynos4_gpios_2[] = {
 #ifdef CONFIG_ARCH_EXYNOS4
+static struct samsung_gpio_chip exynos4_gpios_2[] = {
        {
                .chip   = {
                        .base   = EXYNOS4_GPJ0(0),
@@ -2367,11 +2369,11 @@ static struct samsung_gpio_chip exynos4_gpios_2[] = {
                        .to_irq = samsung_gpiolib_to_irq,
                },
        },
-#endif
 };
+#endif
 
-static struct samsung_gpio_chip exynos4_gpios_3[] = {
 #ifdef CONFIG_ARCH_EXYNOS4
+static struct samsung_gpio_chip exynos4_gpios_3[] = {
        {
                .chip   = {
                        .base   = EXYNOS4_GPZ(0),
@@ -2379,8 +2381,8 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
                        .label  = "GPZ",
                },
        },
-#endif
 };
+#endif
 
 #ifdef CONFIG_ARCH_EXYNOS5
 static struct samsung_gpio_chip exynos5_gpios_1[] = {
@@ -2450,6 +2452,12 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = {
                        .ngpio  = EXYNOS5_GPIO_C3_NR,
                        .label  = "GPC3",
                },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPC4(0),
+                       .ngpio  = EXYNOS5_GPIO_C4_NR,
+                       .label  = "GPC4",
+               },
        }, {
                .chip   = {
                        .base   = EXYNOS5_GPD0(0),
@@ -2714,12 +2722,227 @@ static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
 }
 #endif /* defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF) */
 
+static __init void exynos4_gpiolib_init(void)
+{
+#ifdef CONFIG_CPU_EXYNOS4210
+       struct samsung_gpio_chip *chip;
+       int i, nr_chips;
+       void __iomem *gpio_base1, *gpio_base2, *gpio_base3;
+       int group = 0;
+       void __iomem *gpx_base;
+
+       /* gpio part1 */
+       gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
+       if (gpio_base1 == NULL) {
+               pr_err("unable to ioremap for gpio_base1\n");
+               goto err_ioremap1;
+       }
+
+       chip = exynos4_gpios_1;
+       nr_chips = ARRAY_SIZE(exynos4_gpios_1);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS4_PA_GPIO1, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos4_gpios_1,
+                                      nr_chips, gpio_base1);
+
+       /* gpio part2 */
+       gpio_base2 = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
+       if (gpio_base2 == NULL) {
+               pr_err("unable to ioremap for gpio_base2\n");
+               goto err_ioremap2;
+       }
+
+       /* need to set base address for gpx */
+       chip = &exynos4_gpios_2[16];
+       gpx_base = gpio_base2 + 0xC00;
+       for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
+               chip->base = gpx_base;
+
+       chip = exynos4_gpios_2;
+       nr_chips = ARRAY_SIZE(exynos4_gpios_2);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS4_PA_GPIO2, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos4_gpios_2,
+                                      nr_chips, gpio_base2);
+
+       /* gpio part3 */
+       gpio_base3 = ioremap(EXYNOS4_PA_GPIO3, SZ_256);
+       if (gpio_base3 == NULL) {
+               pr_err("unable to ioremap for gpio_base3\n");
+               goto err_ioremap3;
+       }
+
+       chip = exynos4_gpios_3;
+       nr_chips = ARRAY_SIZE(exynos4_gpios_3);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS4_PA_GPIO3, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos4_gpios_3,
+                                      nr_chips, gpio_base3);
+
+#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
+       s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+       s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
+#endif
+
+       return;
+
+err_ioremap3:
+       iounmap(gpio_base2);
+err_ioremap2:
+       iounmap(gpio_base1);
+err_ioremap1:
+       return;
+#endif /* CONFIG_CPU_EXYNOS4210 */
+}
+
+static __init void exynos5_gpiolib_init(void)
+{
+#ifdef CONFIG_SOC_EXYNOS5250
+       struct samsung_gpio_chip *chip;
+       int i, nr_chips;
+       void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4;
+       int group = 0;
+       void __iomem *gpx_base;
+
+       /* gpio part1 */
+       gpio_base1 = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
+       if (gpio_base1 == NULL) {
+               pr_err("unable to ioremap for gpio_base1\n");
+               goto err_ioremap1;
+       }
+
+       /* need to set base address for gpc4 */
+       exonys5_gpios_1[11].base = gpio_base1 + 0x2E0;
+
+       /* need to set base address for gpx */
+       chip = &exynos5_gpios_1[21];
+       gpx_base = gpio_base1 + 0xC00;
+       for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
+               chip->base = gpx_base;
+
+       chip = exynos5_gpios_1;
+       nr_chips = ARRAY_SIZE(exynos5_gpios_1);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS5_PA_GPIO1, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos5_gpios_1,
+                                      nr_chips, gpio_base1);
+
+       /* gpio part2 */
+       gpio_base2 = ioremap(EXYNOS5_PA_GPIO2, SZ_4K);
+       if (gpio_base2 == NULL) {
+               pr_err("unable to ioremap for gpio_base2\n");
+               goto err_ioremap2;
+       }
+
+       chip = exynos5_gpios_2;
+       nr_chips = ARRAY_SIZE(exynos5_gpios_2);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS5_PA_GPIO2, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos5_gpios_2,
+                                      nr_chips, gpio_base2);
+
+       /* gpio part3 */
+       gpio_base3 = ioremap(EXYNOS5_PA_GPIO3, SZ_4K);
+       if (gpio_base3 == NULL) {
+               pr_err("unable to ioremap for gpio_base3\n");
+               goto err_ioremap3;
+       }
+
+       /* need to set base address for gpv */
+       exynos5_gpios_3[0].base = gpio_base3;
+       exynos5_gpios_3[1].base = gpio_base3 + 0x20;
+       exynos5_gpios_3[2].base = gpio_base3 + 0x60;
+       exynos5_gpios_3[3].base = gpio_base3 + 0x80;
+       exynos5_gpios_3[4].base = gpio_base3 + 0xC0;
+
+       chip = exynos5_gpios_3;
+       nr_chips = ARRAY_SIZE(exynos5_gpios_3);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS5_PA_GPIO3, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos5_gpios_3,
+                                      nr_chips, gpio_base3);
+
+       /* gpio part4 */
+       gpio_base4 = ioremap(EXYNOS5_PA_GPIO4, SZ_4K);
+       if (gpio_base4 == NULL) {
+               pr_err("unable to ioremap for gpio_base4\n");
+               goto err_ioremap4;
+       }
+
+       chip = exynos5_gpios_4;
+       nr_chips = ARRAY_SIZE(exynos5_gpios_4);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (!chip->config) {
+                       chip->config = &exynos_gpio_cfg;
+                       chip->group = group++;
+               }
+               exynos_gpiolib_attach_ofnode(chip,
+                               EXYNOS5_PA_GPIO4, i * 0x20);
+       }
+       samsung_gpiolib_add_4bit_chips(exynos5_gpios_4,
+                                      nr_chips, gpio_base4);
+       return;
+
+err_ioremap4:
+       iounmap(gpio_base3);
+err_ioremap3:
+       iounmap(gpio_base2);
+err_ioremap2:
+       iounmap(gpio_base1);
+err_ioremap1:
+       return;
+
+#endif /* CONFIG_SOC_EXYNOS5250 */
+}
+
 /* TODO: cleanup soc_is_* */
 static __init int samsung_gpiolib_init(void)
 {
        struct samsung_gpio_chip *chip;
        int i, nr_chips;
-       void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4;
        int group = 0;
 
        samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
@@ -2785,200 +3008,15 @@ static __init int samsung_gpiolib_init(void)
                s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 #endif
        } else if (soc_is_exynos4210()) {
-#ifdef CONFIG_CPU_EXYNOS4210
-               void __iomem *gpx_base;
-
-               /* gpio part1 */
-               gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
-               if (gpio_base1 == NULL) {
-                       pr_err("unable to ioremap for gpio_base1\n");
-                       goto err_ioremap1;
-               }
-
-               chip = exynos4_gpios_1;
-               nr_chips = ARRAY_SIZE(exynos4_gpios_1);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS4_PA_GPIO1, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_1,
-                                              nr_chips, gpio_base1);
-
-               /* gpio part2 */
-               gpio_base2 = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
-               if (gpio_base2 == NULL) {
-                       pr_err("unable to ioremap for gpio_base2\n");
-                       goto err_ioremap2;
-               }
-
-               /* need to set base address for gpx */
-               chip = &exynos4_gpios_2[16];
-               gpx_base = gpio_base2 + 0xC00;
-               for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
-                       chip->base = gpx_base;
-
-               chip = exynos4_gpios_2;
-               nr_chips = ARRAY_SIZE(exynos4_gpios_2);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS4_PA_GPIO2, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_2,
-                                              nr_chips, gpio_base2);
-
-               /* gpio part3 */
-               gpio_base3 = ioremap(EXYNOS4_PA_GPIO3, SZ_256);
-               if (gpio_base3 == NULL) {
-                       pr_err("unable to ioremap for gpio_base3\n");
-                       goto err_ioremap3;
-               }
-
-               chip = exynos4_gpios_3;
-               nr_chips = ARRAY_SIZE(exynos4_gpios_3);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS4_PA_GPIO3, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_3,
-                                              nr_chips, gpio_base3);
-
-#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
-               s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
-               s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
-#endif
-
-#endif /* CONFIG_CPU_EXYNOS4210 */
+               exynos4_gpiolib_init();
        } else if (soc_is_exynos5250()) {
-#ifdef CONFIG_SOC_EXYNOS5250
-               void __iomem *gpx_base;
-
-               /* gpio part1 */
-               gpio_base1 = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
-               if (gpio_base1 == NULL) {
-                       pr_err("unable to ioremap for gpio_base1\n");
-                       goto err_ioremap1;
-               }
-
-               /* need to set base address for gpx */
-               chip = &exynos5_gpios_1[20];
-               gpx_base = gpio_base1 + 0xC00;
-               for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
-                       chip->base = gpx_base;
-
-               chip = exynos5_gpios_1;
-               nr_chips = ARRAY_SIZE(exynos5_gpios_1);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS5_PA_GPIO1, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos5_gpios_1,
-                                              nr_chips, gpio_base1);
-
-               /* gpio part2 */
-               gpio_base2 = ioremap(EXYNOS5_PA_GPIO2, SZ_4K);
-               if (gpio_base2 == NULL) {
-                       pr_err("unable to ioremap for gpio_base2\n");
-                       goto err_ioremap2;
-               }
-
-               chip = exynos5_gpios_2;
-               nr_chips = ARRAY_SIZE(exynos5_gpios_2);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS5_PA_GPIO2, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos5_gpios_2,
-                                              nr_chips, gpio_base2);
-
-               /* gpio part3 */
-               gpio_base3 = ioremap(EXYNOS5_PA_GPIO3, SZ_4K);
-               if (gpio_base3 == NULL) {
-                       pr_err("unable to ioremap for gpio_base3\n");
-                       goto err_ioremap3;
-               }
-
-               /* need to set base address for gpv */
-               exynos5_gpios_3[0].base = gpio_base3;
-               exynos5_gpios_3[1].base = gpio_base3 + 0x20;
-               exynos5_gpios_3[2].base = gpio_base3 + 0x60;
-               exynos5_gpios_3[3].base = gpio_base3 + 0x80;
-               exynos5_gpios_3[4].base = gpio_base3 + 0xC0;
-
-               chip = exynos5_gpios_3;
-               nr_chips = ARRAY_SIZE(exynos5_gpios_3);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS5_PA_GPIO3, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos5_gpios_3,
-                                              nr_chips, gpio_base3);
-
-               /* gpio part4 */
-               gpio_base4 = ioremap(EXYNOS5_PA_GPIO4, SZ_4K);
-               if (gpio_base4 == NULL) {
-                       pr_err("unable to ioremap for gpio_base4\n");
-                       goto err_ioremap4;
-               }
-
-               chip = exynos5_gpios_4;
-               nr_chips = ARRAY_SIZE(exynos5_gpios_4);
-
-               for (i = 0; i < nr_chips; i++, chip++) {
-                       if (!chip->config) {
-                               chip->config = &exynos_gpio_cfg;
-                               chip->group = group++;
-                       }
-                       exynos_gpiolib_attach_ofnode(chip,
-                                       EXYNOS5_PA_GPIO4, i * 0x20);
-               }
-               samsung_gpiolib_add_4bit_chips(exynos5_gpios_4,
-                                              nr_chips, gpio_base4);
-#endif /* CONFIG_SOC_EXYNOS5250 */
+               exynos5_gpiolib_init();
        } else {
                WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
                return -ENODEV;
        }
 
        return 0;
-
-err_ioremap4:
-       iounmap(gpio_base3);
-err_ioremap3:
-       iounmap(gpio_base2);
-err_ioremap2:
-       iounmap(gpio_base1);
-err_ioremap1:
-       return -ENOMEM;
 }
 core_initcall(samsung_gpiolib_init);