Commit 3c92db9ac0ca3eee8e46e2424b6c074e2e394ad9

Authored by Erik Gilling
1 parent 2d5cd9a38b

[ARM] tegra: add GPIO support

v2: fixes from Mike Rapoport:
	- move gpio-names.h to arch/arm/mach-tegra
    fixes from Russell King
	- include linux/io.h and linux/gpio.h instead of asm/io.h
	  and asm/gpio.h
    additional changes:
    	- add macros to convert between irq and gpio numbers for platform data
	- change for_each_bit to for_each_set_bit in gpio.c
v3:
	- minor bugfixes

Signed-off-by: Colin Cross <ccross@android.com>
Signed-off-by: Erik Gilling <konkers@android.com>

Showing 5 changed files with 650 additions and 0 deletions Side-by-side Diff

arch/arm/mach-tegra/Kconfig
... ... @@ -9,6 +9,7 @@
9 9 bool "Tegra 2 family"
10 10 select CPU_V7
11 11 select ARM_GIC
  12 + select ARCH_REQUIRE_GPIOLIB
12 13 help
13 14 Support for NVIDIA Tegra AP20 and T20 processors, based on the
14 15 ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
arch/arm/mach-tegra/Makefile
... ... @@ -3,6 +3,7 @@
3 3 obj-y += irq.o
4 4 obj-y += clock.o
5 5 obj-y += timer.o
  6 +obj-y += gpio.o
