From mboxrd@z Thu Jan 1 00:00:00 1970 From: Przemyslaw Marczak Date: Mon, 14 Apr 2014 17:19:13 +0200 Subject: [U-Boot] [PATCH v6 3/4] EXYNOS5: GPIO: Support GPIO Command for EXYNOS5 In-Reply-To: <1397295812-4010-4-git-send-email-Akshay.s@samsung.com> References: <1397295812-4010-1-git-send-email-Akshay.s@samsung.com> <1397295812-4010-4-git-send-email-Akshay.s@samsung.com> Message-ID: <534BFC71.8010206@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 Hi, On 04/12/2014 11:43 AM, Akshay Saraswat wrote: > From: Rajeshwari Shinde > > This patch adds support for name to gpio conversion in s5p_gpio > to enable gpio command EXYNOS 5250 & 5420. > 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: Rajeshwari Shinde > Signed-off-by: Akshay Saraswat > --- > arch/arm/include/asm/arch-exynos/gpio.h | 28 +++++++++ > drivers/gpio/s5p_gpio.c | 105 ++++++++++++++++++++++++++++++++ > 2 files changed, 133 insertions(+) > > diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h > index 697e6f3..3736a22 100644 > --- a/arch/arm/include/asm/arch-exynos/gpio.h > +++ b/arch/arm/include/asm/arch-exynos/gpio.h > @@ -1038,6 +1038,34 @@ static inline unsigned int get_bank_num(void) > } > } > > +/* > + * This structure helps mapping symbolic GPIO names into indices from > + * exynos5_gpio_pin/exynos5420_gpio_pin enums. > + * > + * By convention, symbolic GPIO name is defined as follows: > + * > + * g[p], where > + * p is optional > + * - a single character bank name, as defined by the SOC > + * - a single digit set number > + * - bit number within the set (in 0..7 range). > + * > + * essentially form an octal number of the GPIO pin within the bank > + * space. On the 5420 architecture some banks' sets do not start not from zero > + * ('d' starts from 1 and 'j' starts from 4). To compensate for that and > + * maintain flat number space withoout holes, those banks use offsets to be > + * deducted from the pin number. > + */ > +struct gpio_name_num_table { > + char bank; /* bank name symbol */ > + u8 bank_size; /* total number of pins in the bank */ > + char bank_offset; /* offset of the first bank's pin */ > + unsigned int base; /* index of the first bank's pin in the enum */ > +}; > + > +int s5p_name_to_gpio(const char *name); > +#define name_to_gpio(n) s5p_name_to_gpio(n) > + > void gpio_cfg_pin(int gpio, int cfg); > void gpio_set_pull(int gpio, int mode); > void gpio_set_drv(int gpio, int mode); > diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c > index b1b6fbe..9a80b0c 100644 > --- a/drivers/gpio/s5p_gpio.c > +++ b/drivers/gpio/s5p_gpio.c > @@ -28,6 +28,111 @@ > #define RATE_MASK(x) (0x1 << (x + 16)) > #define RATE_SET(x) (0x1 << (x + 16)) > This driver is common so you can't put here SOC specific code. This is also the reason of build break for s5pc1xx architecture. It should be initialized in arch/arm/include/asm/arch-exynos/gpio.h. The same should be defined for Exynos4 and for s5pc1xx: in arch/arm/include/asm/arch-s5pc1xx/gpio.h. This also can require introduce a s5p_gpio.h header with structure gpio_name_num_table. And maybe better name for this structure type is gpio_name_to_num ? > +#define GPIO_ENTRY(name, base, top, offset) { name, top - base, offset, base } > +static const struct gpio_name_num_table exynos5_gpio_table[] = { > + GPIO_ENTRY('a', EXYNOS5_GPIO_A00, EXYNOS5_GPIO_B00, 0), > + GPIO_ENTRY('b', EXYNOS5_GPIO_B00, EXYNOS5_GPIO_C00, 0), > + GPIO_ENTRY('c', EXYNOS5_GPIO_C00, EXYNOS5_GPIO_D00, 0), > + GPIO_ENTRY('d', EXYNOS5_GPIO_D00, EXYNOS5_GPIO_Y00, 0), > + GPIO_ENTRY('y', EXYNOS5_GPIO_Y00, EXYNOS5_GPIO_C40, 0), > + GPIO_ENTRY('x', EXYNOS5_GPIO_X00, EXYNOS5_GPIO_E00, 0), > + GPIO_ENTRY('e', EXYNOS5_GPIO_E00, EXYNOS5_GPIO_F00, 0), > + GPIO_ENTRY('f', EXYNOS5_GPIO_F00, EXYNOS5_GPIO_G00, 0), > + GPIO_ENTRY('g', EXYNOS5_GPIO_G00, EXYNOS5_GPIO_H00, 0), > + GPIO_ENTRY('h', EXYNOS5_GPIO_H00, EXYNOS5_GPIO_V00, 0), > + GPIO_ENTRY('v', EXYNOS5_GPIO_V00, EXYNOS5_GPIO_Z0, 0), > + GPIO_ENTRY('z', EXYNOS5_GPIO_Z0, EXYNOS5_GPIO_MAX_PORT, 0), > + { 0 } > +}; > + > +static const struct gpio_name_num_table exynos5420_gpio_table[] = { > + GPIO_ENTRY('a', EXYNOS5420_GPIO_A00, EXYNOS5420_GPIO_B00, 0), > + GPIO_ENTRY('b', EXYNOS5420_GPIO_B00, EXYNOS5420_GPIO_H00, 0), > + GPIO_ENTRY('h', EXYNOS5420_GPIO_H00, EXYNOS5420_GPIO_Y70, 0), > + GPIO_ENTRY('x', EXYNOS5420_GPIO_X00, EXYNOS5420_GPIO_C00, 0), > + GPIO_ENTRY('c', EXYNOS5420_GPIO_C00, EXYNOS5420_GPIO_D10, 0), > + GPIO_ENTRY('d', EXYNOS5420_GPIO_D10, EXYNOS5420_GPIO_Y00, 010), > + GPIO_ENTRY('y', EXYNOS5420_GPIO_Y00, EXYNOS5420_GPIO_E00, 0), > + GPIO_ENTRY('e', EXYNOS5420_GPIO_E00, EXYNOS5420_GPIO_F00, 0), > + GPIO_ENTRY('f', EXYNOS5420_GPIO_F00, EXYNOS5420_GPIO_G00, 0), > + GPIO_ENTRY('g', EXYNOS5420_GPIO_G00, EXYNOS5420_GPIO_J40, 0), > + GPIO_ENTRY('j', EXYNOS5420_GPIO_J40, EXYNOS5420_GPIO_Z0, 040), > + GPIO_ENTRY('z', EXYNOS5420_GPIO_Z0, EXYNOS5420_GPIO_MAX_PORT, 0), > + { 0 } > +}; > + > +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. > + */ > + if (name[1] == 'p') > + name += 2; > + else > + name++; > + bank_name = *name++; > + 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. > + */ We can't check cpu id for s5pc1xx when exynos is compiled so you shouldn't check proid in this driver, but you can do this in arch-XXXX/gpio.h. So then this is a still s5p common driver. > + 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; > + } > + > + 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; > +} > + > void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg) > { > unsigned int value; > You made a lot of good job. Please just make this driver more common, then I will implement and test this feature for exynos4 and s5pc1xx boards. Thanks -- Przemyslaw Marczak Samsung R&D Institute Poland Samsung Electronics p.marczak at samsung.com