On Mon, Jan 18, 2010 at 02:38:37AM +0000, Ben Dooks wrote:
> From: Kukjin Kim <[email protected]>
> 
> This patch adds Samsung's S5P6440 GPIO support.
> 
> Signed-off-by: Adityapratap Sharma <[email protected]>
> Signed-off-by: Atul Dahiya <[email protected]>
> Signed-off-by: Kukjin Kim <[email protected]>
> [[email protected]: remove changelog comments from internal dev]
> [[email protected]: fix aditya's email address]
> Signed-off-by: Ben Dooks <[email protected]>
> ---
>  arch/arm/mach-s5p6440/Makefile                 |    2 +-
>  arch/arm/mach-s5p6440/include/mach/gpio-core.h |   40 +++
>  arch/arm/mach-s5p6440/include/mach/regs-gpio.h |   54 ++++
>  arch/arm/mach-s5p6440/s5p6440-gpio.c           |  325 
> ++++++++++++++++++++++++
>  arch/arm/plat-s5p/Kconfig                      |    4 +
>  5 files changed, 424 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/mach-s5p6440/include/mach/regs-gpio.h
>  create mode 100644 arch/arm/mach-s5p6440/s5p6440-gpio.c
> 
> diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile
> index a3ffda9..a79b130 100644
> --- a/arch/arm/mach-s5p6440/Makefile
> +++ b/arch/arm/mach-s5p6440/Makefile
> @@ -12,7 +12,7 @@ obj-                                :=
>  
>  # Core support for S5P6440 system
>  
> -obj-$(CONFIG_CPU_S5P6440)    += cpu.o
> +obj-$(CONFIG_CPU_S5P6440)    += cpu.o s5p6440-gpio.o
>  
>  # machine support
>  
> diff --git a/arch/arm/mach-s5p6440/include/mach/gpio-core.h 
> b/arch/arm/mach-s5p6440/include/mach/gpio-core.h
> index ff7fb30..b6368df 100644
> --- a/arch/arm/mach-s5p6440/include/mach/gpio-core.h
> +++ b/arch/arm/mach-s5p6440/include/mach/gpio-core.h
> @@ -16,4 +16,44 @@
>  /* currently we just include the platform support */
>  #include <plat/gpio-core.h>
>  
> +#define con_4bit_shift(__off) ((__off) * 4)
> +
> +/* various helper functions added which are specific to PLAT_S5P platform */
> +
> +/**
> + * s5p6440_gpiolib_set_cfg - S5P style GPIO configuration
> + * @chip: The gpio chip that is being configured.
> + * @nr_chips: no of chips (gpio ports) for the GPIO being configured.
> +*/
> +extern void s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int 
> nr_chips);

this doesn't seem to get outside of arch/arm/mach-s5p6440/s5p6440-gpio.c
so could do with not being added to this header.

> +/**
> + * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
> + * @chip: The gpio chip that is being configured.
> + * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
> + *
> + * This helper deal with the GPIO cases where the control register has 4 bits
> + * of control per GPIO, generally in the form of:
> + * 0000 = Input
> + * 0001 = Output
> + * others = Special functions (dependant on bank)
> + *
> + * Note, since the code to deal with the case where there are two control
> + * registers instead of one, we do not have a seperate set of function
> + * (samsung_gpiolib_add_4bit2_chips)for each case.
> + */
> +extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
> +                                        int nr_chips);
> +extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
> +                                         int nr_chips);

Should have been added to the previous patch moving the code to the
common directory and also should have been in plat-s3c/include/plat/gpio-core.h
instead of here.

> +/**
> + * s5p6440_gpio_setcfg_4bit_rbank - S5P64XX 4bit single register GPIO config.
> + * @chip: The gpio chip that is being configured (always R).
> + * @off: The offset for the GPIO being configured.
> + * @cfg: The configuration value to set.
> + *
> + */
> +extern int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
> +                                       unsigned int off, unsigned int cfg);
>  #endif /* __ASM_ARCH_GPIO_CORE_H */