6 7 obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o
7 8 obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o
8 9 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
arch/arm/mach-tegra/gpio-names.h
  1 +/*
  2 + * arch/arm/mach-tegra/include/mach/gpio-names.h
  3 + *
  4 + * Copyright (c) 2010 Google, Inc
  5 + *
  6 + * Author:
  7 + * Erik Gilling <konkers@google.com>
  8 + *
  9 + * This software is licensed under the terms of the GNU General Public
  10 + * License version 2, as published by the Free Software Foundation, and
  11 + * may be copied, distributed, and modified under those terms.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + */
  18 +
  19 +#ifndef __MACH_TEGRA_GPIO_NAMES_H
  20 +#define __MACH_TEGRA_GPIO_NAMES_H
  21 +
  22 +#define TEGRA_GPIO_PA0 0
  23 +#define TEGRA_GPIO_PA1 1
  24 +#define TEGRA_GPIO_PA2 2
  25 +#define TEGRA_GPIO_PA3 3
  26 +#define TEGRA_GPIO_PA4 4
  27 +#define TEGRA_GPIO_PA5 5
  28 +#define TEGRA_GPIO_PA6 6
  29 +#define TEGRA_GPIO_PA7 7
  30 +#define TEGRA_GPIO_PB0 8
  31 +#define TEGRA_GPIO_PB1 9
  32 +#define TEGRA_GPIO_PB2 10
  33 +#define TEGRA_GPIO_PB3 11
  34 +#define TEGRA_GPIO_PB4 12
  35 +#define TEGRA_GPIO_PB5 13
  36 +#define TEGRA_GPIO_PB6 14
  37 +#define TEGRA_GPIO_PB7 15
  38 +#define TEGRA_GPIO_PC0 16
  39 +#define TEGRA_GPIO_PC1 17
  40 +#define TEGRA_GPIO_PC2 18
  41 +#define TEGRA_GPIO_PC3 19
  42 +#define TEGRA_GPIO_PC4 20
  43 +#define TEGRA_GPIO_PC5 21
  44 +#define TEGRA_GPIO_PC6 22
  45 +#define TEGRA_GPIO_PC7 23
  46 +#define TEGRA_GPIO_PD0 24
  47 +#define TEGRA_GPIO_PD1 25
  48 +#define TEGRA_GPIO_PD2 26
  49 +#define TEGRA_GPIO_PD3 27
  50 +#define TEGRA_GPIO_PD4 28
  51 +#define TEGRA_GPIO_PD5 29
  52 +#define TEGRA_GPIO_PD6 30
  53 +#define TEGRA_GPIO_PD7 31
  54 +#define TEGRA_GPIO_PE0 32
  55 +#define TEGRA_GPIO_PE1 33
  56 +#define TEGRA_GPIO_PE2 34
  57 +#define TEGRA_GPIO_PE3 35
  58 +#define TEGRA_GPIO_PE4 36
  59 +#define TEGRA_GPIO_PE5 37
  60 +#define TEGRA_GPIO_PE6 38
  61 +#define TEGRA_GPIO_PE7 39
  62 +#define TEGRA_GPIO_PF0 40
  63 +#define TEGRA_GPIO_PF1 41
  64 +#define TEGRA_GPIO_PF2 42
  65 +#define TEGRA_GPIO_PF3 43
  66 +#define TEGRA_GPIO_PF4 44
  67 +#define TEGRA_GPIO_PF5 45
  68 +#define TEGRA_GPIO_PF6 46
  69 +#define TEGRA_GPIO_PF7 47
  70 +#define TEGRA_GPIO_PG0 48
  71 +#define TEGRA_GPIO_PG1 49
  72 +#define TEGRA_GPIO_PG2 50
  73 +#define TEGRA_GPIO_PG3 51
  74 +#define TEGRA_GPIO_PG4 52
  75 +#define TEGRA_GPIO_PG5 53
  76 +#define TEGRA_GPIO_PG6 54
  77 +#define TEGRA_GPIO_PG7 55
  78 +#define TEGRA_GPIO_PH0 56
  79 +#define TEGRA_GPIO_PH1 57
  80 +#define TEGRA_GPIO_PH2 58
  81 +#define TEGRA_GPIO_PH3 59
  82 +#define TEGRA_GPIO_PH4 60
  83 +#define TEGRA_GPIO_PH5 61
  84 +#define TEGRA_GPIO_PH6 62
  85 +#define TEGRA_GPIO_PH7 63
  86 +#define TEGRA_GPIO_PI0 64
  87 +#define TEGRA_GPIO_PI1 65
  88 +#define TEGRA_GPIO_PI2 66
  89 +#define TEGRA_GPIO_PI3 67
  90 +#define TEGRA_GPIO_PI4 68
  91 +#define TEGRA_GPIO_PI5 69
  92 +#define TEGRA_GPIO_PI6 70
  93 +#define TEGRA_GPIO_PI7 71
  94 +#define TEGRA_GPIO_PJ0 72
  95 +#define TEGRA_GPIO_PJ1 73
  96 +#define TEGRA_GPIO_PJ2 74
  97 +#define TEGRA_GPIO_PJ3 75
  98 +#define TEGRA_GPIO_PJ4 76
  99 +#define TEGRA_GPIO_PJ5 77
  100 +#define TEGRA_GPIO_PJ6 78
  101 +#define TEGRA_GPIO_PJ7 79
  102 +#define TEGRA_GPIO_PK0 80
  103 +#define TEGRA_GPIO_PK1 81
  104 +#define TEGRA_GPIO_PK2 82
  105 +#define TEGRA_GPIO_PK3 83
  106 +#define TEGRA_GPIO_PK4 84
  107 +#define TEGRA_GPIO_PK5 85
  108 +#define TEGRA_GPIO_PK6 86
  109 +#define TEGRA_GPIO_PK7 87
  110 +#define TEGRA_GPIO_PL0 88
  111 +#define TEGRA_GPIO_PL1 89
  112 +#define TEGRA_GPIO_PL2 90
  113 +#define TEGRA_GPIO_PL3 91
  114 +#define TEGRA_GPIO_PL4 92
  115 +#define TEGRA_GPIO_PL5 93
  116 +#define TEGRA_GPIO_PL6 94
  117 +#define TEGRA_GPIO_PL7 95
  118 +#define TEGRA_GPIO_PM0 96
  119 +#define TEGRA_GPIO_PM1 97
  120 +#define TEGRA_GPIO_PM2 98
  121 +#define TEGRA_GPIO_PM3 99
  122 +#define TEGRA_GPIO_PM4 100
  123 +#define TEGRA_GPIO_PM5 101
  124 +#define TEGRA_GPIO_PM6 102
  125 +#define TEGRA_GPIO_PM7 103
  126 +#define TEGRA_GPIO_PN0 104
  127 +#define TEGRA_GPIO_PN1 105
  128 +#define TEGRA_GPIO_PN2 106
  129 +#define TEGRA_GPIO_PN3 107
  130 +#define TEGRA_GPIO_PN4 108
  131 +#define TEGRA_GPIO_PN5 109
  132 +#define TEGRA_GPIO_PN6 110
  133 +#define TEGRA_GPIO_PN7 111
  134 +#define TEGRA_GPIO_PO0 112
  135 +#define TEGRA_GPIO_PO1 113
  136 +#define TEGRA_GPIO_PO2 114
  137 +#define TEGRA_GPIO_PO3 115
  138 +#define TEGRA_GPIO_PO4 116
  139 +#define TEGRA_GPIO_PO5 117
  140 +#define TEGRA_GPIO_PO6 118
  141 +#define TEGRA_GPIO_PO7 119
  142 +#define TEGRA_GPIO_PP0 120
  143 +#define TEGRA_GPIO_PP1 121
  144 +#define TEGRA_GPIO_PP2 122
  145 +#define TEGRA_GPIO_PP3 123
  146 +#define TEGRA_GPIO_PP4 124
  147 +#define TEGRA_GPIO_PP5 125
  148 +#define TEGRA_GPIO_PP6 126
  149 +#define TEGRA_GPIO_PP7 127
  150 +#define TEGRA_GPIO_PQ0 128
  151 +#define TEGRA_GPIO_PQ1 129
  152 +#define TEGRA_GPIO_PQ2 130
  153 +#define TEGRA_GPIO_PQ3 131
  154 +#define TEGRA_GPIO_PQ4 132
  155 +#define TEGRA_GPIO_PQ5 133
  156 +#define TEGRA_GPIO_PQ6 134
  157 +#define TEGRA_GPIO_PQ7 135
  158 +#define TEGRA_GPIO_PR0 136
  159 +#define TEGRA_GPIO_PR1 137
  160 +#define TEGRA_GPIO_PR2 138
  161 +#define TEGRA_GPIO_PR3 139
  162 +#define TEGRA_GPIO_PR4 140
  163 +#define TEGRA_GPIO_PR5 141
  164 +#define TEGRA_GPIO_PR6 142
  165 +#define TEGRA_GPIO_PR7 143
  166 +#define TEGRA_GPIO_PS0 144
  167 +#define TEGRA_GPIO_PS1 145
  168 +#define TEGRA_GPIO_PS2 146
  169 +#define TEGRA_GPIO_PS3 147
  170 +#define TEGRA_GPIO_PS4 148
  171 +#define TEGRA_GPIO_PS5 149
  172 +#define TEGRA_GPIO_PS6 150
  173 +#define TEGRA_GPIO_PS7 151
  174 +#define TEGRA_GPIO_PT0 152
  175 +#define TEGRA_GPIO_PT1 153
  176 +#define TEGRA_GPIO_PT2 154
  177 +#define TEGRA_GPIO_PT3 155
  178 +#define TEGRA_GPIO_PT4 156
  179 +#define TEGRA_GPIO_PT5 157
  180 +#define TEGRA_GPIO_PT6 158
  181 +#define TEGRA_GPIO_PT7 159
  182 +#define TEGRA_GPIO_PU0 160
  183 +#define TEGRA_GPIO_PU1 161
  184 +#define TEGRA_GPIO_PU2 162
  185 +#define TEGRA_GPIO_PU3 163
  186 +#define TEGRA_GPIO_PU4 164
  187 +#define TEGRA_GPIO_PU5 165
  188 +#define TEGRA_GPIO_PU6 166
  189 +#define TEGRA_GPIO_PU7 167
  190 +#define TEGRA_GPIO_PV0 168
  191 +#define TEGRA_GPIO_PV1 169
  192 +#define TEGRA_GPIO_PV2 170
  193 +#define TEGRA_GPIO_PV3 171
  194 +#define TEGRA_GPIO_PV4 172
  195 +#define TEGRA_GPIO_PV5 173
  196 +#define TEGRA_GPIO_PV6 174
  197 +#define TEGRA_GPIO_PV7 175
  198 +#define TEGRA_GPIO_PW0 176
  199 +#define TEGRA_GPIO_PW1 177
  200 +#define TEGRA_GPIO_PW2 178
  201 +#define TEGRA_GPIO_PW3 179
  202 +#define TEGRA_GPIO_PW4 180
  203 +#define TEGRA_GPIO_PW5 181
  204 +#define TEGRA_GPIO_PW6 182
  205 +#define TEGRA_GPIO_PW7 183
  206 +#define TEGRA_GPIO_PX0 184
  207 +#define TEGRA_GPIO_PX1 185
  208 +#define TEGRA_GPIO_PX2 186
  209 +#define TEGRA_GPIO_PX3 187
  210 +#define TEGRA_GPIO_PX4 188
  211 +#define TEGRA_GPIO_PX5 189
  212 +#define TEGRA_GPIO_PX6 190
  213 +#define TEGRA_GPIO_PX7 191
  214 +#define TEGRA_GPIO_PY0 192
  215 +#define TEGRA_GPIO_PY1 193
  216 +#define TEGRA_GPIO_PY2 194
  217 +#define TEGRA_GPIO_PY3 195
  218 +#define TEGRA_GPIO_PY4 196
  219 +#define TEGRA_GPIO_PY5 197
  220 +#define TEGRA_GPIO_PY6 198
  221 +#define TEGRA_GPIO_PY7 199
  222 +#define TEGRA_GPIO_PZ0 200
  223 +#define TEGRA_GPIO_PZ1 201
  224 +#define TEGRA_GPIO_PZ2 202
  225 +#define TEGRA_GPIO_PZ3 203
  226 +#define TEGRA_GPIO_PZ4 204
  227 +#define TEGRA_GPIO_PZ5 205
  228 +#define TEGRA_GPIO_PZ6 206
  229 +#define TEGRA_GPIO_PZ7 207
  230 +#define TEGRA_GPIO_PAA0 208
  231 +#define TEGRA_GPIO_PAA1 209
  232 +#define TEGRA_GPIO_PAA2 210
  233 +#define TEGRA_GPIO_PAA3 211
  234 +#define TEGRA_GPIO_PAA4 212
  235 +#define TEGRA_GPIO_PAA5 213
  236 +#define TEGRA_GPIO_PAA6 214
  237 +#define TEGRA_GPIO_PAA7 215
  238 +#define TEGRA_GPIO_PBB0 216
  239 +#define TEGRA_GPIO_PBB1 217
  240 +#define TEGRA_GPIO_PBB2 218
  241 +#define TEGRA_GPIO_PBB3 219
  242 +#define TEGRA_GPIO_PBB4 220
  243 +#define TEGRA_GPIO_PBB5 221
  244 +#define TEGRA_GPIO_PBB6 222
  245 +#define TEGRA_GPIO_PBB7 223
  246 +
  247 +#endif
