diff options
Diffstat (limited to 'drivers/gpio/gpio-tegra.c')
| -rw-r--r-- | drivers/gpio/gpio-tegra.c | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 32de6707e3c4..12f349b3830d 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
| 23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
| 25 | #include <linux/of.h> | 25 | #include <linux/of_device.h> |
| 26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
| 27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 28 | #include <linux/irqdomain.h> | 28 | #include <linux/irqdomain.h> |
| @@ -37,7 +37,8 @@ | |||
| 37 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) | 37 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) |
| 38 | #define GPIO_BIT(x) ((x) & 0x7) | 38 | #define GPIO_BIT(x) ((x) & 0x7) |
| 39 | 39 | ||
| 40 | #define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4) | 40 | #define GPIO_REG(x) (GPIO_BANK(x) * tegra_gpio_bank_stride + \ |
| 41 | GPIO_PORT(x) * 4) | ||
| 41 | 42 | ||
| 42 | #define GPIO_CNF(x) (GPIO_REG(x) + 0x00) | 43 | #define GPIO_CNF(x) (GPIO_REG(x) + 0x00) |
| 43 | #define GPIO_OE(x) (GPIO_REG(x) + 0x10) | 44 | #define GPIO_OE(x) (GPIO_REG(x) + 0x10) |
| @@ -48,12 +49,12 @@ | |||
| 48 | #define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60) | 49 | #define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60) |
| 49 | #define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70) | 50 | #define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70) |
| 50 | 51 | ||
| 51 | #define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x800) | 52 | #define GPIO_MSK_CNF(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x00) |
| 52 | #define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x810) | 53 | #define GPIO_MSK_OE(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x10) |
| 53 | #define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0X820) | 54 | #define GPIO_MSK_OUT(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0X20) |
| 54 | #define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0x840) | 55 | #define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x40) |
| 55 | #define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0x850) | 56 | #define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x50) |
| 56 | #define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0x860) | 57 | #define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x60) |
| 57 | 58 | ||
| 58 | #define GPIO_INT_LVL_MASK 0x010101 | 59 | #define GPIO_INT_LVL_MASK 0x010101 |
| 59 | #define GPIO_INT_LVL_EDGE_RISING 0x000101 | 60 | #define GPIO_INT_LVL_EDGE_RISING 0x000101 |
| @@ -78,6 +79,8 @@ struct tegra_gpio_bank { | |||
| 78 | static struct irq_domain *irq_domain; | 79 | static struct irq_domain *irq_domain; |
| 79 | static void __iomem *regs; | 80 | static void __iomem *regs; |
| 80 | static u32 tegra_gpio_bank_count; | 81 | static u32 tegra_gpio_bank_count; |
| 82 | static u32 tegra_gpio_bank_stride; | ||
| 83 | static u32 tegra_gpio_upper_offset; | ||
| 81 | static struct tegra_gpio_bank *tegra_gpio_banks; | 84 | static struct tegra_gpio_bank *tegra_gpio_banks; |
| 82 | 85 | ||
| 83 | static inline void tegra_gpio_writel(u32 val, u32 reg) | 86 | static inline void tegra_gpio_writel(u32 val, u32 reg) |
| @@ -333,6 +336,26 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
| 333 | #endif | 336 | #endif |
| 334 | }; | 337 | }; |
| 335 | 338 | ||
| 339 | struct tegra_gpio_soc_config { | ||
| 340 | u32 bank_stride; | ||
| 341 | u32 upper_offset; | ||
| 342 | }; | ||
| 343 | |||
| 344 | static struct tegra_gpio_soc_config tegra20_gpio_config = { | ||
| 345 | .bank_stride = 0x80, | ||
| 346 | .upper_offset = 0x800, | ||
| 347 | }; | ||
| 348 | |||
| 349 | static struct tegra_gpio_soc_config tegra30_gpio_config = { | ||
| 350 | .bank_stride = 0x100, | ||
| 351 | .upper_offset = 0x80, | ||
| 352 | }; | ||
| 353 | |||
| 354 | static struct of_device_id tegra_gpio_of_match[] __devinitdata = { | ||
| 355 | { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config }, | ||
| 356 | { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config }, | ||
| 357 | { }, | ||
| 358 | }; | ||
| 336 | 359 | ||
| 337 | /* This lock class tells lockdep that GPIO irqs are in a different | 360 | /* This lock class tells lockdep that GPIO irqs are in a different |
| 338 | * category than their parents, so it won't report false recursion. | 361 | * category than their parents, so it won't report false recursion. |
| @@ -341,6 +364,8 @@ static struct lock_class_key gpio_lock_class; | |||
| 341 | 364 | ||
| 342 | static int __devinit tegra_gpio_probe(struct platform_device *pdev) | 365 | static int __devinit tegra_gpio_probe(struct platform_device *pdev) |
| 343 | { | 366 | { |
| 367 | const struct of_device_id *match; | ||
| 368 | struct tegra_gpio_soc_config *config; | ||
| 344 | int irq_base; | 369 | int irq_base; |
| 345 | struct resource *res; | 370 | struct resource *res; |
| 346 | struct tegra_gpio_bank *bank; | 371 | struct tegra_gpio_bank *bank; |
| @@ -348,6 +373,15 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
| 348 | int i; | 373 | int i; |
| 349 | int j; | 374 | int j; |
| 350 | 375 | ||
| 376 | match = of_match_device(tegra_gpio_of_match, &pdev->dev); | ||
| 377 | if (match) | ||
| 378 | config = (struct tegra_gpio_soc_config *)match->data; | ||
| 379 | else | ||
| 380 | config = &tegra20_gpio_config; | ||
| 381 | |||
| 382 | tegra_gpio_bank_stride = config->bank_stride; | ||
| 383 | tegra_gpio_upper_offset = config->upper_offset; | ||
| 384 | |||
| 351 | for (;;) { | 385 | for (;;) { |
| 352 | res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count); | 386 | res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count); |
| 353 | if (!res) | 387 | if (!res) |
| @@ -402,7 +436,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
| 402 | return -ENODEV; | 436 | return -ENODEV; |
| 403 | } | 437 | } |
| 404 | 438 | ||
| 405 | for (i = 0; i < 7; i++) { | 439 | for (i = 0; i < tegra_gpio_bank_count; i++) { |
| 406 | for (j = 0; j < 4; j++) { | 440 | for (j = 0; j < 4; j++) { |
| 407 | int gpio = tegra_gpio_compose(i, j, 0); | 441 | int gpio = tegra_gpio_compose(i, j, 0); |
| 408 | tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio)); | 442 | tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio)); |
| @@ -441,11 +475,6 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
| 441 | return 0; | 475 | return 0; |
| 442 | } | 476 | } |
| 443 | 477 | ||
| 444 | static struct of_device_id tegra_gpio_of_match[] __devinitdata = { | ||
| 445 | { .compatible = "nvidia,tegra20-gpio", }, | ||
| 446 | { }, | ||
| 447 | }; | ||
| 448 | |||
| 449 | static struct platform_driver tegra_gpio_driver = { | 478 | static struct platform_driver tegra_gpio_driver = { |
| 450 | .driver = { | 479 | .driver = { |
| 451 | .name = "tegra-gpio", | 480 | .name = "tegra-gpio", |
| @@ -485,7 +514,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) | |||
| 485 | int i; | 514 | int i; |
| 486 | int j; | 515 | int j; |
| 487 | 516 | ||
| 488 | for (i = 0; i < 7; i++) { | 517 | for (i = 0; i < tegra_gpio_bank_count; i++) { |
| 489 | for (j = 0; j < 4; j++) { | 518 | for (j = 0; j < 4; j++) { |
| 490 | int gpio = tegra_gpio_compose(i, j, 0); | 519 | int gpio = tegra_gpio_compose(i, j, 0); |
| 491 | seq_printf(s, | 520 | seq_printf(s, |
