diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-01 23:31:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-01 23:31:25 -0400 |
commit | 16ee792e45cf0c97ce061fce03c36cab5551ec72 (patch) | |
tree | dc68af705fbac4b5d71325aa972730199bb187dd /drivers/gpio | |
parent | f906fb1d70e016726fccfb0d978c5d425503db9d (diff) | |
parent | efa62e1355f0495f37f1296754b8880947c8da72 (diff) |
Merge branch 'next/devel' of git://git.linaro.org/people/arnd/arm-soc
* 'next/devel' of git://git.linaro.org/people/arnd/arm-soc: (50 commits)
ARM: tegra: update defconfig
arm/tegra: Harmony: Configure PMC for low-level interrupts
arm/tegra: device tree support for ventana board
arm/tegra: add support for ventana pinmuxing
arm/tegra: prepare Seaboard pinmux code for derived boards
arm/tegra: pinmux: ioremap registers
gpio/tegra: Convert to a platform device
arm/tegra: Convert pinmux driver to a platform device
arm/dt: Tegra: Add pinmux node to tegra20.dtsi
arm/tegra: Prep boards for gpio/pinmux conversion to pdevs
ARM: mx5: fix clock usage for suspend
ARM i.MX entry-macro.S: remove now unused code
ARM i.MX boards: use CONFIG_MULTI_IRQ_HANDLER
ARM i.MX tzic: add handle_irq function
ARM i.MX avic: add handle_irq function
ARM: mx25: Add the missing IIM base definition
ARM i.MX avic: convert to use generic irq chip
mx31moboard: Add poweroff support
ARM: mach-qong: Add watchdog support
ARM: davinci: AM18x: Add wl1271/wlan support
...
Fix up conflicts in:
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-mx5/devices-imx53.h
arch/arm/plat-mxc/include/mach/memory.h
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-tegra.c | 143 |
1 files changed, 95 insertions, 48 deletions
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 6b65207c8106..61044c889f7f 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
@@ -20,10 +20,11 @@ | |||
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 | ||
@@ -35,9 +36,7 @@ | |||
35 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) | 36 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) |
36 | #define GPIO_BIT(x) ((x) & 0x7) | 37 | #define GPIO_BIT(x) ((x) & 0x7) |
37 | 38 | ||
38 | #define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \ | 39 | #define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4) |
39 | GPIO_BANK(x) * 0x80 + \ | ||
40 | GPIO_PORT(x) * 4) | ||
41 | 40 | ||
42 | #define GPIO_CNF(x) (GPIO_REG(x) + 0x00) | 41 | #define GPIO_CNF(x) (GPIO_REG(x) + 0x00) |
43 | #define GPIO_OE(x) (GPIO_REG(x) + 0x10) | 42 | #define GPIO_OE(x) (GPIO_REG(x) + 0x10) |
@@ -76,15 +75,18 @@ struct tegra_gpio_bank { | |||
76 | }; | 75 | }; |
77 | 76 | ||
78 | 77 | ||
79 | static struct tegra_gpio_bank tegra_gpio_banks[] = { | 78 | static void __iomem *regs; |
80 | {.bank = 0, .irq = INT_GPIO1}, | 79 | static struct tegra_gpio_bank tegra_gpio_banks[7]; |
81 | {.bank = 1, .irq = INT_GPIO2}, | 80 | |
82 | {.bank = 2, .irq = INT_GPIO3}, | 81 | static inline void tegra_gpio_writel(u32 val, u32 reg) |
83 | {.bank = 3, .irq = INT_GPIO4}, | 82 | { |
84 | {.bank = 4, .irq = INT_GPIO5}, | 83 | __raw_writel(val, regs + reg); |
85 | {.bank = 5, .irq = INT_GPIO6}, | 84 | } |
86 | {.bank = 6, .irq = INT_GPIO7}, | 85 | |
87 | }; | 86 | static inline u32 tegra_gpio_readl(u32 reg) |
87 | { | ||
88 | return __raw_readl(regs + reg); | ||
89 | } | ||
88 | 90 | ||
89 | static int tegra_gpio_compose(int bank, int port, int bit) | 91 | static int tegra_gpio_compose(int bank, int port, int bit) |
90 | { | 92 | { |
@@ -98,7 +100,7 @@ static void tegra_gpio_mask_write(u32 reg, int gpio, int value) | |||
98 | val = 0x100 << GPIO_BIT(gpio); | 100 | val = 0x100 << GPIO_BIT(gpio); |
99 | if (value) | 101 | if (value) |
100 | val |= 1 << GPIO_BIT(gpio); | 102 | val |= 1 << GPIO_BIT(gpio); |
101 | __raw_writel(val, reg); | 103 | tegra_gpio_writel(val, reg); |
102 | } | 104 | } |
103 | 105 | ||
104 | void tegra_gpio_enable(int gpio) | 106 | void tegra_gpio_enable(int gpio) |
@@ -118,7 +120,7 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
118 | 120 | ||
119 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) | 121 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) |
120 | { | 122 | { |
121 | return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; | 123 | return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; |
122 | } | 124 | } |
123 | 125 | ||
124 | 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) |
@@ -155,7 +157,7 @@ static void tegra_gpio_irq_ack(struct irq_data *d) | |||
155 | { | 157 | { |
156 | int gpio = d->irq - INT_GPIO_BASE; | 158 | int gpio = d->irq - INT_GPIO_BASE; |
157 | 159 | ||
158 | __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio)); | 160 | tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio)); |
159 | } | 161 | } |
160 | 162 | ||
161 | static void tegra_gpio_irq_mask(struct irq_data *d) | 163 | static void tegra_gpio_irq_mask(struct irq_data *d) |
@@ -208,10 +210,10 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
208 | 210 | ||
209 | spin_lock_irqsave(&bank->lvl_lock[port], flags); | 211 | spin_lock_irqsave(&bank->lvl_lock[port], flags); |
210 | 212 | ||
211 | val = __raw_readl(GPIO_INT_LVL(gpio)); | 213 | val = tegra_gpio_readl(GPIO_INT_LVL(gpio)); |
212 | val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); | 214 | val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); |
213 | val |= lvl_type << GPIO_BIT(gpio); | 215 | val |= lvl_type << GPIO_BIT(gpio); |
214 | __raw_writel(val, GPIO_INT_LVL(gpio)); | 216 | tegra_gpio_writel(val, GPIO_INT_LVL(gpio)); |
215 | 217 | ||
216 | spin_unlock_irqrestore(&bank->lvl_lock[port], flags); | 218 | spin_unlock_irqrestore(&bank->lvl_lock[port], flags); |
217 | 219 | ||
@@ -237,12 +239,12 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
237 | 239 | ||
238 | for (port = 0; port < 4; port++) { | 240 | for (port = 0; port < 4; port++) { |
239 | int gpio = tegra_gpio_compose(bank->bank, port, 0); | 241 | int gpio = tegra_gpio_compose(bank->bank, port, 0); |
240 | unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) & | 242 | unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) & |
241 | __raw_readl(GPIO_INT_ENB(gpio)); | 243 | tegra_gpio_readl(GPIO_INT_ENB(gpio)); |
242 | u32 lvl = __raw_readl(GPIO_INT_LVL(gpio)); | 244 | u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio)); |
243 | 245 | ||
244 | for_each_set_bit(pin, &sta, 8) { | 246 | for_each_set_bit(pin, &sta, 8) { |
245 | __raw_writel(1 << pin, GPIO_INT_CLR(gpio)); | 247 | tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio)); |
246 | 248 | ||
247 | /* if gpio is edge triggered, clear condition | 249 | /* if gpio is edge triggered, clear condition |
248 | * before executing the hander so that we don't | 250 | * before executing the hander so that we don't |
@@ -276,11 +278,11 @@ void tegra_gpio_resume(void) | |||
276 | 278 | ||
277 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { | 279 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { |
278 | unsigned int gpio = (b<<5) | (p<<3); | 280 | unsigned int gpio = (b<<5) | (p<<3); |
279 | __raw_writel(bank->cnf[p], GPIO_CNF(gpio)); | 281 | tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio)); |
280 | __raw_writel(bank->out[p], GPIO_OUT(gpio)); | 282 | tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio)); |
281 | __raw_writel(bank->oe[p], GPIO_OE(gpio)); | 283 | tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio)); |
282 | __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); | 284 | tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); |
283 | __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); | 285 | tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); |
284 | } | 286 | } |
285 | } | 287 | } |
286 | 288 | ||
@@ -299,11 +301,11 @@ void tegra_gpio_suspend(void) | |||
299 | 301 | ||
300 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { | 302 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { |
301 | unsigned int gpio = (b<<5) | (p<<3); | 303 | unsigned int gpio = (b<<5) | (p<<3); |
302 | bank->cnf[p] = __raw_readl(GPIO_CNF(gpio)); | 304 | bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio)); |
303 | bank->out[p] = __raw_readl(GPIO_OUT(gpio)); | 305 | bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio)); |
304 | bank->oe[p] = __raw_readl(GPIO_OE(gpio)); | 306 | bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio)); |
305 | bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio)); | 307 | bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio)); |
306 | bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio)); | 308 | bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio)); |
307 | } | 309 | } |
308 | } | 310 | } |
309 | local_irq_restore(flags); | 311 | local_irq_restore(flags); |
@@ -333,28 +335,55 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
333 | */ | 335 | */ |
334 | static struct lock_class_key gpio_lock_class; | 336 | static struct lock_class_key gpio_lock_class; |
335 | 337 | ||
336 | static int __init tegra_gpio_init(void) | 338 | static int __devinit tegra_gpio_probe(struct platform_device *pdev) |
337 | { | 339 | { |
340 | struct resource *res; | ||
338 | struct tegra_gpio_bank *bank; | 341 | struct tegra_gpio_bank *bank; |
339 | int gpio; | 342 | int gpio; |
340 | int i; | 343 | int i; |
341 | int j; | 344 | int j; |
342 | 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 | |||
343 | for (i = 0; i < 7; i++) { | 377 | for (i = 0; i < 7; i++) { |
344 | for (j = 0; j < 4; j++) { | 378 | for (j = 0; j < 4; j++) { |
345 | int gpio = tegra_gpio_compose(i, j, 0); | 379 | int gpio = tegra_gpio_compose(i, j, 0); |
346 | __raw_writel(0x00, GPIO_INT_ENB(gpio)); | 380 | tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio)); |
347 | } | 381 | } |
348 | } | 382 | } |
349 | 383 | ||
350 | #ifdef CONFIG_OF_GPIO | 384 | #ifdef CONFIG_OF_GPIO |
351 | /* | 385 | tegra_gpio_chip.of_node = pdev->dev.of_node; |
352 | * This isn't ideal, but it gets things hooked up until this | 386 | #endif |
353 | * driver is converted into a platform_device | ||
354 | */ | ||
355 | tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL, | ||
356 | "nvidia,tegra20-gpio"); | ||
357 | #endif /* CONFIG_OF_GPIO */ | ||
358 | 387 | ||
359 | gpiochip_add(&tegra_gpio_chip); | 388 | gpiochip_add(&tegra_gpio_chip); |
360 | 389 | ||
@@ -384,6 +413,24 @@ static int __init tegra_gpio_init(void) | |||
384 | return 0; | 413 | return 0; |
385 | } | 414 | } |
386 | 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 | } | ||
387 | postcore_initcall(tegra_gpio_init); | 434 | postcore_initcall(tegra_gpio_init); |
388 | 435 | ||
389 | 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) |
@@ -416,13 +463,13 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) | |||
416 | seq_printf(s, | 463 | seq_printf(s, |
417 | "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", | 464 | "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", |
418 | i, j, | 465 | i, j, |
419 | __raw_readl(GPIO_CNF(gpio)), | 466 | tegra_gpio_readl(GPIO_CNF(gpio)), |
420 | __raw_readl(GPIO_OE(gpio)), | 467 | tegra_gpio_readl(GPIO_OE(gpio)), |
421 | __raw_readl(GPIO_OUT(gpio)), | 468 | tegra_gpio_readl(GPIO_OUT(gpio)), |
422 | __raw_readl(GPIO_IN(gpio)), | 469 | tegra_gpio_readl(GPIO_IN(gpio)), |
423 | __raw_readl(GPIO_INT_STA(gpio)), | 470 | tegra_gpio_readl(GPIO_INT_STA(gpio)), |
424 | __raw_readl(GPIO_INT_ENB(gpio)), | 471 | tegra_gpio_readl(GPIO_INT_ENB(gpio)), |
425 | __raw_readl(GPIO_INT_LVL(gpio))); | 472 | tegra_gpio_readl(GPIO_INT_LVL(gpio))); |
426 | } | 473 | } |
427 | } | 474 | } |
428 | return 0; | 475 | return 0; |