diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/mxc_gpio.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c index 815407b..a49d204 100644 --- a/drivers/gpio/mxc_gpio.c +++ b/drivers/gpio/mxc_gpio.c @@ -14,6 +14,11 @@ #include <asm/arch/imx-regs.h> #include <asm/gpio.h> #include <asm/io.h> +#include <errno.h> +#ifdef CONFIG_MXC_RDC +#include <asm/imx-common/rdc-sema.h> +#include <asm/arch/imx-rdc.h> +#endif enum mxc_gpio_direction { MXC_GPIO_DIRECTION_IN, @@ -52,6 +57,27 @@ static unsigned long gpio_ports[] = { #endif }; +#ifdef CONFIG_MXC_RDC +static unsigned int gpio_rdc[] = { + RDC_PER_GPIO1, + RDC_PER_GPIO2, + RDC_PER_GPIO3, + RDC_PER_GPIO4, + RDC_PER_GPIO5, + RDC_PER_GPIO6, + RDC_PER_GPIO7, +}; + +#define RDC_CHECK(x) imx_rdc_check_permission(gpio_rdc[x]) +#define RDC_SPINLOCK_UP(x) imx_rdc_sema_lock(gpio_rdc[x]) +#define RDC_SPINLOCK_DOWN(x) imx_rdc_sema_unlock(gpio_rdc[x]) +#else +#define RDC_CHECK(x) 0 +#define RDC_SPINLOCK_UP(x) +#define RDC_SPINLOCK_DOWN(x) +#endif + + static int mxc_gpio_direction(unsigned int gpio, enum mxc_gpio_direction direction) { @@ -62,6 +88,11 @@ static int mxc_gpio_direction(unsigned int gpio, if (port >= ARRAY_SIZE(gpio_ports)) return -1; + if (RDC_CHECK(port)) + return -1; + + RDC_SPINLOCK_UP(port); + gpio &= 0x1f; regs = (struct gpio_regs *)gpio_ports[port]; @@ -77,6 +108,8 @@ static int mxc_gpio_direction(unsigned int gpio, } writel(l, ®s->gpio_dir); + RDC_SPINLOCK_DOWN(port); + return 0; } @@ -89,6 +122,11 @@ int gpio_set_value(unsigned gpio, int value) if (port >= ARRAY_SIZE(gpio_ports)) return -1; + if (RDC_CHECK(port)) + return -1; + + RDC_SPINLOCK_UP(port); + gpio &= 0x1f; regs = (struct gpio_regs *)gpio_ports[port]; @@ -100,6 +138,8 @@ int gpio_set_value(unsigned gpio, int value) l &= ~(1 << gpio); writel(l, ®s->gpio_dr); + RDC_SPINLOCK_DOWN(port); + return 0; } @@ -112,12 +152,19 @@ int gpio_get_value(unsigned gpio) if (port >= ARRAY_SIZE(gpio_ports)) return -1; + if (RDC_CHECK(port)) + return -1; + + RDC_SPINLOCK_UP(port); + gpio &= 0x1f; regs = (struct gpio_regs *)gpio_ports[port]; val = (readl(®s->gpio_psr) >> gpio) & 0x01; + RDC_SPINLOCK_DOWN(port); + return val; } @@ -126,6 +173,10 @@ int gpio_request(unsigned gpio, const char *label) unsigned int port = GPIO_TO_PORT(gpio); if (port >= ARRAY_SIZE(gpio_ports)) return -1; + + if (RDC_CHECK(port)) + return -1; + return 0; } |