If we can find a new place for this definition we can elimiante all
users of <mach/gpio-core.h> and just use <plat/gpio-core.h> instead.

Since it is just the one definition it could go into <plat/gpio-core.h>

> diff --git a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h 
> b/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
> new file mode 100644
> index 0000000..82ff753
> --- /dev/null
> +++ b/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
> @@ -0,0 +1,54 @@
> +/* linux/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
> + *
> + * Copyright (c) 2009 Samsung Electronics Co., Ltd.
> + *           http://www.samsung.com/
> + *
> + * S5P6440 - GPIO register definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __ASM_ARCH_REGS_GPIO_H
> +#define __ASM_ARCH_REGS_GPIO_H __FILE__
> +
> +#include <mach/map.h>
> +
> +/* Base addresses for each of the banks */
> +#define S5P6440_GPA_BASE             (S5P_VA_GPIO + 0x0000)
> +#define S5P6440_GPB_BASE             (S5P_VA_GPIO + 0x0020)
> +#define S5P6440_GPC_BASE             (S5P_VA_GPIO + 0x0040)
> +#define S5P6440_GPF_BASE             (S5P_VA_GPIO + 0x00A0)
> +#define S5P6440_GPG_BASE             (S5P_VA_GPIO + 0x00C0)
> +#define S5P6440_GPH_BASE             (S5P_VA_GPIO + 0x00E0)
> +#define S5P6440_GPI_BASE             (S5P_VA_GPIO + 0x0100)
> +#define S5P6440_GPJ_BASE             (S5P_VA_GPIO + 0x0120)
> +#define S5P6440_GPN_BASE             (S5P_VA_GPIO + 0x0830)
> +#define S5P6440_GPP_BASE             (S5P_VA_GPIO + 0x0160)
> +#define S5P6440_GPR_BASE             (S5P_VA_GPIO + 0x0290)
> +#define S5P6440_EINT0CON0            (S5P_VA_GPIO + 0x900)
> +#define S5P6440_EINT0FLTCON0         (S5P_VA_GPIO + 0x910)
> +#define S5P6440_EINT0FLTCON1         (S5P_VA_GPIO + 0x914)
> +#define S5P6440_EINT0MASK            (S5P_VA_GPIO + 0x920)
> +#define S5P6440_EINT0PEND            (S5P_VA_GPIO + 0x924)
> +
> +/* for LCD */
> +#define S5P6440_SPCON_LCD_SEL_RGB    (1 << 0)
> +#define S5P6440_SPCON_LCD_SEL_MASK   (3 << 0)
> +
> +/* These set of macros are not really useful for the
> + * GPF/GPI/GPJ/GPN/GPP,
> + * useful for others set of GPIO's (4 bit)
> + */
> +#define S5P6440_GPIO_CONMASK(__gpio) (0xf << ((__gpio) * 4))
> +#define S5P6440_GPIO_INPUT(__gpio)   (0x0 << ((__gpio) * 4))
> +#define S5P6440_GPIO_OUTPUT(__gpio)  (0x1 << ((__gpio) * 4))
> +
> +/* Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
> + * */
> +#define S5P6440_GPIO2_CONMASK(__gpio)        (0x3 << ((__gpio) * 2))
> +#define S5P6440_GPIO2_INPUT(__gpio)  (0x0 << ((__gpio) * 2))
> +#define S5P6440_GPIO2_OUTPUT(__gpio) (0x1 << ((__gpio) * 2))
> +
> +#endif /* __ASM_ARCH_REGS_GPIO_H */
> diff --git a/arch/arm/mach-s5p6440/s5p6440-gpio.c 
> b/arch/arm/mach-s5p6440/s5p6440-gpio.c
> new file mode 100644
> index 0000000..dff1703
> --- /dev/null
> +++ b/arch/arm/mach-s5p6440/s5p6440-gpio.c
> @@ -0,0 +1,325 @@
> +/* arch/arm/mach-s5p6440/s5p6440-gpio.c
> + *
> + * Copyright (c) 2009 Samsung Electronics Co., Ltd.
> + *           http://www.samsung.com/
> + *
> + * S5P6440 - GPIOlib support
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/irq.h>
> +#include <linux/io.h>
> +#include <mach/map.h>
> +#include <mach/gpio.h>
> +#include <mach/gpio-core.h>
> +#include <mach/regs-gpio.h>
> +#include <plat/gpio-cfg.h>
> +#include <plat/gpio-cfg-helpers.h>
> +
> +#define GPIODAT_OFF  (0x04)
> +#define con_4bit_shift(__off) ((__off) * 4)

That should have already come from the header file.

> +/* GPIO bank summary:
> +*
> +* Bank       GPIOs   Style   SlpCon  ExtInt Group
> +* A  6       4Bit    Yes     1
> +* B  7       4Bit    Yes     1
> +* C  8       4Bit    Yes     2
> +* F  2       2Bit    Yes     4 [1]
> +* G  7       4Bit    Yes     5
> +* H  10      4Bit[2] Yes     6
> +* I  16      2Bit    Yes     None
> +* J  12      2Bit    Yes     None
> +* N  16      2Bit    No      IRQ_EINT
> +* P  8       2Bit    Yes     8
> +* R  15      4Bit[2] Yes     8
> +*
> +* [1] BANKF pins 14,15 do not form part of the external interrupt sources
> +* [2] BANK has two control registers, GPxCON0 and GPxCON1
> +*/
> +
> +static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
> +                                          unsigned int offset)
> +{
> +     struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
> +     void __iomem *base = ourchip->base;
> +     void __iomem *regcon = base;
> +     unsigned long con;
> +
> +     switch (offset) {
> +     case 6:
> +             offset += 1;
> +     case 0:
> +     case 1:
> +     case 2:
> +     case 3:
> +     case 4:
> +     case 5:
> +             regcon -= 4;
> +             break;
> +     default:
> +             offset -= 7;
> +             break;
> +     }
> +
> +     con = __raw_readl(regcon);
> +     con &= ~(0xf << con_4bit_shift(offset));
> +     __raw_writel(con, regcon);
> +
> +     return 0;
> +}
> +
> +static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
> +                                           unsigned int offset, int value)
> +{
> +     struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
> +     void __iomem *base = ourchip->base;
> +     void __iomem *regcon = base;
> +     unsigned long con;
> +     unsigned long dat;
> +     unsigned con_offset  = offset;
> +
> +     switch (con_offset) {
> +     case 6:
> +             con_offset += 1;
> +     case 0:
> +     case 1:
> +     case 2:
> +     case 3:
> +     case 4:
> +     case 5:
> +             regcon -= 4;
> +             break;
> +     default:
> +             con_offset -= 7;
> +             break;
> +     }
> +
> +     con = __raw_readl(regcon);
> +     con &= ~(0xf << con_4bit_shift(con_offset));
> +     con |= 0x1 << con_4bit_shift(con_offset);
> +
> +     dat = __raw_readl(base + GPIODAT_OFF);
> +     if (value)
> +             dat |= 1 << offset;
> +     else
> +             dat &= ~(1 << offset);
> +
> +     __raw_writel(con, regcon);
> +     __raw_writel(dat, base + GPIODAT_OFF);
> +
> +     return 0;
> +}
> +
> +int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
> +                                unsigned int off, unsigned int cfg)
> +{
> +     void __iomem *reg = chip->base;
> +     unsigned int shift;
> +     u32 con;
> +
> +     switch (off) {
> +     case 0:
> +     case 1:
> +     case 2:
> +     case 3:
> +     case 4:
> +     case 5:
> +             shift = (off & 7) * 4;
> +             reg -= 4;
> +             break;
> +     case 6:
> +             shift = ((off + 1) & 7) * 4;
> +             reg -= 4;
> +     default:
> +             shift = ((off + 1) & 7) * 4;
> +             break;
> +     }
> +
> +     if (s3c_gpio_is_cfg_special(cfg)) {
> +             cfg &= 0xf;
> +             cfg <<= shift;
> +     }
> +
> +     con = __raw_readl(reg);
> +     con &= ~(0xf << shift);
> +     con |= cfg;
> +     __raw_writel(con, reg);
> +
> +     return 0;
> +}
> +
> +static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = {
> +     {
> +             .cfg_eint       = 0,
> +     }, {
> +             .cfg_eint       = 7,
> +     }, {
> +             .cfg_eint       = 3,
> +             .set_config     = s5p6440_gpio_setcfg_4bit_rbank,
> +     }, {
> +             .cfg_eint       = 0,
> +             .set_config     = s3c_gpio_setcfg_s3c24xx,
> +     }, {
> +             .cfg_eint       = 2,
> +             .set_config     = s3c_gpio_setcfg_s3c24xx,
> +     }, {
> +             .cfg_eint       = 3,
> +             .set_config     = s3c_gpio_setcfg_s3c24xx,
> +     },
> +};
> +
> +static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
> +     {
> +             .base   = S5P6440_GPA_BASE,
> +             .config = &s5p6440_gpio_cfgs[1],
> +             .chip   = {
> +                     .base   = S5P6440_GPA(0),
> +                     .ngpio  = S5P6440_GPIO_A_NR,
> +                     .label  = "GPA",
> +             },
> +     }, {
> +             .base   = S5P6440_GPB_BASE,
> +             .config = &s5p6440_gpio_cfgs[1],
> +             .chip   = {
> +                     .base   = S5P6440_GPB(0),
> +                     .ngpio  = S5P6440_GPIO_B_NR,
> +                     .label  = "GPB",
> +             },
> +     }, {
> +             .base   = S5P6440_GPC_BASE,
> +             .config = &s5p6440_gpio_cfgs[1],
> +             .chip   = {
> +                     .base   = S5P6440_GPC(0),
> +                     .ngpio  = S5P6440_GPIO_C_NR,
> +                     .label  = "GPC",
> +             },
> +     }, {
> +             .base   = S5P6440_GPG_BASE,
> +             .config = &s5p6440_gpio_cfgs[1],
> +             .chip   = {
> +                     .base   = S5P6440_GPG(0),
> +                     .ngpio  = S5P6440_GPIO_G_NR,
> +                     .label  = "GPG",
> +             },
> +     },
> +};
> +
> +static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
> +     {
> +             .base   = S5P6440_GPH_BASE + 0x4,
> +             .config = &s5p6440_gpio_cfgs[1],
> +             .chip   = {
> +                     .base   = S5P6440_GPH(0),
> +                     .ngpio  = S5P6440_GPIO_H_NR,
> +                     .label  = "GPH",
> +             },
> +     },
> +};
> +
> +static struct s3c_gpio_chip gpio_rbank_4bit2[] = {
> +     {
> +             .base   = S5P6440_GPR_BASE + 0x4,
> +             .config = &s5p6440_gpio_cfgs[2],
> +             .chip   = {
> +                     .base   = S5P6440_GPR(0),
> +                     .ngpio  = S5P6440_GPIO_R_NR,
> +                     .label  = "GPR",
> +             },
> +     },
> +};
> +
> +static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
> +     {
> +             .base   = S5P6440_GPF_BASE,
> +             .config = &s5p6440_gpio_cfgs[5],
> +             .chip   = {
> +                     .base   = S5P6440_GPF(0),
> +                     .ngpio  = S5P6440_GPIO_F_NR,
> +                     .label  = "GPF",
> +             },
> +     }, {
> +             .base   = S5P6440_GPI_BASE,
> +             .config = &s5p6440_gpio_cfgs[3],
> +             .chip   = {
> +                     .base   = S5P6440_GPI(0),
> +                     .ngpio  = S5P6440_GPIO_I_NR,
> +                     .label  = "GPI",
> +             },
> +     }, {
> +             .base   = S5P6440_GPJ_BASE,
> +             .config = &s5p6440_gpio_cfgs[3],
> +             .chip   = {
> +                     .base   = S5P6440_GPJ(0),
> +                     .ngpio  = S5P6440_GPIO_J_NR,
> +                     .label  = "GPJ",
> +             },
> +     }, {
> +             .base   = S5P6440_GPN_BASE,
> +             .config = &s5p6440_gpio_cfgs[4],
> +             .chip   = {
> +                     .base   = S5P6440_GPN(0),
> +                     .ngpio  = S5P6440_GPIO_N_NR,
> +                     .label  = "GPN",
> +             },
> +     }, {
> +             .base   = S5P6440_GPP_BASE,
> +             .config = &s5p6440_gpio_cfgs[5],
> +             .chip   = {
> +                     .base   = S5P6440_GPP(0),
> +                     .ngpio  = S5P6440_GPIO_P_NR,
> +                     .label  = "GPP",
> +             },
> +     },
> +};
> +
> +void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int 
> nr_chips)
> +{
> +     for (; nr_chips > 0; nr_chips--, chipcfg++) {
> +             if (!chipcfg->set_config)
> +                     chipcfg->set_config     = s3c_gpio_setcfg_s3c64xx_4bit;
> +             if (!chipcfg->set_pull)
> +                     chipcfg->set_pull       = s3c_gpio_setpull_updown;
> +             if (!chipcfg->get_pull)
> +                     chipcfg->get_pull       = s3c_gpio_getpull_updown;
> +     }
> +}
> +
> +static void __init s5p6440_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
> +                                             int nr_chips)
> +{
> +     for (; nr_chips > 0; nr_chips--, chip++) {
> +             chip->chip.direction_input = s5p6440_gpiolib_rbank_4bit2_input;
> +             chip->chip.direction_output =
> +                                     s5p6440_gpiolib_rbank_4bit2_output;
> +             s3c_gpiolib_add(chip);
> +     }
> +}
> +
> +static int __init s5p6440_gpiolib_init(void)
> +{
> +     struct s3c_gpio_chip *chips = s5p6440_gpio_2bit;
> +     int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit);
> +
> +     s5p6440_gpiolib_set_cfg(s5p6440_gpio_cfgs,
> +                             ARRAY_SIZE(s5p6440_gpio_cfgs));
> +
> +     for (; nr_chips > 0; nr_chips--, chips++)
> +             s3c_gpiolib_add(chips);
> +
> +     samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
> +                             ARRAY_SIZE(s5p6440_gpio_4bit));
> +
> +     samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
> +                             ARRAY_SIZE(s5p6440_gpio_4bit2));
> +
> +     s5p6440_gpio_add_rbank_4bit2(gpio_rbank_4bit2,
> +                             ARRAY_SIZE(gpio_rbank_4bit2));
> +
> +     return 0;
> +}
> +arch_initcall(s5p6440_gpiolib_init);
> diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
> index 7e08b40..9d8686c 100644
> --- a/arch/arm/plat-s5p/Kconfig
> +++ b/arch/arm/plat-s5p/Kconfig
> @@ -14,6 +14,10 @@ config PLAT_S5P
>       select NO_IOPORT
>       select ARCH_REQUIRE_GPIOLIB
>       select S3C_GPIO_TRACK
> +     select SAMSUNG_GPIOLIB
> +     select S3C_GPIO_CFG_S3C64XX
> +     select S3C_GPIO_PULL_UPDOWN
> +     select S3C_GPIO_CFG_S3C24XX
>       select PLAT_SAMSUNG
>       select SAMSUNG_CLKSRC
>       select SAMSUNG_IRQ_VIC_TIMER
> -- 
> 1.6.0.4
> 

-- 
-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to