From mboxrd@z Thu Jan 1 00:00:00 1970 From: Minkyu Kang Date: Tue, 06 May 2014 11:47:32 +0900 Subject: [U-Boot] [PATCH v11 1/2] S5P: Exynos: Add GPIO pin numbering and rename definitions In-Reply-To: <1399286346-12221-2-git-send-email-akshay.s@samsung.com> References: <1399286346-12221-1-git-send-email-akshay.s@samsung.com> <1399286346-12221-2-git-send-email-akshay.s@samsung.com> Message-ID: <53684D44.50108@samsung.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Dear Akshay Saraswat, On 05/05/14 19:39, Akshay Saraswat wrote: > This patch includes following changes : > * Adds gpio pin numbering support for EXYNOS SOCs. > To have consistent 0..n-1 GPIO numbering the banks are divided > into different parts where ever they have holes in them. > > * Rename GPIO definitions from GPIO_... to S5P_GPIO_... > These changes were done to enable cmd_gpio for EXYNOS and > cmd_gpio has GPIO_INPUT same as s5p_gpio driver and hence > getting a error during compilation. > > * Adds support for name to gpio conversion in s5p_gpio to enable > gpio command EXYNOS SoCs. Function has been added to asm/gpio.h > to decode the input gpio name to gpio number. > Example: SMDK5420 # gpio set gpa00 > > Signed-off-by: Leela Krishna Amudala > Signed-off-by: Rajeshwari Shinde > Signed-off-by: Akshay Saraswat > --- please add changes log. > arch/arm/cpu/armv7/exynos/pinmux.c | 549 +++++---- > arch/arm/dts/exynos4210-origen.dts | 4 +- > arch/arm/dts/exynos4210-trats.dts | 6 +- > arch/arm/dts/exynos4210-universal_c210.dts | 4 +- > arch/arm/dts/exynos4412-trats2.dts | 4 +- > arch/arm/include/asm/arch-exynos/cpu.h | 17 +- > arch/arm/include/asm/arch-exynos/gpio.h | 1761 +++++++++++++++++++++++----- > arch/arm/include/asm/arch-s5pc1xx/gpio.h | 950 ++++++++++++--- > board/samsung/arndale/arndale.c | 11 +- > board/samsung/goni/goni.c | 26 +- > board/samsung/smdk5250/exynos5-dt.c | 20 +- > board/samsung/smdk5250/smdk5250.c | 19 +- > board/samsung/smdk5420/smdk5420.c | 15 +- > board/samsung/smdkc100/smdkc100.c | 5 +- > board/samsung/smdkv310/smdkv310.c | 17 +- > board/samsung/trats/trats.c | 39 +- > board/samsung/trats2/trats2.c | 74 +- > board/samsung/universal_c210/universal.c | 51 +- > drivers/gpio/s5p_gpio.c | 198 +++- > 19 files changed, 2883 insertions(+), 887 deletions(-) > > diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c > index 9edb475..9e26340 100644 > --- a/arch/arm/cpu/armv7/exynos/pinmux.c > +++ b/arch/arm/cpu/armv7/exynos/pinmux.c > @@ -197,19 +172,19 @@ static int exynos5420_mmc_config(int peripheral, int flags) > * this same assumption. > */ > if ((peripheral == PERIPH_ID_SDMMC0) && (i == 2)) { Should be.. (i == start + 2)?? > - s5p_gpio_set_value(bank, i, 1); > - s5p_gpio_cfg_pin(bank, i, GPIO_OUTPUT); > + gpio_set_value(i, 1); > + gpio_cfg_pin(i, S5P_GPIO_OUTPUT); > } else { > - s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); > + gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2)); > } > - s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); > - s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); > + gpio_set_pull(i, S5P_GPIO_PULL_NONE); > + gpio_set_drv(i, S5P_GPIO_DRV_4X); > } > > - for (i = 3; i <= 6; i++) { > - s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); > - s5p_gpio_set_pull(bank, i, GPIO_PULL_UP); > - s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); > + for (i = (start + 3); i <= (start + 6); i++) { > + gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2)); > + gpio_set_pull(i, S5P_GPIO_PULL_UP); > + gpio_set_drv(i, S5P_GPIO_DRV_4X); > } > > return 0; > diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h > index d6868fa..c49be8b 100644 > --- a/arch/arm/include/asm/arch-exynos/gpio.h > +++ b/arch/arm/include/asm/arch-exynos/gpio.h > -/* functions */ > -void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg); > -void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en); > -void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio); > -void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en); > -unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio); > -void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode); > -void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode); > -void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode); > +static inline struct gpio_info *get_gpio_data(void) > +{ > + if (cpu_is_exynos5()) { > + if (proid_is_exynos5420()) > + return exynos5420_gpio_data; > + else > + return exynos5_gpio_data; > + } else if (cpu_is_exynos4()) { > + if (proid_is_exynos4412()) > + return exynos4x12_gpio_data; > + else > + return exynos4_gpio_data; > + } else { > + return NULL; > + } else does not needed. just return NULL; > +} > > -/* GPIO pins per bank */ > -#define GPIO_PER_BANK 8 > -#define S5P_GPIO_PART_SHIFT (24) > -#define S5P_GPIO_PART_MASK (0xff) > -#define S5P_GPIO_BANK_SHIFT (8) > -#define S5P_GPIO_BANK_MASK (0xffff) > -#define S5P_GPIO_PIN_MASK (0xff) > - > -#define S5P_GPIO_SET_PART(x) \ > - (((x) & S5P_GPIO_PART_MASK) << S5P_GPIO_PART_SHIFT) > - > -#define S5P_GPIO_GET_PART(x) \ > - (((x) >> S5P_GPIO_PART_SHIFT) & S5P_GPIO_PART_MASK) > - > -#define S5P_GPIO_SET_PIN(x) \ > - ((x) & S5P_GPIO_PIN_MASK) > - > -#define EXYNOS4_GPIO_SET_BANK(part, bank) \ > - ((((unsigned)&(((struct exynos4_gpio_part##part *) \ > - EXYNOS4_GPIO_PART##part##_BASE)->bank) \ > - - EXYNOS4_GPIO_PART##part##_BASE) \ > - & S5P_GPIO_BANK_MASK) << S5P_GPIO_BANK_SHIFT) > - > -#define EXYNOS4X12_GPIO_SET_BANK(part, bank) \ > - ((((unsigned)&(((struct exynos4x12_gpio_part##part *) \ > - EXYNOS4X12_GPIO_PART##part##_BASE)->bank) \ > - - EXYNOS4X12_GPIO_PART##part##_BASE) \ > - & S5P_GPIO_BANK_MASK) << S5P_GPIO_BANK_SHIFT) > - > -#define EXYNOS5_GPIO_SET_BANK(part, bank) \ > - ((((unsigned)&(((struct exynos5420_gpio_part##part *) \ > - EXYNOS5420_GPIO_PART##part##_BASE)->bank) \ > - - EXYNOS5_GPIO_PART##part##_BASE) \ > - & S5P_GPIO_BANK_MASK) << S5P_GPIO_BANK_SHIFT) > - > -#define EXYNOS5420_GPIO_SET_BANK(part, bank) \ > - ((((unsigned)&(((struct exynos5420_gpio_part##part *) \ > - EXYNOS5420_GPIO_PART##part##_BASE)->bank) \ > - - EXYNOS5420_GPIO_PART##part##_BASE) \ > - & S5P_GPIO_BANK_MASK) << S5P_GPIO_BANK_SHIFT) > - > -#define exynos4_gpio_get(part, bank, pin) \ > - (S5P_GPIO_SET_PART(part) | \ > - EXYNOS4_GPIO_SET_BANK(part, bank) | \ > - S5P_GPIO_SET_PIN(pin)) > - > -#define exynos4x12_gpio_get(part, bank, pin) \ > - (S5P_GPIO_SET_PART(part) | \ > - EXYNOS4X12_GPIO_SET_BANK(part, bank) | \ > - S5P_GPIO_SET_PIN(pin)) > - > -#define exynos5420_gpio_get(part, bank, pin) \ > - (S5P_GPIO_SET_PART(part) | \ > - EXYNOS5420_GPIO_SET_BANK(part, bank) | \ > - S5P_GPIO_SET_PIN(pin)) > - > -#define exynos5_gpio_get(part, bank, pin) \ > - (S5P_GPIO_SET_PART(part) | \ > - EXYNOS5_GPIO_SET_BANK(part, bank) | \ > - S5P_GPIO_SET_PIN(pin)) > - > -static inline unsigned int s5p_gpio_base(int gpio) > +static inline unsigned int get_bank_num(void) > { > - unsigned gpio_part = S5P_GPIO_GET_PART(gpio); > - > - switch (gpio_part) { > - case 1: > - return samsung_get_base_gpio_part1(); > - case 2: > - return samsung_get_base_gpio_part2(); > - case 3: > - return samsung_get_base_gpio_part3(); > - case 4: > - return samsung_get_base_gpio_part4(); > - default: > + if (cpu_is_exynos5()) { > + if (proid_is_exynos5420()) > + return EXYNOS5420_GPIO_NUM_PARTS; > + else > + return EXYNOS5_GPIO_NUM_PARTS; > + } else if (cpu_is_exynos4()) { > + if (proid_is_exynos4412()) > + return EXYNOS4X12_GPIO_NUM_PARTS; > + else > + return EXYNOS4_GPIO_NUM_PARTS; > + } else { > return 0; > } ditto. return 0; > } > diff --git a/arch/arm/include/asm/arch-s5pc1xx/gpio.h b/arch/arm/include/asm/arch-s5pc1xx/gpio.h > index da8df74..74e9b5a 100644 > --- a/arch/arm/include/asm/arch-s5pc1xx/gpio.h > +++ b/arch/arm/include/asm/arch-s5pc1xx/gpio.h > -#define S5P_GPIO_SET_PIN(x) \ > - ((x) & S5P_GPIO_PIN_MASK) > +static inline struct gpio_info *get_gpio_data(void) > +{ > + if (cpu_is_s5pc100()) > + return s5pc100_gpio_data; > + else if (cpu_is_s5pc110()) > + return s5pc110_gpio_data; > + else > + return NULL; ditto. > +} > > -#define S5PC100_SET_BANK(bank) \ > - (((unsigned)&(((struct s5pc100_gpio *) \ > - S5PC100_GPIO_BASE)->bank) - S5PC100_GPIO_BASE) \ > - & S5P_GPIO_BANK_MASK) << S5P_GPIO_BANK_SHIFT) > +static inline unsigned int get_bank_num(void) > +{ > + if (cpu_is_s5pc100()) > + return S5PC100_GPIO_NUM_PARTS; > + else if (cpu_is_s5pc110()) > + return S5PC110_GPIO_NUM_PARTS; > + else > + return 0; ditto. > +} > > -#define S5PC110_SET_BANK(bank) \ > - ((((unsigned)&(((struct s5pc110_gpio *) \ > - S5PC110_GPIO_BASE)->bank) - S5PC110_GPIO_BASE) \ > - & S5P_GPIO_BANK_MASK) << S5P_GPIO_BANK_SHIFT) > diff --git a/board/samsung/goni/goni.c b/board/samsung/goni/goni.c > index 61b9ece..60bb998 100644 > --- a/board/samsung/goni/goni.c > +++ b/board/samsung/goni/goni.c > @@ -17,8 +17,6 @@ > > DECLARE_GLOBAL_DATA_PTR; > > -static struct s5pc110_gpio *s5pc110_gpio; > - > u32 get_board_rev(void) > { > return 0; > @@ -27,8 +25,6 @@ u32 get_board_rev(void) > int board_init(void) > { > /* Set Initial global variables */ > - s5pc110_gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE; > - > gd->bd->bi_arch_number = MACH_TYPE_GONI; > gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; > > @@ -82,7 +78,7 @@ int board_mmc_init(bd_t *bis) > int i, ret, ret_sd = 0; > > /* MASSMEMORY_EN: XMSMDATA7: GPJ2[7] output high */ > - s5p_gpio_direction_output(&s5pc110_gpio->j2, 7, 1); > + gpio_direction_output(S5PC110_GPIO_J27, 1); > > /* > * MMC0 GPIO > @@ -91,15 +87,15 @@ int board_mmc_init(bd_t *bis) > * GPG0[2] SD_0_CDn -> Not used > * GPG0[3:6] SD_0_DATA[0:3] > */ > - for (i = 0; i < 7; i++) { > + for (i = S5PC110_GPIO_G00; i < S5PC110_GPIO_G07; i++) { > if (i == 2) if (i == S5PC110_GPIO_G02) > continue; > /* GPG0[0:6] special function 2 */ > - s5p_gpio_cfg_pin(&s5pc110_gpio->g0, i, 0x2); > + gpio_cfg_pin(i, 0x2); > /* GPG0[0:6] pull disable */ > - s5p_gpio_set_pull(&s5pc110_gpio->g0, i, GPIO_PULL_NONE); > + gpio_set_pull(i, S5P_GPIO_PULL_NONE); > /* GPG0[0:6] drv 4x */ > - s5p_gpio_set_drv(&s5pc110_gpio->g0, i, GPIO_DRV_4X); > + gpio_set_drv(i, S5P_GPIO_DRV_4X); > } > > ret = s5p_mmc_init(0, 4); > @@ -110,20 +106,20 @@ int board_mmc_init(bd_t *bis) > * SD card (T_FLASH) detect and init > * T_FLASH_DETECT: EINT28: GPH3[4] input mode > */ > - s5p_gpio_cfg_pin(&s5pc110_gpio->h3, 4, GPIO_INPUT); > - s5p_gpio_set_pull(&s5pc110_gpio->h3, 4, GPIO_PULL_UP); > + gpio_cfg_pin(S5PC110_GPIO_H34, S5P_GPIO_INPUT); > + gpio_set_pull(S5PC110_GPIO_H34, S5P_GPIO_PULL_UP); > > - if (!s5p_gpio_get_value(&s5pc110_gpio->h3, 4)) { > + if (!gpio_get_value(S5PC110_GPIO_H34)) { > for (i = 0; i < 7; i++) { for (i = S5PC110_GPIO_G20; i < S5PC110_GPIO_G27; i++) > if (i == 2) i == S5PC110_GPIO_G22 > continue; > > /* GPG2[0:6] special function 2 */ > - s5p_gpio_cfg_pin(&s5pc110_gpio->g2, i, 0x2); > + gpio_cfg_pin(S5PC110_GPIO_G20 + i, 0x2); > /* GPG2[0:6] pull disable */ > - s5p_gpio_set_pull(&s5pc110_gpio->g2, i, GPIO_PULL_NONE); > + gpio_set_pull(S5PC110_GPIO_G20 + i, S5P_GPIO_PULL_NONE); > /* GPG2[0:6] drv 4x */ > - s5p_gpio_set_drv(&s5pc110_gpio->g2, i, GPIO_DRV_4X); > + gpio_set_drv(S5PC110_GPIO_G20 + i, S5P_GPIO_DRV_4X); > } > > ret_sd = s5p_mmc_init(2, 4); > diff --git a/board/samsung/smdkv310/smdkv310.c b/board/samsung/smdkv310/smdkv310.c > index 81a3060..416d0ea 100644 > --- a/board/samsung/smdkv310/smdkv310.c > +++ b/board/samsung/smdkv310/smdkv310.c > @@ -15,15 +15,13 @@ > #include > > DECLARE_GLOBAL_DATA_PTR; > -struct exynos4_gpio_part1 *gpio1; > -struct exynos4_gpio_part2 *gpio2; > > static void smc9115_pre_init(void) > { > u32 smc_bw_conf, smc_bc_conf; > > /* gpio configuration GPK0CON */ > - s5p_gpio_cfg_pin(&gpio2->y0, CONFIG_ENV_SROM_BANK, GPIO_FUNC(2)); > + gpio_cfg_pin(EXYNOS4_GPIO_Y00 + CONFIG_ENV_SROM_BANK, S5P_GPIO_FUNC(2)); > > /* Ethernet needs bus width of 16 bits */ > smc_bw_conf = SROMC_DATA16_WIDTH(CONFIG_ENV_SROM_BANK); > @@ -38,9 +36,6 @@ static void smc9115_pre_init(void) > > int board_init(void) > { > - gpio1 = (struct exynos4_gpio_part1 *) EXYNOS4_GPIO_PART1_BASE; > - gpio2 = (struct exynos4_gpio_part2 *) EXYNOS4_GPIO_PART2_BASE; > - > smc9115_pre_init(); > > gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL); > @@ -103,21 +98,21 @@ int board_mmc_init(bd_t *bis) > * GPK2[2] SD_2_CDn > * GPK2[3:6] SD_2_DATA[0:3](2) > */ > - for (i = 0; i < 7; i++) { > + for (i = EXYNOS4_GPIO_K20; i < EXYNOS4_GPIO_K27; i++) { > /* GPK2[0:6] special function 2 */ > - s5p_gpio_cfg_pin(&gpio2->k2, i, GPIO_FUNC(0x2)); > + gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2)); > > /* GPK2[0:6] drv 4x */ > - s5p_gpio_set_drv(&gpio2->k2, i, GPIO_DRV_4X); > + gpio_set_drv(i, S5P_GPIO_DRV_4X); > > /* GPK2[0:1] pull disable */ > if (i == 0 || i == 1) { (i == EXYNOS4_GPIO_K20 || i == EXYNOS4_GPIO_K21) > - s5p_gpio_set_pull(&gpio2->k2, i, GPIO_PULL_NONE); > + gpio_set_pull(i, S5P_GPIO_PULL_NONE); > continue; > } > > /* GPK2[2:6] pull up */ > - s5p_gpio_set_pull(&gpio2->k2, i, GPIO_PULL_UP); > + gpio_set_pull(i, S5P_GPIO_PULL_UP); > } > err = s5p_mmc_init(2, 4); > return err; > diff --git a/board/samsung/universal_c210/universal.c b/board/samsung/universal_c210/universal.c > index f9d71b6..9a2bd45 100644 > --- a/board/samsung/universal_c210/universal.c > +++ b/board/samsung/universal_c210/universal.c > @@ -27,8 +27,6 @@ > > DECLARE_GLOBAL_DATA_PTR; > > -struct exynos4_gpio_part1 *gpio1; > -struct exynos4_gpio_part2 *gpio2; > unsigned int board_rev; > > u32 get_board_rev(void) > @@ -312,35 +310,35 @@ void exynos_cfg_lcd_gpio(void) > > for (i = 0; i < 8; i++) { > /* set GPF0,1,2[0:7] for RGB Interface and Data lines (32bit) */ > - s5p_gpio_cfg_pin(&gpio1->f0, i, GPIO_FUNC(2)); > - s5p_gpio_cfg_pin(&gpio1->f1, i, GPIO_FUNC(2)); > - s5p_gpio_cfg_pin(&gpio1->f2, i, GPIO_FUNC(2)); > + gpio_cfg_pin(EXYNOS4_GPIO_F00 + i, S5P_GPIO_FUNC(2)); > + gpio_cfg_pin(EXYNOS4_GPIO_F10 + i, S5P_GPIO_FUNC(2)); > + gpio_cfg_pin(EXYNOS4_GPIO_F20 + i, S5P_GPIO_FUNC(2)); > /* pull-up/down disable */ > - s5p_gpio_set_pull(&gpio1->f0, i, GPIO_PULL_NONE); > - s5p_gpio_set_pull(&gpio1->f1, i, GPIO_PULL_NONE); > - s5p_gpio_set_pull(&gpio1->f2, i, GPIO_PULL_NONE); > + gpio_set_pull(EXYNOS4_GPIO_F00 + i, S5P_GPIO_PULL_NONE); > + gpio_set_pull(EXYNOS4_GPIO_F10 + i, S5P_GPIO_PULL_NONE); > + gpio_set_pull(EXYNOS4_GPIO_F20 + i, S5P_GPIO_PULL_NONE); > > /* drive strength to max (24bit) */ > - s5p_gpio_set_drv(&gpio1->f0, i, GPIO_DRV_4X); > - s5p_gpio_set_rate(&gpio1->f0, i, GPIO_DRV_SLOW); > - s5p_gpio_set_drv(&gpio1->f1, i, GPIO_DRV_4X); > - s5p_gpio_set_rate(&gpio1->f1, i, GPIO_DRV_SLOW); > - s5p_gpio_set_drv(&gpio1->f2, i, GPIO_DRV_4X); > - s5p_gpio_set_rate(&gpio1->f0, i, GPIO_DRV_SLOW); > + gpio_set_drv(EXYNOS4_GPIO_F00 + i, S5P_GPIO_DRV_4X); > + gpio_set_rate(EXYNOS4_GPIO_F00 + i, S5P_GPIO_DRV_SLOW); > + gpio_set_drv(EXYNOS4_GPIO_F10 + i, S5P_GPIO_DRV_4X); > + gpio_set_rate(EXYNOS4_GPIO_F10 + i, S5P_GPIO_DRV_SLOW); > + gpio_set_drv(EXYNOS4_GPIO_F20 + i, S5P_GPIO_DRV_4X); > + gpio_set_rate(EXYNOS4_GPIO_F00 + i, S5P_GPIO_DRV_SLOW); > } > > - for (i = 0; i < f3_end; i++) { > + for (i = EXYNOS4_GPIO_F30; i < (EXYNOS4_GPIO_F30 + f3_end); i++) { > /* set GPF3[0:3] for RGB Interface and Data lines (32bit) */ > - s5p_gpio_cfg_pin(&gpio1->f3, i, GPIO_FUNC(2)); > + gpio_cfg_pin(i, S5P_GPIO_FUNC(2)); > /* pull-up/down disable */ > - s5p_gpio_set_pull(&gpio1->f3, i, GPIO_PULL_NONE); > + gpio_set_pull(i, S5P_GPIO_PULL_NONE); > /* drive strength to max (24bit) */ > - s5p_gpio_set_drv(&gpio1->f3, i, GPIO_DRV_4X); > - s5p_gpio_set_rate(&gpio1->f3, i, GPIO_DRV_SLOW); > + missing set the drv? > + gpio_set_rate(i, S5P_GPIO_DRV_SLOW); > } > > /* gpio pad configuration for LCD reset. */ > - s5p_gpio_cfg_pin(&gpio2->y4, 5, GPIO_OUTPUT); > + gpio_cfg_pin(EXYNOS4_GPIO_Y45, S5P_GPIO_OUTPUT); > > spi_init(); > } > diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c > index 11a0472..49e99cb 100644 > --- a/drivers/gpio/s5p_gpio.c > +++ b/drivers/gpio/s5p_gpio.c > @@ -8,11 +8,9 @@ > #include > #include > #include > +#include > > -#define S5P_GPIO_GET_BANK(x) ((x >> S5P_GPIO_BANK_SHIFT) \ > - & S5P_GPIO_BANK_MASK) > - > -#define S5P_GPIO_GET_PIN(x) (x & S5P_GPIO_PIN_MASK) > +#define S5P_GPIO_GET_PIN(x) (x % GPIO_PER_BANK) > > #define CON_MASK(x) (0xf << ((x) << 2)) > #define CON_SFR(x, v) ((v) << ((x) << 2)) > @@ -28,7 +26,100 @@ > #define RATE_MASK(x) (0x1 << (x + 16)) > #define RATE_SET(x) (0x1 << (x + 16)) > > -void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg) > +#define name_to_gpio(n) s5p_name_to_gpio(n) > +static inline int s5p_name_to_gpio(const char *name) > +{ > + unsigned num, irregular_set_number, irregular_bank_base; > + const struct gpio_name_num_table *tabp; > + char this_bank, bank_name, irregular_bank_name; > + char *endp; > + > + /* > + * The gpio name starts with either 'g' ot 'gp' followed by the bank > + * name character. Skip one or two characters depending on the prefix. > + */ so, why don't you check name[0]? > + if (name[1] == 'p') > + name += 2; > + else > + name++; > + bank_name = *name++; I think you should check the address (the name) before you access. > + if (!*name) > + return -1; /* At least one digit is required/expected. */ > + > + /* > + * On both exynos5 and exynos5420 architectures there is a bank of > + * GPIOs which does not fall into the regular address pattern. Those > + * banks are c4 on Exynos5 and y7 on Exynos5420. The rest of the below > + * assignments help to handle these irregularities. > + */ > +#if defined(CONFIG_EXYNOS4) || defined(CONFIG_EXYNOS5) > + if (cpu_is_exynos5()) { > + if (proid_is_exynos5420()) { > + tabp = exynos5420_gpio_table; > + irregular_bank_name = 'y'; > + irregular_set_number = '7'; > + irregular_bank_base = EXYNOS5420_GPIO_Y70; > + } else { > + tabp = exynos5_gpio_table; > + irregular_bank_name = 'c'; > + irregular_set_number = '4'; > + irregular_bank_base = EXYNOS5_GPIO_C40; > + } > + } else { > + if (proid_is_exynos4412()) > + tabp = exynos4x12_gpio_table; > + else > + tabp = exynos4_gpio_table; > + irregular_bank_name = 0; > + irregular_set_number = 0; > + irregular_bank_base = 0; > + } > +#else > + if (cpu_is_s5pc110()) > + tabp = s5pc110_gpio_table; > + else > + tabp = s5pc100_gpio_table; > + irregular_bank_name = 0; > + irregular_set_number = 0; > + irregular_bank_base = 0; > +#endif > + > + this_bank = tabp->bank; > + do { > + if (bank_name == this_bank) { > + unsigned pin_index; /* pin number within the bank */ > + if ((bank_name == irregular_bank_name) && > + (name[0] == irregular_set_number)) { > + pin_index = name[1] - '0'; > + /* Irregular sets have 8 pins. */ > + if (pin_index >= GPIO_PER_BANK) > + return -1; > + num = irregular_bank_base + pin_index; > + } else { > + pin_index = simple_strtoul(name, &endp, 8); > + pin_index -= tabp->bank_offset; > + /* > + * Sanity check: bunk 'z' has no set number, > + * for all other banks there must be exactly > + * two octal digits, and the resulting number > + * should not exceed the number of pins in the > + * bank. > + */ > + if (((bank_name != 'z') && !name[1]) || > + *endp || > + (pin_index >= tabp->bank_size)) > + return -1; > + num = tabp->base + pin_index; > + } > + return num; > + } > + this_bank = (++tabp)->bank; > + } while (this_bank); > + > + return -1; > +} > + > +static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg) > { > unsigned int value; > > @@ -38,18 +129,7 @@ void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg) > writel(value, &bank->con); > } > > -void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en) > -{ > - s5p_gpio_cfg_pin(bank, gpio, GPIO_OUTPUT); > - s5p_gpio_set_value(bank, gpio, en); > -} > - > -void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio) > -{ > - s5p_gpio_cfg_pin(bank, gpio, GPIO_INPUT); > -} > - > -void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en) > +static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en) > { > unsigned int value; > > @@ -60,7 +140,19 @@ void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en) > writel(value, &bank->dat); > } > > -unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio) > +static void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, > + int gpio, int en) > +{ > + s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_OUTPUT); > + s5p_gpio_set_value(bank, gpio, en); > +} > + > +static void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio) > +{ > + s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_INPUT); > +} > + > +static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio) > { > unsigned int value; > > @@ -68,7 +160,7 @@ unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio) > return !!(value & DAT_MASK(gpio)); > } > > -void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode) > +static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode) > { > unsigned int value; > > @@ -76,8 +168,8 @@ void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode) > value &= ~PULL_MASK(gpio); > > switch (mode) { > - case GPIO_PULL_DOWN: > - case GPIO_PULL_UP: > + case S5P_GPIO_PULL_DOWN: > + case S5P_GPIO_PULL_UP: > value |= PULL_MODE(gpio, mode); > break; > default: > @@ -87,7 +179,7 @@ void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode) > writel(value, &bank->pull); > } > > -void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode) > +static void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode) > { > unsigned int value; > > @@ -95,10 +187,10 @@ void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode) > value &= ~DRV_MASK(gpio); > > switch (mode) { > - case GPIO_DRV_1X: > - case GPIO_DRV_2X: > - case GPIO_DRV_3X: > - case GPIO_DRV_4X: > + case S5P_GPIO_DRV_1X: > + case S5P_GPIO_DRV_2X: > + case S5P_GPIO_DRV_3X: > + case S5P_GPIO_DRV_4X: > value |= DRV_SET(gpio, mode); > break; > default: > @@ -108,7 +200,7 @@ void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode) > writel(value, &bank->drv); > } > > -void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode) > +static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode) > { > unsigned int value; > > @@ -116,8 +208,8 @@ void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode) > value &= ~RATE_MASK(gpio); > > switch (mode) { > - case GPIO_DRV_FAST: > - case GPIO_DRV_SLOW: > + case S5P_GPIO_DRV_FAST: > + case S5P_GPIO_DRV_SLOW: > value |= RATE_SET(gpio); > break; > default: > @@ -127,12 +219,26 @@ void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode) > writel(value, &bank->drv); > } > > -struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio) > +struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio) > { > - unsigned bank = S5P_GPIO_GET_BANK(gpio); > - unsigned base = s5p_gpio_base(gpio); > - > - return (struct s5p_gpio_bank *)(base + bank); > + const struct gpio_info *data; > + unsigned int upto; > + int i, count; > + > + data = get_gpio_data(); > + count = get_bank_num(); > + for (i = upto = 0; i < count; > + i++, upto = data->max_gpio, data++) { Could you please move upto = 0, upto = data->max_gpio, data++ to somewhere for code readability? please make simple for statement. for (i = upto; i + debug("i=%d, upto=%d\n", i, upto); > + if (gpio < data->max_gpio) { > + struct s5p_gpio_bank *bank; > + bank = (struct s5p_gpio_bank *)data->reg_addr; > + bank += (gpio - upto) / GPIO_PER_BANK; > + debug("gpio=%d, bank=%p\n", gpio, bank); > + return bank; > + } > + } > + return NULL; > } > > int s5p_gpio_get_pin(unsigned gpio) > @@ -179,3 +285,27 @@ int gpio_set_value(unsigned gpio, int value) > > return 0; > } > + > +void gpio_set_pull(int gpio, int mode) > +{ > + s5p_gpio_set_pull(s5p_gpio_get_bank(gpio), > + s5p_gpio_get_pin(gpio), mode); > +} > + > +void gpio_set_drv(int gpio, int mode) > +{ > + s5p_gpio_set_drv(s5p_gpio_get_bank(gpio), > + s5p_gpio_get_pin(gpio), mode); > +} > + > +void gpio_cfg_pin(int gpio, int cfg) > +{ > + s5p_gpio_cfg_pin(s5p_gpio_get_bank(gpio), > + s5p_gpio_get_pin(gpio), cfg); > +} > + > +void gpio_set_rate(int gpio, int mode) > +{ > + s5p_gpio_set_rate(s5p_gpio_get_bank(gpio), > + s5p_gpio_get_pin(gpio), mode); > +} > Thanks, Minkyu Kang.