Patchwork [U-Boot,4/4,V3] EXYNOS5: GPIO: Enable GPIO Command for EXYNOS5

login
register
mail settings
Submitter Rajeshwari Birje
Date Feb. 7, 2013, noon
Message ID <1360238430-27715-5-git-send-email-rajeshwari.s@samsung.com>
Download mbox | patch
Permalink /patch/218903/
State Changes Requested
Delegated to: Minkyu Kang
Headers show

Comments

Rajeshwari Birje - Feb. 7, 2013, noon
This patch enables GPIO Command for EXYNOS5.
Function has been added to asm/gpio.h to decode the
input gpio name to gpio number.
example: gpio set gpa00

Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
---
Changes in V2:
        - New patch
Changes in V3:
	- Created a table to know the base address of input bank.
 arch/arm/cpu/armv7/exynos/pinmux.c      |   50 +++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-exynos/gpio.h |    8 +++++
 include/configs/exynos5250-dt.h         |    1 +
 3 files changed, 59 insertions(+), 0 deletions(-)
Minkyu Kang - Feb. 8, 2013, 4:31 a.m.
Dear Rajeshwari,

On 07/02/13 21:00, Rajeshwari Shinde wrote:
> This patch enables GPIO Command for EXYNOS5.
> Function has been added to asm/gpio.h to decode the
> input gpio name to gpio number.
> example: gpio set gpa00
> 
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> ---
> Changes in V2:
>         - New patch
> Changes in V3:
> 	- Created a table to know the base address of input bank.
>  arch/arm/cpu/armv7/exynos/pinmux.c      |   50 +++++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-exynos/gpio.h |    8 +++++
>  include/configs/exynos5250-dt.h         |    1 +
>  3 files changed, 59 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
> index 28b0306..a01ce0c 100644
> --- a/arch/arm/cpu/armv7/exynos/pinmux.c
> +++ b/arch/arm/cpu/armv7/exynos/pinmux.c
> @@ -27,6 +27,21 @@
>  #include <asm/arch/pinmux.h>
>  #include <asm/arch/sromc.h>
>  
> +struct gpio_name_num_table exynos5_gpio_table[] = {
> +	{ 'a', GPIO_A00 },
> +	{ 'b', GPIO_B00 },
> +	{ 'c', GPIO_C00 },
> +	{ 'd', GPIO_D00 },
> +	{ 'y', GPIO_Y00 },
> +	{ 'x', GPIO_X00 },
> +	{ 'e', GPIO_E00 },
> +	{ 'f', GPIO_F00 },
> +	{ 'g', GPIO_G00 },
> +	{ 'h', GPIO_H00 },
> +	{ 'v', GPIO_V00 },
> +	{ 'z', GPIO_Z0 },
> +};
> +
>  static void exynos5_uart_config(int peripheral)
>  {
>  	int i, start, count;
> @@ -448,3 +463,38 @@ int pinmux_decode_periph_id(const void *blob, int node)
>  		return PERIPH_ID_NONE;
>  }
>  #endif
> +
> +int name_to_gpio(const char *name)

This function should be support exynos4 also.

> +{
> +	unsigned int num, i;
> +
> +	name++;

Please check NULL pointer before you use it.
And I think you should check length of name.
"name++" seems to dangerous.

How about parse the string to bank and number before you use?

> +
> +	if (*name == 'p')
> +		++name;

else?
is not error?

> +
> +	for (i = 0; i < ARRAY_SIZE(exynos5_gpio_table); i++) {
> +		if (*name == exynos5_gpio_table[i].bank) {
> +			if (*name == 'c') {
> +				name++;
> +				num = simple_strtoul(name, NULL, 10);
> +				if (num >= 40) {
> +					num = GPIO_C40 + (num - 40);
> +				} else {
> +					num = simple_strtoul(name, NULL, 8);
> +					num = exynos5_gpio_table[i].base + num;
> +				}
> +			} else {
> +				name++;
> +				num = simple_strtoul(name, NULL, 8);
> +				num = exynos5_gpio_table[i].base + num;
> +			}
> +			break;

			return num;

> +		}
> +	}

	return -1;

> +
> +	if (i == ARRAY_SIZE(exynos5_gpio_table))
> +		return -1;
> +	
> +	return num;
> +}
> diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h
> index 38b959d..016a112 100644
> --- a/arch/arm/include/asm/arch-exynos/gpio.h
> +++ b/arch/arm/include/asm/arch-exynos/gpio.h
> @@ -657,6 +657,14 @@ static inline unsigned int s5p_gpio_part_max(int nr)
>  void gpio_cfg_pin(int gpio, int cfg);
>  void gpio_set_pull(int gpio, int mode);
>  void gpio_set_drv(int gpio, int mode);
> +
> +struct gpio_name_num_table {
> +	char bank;
> +	unsigned int base;
> +};
> +
> +int name_to_gpio(const char *name);
> +#define name_to_gpio(n) name_to_gpio(n)
>  #endif
>  
>  /* Pin configurations */
> diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h
> index b1b24a9..a32cc3e 100644
> --- a/include/configs/exynos5250-dt.h
> +++ b/include/configs/exynos5250-dt.h
> @@ -113,6 +113,7 @@
>  #define CONFIG_CMD_EXT2
>  #define CONFIG_CMD_FAT
>  #define CONFIG_CMD_NET
> +#define CONFIG_CMD_GPIO
>  
>  #define CONFIG_BOOTDELAY		3
>  #define CONFIG_ZERO_BOOTDELAY_CHECK
> 

