From 28d27cf4ce8378180eda32aa7d8e778c9e72a54f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 2 Feb 2009 15:27:55 -0500 Subject: [PATCH] [ARM] Orion: make gpio /input/output validation separate Especially on Kirkwood, a couple GPIOs are actually only output capable. Let's separate the ability to configure a GPIO as input or output to accommodate this restriction. Signed-off-by: Nicolas Pitre --- arch/arm/plat-orion/gpio.c | 29 +++++++++++++++++-------- arch/arm/plat-orion/include/plat/gpio.h | 6 ++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index 0d12c2164766..32eb9e33bebb 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -19,7 +19,8 @@ static DEFINE_SPINLOCK(gpio_lock); static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ -static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)]; +static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)]; +static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)]; static inline void __set_direction(unsigned pin, int input) { @@ -53,7 +54,7 @@ int gpio_direction_input(unsigned pin) { unsigned long flags; - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_input)) { pr_debug("%s: invalid GPIO %d\n", __func__, pin); return -EINVAL; } @@ -83,7 +84,7 @@ int gpio_direction_output(unsigned pin, int value) unsigned long flags; u32 u; - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_output)) { pr_debug("%s: invalid GPIO %d\n", __func__, pin); return -EINVAL; } @@ -161,7 +162,9 @@ int gpio_request(unsigned pin, const char *label) unsigned long flags; int ret; - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + if (pin >= GPIO_MAX || + !(test_bit(pin, gpio_valid_input) || + test_bit(pin, gpio_valid_output))) { pr_debug("%s: invalid GPIO %d\n", __func__, pin); return -EINVAL; } @@ -183,7 +186,9 @@ EXPORT_SYMBOL(gpio_request); void gpio_free(unsigned pin) { - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + if (pin >= GPIO_MAX || + !(test_bit(pin, gpio_valid_input) || + test_bit(pin, gpio_valid_output))) { pr_debug("%s: invalid GPIO %d\n", __func__, pin); return; } @@ -208,12 +213,18 @@ void __init orion_gpio_set_unused(unsigned pin) __set_direction(pin, 0); } -void __init orion_gpio_set_valid(unsigned pin, int valid) +void __init orion_gpio_set_valid(unsigned pin, int mode) { - if (valid) - __set_bit(pin, gpio_valid); + if (mode == 1) + mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK; + if (mode & GPIO_INPUT_OK) + __set_bit(pin, gpio_valid_input); else - __clear_bit(pin, gpio_valid); + __clear_bit(pin, gpio_valid_input); + if (mode & GPIO_OUTPUT_OK) + __set_bit(pin, gpio_valid_output); + else + __clear_bit(pin, gpio_valid_output); } void orion_gpio_set_blink(unsigned pin, int blink) diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h index ec743e82c876..33f6c6aec185 100644 --- a/arch/arm/plat-orion/include/plat/gpio.h +++ b/arch/arm/plat-orion/include/plat/gpio.h @@ -25,9 +25,13 @@ void gpio_set_value(unsigned pin, int value); * Orion-specific GPIO API extensions. */ void orion_gpio_set_unused(unsigned pin); -void orion_gpio_set_valid(unsigned pin, int valid); void orion_gpio_set_blink(unsigned pin, int blink); +#define GPIO_BIDI_OK (1 << 0) +#define GPIO_INPUT_OK (1 << 1) +#define GPIO_OUTPUT_OK (1 << 2) +void orion_gpio_set_valid(unsigned pin, int mode); + /* * GPIO interrupt handling. */ -- 2.39.5