arch/arm/mach-tegra/gpio.c
  1 +/*
  2 + * arch/arm/mach-tegra/gpio.c
  3 + *
  4 + * Copyright (c) 2010 Google, Inc
  5 + *
  6 + * Author:
  7 + * Erik Gilling <konkers@google.com>
  8 + *
  9 + * This software is licensed under the terms of the GNU General Public
  10 + * License version 2, as published by the Free Software Foundation, and
  11 + * may be copied, distributed, and modified under those terms.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + */
  19 +
  20 +#include <linux/init.h>
  21 +#include <linux/irq.h>
  22 +
  23 +#include <linux/io.h>
  24 +#include <linux/gpio.h>
  25 +
  26 +#include <mach/iomap.h>
  27 +
  28 +#define GPIO_BANK(x) ((x) >> 5)
  29 +#define GPIO_PORT(x) (((x) >> 3) & 0x3)
  30 +#define GPIO_BIT(x) ((x) & 0x7)
  31 +
  32 +#define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \
  33 + GPIO_BANK(x) * 0x80 + \
  34 + GPIO_PORT(x) * 4)
  35 +
  36 +#define GPIO_CNF(x) (GPIO_REG(x) + 0x00)
  37 +#define GPIO_OE(x) (GPIO_REG(x) + 0x10)
  38 +#define GPIO_OUT(x) (GPIO_REG(x) + 0X20)
  39 +#define GPIO_IN(x) (GPIO_REG(x) + 0x30)
  40 +#define GPIO_INT_STA(x) (GPIO_REG(x) + 0x40)
  41 +#define GPIO_INT_ENB(x) (GPIO_REG(x) + 0x50)
  42 +#define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60)
  43 +#define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70)
  44 +
  45 +#define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x800)
  46 +#define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x810)
  47 +#define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0X820)
  48 +#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0x840)
  49 +#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0x850)
  50 +#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0x860)
  51 +
  52 +#define GPIO_INT_LVL_MASK 0x010101
  53 +#define GPIO_INT_LVL_EDGE_RISING 0x000101
  54 +#define GPIO_INT_LVL_EDGE_FALLING 0x000100
  55 +#define GPIO_INT_LVL_EDGE_BOTH 0x010100
  56 +#define GPIO_INT_LVL_LEVEL_HIGH 0x000001
  57 +#define GPIO_INT_LVL_LEVEL_LOW 0x000000
  58 +
  59 +struct tegra_gpio_bank {
  60 + int bank;
  61 + int irq;
  62 + spinlock_t lvl_lock[4];
  63 +};
  64 +
  65 +
  66 +static struct tegra_gpio_bank tegra_gpio_banks[] = {
  67 + {.bank = 0, .irq = INT_GPIO1},
  68 + {.bank = 1, .irq = INT_GPIO2},
  69 + {.bank = 2, .irq = INT_GPIO3},
  70 + {.bank = 3, .irq = INT_GPIO4},
  71 + {.bank = 4, .irq = INT_GPIO5},
  72 + {.bank = 5, .irq = INT_GPIO6},
  73 + {.bank = 6, .irq = INT_GPIO7},
  74 +};
  75 +
  76 +static int tegra_gpio_compose(int bank, int port, int bit)
  77 +{
  78 + return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
  79 +}
  80 +
  81 +static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
  82 +{
  83 + u32 val;
  84 +
  85 + val = 0x100 << GPIO_BIT(gpio);
  86 + if (value)
  87 + val |= 1 << GPIO_BIT(gpio);
  88 + __raw_writel(val, reg);
  89 +}
  90 +
  91 +void tegra_gpio_enable(int gpio)
  92 +{
  93 + tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
  94 +}
  95 +
  96 +void tegra_gpio_disable(int gpio)
  97 +{
  98 + tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
  99 +}
  100 +
  101 +static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  102 +{
  103 + tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
  104 +}
  105 +
  106 +static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
  107 +{
  108 + return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
  109 +}
  110 +
  111 +static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
  112 +{
  113 + tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
  114 + return 0;
  115 +}
  116 +
  117 +static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
  118 + int value)
  119 +{
  120 + tegra_gpio_set(chip, offset, value);
  121 + tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
  122 + return 0;
  123 +}
  124 +
  125 +
  126 +
  127 +static struct gpio_chip tegra_gpio_chip = {
  128 + .label = "tegra-gpio",
  129 + .direction_input = tegra_gpio_direction_input,
  130 + .get = tegra_gpio_get,
  131 + .direction_output = tegra_gpio_direction_output,
  132 + .set = tegra_gpio_set,
  133 + .base = 0,
  134 + .ngpio = ARCH_NR_GPIOS,
  135 +};
  136 +
  137 +static void tegra_gpio_irq_ack(unsigned int irq)
  138 +{
  139 + int gpio = irq - INT_GPIO_BASE;
  140 +
  141 + __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
  142 +}
  143 +
  144 +static void tegra_gpio_irq_mask(unsigned int irq)
  145 +{
  146 + int gpio = irq - INT_GPIO_BASE;
  147 +
  148 + tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
  149 +}
  150 +
  151 +static void tegra_gpio_irq_unmask(unsigned int irq)
  152 +{
  153 + int gpio = irq - INT_GPIO_BASE;
  154 +
  155 + tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
  156 +}
  157 +
  158 +static int tegra_gpio_irq_set_type(unsigned int irq, unsigned int type)
  159 +{
  160 + int gpio = irq - INT_GPIO_BASE;
  161 + struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
  162 + int port = GPIO_PORT(gpio);
  163 + int lvl_type;
  164 + int val;
  165 + unsigned long flags;
  166 +
  167 + switch (type & IRQ_TYPE_SENSE_MASK) {
  168 + case IRQ_TYPE_EDGE_RISING:
  169 + lvl_type = GPIO_INT_LVL_EDGE_RISING;
  170 + break;
  171 +
  172 + case IRQ_TYPE_EDGE_FALLING:
  173 + lvl_type = GPIO_INT_LVL_EDGE_FALLING;
  174 + break;
  175 +
  176 + case IRQ_TYPE_EDGE_BOTH:
  177 + lvl_type = GPIO_INT_LVL_EDGE_BOTH;
  178 + break;
  179 +
  180 + case IRQ_TYPE_LEVEL_HIGH:
  181 + lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
  182 + break;
  183 +
  184 + case IRQ_TYPE_LEVEL_LOW:
  185 + lvl_type = GPIO_INT_LVL_LEVEL_LOW;
  186 + break;
  187 +
  188 + default:
  189 + return -EINVAL;
  190 + }
  191 +
  192 + spin_lock_irqsave(&bank->lvl_lock[port], flags);
  193 +
  194 + val = __raw_readl(GPIO_INT_LVL(gpio));
  195 + val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
  196 + val |= lvl_type << GPIO_BIT(gpio);
  197 + __raw_writel(val, GPIO_INT_LVL(gpio));
  198 +
  199 + spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
  200 +
  201 + if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
  202 + __set_irq_handler_unlocked(irq, handle_level_irq);
  203 + else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
  204 + __set_irq_handler_unlocked(irq, handle_edge_irq);
  205 +
  206 + return 0;
  207 +}
  208 +
  209 +static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
  210 +{
  211 + struct tegra_gpio_bank *bank;
  212 + int port;
  213 + int pin;
  214 + int unmasked = 0;
  215 +
  216 + desc->chip->ack(irq);
  217 +
  218 + bank = get_irq_data(irq);
  219 +
  220 + for (port = 0; port < 4; port++) {
  221 + int gpio = tegra_gpio_compose(bank->bank, port, 0);
  222 + unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
  223 + __raw_readl(GPIO_INT_ENB(gpio));
  224 + u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
  225 +
  226 + for_each_set_bit(pin, &sta, 8) {
  227 + __raw_writel(1 << pin, GPIO_INT_CLR(gpio));
  228 +
  229 + /* if gpio is edge triggered, clear condition
  230 + * before executing the hander so that we don't
  231 + * miss edges
  232 + */
  233 + if (lvl & (0x100 << pin)) {
  234 + unmasked = 1;
  235 + desc->chip->unmask(irq);
  236 + }
  237 +
  238 + generic_handle_irq(gpio_to_irq(gpio + pin));
  239 + }
  240 + }
  241 +
  242 + if (!unmasked)
  243 + desc->chip->unmask(irq);
  244 +
  245 +}
  246 +
  247 +
  248 +static struct irq_chip tegra_gpio_irq_chip = {
  249 + .name = "GPIO",
  250 + .ack = tegra_gpio_irq_ack,
  251 + .mask = tegra_gpio_irq_mask,
  252 + .unmask = tegra_gpio_irq_unmask,
  253 + .set_type = tegra_gpio_irq_set_type,
  254 +};
  255 +
  256 +
  257 +/* This lock class tells lockdep that GPIO irqs are in a different
  258 + * category than their parents, so it won't report false recursion.
  259 + */
  260 +static struct lock_class_key gpio_lock_class;
  261 +
  262 +static int __init tegra_gpio_init(void)
  263 +{
  264 + struct tegra_gpio_bank *bank;
  265 + int i;
  266 + int j;
  267 +
  268 + for (i = 0; i < 7; i++) {
  269 + for (j = 0; j < 4; j++) {
  270 + int gpio = tegra_gpio_compose(i, j, 0);
  271 + __raw_writel(0x00, GPIO_INT_ENB(gpio));
  272 + }
  273 + }
  274 +
  275 + gpiochip_add(&tegra_gpio_chip);
  276 +
  277 + for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) {
  278 + bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
  279 +
  280 + lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
  281 + set_irq_chip_data(i, bank);
  282 + set_irq_chip(i, &tegra_gpio_irq_chip);
  283 + set_irq_handler(i, handle_simple_irq);
  284 + set_irq_flags(i, IRQF_VALID);
  285 + }
  286 +
  287 + for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
  288 + bank = &tegra_gpio_banks[i];
  289 +
  290 + set_irq_chained_handler(bank->irq, tegra_gpio_irq_handler);
  291 + set_irq_data(bank->irq, bank);
  292 +
  293 + for (j = 0; j < 4; j++)
  294 + spin_lock_init(&bank->lvl_lock[j]);
  295 + }
  296 +
  297 + return 0;
  298 +}
  299 +
  300 +postcore_initcall(tegra_gpio_init);
  301 +
  302 +#ifdef CONFIG_DEBUG_FS
  303 +
  304 +#include <linux/debugfs.h>
  305 +#include <linux/seq_file.h>
  306 +
  307 +static int dbg_gpio_show(struct seq_file *s, void *unused)
  308 +{
  309 + int i;
  310 + int j;
  311 +
  312 + for (i = 0; i < 7; i++) {
  313 + for (j = 0; j < 4; j++) {
  314 + int gpio = tegra_gpio_compose(i, j, 0);
  315 + seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
  316 + i, j,
  317 + __raw_readl(GPIO_CNF(gpio)),
  318 + __raw_readl(GPIO_OE(gpio)),
  319 + __raw_readl(GPIO_OUT(gpio)),
  320 + __raw_readl(GPIO_IN(gpio)),
  321 + __raw_readl(GPIO_INT_STA(gpio)),
  322 + __raw_readl(GPIO_INT_ENB(gpio)),
  323 + __raw_readl(GPIO_INT_LVL(gpio)));
  324 + }
  325 + }
  326 + return 0;
  327 +}
  328 +
  329 +static int dbg_gpio_open(struct inode *inode, struct file *file)
  330 +{
  331 + return single_open(file, dbg_gpio_show, &inode->i_private);
  332 +}
  333 +
  334 +static const struct file_operations debug_fops = {
  335 + .open = dbg_gpio_open,
  336 + .read = seq_read,
  337 + .llseek = seq_lseek,
  338 + .release = single_release,
  339 +};
  340 +
  341 +static int __init tegra_gpio_debuginit(void)
  342 +{
  343 + (void) debugfs_create_file("tegra_gpio", S_IRUGO,
  344 + NULL, NULL, &debug_fops);
  345 + return 0;
  346 +}
  347 +late_initcall(tegra_gpio_debuginit);
  348 +#endif
