summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:45:10 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:45:10 -0800
commit6a4c4d56e19381689fe0e8f99ad54d1f0c80f3d7 (patch)
tree2355fca26fc3dd8d074218a60eb117f41586c479 /drivers
parent0c4a3989e5d5bbccf2090ed78ccf6805e791d101 (diff)
parent0ff78b252c872587f36afafa85f473fdebe8dc6f (diff)
Merge branch 'buckets/mach-tegra' into after-buckets
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/gpio-tegra.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 5837b8c1dd79..e42ebe0be017 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -6,6 +6,8 @@
* Author:
* Erik Gilling <konkers@google.com>
*
+ * Copyright (c) 2011 NVIDIA Corporation.
+ *
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
@@ -20,6 +22,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/io.h>
#include <linux/gpio.h>
@@ -36,10 +39,6 @@
#define GPIO_PORT(x) (((x) >> 3) & 0x3)
#define GPIO_BIT(x) ((x) & 0x7)
-#define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \
- GPIO_BANK(x) * 0x80 + \
- GPIO_PORT(x) * 4)
-
#define GPIO_CNF(x) (GPIO_REG(x) + 0x00)
#define GPIO_OE(x) (GPIO_REG(x) + 0x10)
#define GPIO_OUT(x) (GPIO_REG(x) + 0X20)
@@ -49,12 +48,29 @@
#define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60)
#define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \
+ GPIO_BANK(x) * 0x80 + \
+ GPIO_PORT(x) * 4)
+
#define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x800)
#define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x810)
#define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0X820)
#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0x840)
#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0x850)
#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0x860)
+#else
+#define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \
+ GPIO_BANK(x) * 0x100 + \
+ GPIO_PORT(x) * 4)
+
+#define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x80)
+#define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x90)
+#define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0XA0)
+#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0xC0)
+#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0xD0)
+#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0xE0)
+#endif
#define GPIO_INT_LVL_MASK 0x010101
#define GPIO_INT_LVL_EDGE_RISING 0x000101
@@ -67,7 +83,7 @@ struct tegra_gpio_bank {
int bank;
int irq;
spinlock_t lvl_lock[4];
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
u32 cnf[4];
u32 out[4];
u32 oe[4];
@@ -85,6 +101,9 @@ static struct tegra_gpio_bank tegra_gpio_banks[] = {
{.bank = 4, .irq = INT_GPIO5},
{.bank = 5, .irq = INT_GPIO6},
{.bank = 6, .irq = INT_GPIO7},
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ {.bank = 7, .irq = INT_GPIO8},
+#endif
};
static int tegra_gpio_compose(int bank, int port, int bit)
@@ -153,6 +172,15 @@ static void tegra_gpio_irq_ack(struct irq_data *d)
int gpio = d->irq - INT_GPIO_BASE;
__raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+
+#ifdef CONFIG_TEGRA_FPGA_PLATFORM
+ /* FPGA platforms have a serializer between the GPIO
+ block and interrupt controller. Allow time for
+ clearing of the GPIO interrupt to propagate to the
+ interrupt controller before re-enabling the IRQ
+ to prevent double interrupts. */
+ udelay(15);
+#endif
}
static void tegra_gpio_irq_mask(struct irq_data *d)
@@ -246,7 +274,7 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static void tegra_gpio_resume(void)
{
unsigned long flags;
@@ -352,7 +380,7 @@ static int __init tegra_gpio_init(void)
int i;
int j;
- for (i = 0; i < 7; i++) {
+ for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
__raw_writel(0x00, GPIO_INT_ENB(gpio));
@@ -419,7 +447,8 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
int i;
int j;
- for (i = 0; i < 7; i++) {
+ seq_printf(s, "Bank:Port CNF OE OUT IN INT_STA INT_ENB INT_LVL\n");
+ for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
seq_printf(s,