diff options
Diffstat (limited to 'drivers/gpio/gpio-samsung.c')
-rw-r--r-- | drivers/gpio/gpio-samsung.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 866251852719..6b4d23fd158e 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c | |||
@@ -24,6 +24,9 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/sysdev.h> | 25 | #include <linux/sysdev.h> |
26 | #include <linux/ioport.h> | 26 | #include <linux/ioport.h> |
27 | #include <linux/of.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/of_address.h> | ||
27 | 30 | ||
28 | #include <asm/irq.h> | 31 | #include <asm/irq.h> |
29 | 32 | ||
@@ -2374,6 +2377,63 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { | |||
2374 | #endif | 2377 | #endif |
2375 | }; | 2378 | }; |
2376 | 2379 | ||
2380 | #if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) | ||
2381 | static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np, | ||
2382 | const void *gpio_spec, u32 *flags) | ||
2383 | { | ||
2384 | const __be32 *gpio = gpio_spec; | ||
2385 | const u32 n = be32_to_cpup(gpio); | ||
2386 | unsigned int pin = gc->base + be32_to_cpu(gpio[0]); | ||
2387 | |||
2388 | if (WARN_ON(gc->of_gpio_n_cells < 4)) | ||
2389 | return -EINVAL; | ||
2390 | |||
2391 | if (n > gc->ngpio) | ||
2392 | return -EINVAL; | ||
2393 | |||
2394 | if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1])))) | ||
2395 | pr_warn("gpio_xlate: failed to set pin function\n"); | ||
2396 | if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2]))) | ||
2397 | pr_warn("gpio_xlate: failed to set pin pull up/down\n"); | ||
2398 | if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3]))) | ||
2399 | pr_warn("gpio_xlate: failed to set pin drive strength\n"); | ||
2400 | |||
2401 | return n; | ||
2402 | } | ||
2403 | |||
2404 | static const struct of_device_id exynos4_gpio_dt_match[] __initdata = { | ||
2405 | { .compatible = "samsung,exynos4-gpio", }, | ||
2406 | {} | ||
2407 | }; | ||
2408 | |||
2409 | static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, | ||
2410 | u64 base, u64 offset) | ||
2411 | { | ||
2412 | struct gpio_chip *gc = &chip->chip; | ||
2413 | u64 address; | ||
2414 | |||
2415 | if (!of_have_populated_dt()) | ||
2416 | return; | ||
2417 | |||
2418 | address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset; | ||
2419 | gc->of_node = of_find_matching_node_by_address(NULL, | ||
2420 | exynos4_gpio_dt_match, address); | ||
2421 | if (!gc->of_node) { | ||
2422 | pr_info("gpio: device tree node not found for gpio controller" | ||
2423 | " with base address %08llx\n", address); | ||
2424 | return; | ||
2425 | } | ||
2426 | gc->of_gpio_n_cells = 4; | ||
2427 | gc->of_xlate = exynos4_gpio_xlate; | ||
2428 | } | ||
2429 | #elif defined(CONFIG_ARCH_EXYNOS4) | ||
2430 | static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, | ||
2431 | u64 base, u64 offset) | ||
2432 | { | ||
2433 | return; | ||
2434 | } | ||
2435 | #endif /* defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) */ | ||
2436 | |||
2377 | /* TODO: cleanup soc_is_* */ | 2437 | /* TODO: cleanup soc_is_* */ |
2378 | static __init int samsung_gpiolib_init(void) | 2438 | static __init int samsung_gpiolib_init(void) |
2379 | { | 2439 | { |
@@ -2455,6 +2515,10 @@ static __init int samsung_gpiolib_init(void) | |||
2455 | chip->config = &exynos4_gpio_cfg; | 2515 | chip->config = &exynos4_gpio_cfg; |
2456 | chip->group = group++; | 2516 | chip->group = group++; |
2457 | } | 2517 | } |
2518 | #ifdef CONFIG_CPU_EXYNOS4210 | ||
2519 | exynos4_gpiolib_attach_ofnode(chip, | ||
2520 | EXYNOS4_PA_GPIO1, i * 0x20); | ||
2521 | #endif | ||
2458 | } | 2522 | } |
2459 | samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1); | 2523 | samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1); |
2460 | 2524 | ||
@@ -2467,6 +2531,10 @@ static __init int samsung_gpiolib_init(void) | |||
2467 | chip->config = &exynos4_gpio_cfg; | 2531 | chip->config = &exynos4_gpio_cfg; |
2468 | chip->group = group++; | 2532 | chip->group = group++; |
2469 | } | 2533 | } |
2534 | #ifdef CONFIG_CPU_EXYNOS4210 | ||
2535 | exynos4_gpiolib_attach_ofnode(chip, | ||
2536 | EXYNOS4_PA_GPIO2, i * 0x20); | ||
2537 | #endif | ||
2470 | } | 2538 | } |
2471 | samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2); | 2539 | samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2); |
2472 | 2540 | ||
@@ -2479,6 +2547,10 @@ static __init int samsung_gpiolib_init(void) | |||
2479 | chip->config = &exynos4_gpio_cfg; | 2547 | chip->config = &exynos4_gpio_cfg; |
2480 | chip->group = group++; | 2548 | chip->group = group++; |
2481 | } | 2549 | } |
2550 | #ifdef CONFIG_CPU_EXYNOS4210 | ||
2551 | exynos4_gpiolib_attach_ofnode(chip, | ||
2552 | EXYNOS4_PA_GPIO3, i * 0x20); | ||
2553 | #endif | ||
2482 | } | 2554 | } |
2483 | samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3); | 2555 | samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3); |
2484 | 2556 | ||