diff options
author | Ye.Li <B37916@freescale.com> | 2014-04-11 15:29:32 +0800 |
---|---|---|
committer | Ye.Li <B37916@freescale.com> | 2014-04-14 16:39:24 +0800 |
commit | 54a7dcd4011928c4945414b775961096e38c84fe (patch) | |
tree | 94ad8838b6f04f0f87be0a194ed19dd37386fd4e | |
parent | dbb19c033e8e4de78326ffc90f1629b334b3204f (diff) | |
download | u-boot-imx-54a7dcd4011928c4945414b775961096e38c84fe.zip u-boot-imx-54a7dcd4011928c4945414b775961096e38c84fe.tar.gz u-boot-imx-54a7dcd4011928c4945414b775961096e38c84fe.tar.bz2 |
ENGR00307874 GPIO: Modify driver mxc_gpio to support RDC Semaphores
For GPIO group which shared by multiple masters, it may set in RDC
to shared and semaphore required. Before access the GPIO register,
the GPIO driver must get the RDC semaphore, and release the semaphore
after the GPIO register access.
When CONFIG_MXC_RDC is set, the features related to RDC semaphores
is enabled in mxc_gpio driver.
Signed-off-by: Ye.Li <B37916@freescale.com>
-rw-r--r-- | drivers/gpio/mxc_gpio.c | 50 |
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, ®s->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, ®s->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(®s->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; } |