Thanks.
Minkyu Kang.
Simon Glass - Feb. 8, 2013, 4:08 p.m.
Hi Rajeshwari,

On Thu, Feb 7, 2013 at 4:00 AM, Rajeshwari Shinde
<rajeshwari.s@samsung.com> wrote:
> This patch enables GPIO Command for EXYNOS5.
> Function has been added to asm/gpio.h to decode the
> input gpio name to gpio number.
> example: gpio set gpa00
>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> ---
> Changes in V2:
>         - New patch
> Changes in V3:
>         - Created a table to know the base address of input bank.
>  arch/arm/cpu/armv7/exynos/pinmux.c      |   50 +++++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-exynos/gpio.h |    8 +++++
>  include/configs/exynos5250-dt.h         |    1 +
>  3 files changed, 59 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
> index 28b0306..a01ce0c 100644
> --- a/arch/arm/cpu/armv7/exynos/pinmux.c
> +++ b/arch/arm/cpu/armv7/exynos/pinmux.c
> @@ -27,6 +27,21 @@
>  #include <asm/arch/pinmux.h>
>  #include <asm/arch/sromc.h>
>
> +struct gpio_name_num_table exynos5_gpio_table[] = {
> +       { 'a', GPIO_A00 },
> +       { 'b', GPIO_B00 },
> +       { 'c', GPIO_C00 },
> +       { 'd', GPIO_D00 },
> +       { 'y', GPIO_Y00 },
> +       { 'x', GPIO_X00 },
> +       { 'e', GPIO_E00 },
> +       { 'f', GPIO_F00 },
> +       { 'g', GPIO_G00 },
> +       { 'h', GPIO_H00 },
> +       { 'v', GPIO_V00 },
> +       { 'z', GPIO_Z0 },
> +};
> +
>  static void exynos5_uart_config(int peripheral)
>  {
>         int i, start, count;
> @@ -448,3 +463,38 @@ int pinmux_decode_periph_id(const void *blob, int node)
>                 return PERIPH_ID_NONE;
>  }
>  #endif
> +
> +int name_to_gpio(const char *name)
> +{
> +       unsigned int num, i;
> +

Perhaps check name is at least 3 chars here?

> +       name++;
> +
> +       if (*name == 'p')
> +               ++name;
> +
> +       for (i = 0; i < ARRAY_SIZE(exynos5_gpio_table); i++) {
> +               if (*name == exynos5_gpio_table[i].bank) {
> +                       if (*name == 'c') {
> +                               name++;
> +                               num = simple_strtoul(name, NULL, 10);
> +                               if (num >= 40) {
> +                                       num = GPIO_C40 + (num - 40);
> +                               } else {
> +                                       num = simple_strtoul(name, NULL, 8);
> +                                       num = exynos5_gpio_table[i].base + num;

Here can you somehow check that the number is valid. For example we
want 'a99' to give an error. Maybe your table needs to hold the number
of GPIOs that each letter has. Then you can return -1 on error.

> +                               }
> +                       } else {
> +                               name++;
> +                               num = simple_strtoul(name, NULL, 8);
> +                               num = exynos5_gpio_table[i].base + num;
> +                       }
> +                       break;
> +               }
> +       }
> +
> +       if (i == ARRAY_SIZE(exynos5_gpio_table))
> +               return -1;
> +
> +       return num;
> +}
> diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h
> index 38b959d..016a112 100644
> --- a/arch/arm/include/asm/arch-exynos/gpio.h
> +++ b/arch/arm/include/asm/arch-exynos/gpio.h
> @@ -657,6 +657,14 @@ static inline unsigned int s5p_gpio_part_max(int nr)
>  void gpio_cfg_pin(int gpio, int cfg);
>  void gpio_set_pull(int gpio, int mode);
>  void gpio_set_drv(int gpio, int mode);
> +
> +struct gpio_name_num_table {
> +       char bank;
> +       unsigned int base;

add comment: this is the starting GPIO number of this bank: e.g. GPIO_A00

> +};
> +
> +int name_to_gpio(const char *name);
> +#define name_to_gpio(n) name_to_gpio(n)

