
Hi,
On 04/12/2014 11:43 AM, Akshay Saraswat wrote:
From: Rajeshwari Shinde rajeshwari.s@samsung.com
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 rajeshwari.s@samsung.com Signed-off-by: Akshay Saraswat akshay.s@samsung.com
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]<bank><set><bit>, where
- p is optional
- <bank> - a single character bank name, as defined by the SOC
- <set> - a single digit set number
- <bit> - bit number within the set (in 0..7 range).
- <set><bit> 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