diff options
author | Heiko Stuebner <heiko@sntech.de> | 2012-09-07 06:49:47 +0900 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2012-09-07 14:02:50 +0900 |
commit | 172c6a13653ac8cd6a231293b87c93821e90c1d6 (patch) | |
tree | e8921c1272a316a0c1465a425b29631127589a50 /drivers/gpio/gpio-samsung.c | |
parent | 4cbe5a555fa58a79b6ecbb6c531b8bab0650778d (diff) |
gpio: samsung: add devicetree init for s3c24xx arches
Until now the EXYNOS-SoC was the only Samsung-SoC supporting the GPIOs
via the device tree. This patch implements dt-support for the
s3c24xx arches.
The controllers contain only 3 cells, as the underlying gpio controller
does not support controlling the drive strength on a gpio level.
Tested with the gpio-keys driver on a s3c2416 based machine.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Thomas Abraham <thomas.abraham@linaro.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
[kgene.kim@samsung.com: fixed build error]
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/gpio/gpio-samsung.c')
-rw-r--r-- | drivers/gpio/gpio-samsung.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index ba126cc04073..f4814a889a5b 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -938,6 +938,67 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip) s3c_gpiolib_track(chip); } +#if defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) +static int s3c24xx_gpio_xlate(struct gpio_chip *gc, + const struct of_phandle_args *gpiospec, u32 *flags) +{ + unsigned int pin; + + if (WARN_ON(gc->of_gpio_n_cells < 3)) + return -EINVAL; + + if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) + return -EINVAL; + + if (gpiospec->args[0] > gc->ngpio) + return -EINVAL; + + pin = gc->base + gpiospec->args[0]; + + if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1]))) + pr_warn("gpio_xlate: failed to set pin function\n"); + if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff)) + pr_warn("gpio_xlate: failed to set pin pull up/down\n"); + + if (flags) + *flags = gpiospec->args[2] >> 16; + + return gpiospec->args[0]; +} + +static const struct of_device_id s3c24xx_gpio_dt_match[] __initdata = { + { .compatible = "samsung,s3c24xx-gpio", }, + {} +}; + +static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, + u64 base, u64 offset) +{ + struct gpio_chip *gc = &chip->chip; + u64 address; + + if (!of_have_populated_dt()) + return; + + address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset; + gc->of_node = of_find_matching_node_by_address(NULL, + s3c24xx_gpio_dt_match, address); + if (!gc->of_node) { + pr_info("gpio: device tree node not found for gpio controller" + " with base address %08llx\n", address); + return; + } + gc->of_gpio_n_cells = 3; + gc->of_xlate = s3c24xx_gpio_xlate; +} +#else +static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, + u64 base, u64 offset) +{ + return; +} +#endif /* defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) */ + static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip, int nr_chips, void __iomem *base) { @@ -962,6 +1023,8 @@ static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip, gc->direction_output = samsung_gpiolib_2bit_output; samsung_gpiolib_add(chip); + + s3c24xx_gpiolib_attach_ofnode(chip, S3C24XX_PA_GPIO, i * 0x10); } } |