What does this #define do?

>  #endif
>
>  /* Pin configurations */
> diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h
> index b1b24a9..a32cc3e 100644
> --- a/include/configs/exynos5250-dt.h
> +++ b/include/configs/exynos5250-dt.h
> @@ -113,6 +113,7 @@
>  #define CONFIG_CMD_EXT2
>  #define CONFIG_CMD_FAT
>  #define CONFIG_CMD_NET
> +#define CONFIG_CMD_GPIO
>
>  #define CONFIG_BOOTDELAY               3
>  #define CONFIG_ZERO_BOOTDELAY_CHECK
> --
> 1.7.4.4
>

Regards,
Simon

Patch

diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
index 28b0306..a01ce0c 100644
--- a/arch/arm/cpu/armv7/exynos/pinmux.c
+++ b/arch/arm/cpu/armv7/exynos/pinmux.c
@@ -27,6 +27,21 @@ 
 #include <asm/arch/pinmux.h>
 #include <asm/arch/sromc.h>
 
+struct gpio_name_num_table exynos5_gpio_table[] = {
+	{ 'a', GPIO_A00 },
+	{ 'b', GPIO_B00 },
+	{ 'c', GPIO_C00 },
+	{ 'd', GPIO_D00 },
+	{ 'y', GPIO_Y00 },
+	{ 'x', GPIO_X00 },
+	{ 'e', GPIO_E00 },
+	{ 'f', GPIO_F00 },
+	{ 'g', GPIO_G00 },
+	{ 'h', GPIO_H00 },
+	{ 'v', GPIO_V00 },
+	{ 'z', GPIO_Z0 },
+};
+
 static void exynos5_uart_config(int peripheral)
 {
 	int i, start, count;
@@ -448,3 +463,38 @@  int pinmux_decode_periph_id(const void *blob, int node)
 		return PERIPH_ID_NONE;
 }
 #endif
+
+int name_to_gpio(const char *name)
+{
+	unsigned int num, i;
+
+	name++;
+
+	if (*name == 'p')
+		++name;
+
+	for (i = 0; i < ARRAY_SIZE(exynos5_gpio_table); i++) {
+		if (*name == exynos5_gpio_table[i].bank) {
+			if (*name == 'c') {
+				name++;
+				num = simple_strtoul(name, NULL, 10);
+				if (num >= 40) {
+					num = GPIO_C40 + (num - 40);
+				} else {
+					num = simple_strtoul(name, NULL, 8);
+					num = exynos5_gpio_table[i].base + num;
+				}
+			} else {
+				name++;
+				num = simple_strtoul(name, NULL, 8);
+				num = exynos5_gpio_table[i].base + num;
+			}
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(exynos5_gpio_table))
+		return -1;
+	
+	return num;
+}
diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h
index 38b959d..016a112 100644
--- a/arch/arm/include/asm/arch-exynos/gpio.h
+++ b/arch/arm/include/asm/arch-exynos/gpio.h
@@ -657,6 +657,14 @@  static inline unsigned int s5p_gpio_part_max(int nr)
 void gpio_cfg_pin(int gpio, int cfg);
 void gpio_set_pull(int gpio, int mode);
 void gpio_set_drv(int gpio, int mode);
+
+struct gpio_name_num_table {
+	char bank;
+	unsigned int base;
+};
+
+int name_to_gpio(const char *name);
+#define name_to_gpio(n) name_to_gpio(n)
 #endif
 
 /* Pin configurations */
diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h
index b1b24a9..a32cc3e 100644
--- a/include/configs/exynos5250-dt.h
+++ b/include/configs/exynos5250-dt.h
@@ -113,6 +113,7 @@ 
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_FAT
 #define CONFIG_CMD_NET
+#define CONFIG_CMD_GPIO
 
 #define CONFIG_BOOTDELAY		3
 #define CONFIG_ZERO_BOOTDELAY_CHECK