summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/mxc_gpio.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index a388064..399c4c2 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -28,6 +28,10 @@
#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,
@@ -54,6 +58,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)
{
@@ -64,6 +89,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];
@@ -79,6 +109,8 @@ static int mxc_gpio_direction(unsigned int gpio,
}
writel(l, &regs->gpio_dir);
+ RDC_SPINLOCK_DOWN(port);
+
return 0;
}
@@ -91,6 +123,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];
@@ -102,6 +139,8 @@ int gpio_set_value(unsigned gpio, int value)
l &= ~(1 << gpio);
writel(l, &regs->gpio_dr);
+ RDC_SPINLOCK_DOWN(port);
+
return 0;
}
@@ -114,12 +153,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;
}
@@ -128,6 +174,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;
}