diff options
-rw-r--r-- | arch/arm/configs/tegra_harmony_android_defconfig | 5 | ||||
-rw-r--r-- | arch/arm/configs/tegra_harmony_gnu_linux_defconfig | 5 | ||||
-rw-r--r-- | arch/arm/configs/tegra_whistler_android_defconfig | 4 | ||||
-rw-r--r-- | arch/arm/configs/tegra_whistler_gnu_linux_defconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/gpio.c | 361 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/gpio-names.h | 252 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/gpio.h | 35 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/irqs.h | 16 | ||||
-rw-r--r-- | arch/arm/mach-tegra/irq.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/power-t2.c | 38 | ||||
-rwxr-xr-x | arch/arm/mach-tegra/tegra_sysmap.c | 8 |
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")) |