diff options
Diffstat (limited to 'drivers/gpio/gpio-tegra.c')
-rw-r--r-- | drivers/gpio/gpio-tegra.c | 166 |
1 files changed, 111 insertions, 55 deletions
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 747eb40e8afe..61044c889f7f 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
@@ -20,13 +20,15 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | |||
24 | #include <linux/io.h> | 23 | #include <linux/io.h> |
25 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
26 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/module.h> | ||
27 | 28 | ||
28 | #include <asm/mach/irq.h> | 29 | #include <asm/mach/irq.h> |
29 | 30 | ||
31 | #include <mach/gpio-tegra.h> | ||
30 | #include <mach/iomap.h> | 32 | #include <mach/iomap.h> |
31 | #include <mach/suspend.h> | 33 | #include <mach/suspend.h> |
32 | 34 | ||
@@ -34,9 +36,7 @@ | |||
34 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) | 36 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) |
35 | #define GPIO_BIT(x) ((x) & 0x7) | 37 | #define GPIO_BIT(x) ((x) & 0x7) |
36 | 38 | ||
37 | #define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \ | 39 | #define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4) |
38 | GPIO_BANK(x) * 0x80 + \ | ||
39 | GPIO_PORT(x) * 4) | ||
40 | 40 | ||
41 | #define GPIO_CNF(x) (GPIO_REG(x) + 0x00) | 41 | #define GPIO_CNF(x) (GPIO_REG(x) + 0x00) |
42 | #define GPIO_OE(x) (GPIO_REG(x) + 0x10) | 42 | #define GPIO_OE(x) (GPIO_REG(x) + 0x10) |
@@ -75,15 +75,18 @@ struct tegra_gpio_bank { | |||
75 | }; | 75 | }; |
76 | 76 | ||
77 | 77 | ||
78 | static struct tegra_gpio_bank tegra_gpio_banks[] = { | 78 | static void __iomem *regs; |
79 | {.bank = 0, .irq = INT_GPIO1}, | 79 | static struct tegra_gpio_bank tegra_gpio_banks[7]; |
80 | {.bank = 1, .irq = INT_GPIO2}, | 80 | |
81 | {.bank = 2, .irq = INT_GPIO3}, | 81 | static inline void tegra_gpio_writel(u32 val, u32 reg) |
82 | {.bank = 3, .irq = INT_GPIO4}, | 82 | { |
83 | {.bank = 4, .irq = INT_GPIO5}, | 83 | __raw_writel(val, regs + reg); |
84 | {.bank = 5, .irq = INT_GPIO6}, | 84 | } |
85 | {.bank = 6, .irq = INT_GPIO7}, | 85 | |
86 | }; | 86 | static inline u32 tegra_gpio_readl(u32 reg) |
87 | { | ||
88 | return __raw_readl(regs + reg); | ||
89 | } | ||
87 | 90 | ||
88 | static int tegra_gpio_compose(int bank, int port, int bit) | 91 | static int tegra_gpio_compose(int bank, int port, int bit) |
89 | { | 92 | { |
@@ -97,7 +100,7 @@ static void tegra_gpio_mask_write(u32 reg, int gpio, int value) | |||
97 | val = 0x100 << GPIO_BIT(gpio); | 100 | val = 0x100 << GPIO_BIT(gpio); |
98 | if (value) | 101 | if (value) |
99 | val |= 1 << GPIO_BIT(gpio); | 102 | val |= 1 << GPIO_BIT(gpio); |
100 | __raw_writel(val, reg); | 103 | tegra_gpio_writel(val, reg); |
101 | } | 104 | } |
102 | 105 | ||
103 | void tegra_gpio_enable(int gpio) | 106 | void tegra_gpio_enable(int gpio) |
@@ -117,7 +120,7 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
117 | 120 | ||
118 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) | 121 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) |
119 | { | 122 | { |
120 | return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; | 123 | return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; |
121 | } | 124 | } |
122 | 125 | ||
123 | static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | 126 | static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
@@ -134,7 +137,10 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | |||
134 | return 0; | 137 | return 0; |
135 | } | 138 | } |
136 | 139 | ||
137 | 140 | static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |
141 | { | ||
142 | return TEGRA_GPIO_TO_IRQ(offset); | ||
143 | } | ||
138 | 144 | ||
139 | static struct gpio_chip tegra_gpio_chip = { | 145 | static struct gpio_chip tegra_gpio_chip = { |
140 | .label = "tegra-gpio", | 146 | .label = "tegra-gpio", |
@@ -142,6 +148,7 @@ static struct gpio_chip tegra_gpio_chip = { | |||
142 | .get = tegra_gpio_get, | 148 | .get = tegra_gpio_get, |
143 | .direction_output = tegra_gpio_direction_output, | 149 | .direction_output = tegra_gpio_direction_output, |
144 | .set = tegra_gpio_set, | 150 | .set = tegra_gpio_set, |
151 | .to_irq = tegra_gpio_to_irq, | ||
145 | .base = 0, | 152 | .base = 0, |
146 | .ngpio = TEGRA_NR_GPIOS, | 153 | .ngpio = TEGRA_NR_GPIOS, |
147 | }; | 154 | }; |
@@ -150,7 +157,7 @@ static void tegra_gpio_irq_ack(struct irq_data *d) | |||
150 | { | 157 | { |
151 | int gpio = d->irq - INT_GPIO_BASE; | 158 | int gpio = d->irq - INT_GPIO_BASE; |
152 | 159 | ||
153 | __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio)); | 160 | tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio)); |
154 | } | 161 | } |
155 | 162 | ||
156 | static void tegra_gpio_irq_mask(struct irq_data *d) | 163 | static void tegra_gpio_irq_mask(struct irq_data *d) |
@@ -203,10 +210,10 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
203 | 210 | ||
204 | spin_lock_irqsave(&bank->lvl_lock[port], flags); | 211 | spin_lock_irqsave(&bank->lvl_lock[port], flags); |
205 | 212 | ||
206 | val = __raw_readl(GPIO_INT_LVL(gpio)); | 213 | val = tegra_gpio_readl(GPIO_INT_LVL(gpio)); |
207 | val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); | 214 | val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); |
208 | val |= lvl_type << GPIO_BIT(gpio); | 215 | val |= lvl_type << GPIO_BIT(gpio); |
209 | __raw_writel(val, GPIO_INT_LVL(gpio)); | 216 | tegra_gpio_writel(val, GPIO_INT_LVL(gpio)); |
210 | 217 | ||
211 | spin_unlock_irqrestore(&bank->lvl_lock[port], flags); | 218 | spin_unlock_irqrestore(&bank->lvl_lock[port], flags); |
212 | 219 | ||
@@ -232,12 +239,12 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
232 | 239 | ||
233 | for (port = 0; port < 4; port++) { | 240 | for (port = 0; port < 4; port++) { |
234 | int gpio = tegra_gpio_compose(bank->bank, port, 0); | 241 | int gpio = tegra_gpio_compose(bank->bank, port, 0); |
235 | unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) & | 242 | unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) & |
236 | __raw_readl(GPIO_INT_ENB(gpio)); | 243 | tegra_gpio_readl(GPIO_INT_ENB(gpio)); |
237 | u32 lvl = __raw_readl(GPIO_INT_LVL(gpio)); | 244 | u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio)); |
238 | 245 | ||
239 | for_each_set_bit(pin, &sta, 8) { | 246 | for_each_set_bit(pin, &sta, 8) { |
240 | __raw_writel(1 << pin, GPIO_INT_CLR(gpio)); | 247 | tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio)); |
241 | 248 | ||
242 | /* if gpio is edge triggered, clear condition | 249 | /* if gpio is edge triggered, clear condition |
243 | * before executing the hander so that we don't | 250 | * before executing the hander so that we don't |
@@ -271,11 +278,11 @@ void tegra_gpio_resume(void) | |||
271 | 278 | ||
272 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { | 279 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { |
273 | unsigned int gpio = (b<<5) | (p<<3); | 280 | unsigned int gpio = (b<<5) | (p<<3); |
274 | __raw_writel(bank->cnf[p], GPIO_CNF(gpio)); | 281 | tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio)); |
275 | __raw_writel(bank->out[p], GPIO_OUT(gpio)); | 282 | tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio)); |
276 | __raw_writel(bank->oe[p], GPIO_OE(gpio)); | 283 | tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio)); |
277 | __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); | 284 | tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); |
278 | __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); | 285 | tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); |
279 | } | 286 | } |
280 | } | 287 | } |
281 | 288 | ||
@@ -294,11 +301,11 @@ void tegra_gpio_suspend(void) | |||
294 | 301 | ||
295 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { | 302 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { |
296 | unsigned int gpio = (b<<5) | (p<<3); | 303 | unsigned int gpio = (b<<5) | (p<<3); |
297 | bank->cnf[p] = __raw_readl(GPIO_CNF(gpio)); | 304 | bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio)); |
298 | bank->out[p] = __raw_readl(GPIO_OUT(gpio)); | 305 | bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio)); |
299 | bank->oe[p] = __raw_readl(GPIO_OE(gpio)); | 306 | bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio)); |
300 | bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio)); | 307 | bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio)); |
301 | bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio)); | 308 | bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio)); |
302 | } | 309 | } |
303 | } | 310 | } |
304 | local_irq_restore(flags); | 311 | local_irq_restore(flags); |
@@ -328,38 +335,69 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
328 | */ | 335 | */ |
329 | static struct lock_class_key gpio_lock_class; | 336 | static struct lock_class_key gpio_lock_class; |
330 | 337 | ||
331 | static int __init tegra_gpio_init(void) | 338 | static int __devinit tegra_gpio_probe(struct platform_device *pdev) |
332 | { | 339 | { |
340 | struct resource *res; | ||
333 | struct tegra_gpio_bank *bank; | 341 | struct tegra_gpio_bank *bank; |
342 | int gpio; | ||
334 | int i; | 343 | int i; |
335 | int j; | 344 | int j; |
336 | 345 | ||
346 | for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) { | ||
347 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | ||
348 | if (!res) { | ||
349 | dev_err(&pdev->dev, "Missing IRQ resource\n"); | ||
350 | return -ENODEV; | ||
351 | } | ||
352 | |||
353 | bank = &tegra_gpio_banks[i]; | ||
354 | bank->bank = i; | ||
355 | bank->irq = res->start; | ||
356 | } | ||
357 | |||
358 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
359 | if (!res) { | ||
360 | dev_err(&pdev->dev, "Missing MEM resource\n"); | ||
361 | return -ENODEV; | ||
362 | } | ||
363 | |||
364 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
365 | resource_size(res), | ||
366 | dev_name(&pdev->dev))) { | ||
367 | dev_err(&pdev->dev, "Couldn't request MEM resource\n"); | ||
368 | return -ENODEV; | ||
369 | } | ||
370 | |||
371 | regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | ||
372 | if (!regs) { | ||
373 | dev_err(&pdev->dev, "Couldn't ioremap regs\n"); | ||
374 | return -ENODEV; | ||
375 | } | ||
376 | |||
337 | for (i = 0; i < 7; i++) { | 377 | for (i = 0; i < 7; i++) { |
338 | for (j = 0; j < 4; j++) { | 378 | for (j = 0; j < 4; j++) { |
339 | int gpio = tegra_gpio_compose(i, j, 0); | 379 | int gpio = tegra_gpio_compose(i, j, 0); |
340 | __raw_writel(0x00, GPIO_INT_ENB(gpio)); | 380 | tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio)); |
341 | } | 381 | } |
342 | } | 382 | } |
343 | 383 | ||
344 | #ifdef CONFIG_OF_GPIO | 384 | #ifdef CONFIG_OF_GPIO |
345 | /* | 385 | tegra_gpio_chip.of_node = pdev->dev.of_node; |
346 | * This isn't ideal, but it gets things hooked up until this | 386 | #endif |
347 | * driver is converted into a platform_device | ||
348 | */ | ||
349 | tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL, | ||
350 | "nvidia,tegra20-gpio"); | ||
351 | #endif /* CONFIG_OF_GPIO */ | ||
352 | 387 | ||
353 | gpiochip_add(&tegra_gpio_chip); | 388 | gpiochip_add(&tegra_gpio_chip); |
354 | 389 | ||
355 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { | 390 | for (gpio = 0; gpio < TEGRA_NR_GPIOS; gpio++) { |
356 | bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; | 391 | int irq = TEGRA_GPIO_TO_IRQ(gpio); |
392 | /* No validity check; all Tegra GPIOs are valid IRQs */ | ||
357 | 393 | ||
358 | irq_set_lockdep_class(i, &gpio_lock_class); | 394 | bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; |
359 | irq_set_chip_data(i, bank); | 395 | |
360 | irq_set_chip_and_handler(i, &tegra_gpio_irq_chip, | 396 | irq_set_lockdep_class(irq, &gpio_lock_class); |
397 | irq_set_chip_data(irq, bank); | ||
398 | irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip, | ||
361 | handle_simple_irq); | 399 | handle_simple_irq); |
362 | set_irq_flags(i, IRQF_VALID); | 400 | set_irq_flags(irq, IRQF_VALID); |
363 | } | 401 | } |
364 | 402 | ||
365 | for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) { | 403 | for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) { |
@@ -375,6 +413,24 @@ static int __init tegra_gpio_init(void) | |||
375 | return 0; | 413 | return 0; |
376 | } | 414 | } |
377 | 415 | ||
416 | static struct of_device_id tegra_gpio_of_match[] __devinitdata = { | ||
417 | { .compatible = "nvidia,tegra20-gpio", }, | ||
418 | { }, | ||
419 | }; | ||
420 | |||
421 | static struct platform_driver tegra_gpio_driver = { | ||
422 | .driver = { | ||
423 | .name = "tegra-gpio", | ||
424 | .owner = THIS_MODULE, | ||
425 | .of_match_table = tegra_gpio_of_match, | ||
426 | }, | ||
427 | .probe = tegra_gpio_probe, | ||
428 | }; | ||
429 | |||
430 | static int __init tegra_gpio_init(void) | ||
431 | { | ||
432 | return platform_driver_register(&tegra_gpio_driver); | ||
433 | } | ||
378 | postcore_initcall(tegra_gpio_init); | 434 | postcore_initcall(tegra_gpio_init); |
379 | 435 | ||
380 | void __init tegra_gpio_config(struct tegra_gpio_table *table, int num) | 436 | void __init tegra_gpio_config(struct tegra_gpio_table *table, int num) |
@@ -407,13 +463,13 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) | |||
407 | seq_printf(s, | 463 | seq_printf(s, |
408 | "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", | 464 | "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", |
409 | i, j, | 465 | i, j, |
410 | __raw_readl(GPIO_CNF(gpio)), | 466 | tegra_gpio_readl(GPIO_CNF(gpio)), |
411 | __raw_readl(GPIO_OE(gpio)), | 467 | tegra_gpio_readl(GPIO_OE(gpio)), |
412 | __raw_readl(GPIO_OUT(gpio)), | 468 | tegra_gpio_readl(GPIO_OUT(gpio)), |
413 | __raw_readl(GPIO_IN(gpio)), | 469 | tegra_gpio_readl(GPIO_IN(gpio)), |
414 | __raw_readl(GPIO_INT_STA(gpio)), | 470 | tegra_gpio_readl(GPIO_INT_STA(gpio)), |
415 | __raw_readl(GPIO_INT_ENB(gpio)), | 471 | tegra_gpio_readl(GPIO_INT_ENB(gpio)), |
416 | __raw_readl(GPIO_INT_LVL(gpio))); | 472 | tegra_gpio_readl(GPIO_INT_LVL(gpio))); |
417 | } | 473 | } |
418 | } | 474 | } |
419 | return 0; | 475 | return 0; |