summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/mxc_gpio.c53
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, &regs->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, &regs->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(&regs->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;
}