summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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"))