diff options
Diffstat (limited to 'drivers/gpio/mxc_gpio.c')
-rw-r--r-- | drivers/gpio/mxc_gpio.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c index 70fe5b6..3631803 100644 --- a/drivers/gpio/mxc_gpio.c +++ b/drivers/gpio/mxc_gpio.c @@ -5,6 +5,8 @@ * Copyright (C) 2011 * Stefano Babic, DENX Software Engineering, <sbabic@denx.de> * + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> @@ -14,6 +16,11 @@ #include <asm/arch/imx-regs.h> #include <asm/gpio.h> #include <asm/io.h> +#include <errno.h> +#ifdef CONFIG_IMX_RDC +#include <asm/imx-common/rdc-sema.h> +#include <asm/arch/imx-rdc.h> +#endif enum mxc_gpio_direction { MXC_GPIO_DIRECTION_IN, @@ -58,6 +65,27 @@ static unsigned long gpio_ports[] = { #endif }; +#ifdef CONFIG_IMX_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], 0) +#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) { @@ -68,6 +96,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]; @@ -83,6 +116,8 @@ static int mxc_gpio_direction(unsigned int gpio, } writel(l, ®s->gpio_dir); + RDC_SPINLOCK_DOWN(port); + return 0; } @@ -95,6 +130,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]; @@ -106,6 +146,8 @@ int gpio_set_value(unsigned gpio, int value) l &= ~(1 << gpio); writel(l, ®s->gpio_dr); + RDC_SPINLOCK_DOWN(port); + return 0; } @@ -118,12 +160,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; } @@ -132,6 +181,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; } |