arch/arm/mach-tegra/include/mach/gpio.h
  1 +/*
  2 + * arch/arm/mach-tegra/include/mach/gpio.h
  3 + *
  4 + * Copyright (C) 2010 Google, Inc.
  5 + *
  6 + * Author:
  7 + * Erik Gilling <konkers@google.com>
  8 + *
  9 + * This software is licensed under the terms of the GNU General Public
  10 + * License version 2, as published by the Free Software Foundation, and
  11 + * may be copied, distributed, and modified under those terms.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + */
  19 +
  20 +#ifndef __MACH_TEGRA_GPIO_H
  21 +#define __MACH_TEGRA_GPIO_H
  22 +
  23 +#include <mach/irqs.h>
  24 +
  25 +#define ARCH_NR_GPIOS INT_GPIO_NR
  26 +
  27 +#include <asm-generic/gpio.h>
  28 +
  29 +#define gpio_get_value __gpio_get_value
  30 +#define gpio_set_value __gpio_set_value
  31 +#define gpio_cansleep __gpio_cansleep
  32 +
  33 +#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
  34 +#define TEGRA_IRQ_TO_GPIO(irq) ((gpio) - INT_GPIO_BASE)
  35 +
  36 +static inline int gpio_to_irq(unsigned int gpio)
  37 +{
  38 + if (gpio < ARCH_NR_GPIOS)
  39 + return INT_GPIO_BASE + gpio;
  40 + return -EINVAL;
  41 +}
  42 +
  43 +static inline int irq_to_gpio(unsigned int irq)
  44 +{
  45 + if ((irq >= INT_GPIO_BASE) && (irq < INT_GPIO_BASE + INT_GPIO_NR))
  46 + return irq - INT_GPIO_BASE;
  47 + return -EINVAL;
  48 +}
  49 +
  50 +void tegra_gpio_enable(int gpio);
  51 +void tegra_gpio_disable(int gpio);
  52 +
  53 +#endif