aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Gilling <konkers@android.com>2010-03-15 22:40:06 -0400
committerErik Gilling <konkers@android.com>2010-08-05 17:57:02 -0400
commit3c92db9ac0ca3eee8e46e2424b6c074e2e394ad9 (patch)
tree91bce4b3fa4cd34e415476a903d71dd759f9d598
parent2d5cd9a38b3792426115adbedce539bd45ee640e (diff)
[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>
-rw-r--r--arch/arm/mach-tegra/Kconfig1
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/gpio-names.h247
-rw-r--r--arch/arm/mach-tegra/gpio.c348
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio.h53
5 files changed, 650 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index bcbda96ec84c..a57713c1954a 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -9,6 +9,7 @@ config ARCH_TEGRA_2x_SOC
9 bool "Tegra 2 family" 9 bool "Tegra 2 family"
10 select CPU_V7 10 select CPU_V7
11 select ARM_GIC 11 select ARM_GIC
12 select ARCH_REQUIRE_GPIOLIB
12 help 13 help
13 Support for NVIDIA Tegra AP20 and T20 processors, based on the 14 Support for NVIDIA Tegra AP20 and T20 processors, based on the
14 ARM CortexA9MP CPU and the ARM PL310 L2 cache controller 15 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 01f47fd4044e..122f7dc4eaa1 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -3,6 +3,7 @@ obj-y += io.o
3obj-y += irq.o 3obj-y += irq.o
4obj-y += clock.o 4obj-y += clock.o
5obj-y += timer.o 5obj-y += timer.o
6obj-y += gpio.o
6obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o 7obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o
7obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o 8obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o
8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 9obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-tegra/gpio-names.h b/arch/arm/mach-tegra/gpio-names.h
new file mode 100644
index 000000000000..f28220a641b2
--- /dev/null
+++ b/arch/arm/mach-tegra/gpio-names.h
@@ -0,0 +1,247 @@
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
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
new file mode 100644
index 000000000000..fe78fba25f3c
--- /dev/null
+++ b/arch/arm/mach-tegra/gpio.c
@@ -0,0 +1,348 @@
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
59struct tegra_gpio_bank {
60 int bank;
61 int irq;
62 spinlock_t lvl_lock[4];
63};
64
65
66static 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
76static int tegra_gpio_compose(int bank, int port, int bit)
77{
78 return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
79}
80
81static 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
91void tegra_gpio_enable(int gpio)
92{
93 tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
94}
95
96void tegra_gpio_disable(int gpio)
97{
98 tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
99}
100
101static 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
106static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
107{
108 return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
109}
110
111static 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
117static 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
127static 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
137static 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
144static 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
151static 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
158static 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
209static 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
248static 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 */
260static struct lock_class_key gpio_lock_class;
261
262static 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
300postcore_initcall(tegra_gpio_init);
301
302#ifdef CONFIG_DEBUG_FS
303
304#include <linux/debugfs.h>
305#include <linux/seq_file.h>
306
307static 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
329static int dbg_gpio_open(struct inode *inode, struct file *file)
330{
331 return single_open(file, dbg_gpio_show, &inode->i_private);
332}
333
334static 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
341static 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}
347late_initcall(tegra_gpio_debuginit);
348#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
new file mode 100644
index 000000000000..540e822e50f7
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/gpio.h
@@ -0,0 +1,53 @@
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
36static 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
43static 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
50void tegra_gpio_enable(int gpio);
51void tegra_gpio_disable(int gpio);
52
53#endif