summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2010-02-26 21:42:09 +0530
committerGary King <gking@nvidia.com>2010-03-09 18:34:07 -0800
commitd310232503566555bdd513b7b86c5a4c3be1e540 (patch)
tree3fd1bd757624a3e7ff06c05086d6ca5c0580e4e5
parent538ca3af7d82ab1724f4fa5413fc656825ef777f (diff)
tegra gpio: Implementing the native gpio driver.
Adding the native driver for the gpio which support the gpio chiplib for the kernel and user space gpio client. Tested on whister with the touch panel and scroll wheel. Tested with the lp1 entry exit multiple times on harmony. Change-Id: I2f0f9b8ac9ef4fa2ed35c084a713edd42f732c89 Reviewed-on: http://git-master/r/711 Reviewed-by: Bitan Biswas <bbiswas@nvidia.com> Tested-by: Bitan Biswas <bbiswas@nvidia.com> Reviewed-by: John Davis <jodavis@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com> Tested-by: Gary King <gking@nvidia.com>
-rw-r--r--arch/arm/configs/tegra_harmony_android_defconfig5
-rw-r--r--arch/arm/configs/tegra_harmony_gnu_linux_defconfig5
-rw-r--r--arch/arm/configs/tegra_whistler_android_defconfig4
-rw-r--r--arch/arm/configs/tegra_whistler_gnu_linux_defconfig5
-rw-r--r--arch/arm/mach-tegra/Kconfig1
-rw-r--r--arch/arm/mach-tegra/Makefile2
-rw-r--r--arch/arm/mach-tegra/gpio.c361
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio-names.h252
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio.h35
-rw-r--r--arch/arm/mach-tegra/include/mach/irqs.h16
-rw-r--r--arch/arm/mach-tegra/irq.c1
-rw-r--r--arch/arm/mach-tegra/power-t2.c38
-rwxr-xr-xarch/arm/mach-tegra/tegra_sysmap.c8
13 files changed, 704 insertions, 29 deletions
diff --git a/arch/arm/configs/tegra_harmony_android_defconfig b/arch/arm/configs/tegra_harmony_android_defconfig
index df33d945a67f..208922f3c52b 100644
--- a/arch/arm/configs/tegra_harmony_android_defconfig
+++ b/arch/arm/configs/tegra_harmony_android_defconfig
@@ -1044,6 +1044,11 @@ CONFIG_SPI_TEGRA=y
#
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
# CONFIG_W1 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
diff --git a/arch/arm/configs/tegra_harmony_gnu_linux_defconfig b/arch/arm/configs/tegra_harmony_gnu_linux_defconfig
index a6c64116d1cb..39d18f3b78a8 100644
--- a/arch/arm/configs/tegra_harmony_gnu_linux_defconfig
+++ b/arch/arm/configs/tegra_harmony_gnu_linux_defconfig
@@ -880,6 +880,11 @@ CONFIG_SPI_TEGRA=y
#
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
# CONFIG_W1 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
diff --git a/arch/arm/configs/tegra_whistler_android_defconfig b/arch/arm/configs/tegra_whistler_android_defconfig
index 88f274deb8a8..e202eb92221d 100644
--- a/arch/arm/configs/tegra_whistler_android_defconfig
+++ b/arch/arm/configs/tegra_whistler_android_defconfig
@@ -874,6 +874,10 @@ CONFIG_SPI_TEGRA=y
#
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
CONFIG_W1=y
#
diff --git a/arch/arm/configs/tegra_whistler_gnu_linux_defconfig b/arch/arm/configs/tegra_whistler_gnu_linux_defconfig
index 3d4089539a36..04d850c05414 100644
--- a/arch/arm/configs/tegra_whistler_gnu_linux_defconfig
+++ b/arch/arm/configs/tegra_whistler_gnu_linux_defconfig
@@ -883,6 +883,11 @@ CONFIG_SPI_TEGRA=y
#
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
# CONFIG_W1 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 584ca22af791..37c4a8af3bab 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -17,6 +17,7 @@ config ARCH_TEGRA_2x_SOC
bool "Tegra 2 family"
select CPU_V7
select ARM_GIC
+ select ARCH_REQUIRE_GPIOLIB
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 804825fa89c4..decf60bb0e2e 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -12,7 +12,7 @@ obj-y += clock.o
obj-y += io.o
obj-y += irq.o
obj-y += irq_dma.o
-obj-y += irq_gpio.o
+obj-y += gpio.o
obj-y += timer.o
obj-y += tegra_sysmap.o
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
new file mode 100644
index 000000000000..43f7cdfca9a1
--- /dev/null
+++ b/arch/arm/mach-tegra/gpio.c
@@ -0,0 +1,361 @@
+/*
+ * arch/arm/mach-tegra/gpio.c
+ *
+ * The tegra gpio driver.
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+
+#define GPIO_BANK(x) ((x) >> 5)
+#define GPIO_PORT(x) (((x) >> 3) & 0x3)
+#define GPIO_BIT(x) ((x) & 0x7)
+
+extern unsigned long tegra_get_module_inst_base(const char *name, int inst);
+static unsigned long add_gpio_base = 0;
+#define GPIO_REG(x) ((add_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)
+#define GPIO_IN(x) (GPIO_REG(x) + 0x30)
+
+#define GPIO_INT_STA(x) (GPIO_REG(x) + 0x40)
+#define GPIO_INT_ENB(x) (GPIO_REG(x) + 0x50)
+#define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60)
+#define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70)
+
+#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)
+
+#define GPIO_INT_LVL_MASK 0x010101
+#define GPIO_INT_LVL_EDGE_RISING 0x000101
+#define GPIO_INT_LVL_EDGE_FALLING 0x000100
+#define GPIO_INT_LVL_EDGE_BOTH 0x010100
+#define GPIO_INT_LVL_LEVEL_HIGH 0x000001
+#define GPIO_INT_LVL_LEVEL_LOW 0x000000
+
+#define MAX_GPIO_INSTANCES 10
+struct tegra_gpio_bank {
+ int bank;
+ int irq;
+ spinlock_t lvl_lock[4];
+};
+
+static struct tegra_gpio_bank tegra_gpio_banks[] = {
+ {.bank = 0, .irq = INT_GPIO1},
+ {.bank = 1, .irq = INT_GPIO2},
+ {.bank = 2, .irq = INT_GPIO3},
+ {.bank = 3, .irq = INT_GPIO4},
+ {.bank = 4, .irq = INT_GPIO5},
+ {.bank = 5, .irq = INT_GPIO6},
+ {.bank = 6, .irq = INT_GPIO7},
+};
+
+static int tegra_gpio_compose(int bank, int port, int bit)
+{
+ return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
+}
+
+static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
+{
+ u32 val;
+
+ val = 0x100 << GPIO_BIT(gpio);
+ if (value)
+ val |= 1 << GPIO_BIT(gpio);
+ __raw_writel(val, reg);
+}
+
+void tegra_gpio_enable(int gpio)
+{
+ tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
+}
+
+void tegra_gpio_disable(int gpio)
+{
+ tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
+}
+
+static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
+}
+
+static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+}
+
+static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
+ return 0;
+}
+
+static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
+ return 0;
+}
+static struct gpio_chip tegra_gpio_chip = {
+ .label = "tegra-gpio",
+ .direction_input = tegra_gpio_direction_input,
+ .get = tegra_gpio_get,
+ .direction_output = tegra_gpio_direction_output,
+ .set = tegra_gpio_set,
+ .base = 0,
+ .ngpio = ARCH_NR_GPIOS,
+};
+
+static void tegra_gpio_irq_ack(unsigned int irq)
+{
+ int gpio = irq - INT_GPIO_BASE;
+
+ __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+}
+
+static void tegra_gpio_irq_mask(unsigned int irq)
+{
+ int gpio = irq - INT_GPIO_BASE;
+
+ tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
+}
+
+static void tegra_gpio_irq_unmask(unsigned int irq)
+{
+ int gpio = irq - INT_GPIO_BASE;
+
+ tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
+}
+
+static int tegra_gpio_irq_set_type(unsigned int irq, unsigned int type)
+{
+ int gpio = irq - INT_GPIO_BASE;
+ struct tegra_gpio_bank *bank = get_irq_data(irq);
+ int port = GPIO_PORT(gpio);
+ int lvl_type;
+ int val;
+ unsigned long flags;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ lvl_type = GPIO_INT_LVL_EDGE_RISING;
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ lvl_type = GPIO_INT_LVL_EDGE_FALLING;
+ break;
+
+ case IRQ_TYPE_EDGE_BOTH:
+ lvl_type = GPIO_INT_LVL_EDGE_BOTH;
+ break;
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
+ break;
+
+ case IRQ_TYPE_LEVEL_LOW:
+ lvl_type = GPIO_INT_LVL_LEVEL_LOW;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&bank->lvl_lock[port], flags);
+
+ val = __raw_readl(GPIO_INT_LVL(gpio));
+ val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
+ val |= lvl_type << GPIO_BIT(gpio);
+ __raw_writel( val, GPIO_INT_LVL(gpio));
+
+ spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
+
+ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ __set_irq_handler_unlocked(irq, handle_level_irq);
+ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+ __set_irq_handler_unlocked(irq, handle_edge_irq);
+
+ return 0;
+}
+
+static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable)
+{
+ if (enable)
+ tegra_gpio_irq_unmask(irq);
+ else
+ tegra_gpio_irq_mask(irq);
+ return 0;
+}
+
+static struct irq_chip tegra_gpio_irq_chip = {
+ .name = "GPIO",
+ .ack = tegra_gpio_irq_ack,
+ .mask = tegra_gpio_irq_mask,
+ .unmask = tegra_gpio_irq_unmask,
+ .set_type = tegra_gpio_irq_set_type,
+ .set_wake = tegra_gpio_wake_enable,
+};
+
+static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ struct tegra_gpio_bank *bank;
+ int port;
+ int pin;
+ int unmasked = 0;
+
+ desc->chip->ack(irq);
+
+ bank = get_irq_data(irq);
+
+ for (port = 0; port < 4; port++) {
+ int gpio = tegra_gpio_compose(bank->bank, port, 0);
+ u8 sta = __raw_readl(GPIO_INT_STA(gpio)) &
+ __raw_readl(GPIO_INT_ENB(gpio));
+ u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+
+ for (pin = 0; pin < 8; pin++) {
+ if (sta & (1 << pin)) {
+ __raw_writel(1 << pin,
+ GPIO_INT_CLR(gpio));
+
+ /* if gpio is edge triggered, clear condition
+ * before executing the hander so that we don't
+ * miss edges
+ */
+ if (lvl & (0x100 << pin)) {
+ unmasked = 1;
+ desc->chip->unmask(irq);
+ }
+
+ generic_handle_irq(gpio_to_irq(gpio + pin));
+ }
+ }
+ }
+ if (!unmasked)
+ desc->chip->unmask(irq);
+
+}
+
+/* This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int __init tegra_gpio_init(void)
+{
+ struct tegra_gpio_bank *bank;
+ int i;
+ int j;
+ unsigned long phys;
+
+ phys = tegra_get_module_inst_base("gpio",0);
+ add_gpio_base = IO_ADDRESS(phys);
+
+ 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));
+ }
+ }
+
+ gpiochip_add(&tegra_gpio_chip);
+
+ for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) {
+ bank = &tegra_gpio_banks[GPIO_BANK(i-INT_GPIO_BASE)];
+
+ lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
+ set_irq_chip_data(i, bank);
+ set_irq_chip(i, &tegra_gpio_irq_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+ bank = &tegra_gpio_banks[i];
+
+ set_irq_chained_handler(bank->irq, tegra_gpio_irq_handler);
+ set_irq_data(bank->irq, bank);
+
+ for (j = 0; j < 4; j++)
+ bank->lvl_lock[j] = SPIN_LOCK_UNLOCKED;
+ }
+ return 0;
+}
+
+postcore_initcall(tegra_gpio_init);
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static int dbg_gpio_show(struct seq_file *s, void *unused)
+{
+ int i;
+ int j;
+
+ for (i = 0; i < 7; i++) {
+ for (j = 0; j < 4; j++) {
+ int gpio = tegra_gpio_compose(i, j, 0);
+ seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
+ i, j,
+ __raw_readl(GPIO_CNF(gpio)),
+ __raw_readl(GPIO_OE(gpio)),
+ __raw_readl(GPIO_OUT(gpio)),
+ __raw_readl(GPIO_IN(gpio)),
+ __raw_readl(GPIO_INT_STA(gpio)),
+ __raw_readl(GPIO_INT_ENB(gpio)),
+ __raw_readl(GPIO_INT_LVL(gpio)));
+ }
+ }
+ return 0;
+}
+
+static int dbg_gpio_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dbg_gpio_show, &inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+ .open = dbg_gpio_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+static int __init tegra_gpio_debuginit(void)
+{
+ (void) debugfs_create_file("tegra_gpio", S_IRUGO,
+ NULL, NULL, &debug_fops);
+ return 0;
+}
+late_initcall(tegra_gpio_debuginit);
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio-names.h b/arch/arm/mach-tegra/include/mach/gpio-names.h
new file mode 100644
index 000000000000..646081645dec
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/gpio-names.h
@@ -0,0 +1,252 @@
+/*
+ * arch/arm/mach-tegra/include/mach/gpio-names.h
+ *
+ * GPIO port id for tegra SOCs.
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __MACH_TEGRA_GPIO_NAMES_H
+#define __MACH_TEGRA_GPIO_NAMES_H
+
+#define TEGRA_GPIO_PA0 0
+#define TEGRA_GPIO_PA1 1
+#define TEGRA_GPIO_PA2 2
+#define TEGRA_GPIO_PA3 3
+#define TEGRA_GPIO_PA4 4
+#define TEGRA_GPIO_PA5 5
+#define TEGRA_GPIO_PA6 6
+#define TEGRA_GPIO_PA7 7
+#define TEGRA_GPIO_PB0 8
+#define TEGRA_GPIO_PB1 9
+#define TEGRA_GPIO_PB2 10
+#define TEGRA_GPIO_PB3 11
+#define TEGRA_GPIO_PB4 12
+#define TEGRA_GPIO_PB5 13
+#define TEGRA_GPIO_PB6 14
+#define TEGRA_GPIO_PB7 15
+#define TEGRA_GPIO_PC0 16
+#define TEGRA_GPIO_PC1 17
+#define TEGRA_GPIO_PC2 18
+#define TEGRA_GPIO_PC3 19
+#define TEGRA_GPIO_PC4 20
+#define TEGRA_GPIO_PC5 21
+#define TEGRA_GPIO_PC6 22
+#define TEGRA_GPIO_PC7 23
+#define TEGRA_GPIO_PD0 24
+#define TEGRA_GPIO_PD1 25
+#define TEGRA_GPIO_PD2 26
+#define TEGRA_GPIO_PD3 27
+#define TEGRA_GPIO_PD4 28
+#define TEGRA_GPIO_PD5 29
+#define TEGRA_GPIO_PD6 30
+#define TEGRA_GPIO_PD7 31
+#define TEGRA_GPIO_PE0 32
+#define TEGRA_GPIO_PE1 33
+#define TEGRA_GPIO_PE2 34
+#define TEGRA_GPIO_PE3 35
+#define TEGRA_GPIO_PE4 36
+#define TEGRA_GPIO_PE5 37
+#define TEGRA_GPIO_PE6 38
+#define TEGRA_GPIO_PE7 39
+#define TEGRA_GPIO_PF0 40
+#define TEGRA_GPIO_PF1 41
+#define TEGRA_GPIO_PF2 42
+#define TEGRA_GPIO_PF3 43
+#define TEGRA_GPIO_PF4 44
+#define TEGRA_GPIO_PF5 45
+#define TEGRA_GPIO_PF6 46
+#define TEGRA_GPIO_PF7 47
+#define TEGRA_GPIO_PG0 48
+#define TEGRA_GPIO_PG1 49
+#define TEGRA_GPIO_PG2 50
+#define TEGRA_GPIO_PG3 51
+#define TEGRA_GPIO_PG4 52
+#define TEGRA_GPIO_PG5 53
+#define TEGRA_GPIO_PG6 54
+#define TEGRA_GPIO_PG7 55
+#define TEGRA_GPIO_PH0 56
+#define TEGRA_GPIO_PH1 57
+#define TEGRA_GPIO_PH2 58
+#define TEGRA_GPIO_PH3 59
+#define TEGRA_GPIO_PH4 60
+#define TEGRA_GPIO_PH5 61
+#define TEGRA_GPIO_PH6 62
+#define TEGRA_GPIO_PH7 63
+#define TEGRA_GPIO_PI0 64
+#define TEGRA_GPIO_PI1 65
+#define TEGRA_GPIO_PI2 66
+#define TEGRA_GPIO_PI3 67
+#define TEGRA_GPIO_PI4 68
+#define TEGRA_GPIO_PI5 69
+#define TEGRA_GPIO_PI6 70
+#define TEGRA_GPIO_PI7 71
+#define TEGRA_GPIO_PJ0 72
+#define TEGRA_GPIO_PJ1 73
+#define TEGRA_GPIO_PJ2 74
+#define TEGRA_GPIO_PJ3 75
+#define TEGRA_GPIO_PJ4 76
+#define TEGRA_GPIO_PJ5 77
+#define TEGRA_GPIO_PJ6 78
+#define TEGRA_GPIO_PJ7 79
+#define TEGRA_GPIO_PK0 80
+#define TEGRA_GPIO_PK1 81
+#define TEGRA_GPIO_PK2 82
+#define TEGRA_GPIO_PK3 83
+#define TEGRA_GPIO_PK4 84
+#define TEGRA_GPIO_PK5 85
+#define TEGRA_GPIO_PK6 86
+#define TEGRA_GPIO_PK7 87
+#define TEGRA_GPIO_PL0 88
+#define TEGRA_GPIO_PL1 89
+#define TEGRA_GPIO_PL2 90
+#define TEGRA_GPIO_PL3 91
+#define TEGRA_GPIO_PL4 92
+#define TEGRA_GPIO_PL5 93
+#define TEGRA_GPIO_PL6 94
+#define TEGRA_GPIO_PL7 95
+#define TEGRA_GPIO_PM0 96
+#define TEGRA_GPIO_PM1 97
+#define TEGRA_GPIO_PM2 98
+#define TEGRA_GPIO_PM3 99
+#define TEGRA_GPIO_PM4 100
+#define TEGRA_GPIO_PM5 101
+#define TEGRA_GPIO_PM6 102
+#define TEGRA_GPIO_PM7 103
+#define TEGRA_GPIO_PN0 104
+#define TEGRA_GPIO_PN1 105
+#define TEGRA_GPIO_PN2 106
+#define TEGRA_GPIO_PN3 107
+#define TEGRA_GPIO_PN4 108
+#define TEGRA_GPIO_PN5 109
+#define TEGRA_GPIO_PN6 110
+#define TEGRA_GPIO_PN7 111
+#define TEGRA_GPIO_PO0 112
+#define TEGRA_GPIO_PO1 113
+#define TEGRA_GPIO_PO2 114
+#define TEGRA_GPIO_PO3 115
+#define TEGRA_GPIO_PO4 116
+#define TEGRA_GPIO_PO5 117
+#define TEGRA_GPIO_PO6 118
+#define TEGRA_GPIO_PO7 119
+#define TEGRA_GPIO_PP0 120
+#define TEGRA_GPIO_PP1 121
+#define TEGRA_GPIO_PP2 122
+#define TEGRA_GPIO_PP3 123
+#define TEGRA_GPIO_PP4 124
+#define TEGRA_GPIO_PP5 125
+#define TEGRA_GPIO_PP6 126
+#define TEGRA_GPIO_PP7 127
+#define TEGRA_GPIO_PQ0 128
+#define TEGRA_GPIO_PQ1 129
+#define TEGRA_GPIO_PQ2 130
+#define TEGRA_GPIO_PQ3 131
+#define TEGRA_GPIO_PQ4 132
+#define TEGRA_GPIO_PQ5 133
+#define TEGRA_GPIO_PQ6 134
+#define TEGRA_GPIO_PQ7 135
+#define TEGRA_GPIO_PR0 136
+#define TEGRA_GPIO_PR1 137
+#define TEGRA_GPIO_PR2 138
+#define TEGRA_GPIO_PR3 139
+#define TEGRA_GPIO_PR4 140
+#define TEGRA_GPIO_PR5 141
+#define TEGRA_GPIO_PR6 142
+#define TEGRA_GPIO_PR7 143
+#define TEGRA_GPIO_PS0 144
+#define TEGRA_GPIO_PS1 145
+#define TEGRA_GPIO_PS2 146
+#define TEGRA_GPIO_PS3 147
+#define TEGRA_GPIO_PS4 148
+#define TEGRA_GPIO_PS5 149
+#define TEGRA_GPIO_PS6 150
+#define TEGRA_GPIO_PS7 151
+#define TEGRA_GPIO_PT0 152
+#define TEGRA_GPIO_PT1 153
+#define TEGRA_GPIO_PT2 154
+#define TEGRA_GPIO_PT3 155
+#define TEGRA_GPIO_PT4 156
+#define TEGRA_GPIO_PT5 157
+#define TEGRA_GPIO_PT6 158
+#define TEGRA_GPIO_PT7 159
+#define TEGRA_GPIO_PU0 160
+#define TEGRA_GPIO_PU1 161
+#define TEGRA_GPIO_PU2 162
+#define TEGRA_GPIO_PU3 163
+#define TEGRA_GPIO_PU4 164
+#define TEGRA_GPIO_PU5 165
+#define TEGRA_GPIO_PU6 166
+#define TEGRA_GPIO_PU7 167
+#define TEGRA_GPIO_PV0 168
+#define TEGRA_GPIO_PV1 169
+#define TEGRA_GPIO_PV2 170
+#define TEGRA_GPIO_PV3 171
+#define TEGRA_GPIO_PV4 172
+#define TEGRA_GPIO_PV5 173
+#define TEGRA_GPIO_PV6 174
+#define TEGRA_GPIO_PV7 175
+#define TEGRA_GPIO_PW0 176
+#define TEGRA_GPIO_PW1 177
+#define TEGRA_GPIO_PW2 178
+#define TEGRA_GPIO_PW3 179
+#define TEGRA_GPIO_PW4 180
+#define TEGRA_GPIO_PW5 181
+#define TEGRA_GPIO_PW6 182
+#define TEGRA_GPIO_PW7 183
+#define TEGRA_GPIO_PX0 184
+#define TEGRA_GPIO_PX1 185
+#define TEGRA_GPIO_PX2 186
+#define TEGRA_GPIO_PX3 187
+#define TEGRA_GPIO_PX4 188
+#define TEGRA_GPIO_PX5 189
+#define TEGRA_GPIO_PX6 190
+#define TEGRA_GPIO_PX7 191
+#define TEGRA_GPIO_PY0 192
+#define TEGRA_GPIO_PY1 193
+#define TEGRA_GPIO_PY2 194
+#define TEGRA_GPIO_PY3 195
+#define TEGRA_GPIO_PY4 196
+#define TEGRA_GPIO_PY5 197
+#define TEGRA_GPIO_PY6 198
+#define TEGRA_GPIO_PY7 199
+#define TEGRA_GPIO_PZ0 200
+#define TEGRA_GPIO_PZ1 201
+#define TEGRA_GPIO_PZ2 202
+#define TEGRA_GPIO_PZ3 203
+#define TEGRA_GPIO_PZ4 204
+#define TEGRA_GPIO_PZ5 205
+#define TEGRA_GPIO_PZ6 206
+#define TEGRA_GPIO_PZ7 207
+#define TEGRA_GPIO_PAA0 208
+#define TEGRA_GPIO_PAA1 209
+#define TEGRA_GPIO_PAA2 210
+#define TEGRA_GPIO_PAA3 211
+#define TEGRA_GPIO_PAA4 212
+#define TEGRA_GPIO_PAA5 213
+#define TEGRA_GPIO_PAA6 214
+#define TEGRA_GPIO_PAA7 215
+#define TEGRA_GPIO_PBB0 216
+#define TEGRA_GPIO_PBB1 217
+#define TEGRA_GPIO_PBB2 218
+#define TEGRA_GPIO_PBB3 219
+#define TEGRA_GPIO_PBB4 220
+#define TEGRA_GPIO_PBB5 221
+#define TEGRA_GPIO_PBB6 222
+#define TEGRA_GPIO_PBB7 223
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
index 77d55836948e..786cb090f00e 100644
--- a/arch/arm/mach-tegra/include/mach/gpio.h
+++ b/arch/arm/mach-tegra/include/mach/gpio.h
@@ -21,18 +21,31 @@
#ifndef __MACH_TEGRA_GPIO_H
#define __MACH_TEGRA_GPIO_H
-extern int gpio_set_value(unsigned gpio, int value);
+#include <mach/irqs.h>
-extern int gpio_get_value(unsigned gpio);
-
-extern int gpio_direction_input(unsigned gpio);
-
-extern int gpio_direction_output(unsigned gpio, int value);
+#define ARCH_NR_GPIOS INT_GPIO_NR
#include <asm-generic/gpio.h>
-
-extern int gpio_request(unsigned gpio, const char *tag);
-
-extern void gpio_free(unsigned gpio);
-
+#include <mach/gpio-names.h>
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+
+static inline int gpio_to_irq(unsigned int gpio)
+{
+ if (gpio < ARCH_NR_GPIOS)
+ return INT_GPIO_BASE + gpio;
+ return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+ if ((irq >= INT_GPIO_BASE) && (irq < INT_GPIO_BASE + INT_GPIO_NR))
+ return irq - INT_GPIO_BASE;
+ return -EINVAL;
+}
+
+void tegra_gpio_enable(int gpio);
+void tegra_gpio_disable(int gpio);
#endif
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
index ea360219f9b9..eacbb6cf1f63 100644
--- a/arch/arm/mach-tegra/include/mach/irqs.h
+++ b/arch/arm/mach-tegra/include/mach/irqs.h
@@ -26,6 +26,22 @@
#define NR_IRQS 512
#elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
#define NR_IRQS 512
+
+/* Gpio interrupt details */
+#define INT_SEC_BASE 64
+#define INT_GPIO1 (INT_SEC_BASE + 0)
+#define INT_GPIO2 (INT_SEC_BASE + 1)
+#define INT_GPIO3 (INT_SEC_BASE + 2)
+#define INT_GPIO4 (INT_SEC_BASE + 3)
+#define INT_GPIO5 (INT_SEC_BASE + 23)
+
+#define INT_TRI_BASE 96
+#define INT_GPIO6 (INT_TRI_BASE + 23)
+#define INT_GPIO7 (INT_TRI_BASE + 25)
+
+#define INT_GPIO_BASE (128 + 32)
+#define INT_GPIO_NR (7*4* 8)
+
#else
#error "Invalid Tegra SoC family selection"
#endif
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 94ec790c9b2e..d7bd6dc8f05a 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -314,7 +314,6 @@ void __init tegra_init_irq(void)
tegra_irq_register_module(Module, pIrq);
}
- tegra_init_gpio();
#ifdef CONFIG_TEGRA_SYSTEM_DMA
tegra_init_dma();
diff --git a/arch/arm/mach-tegra/power-t2.c b/arch/arm/mach-tegra/power-t2.c
index 22575b7dc3a9..2275f628cba2 100644
--- a/arch/arm/mach-tegra/power-t2.c
+++ b/arch/arm/mach-tegra/power-t2.c
@@ -21,10 +21,10 @@
*/
#include "power.h"
+#include "linux/interrupt.h"
extern void NvPrivAp20MaskIrq(unsigned int irq);
extern void NvPrivAp20UnmaskIrq(unsigned int irq);
-extern void NvPrivGpioUnMaskIrq(unsigned int irq);
extern int enter_power_state(PowerState state, unsigned int proc_id);
extern void prepare_for_wb0(void);
extern void prepare_for_wb1(void);
@@ -170,7 +170,7 @@ void cpu_ap20_do_lp0(void)
//Interrupt, gpio, pin mux, clock management etc
perform_context_operation(PowerModuleContext_Restore);
}
-void prepare_lp1_wake_events(void)
+void prepare_lp1_wake_events(NvBool entry)
{
NvU32 irq_count, irq;
@@ -182,20 +182,31 @@ void prepare_lp1_wake_events(void)
{
printk("irq = %d\n", s_WakeupIrqTable[irq_count]);
- if (irq < MAX_IRQ)
- NvPrivAp20UnmaskIrq(irq);
- else {
- NvU32 irq_top;
- irq_top = NvRmGetIrqForLogicalInterrupt(
- s_hRmGlobal,
- s_WakeupSources[irq_count].Module,
- 0xff);
- NvPrivAp20UnmaskIrq(irq_top);
- NvPrivGpioUnMaskIrq(irq);
+ if (entry) {
+ if (irq < MAX_IRQ)
+ NvPrivAp20UnmaskIrq(irq);
+ else {
+ NvU32 irq_top;
+ irq_top = NvRmGetIrqForLogicalInterrupt(
+ s_hRmGlobal,
+ s_WakeupSources[irq_count].Module,
+ 0xff);
+ NvPrivAp20UnmaskIrq(irq_top);
+ enable_irq_wake(irq);
+ }
+ } else {
+ /* resume path only nullifies gpio interrupt */
+ if (irq >= MAX_IRQ) {
+ disable_irq_wake(irq);
+ }
}
}
}
+ /* Exit if it is called after resume */
+ if (entry == NV_FALSE)
+ return;
+
for (irq_count=0;irq_count<NV_ARRAY_SIZE(s_WakeupIrqTableEx);irq_count++)
{
irq = s_WakeupIrqTableEx[irq_count];
@@ -215,7 +226,7 @@ void cpu_ap20_do_lp1(void)
unsigned int proc_id = smp_processor_id();
prepare_for_wb1();
- prepare_lp1_wake_events();
+ prepare_lp1_wake_events(NV_TRUE);
//Inform RM about entry to LP1 state
NvRmPrivPowerSetState(s_hRmGlobal, NvRmPowerState_LP1);
@@ -268,6 +279,7 @@ void cpu_ap20_do_lp1(void)
NvOsMemcpy((void*)g_pIRAM, (void*)g_iramContextSaveVA,
AVP_CONTEXT_SAVE_AREA_SIZE);
+ prepare_lp1_wake_events(NV_FALSE);
//Restore the saved module(s) context
//Interrupt, gpio, pin mux, clock management etc
perform_context_operation(PowerModuleContext_RestoreLP1);
diff --git a/arch/arm/mach-tegra/tegra_sysmap.c b/arch/arm/mach-tegra/tegra_sysmap.c
index 05da3c3d8b0a..ab504d1d56bb 100755
--- a/arch/arm/mach-tegra/tegra_sysmap.c
+++ b/arch/arm/mach-tegra/tegra_sysmap.c
@@ -30,12 +30,14 @@
static NvRmModuleID tegra_map_name_to_mod(const char *name, int inst)
{
- if (!strcmp(name, "pl310"))
+ if (!strcmp(name, "gpio"))
+ return NVRM_MODULE_ID(NvRmPrivModuleID_Gpio, inst);
+ else if (!strcmp(name, "pcie"))
+ return NVRM_MODULE_ID(NvRmPrivModuleID_Pcie, inst);
+ else if (!strcmp(name, "pl310"))
return NVRM_MODULE_ID(NvRmPrivModuleID_Pl310, inst);
else if (!strcmp(name, "scu"))
return NVRM_MODULE_ID(NvRmPrivModuleID_ArmPerif, inst);
- else if (!strcmp(name, "pcie"))
- return NVRM_MODULE_ID(NvRmPrivModuleID_Pcie, inst);
else if (!strcmp(name, "usbotg"))
return NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, inst);
else if (!strcmp(name, "mc"))