diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2010-03-02 22:52:34 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-03-19 14:29:32 -0400 |
commit | 3e3c62ca5395df48319b808379bc9fd487ff3c29 (patch) | |
tree | e4f9146aefc7401fc5e201c2f7bb1c0f92ea65f1 /arch | |
parent | aaedaa2b5c610ae97f863078075d8d3c6ef91575 (diff) |
ARM: 5972/1: nomadik-gpio: convert to platform driver
On the U8500 platform there are four GPIO blocks, each with a 4K address
space, including the peripheral identification. However, each of these
blocks have a varying number of banks, each of which have 32 GPIOs and
an interrupt line.
The current nomadik-gpio driver implementation can handle each of these
sub-banks easily with one instance each, but cannot as-is be hooked up
to them because it is an AMBA driver and it expects to see a peripheral
with the appropriate peripheral ids but having only one bank and only
one interrupt.
Solve this by converting the driver to a platform driver.
Acked-by: Alessandro Rubini <rubini@unipv.it>
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-nomadik/cpu-8815.c | 83 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/gpio.c | 74 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/gpio.h | 1 |
3 files changed, 90 insertions, 68 deletions
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 9bf33b30a025..91c3c901b469 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/amba/bus.h> | 22 | #include <linux/amba/bus.h> |
23 | #include <linux/platform_device.h> | ||
23 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
24 | 25 | ||
25 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
@@ -30,60 +31,66 @@ | |||
30 | #include <asm/cacheflush.h> | 31 | #include <asm/cacheflush.h> |
31 | #include <asm/hardware/cache-l2x0.h> | 32 | #include <asm/hardware/cache-l2x0.h> |
32 | 33 | ||
34 | #define __MEM_4K_RESOURCE(x) \ | ||
35 | .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} | ||
36 | |||
33 | /* The 8815 has 4 GPIO blocks, let's register them immediately */ | 37 | /* The 8815 has 4 GPIO blocks, let's register them immediately */ |
38 | |||
39 | #define GPIO_RESOURCE(block) \ | ||
40 | { \ | ||
41 | .start = NOMADIK_GPIO##block##_BASE, \ | ||
42 | .end = NOMADIK_GPIO##block##_BASE + SZ_4K - 1, \ | ||
43 | .flags = IORESOURCE_MEM, \ | ||
44 | }, \ | ||
45 | { \ | ||
46 | .start = IRQ_GPIO##block, \ | ||
47 | .end = IRQ_GPIO##block, \ | ||
48 | .flags = IORESOURCE_IRQ, \ | ||
49 | } | ||
50 | |||
51 | #define GPIO_DEVICE(block) \ | ||
52 | { \ | ||
53 | .name = "gpio", \ | ||
54 | .id = block, \ | ||
55 | .num_resources = 2, \ | ||
56 | .resource = &cpu8815_gpio_resources[block * 2], \ | ||
57 | .dev = { \ | ||
58 | .platform_data = &cpu8815_gpio[block], \ | ||
59 | }, \ | ||
60 | } | ||
61 | |||
34 | static struct nmk_gpio_platform_data cpu8815_gpio[] = { | 62 | static struct nmk_gpio_platform_data cpu8815_gpio[] = { |
35 | { | 63 | { |
36 | .name = "GPIO-0-31", | 64 | .name = "GPIO-0-31", |
37 | .first_gpio = 0, | 65 | .first_gpio = 0, |
38 | .first_irq = NOMADIK_GPIO_TO_IRQ(0), | 66 | .first_irq = NOMADIK_GPIO_TO_IRQ(0), |
39 | .parent_irq = IRQ_GPIO0, | ||
40 | }, { | 67 | }, { |
41 | .name = "GPIO-32-63", | 68 | .name = "GPIO-32-63", |
42 | .first_gpio = 32, | 69 | .first_gpio = 32, |
43 | .first_irq = NOMADIK_GPIO_TO_IRQ(32), | 70 | .first_irq = NOMADIK_GPIO_TO_IRQ(32), |
44 | .parent_irq = IRQ_GPIO1, | ||
45 | }, { | 71 | }, { |
46 | .name = "GPIO-64-95", | 72 | .name = "GPIO-64-95", |
47 | .first_gpio = 64, | 73 | .first_gpio = 64, |
48 | .first_irq = NOMADIK_GPIO_TO_IRQ(64), | 74 | .first_irq = NOMADIK_GPIO_TO_IRQ(64), |
49 | .parent_irq = IRQ_GPIO2, | ||
50 | }, { | 75 | }, { |
51 | .name = "GPIO-96-127", /* 124..127 not routed to pin */ | 76 | .name = "GPIO-96-127", /* 124..127 not routed to pin */ |
52 | .first_gpio = 96, | 77 | .first_gpio = 96, |
53 | .first_irq = NOMADIK_GPIO_TO_IRQ(96), | 78 | .first_irq = NOMADIK_GPIO_TO_IRQ(96), |
54 | .parent_irq = IRQ_GPIO3, | ||
55 | } | 79 | } |
56 | }; | 80 | }; |
57 | 81 | ||
58 | #define __MEM_4K_RESOURCE(x) \ | 82 | static struct resource cpu8815_gpio_resources[] = { |
59 | .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} | 83 | GPIO_RESOURCE(0), |
84 | GPIO_RESOURCE(1), | ||
85 | GPIO_RESOURCE(2), | ||
86 | GPIO_RESOURCE(3), | ||
87 | }; | ||
60 | 88 | ||
61 | static struct amba_device cpu8815_amba_gpio[] = { | 89 | static struct platform_device cpu8815_platform_gpio[] = { |
62 | { | 90 | GPIO_DEVICE(0), |
63 | .dev = { | 91 | GPIO_DEVICE(1), |
64 | .init_name = "gpio0", | 92 | GPIO_DEVICE(2), |
65 | .platform_data = cpu8815_gpio + 0, | 93 | GPIO_DEVICE(3), |
66 | }, | ||
67 | __MEM_4K_RESOURCE(NOMADIK_GPIO0_BASE), | ||
68 | }, { | ||
69 | .dev = { | ||
70 | .init_name = "gpio1", | ||
71 | .platform_data = cpu8815_gpio + 1, | ||
72 | }, | ||
73 | __MEM_4K_RESOURCE(NOMADIK_GPIO1_BASE), | ||
74 | }, { | ||
75 | .dev = { | ||
76 | .init_name = "gpio2", | ||
77 | .platform_data = cpu8815_gpio + 2, | ||
78 | }, | ||
79 | __MEM_4K_RESOURCE(NOMADIK_GPIO2_BASE), | ||
80 | }, { | ||
81 | .dev = { | ||
82 | .init_name = "gpio3", | ||
83 | .platform_data = cpu8815_gpio + 3, | ||
84 | }, | ||
85 | __MEM_4K_RESOURCE(NOMADIK_GPIO3_BASE), | ||
86 | }, | ||
87 | }; | 94 | }; |
88 | 95 | ||
89 | static struct amba_device cpu8815_amba_rng = { | 96 | static struct amba_device cpu8815_amba_rng = { |
@@ -93,11 +100,14 @@ static struct amba_device cpu8815_amba_rng = { | |||
93 | __MEM_4K_RESOURCE(NOMADIK_RNG_BASE), | 100 | __MEM_4K_RESOURCE(NOMADIK_RNG_BASE), |
94 | }; | 101 | }; |
95 | 102 | ||
103 | static struct platform_device *platform_devs[] __initdata = { | ||
104 | cpu8815_platform_gpio + 0, | ||
105 | cpu8815_platform_gpio + 1, | ||
106 | cpu8815_platform_gpio + 2, | ||
107 | cpu8815_platform_gpio + 3, | ||
108 | }; | ||
109 | |||
96 | static struct amba_device *amba_devs[] __initdata = { | 110 | static struct amba_device *amba_devs[] __initdata = { |
97 | cpu8815_amba_gpio + 0, | ||
98 | cpu8815_amba_gpio + 1, | ||
99 | cpu8815_amba_gpio + 2, | ||
100 | cpu8815_amba_gpio + 3, | ||
101 | &cpu8815_amba_rng | 111 | &cpu8815_amba_rng |
102 | }; | 112 | }; |
103 | 113 | ||
@@ -105,6 +115,7 @@ static int __init cpu8815_init(void) | |||
105 | { | 115 | { |
106 | int i; | 116 | int i; |
107 | 117 | ||
118 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); | ||
108 | for (i = 0; i < ARRAY_SIZE(amba_devs); i++) | 119 | for (i = 0; i < ARRAY_SIZE(amba_devs); i++) |
109 | amba_device_register(amba_devs[i], &iomem_resource); | 120 | amba_device_register(amba_devs[i], &iomem_resource); |
110 | return 0; | 121 | return 0; |
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 4c3ea1a922ac..092f380063b3 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/amba/bus.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
@@ -303,30 +303,48 @@ static struct gpio_chip nmk_gpio_template = { | |||
303 | .can_sleep = 0, | 303 | .can_sleep = 0, |
304 | }; | 304 | }; |
305 | 305 | ||
306 | static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) | 306 | static int __init nmk_gpio_probe(struct platform_device *dev) |
307 | { | 307 | { |
308 | struct nmk_gpio_platform_data *pdata; | 308 | struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; |
309 | struct nmk_gpio_chip *nmk_chip; | 309 | struct nmk_gpio_chip *nmk_chip; |
310 | struct gpio_chip *chip; | 310 | struct gpio_chip *chip; |
311 | struct resource *res; | ||
312 | int irq; | ||
311 | int ret; | 313 | int ret; |
312 | 314 | ||
313 | pdata = dev->dev.platform_data; | 315 | if (!pdata) |
314 | ret = amba_request_regions(dev, pdata->name); | 316 | return -ENODEV; |
315 | if (ret) | 317 | |
316 | return ret; | 318 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
319 | if (!res) { | ||
320 | ret = -ENOENT; | ||
321 | goto out; | ||
322 | } | ||
323 | |||
324 | irq = platform_get_irq(dev, 0); | ||
325 | if (irq < 0) { | ||
326 | ret = irq; | ||
327 | goto out; | ||
328 | } | ||
329 | |||
330 | if (request_mem_region(res->start, resource_size(res), | ||
331 | dev_name(&dev->dev)) == NULL) { | ||
332 | ret = -EBUSY; | ||
333 | goto out; | ||
334 | } | ||
317 | 335 | ||
318 | nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); | 336 | nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); |
319 | if (!nmk_chip) { | 337 | if (!nmk_chip) { |
320 | ret = -ENOMEM; | 338 | ret = -ENOMEM; |
321 | goto out_amba; | 339 | goto out_release; |
322 | } | 340 | } |
323 | /* | 341 | /* |
324 | * The virt address in nmk_chip->addr is in the nomadik register space, | 342 | * The virt address in nmk_chip->addr is in the nomadik register space, |
325 | * so we can simply convert the resource address, without remapping | 343 | * so we can simply convert the resource address, without remapping |
326 | */ | 344 | */ |
327 | nmk_chip->addr = io_p2v(dev->res.start); | 345 | nmk_chip->addr = io_p2v(res->start); |
328 | nmk_chip->chip = nmk_gpio_template; | 346 | nmk_chip->chip = nmk_gpio_template; |
329 | nmk_chip->parent_irq = pdata->parent_irq; | 347 | nmk_chip->parent_irq = irq; |
330 | spin_lock_init(&nmk_chip->lock); | 348 | spin_lock_init(&nmk_chip->lock); |
331 | 349 | ||
332 | chip = &nmk_chip->chip; | 350 | chip = &nmk_chip->chip; |
@@ -339,7 +357,7 @@ static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) | |||
339 | if (ret) | 357 | if (ret) |
340 | goto out_free; | 358 | goto out_free; |
341 | 359 | ||
342 | amba_set_drvdata(dev, nmk_chip); | 360 | platform_set_drvdata(dev, nmk_chip); |
343 | 361 | ||
344 | nmk_gpio_init_irq(nmk_chip); | 362 | nmk_gpio_init_irq(nmk_chip); |
345 | 363 | ||
@@ -347,51 +365,45 @@ static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) | |||
347 | nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); | 365 | nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); |
348 | return 0; | 366 | return 0; |
349 | 367 | ||
350 | out_free: | 368 | out_free: |
351 | kfree(nmk_chip); | 369 | kfree(nmk_chip); |
352 | out_amba: | 370 | out_release: |
353 | amba_release_regions(dev); | 371 | release_mem_region(res->start, resource_size(res)); |
372 | out: | ||
354 | dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, | 373 | dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, |
355 | pdata->first_gpio, pdata->first_gpio+31); | 374 | pdata->first_gpio, pdata->first_gpio+31); |
356 | return ret; | 375 | return ret; |
357 | } | 376 | } |
358 | 377 | ||
359 | static int nmk_gpio_remove(struct amba_device *dev) | 378 | static int __exit nmk_gpio_remove(struct platform_device *dev) |
360 | { | 379 | { |
361 | struct nmk_gpio_chip *nmk_chip; | 380 | struct nmk_gpio_chip *nmk_chip; |
381 | struct resource *res; | ||
382 | |||
383 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
362 | 384 | ||
363 | nmk_chip = amba_get_drvdata(dev); | 385 | nmk_chip = platform_get_drvdata(dev); |
364 | gpiochip_remove(&nmk_chip->chip); | 386 | gpiochip_remove(&nmk_chip->chip); |
365 | kfree(nmk_chip); | 387 | kfree(nmk_chip); |
366 | amba_release_regions(dev); | 388 | release_mem_region(res->start, resource_size(res)); |
367 | return 0; | 389 | return 0; |
368 | } | 390 | } |
369 | 391 | ||
370 | 392 | ||
371 | /* We have 0x1f080060 and 0x1f180060, accept both using the mask */ | 393 | static struct platform_driver nmk_gpio_driver = { |
372 | static struct amba_id nmk_gpio_ids[] = { | 394 | .driver = { |
373 | { | ||
374 | .id = 0x1f080060, | ||
375 | .mask = 0xffefffff, | ||
376 | }, | ||
377 | {0, 0}, | ||
378 | }; | ||
379 | |||
380 | static struct amba_driver nmk_gpio_driver = { | ||
381 | .drv = { | ||
382 | .owner = THIS_MODULE, | 395 | .owner = THIS_MODULE, |
383 | .name = "gpio", | 396 | .name = "gpio", |
384 | }, | 397 | }, |
385 | .probe = nmk_gpio_probe, | 398 | .probe = nmk_gpio_probe, |
386 | .remove = nmk_gpio_remove, | 399 | .remove = __exit_p(nmk_gpio_remove), |
387 | .suspend = NULL, /* to be done */ | 400 | .suspend = NULL, /* to be done */ |
388 | .resume = NULL, | 401 | .resume = NULL, |
389 | .id_table = nmk_gpio_ids, | ||
390 | }; | 402 | }; |
391 | 403 | ||
392 | static int __init nmk_gpio_init(void) | 404 | static int __init nmk_gpio_init(void) |
393 | { | 405 | { |
394 | return amba_driver_register(&nmk_gpio_driver); | 406 | return platform_driver_register(&nmk_gpio_driver); |
395 | } | 407 | } |
396 | 408 | ||
397 | arch_initcall(nmk_gpio_init); | 409 | arch_initcall(nmk_gpio_init); |
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index 1d665a0abb87..4200811249ca 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h | |||
@@ -65,7 +65,6 @@ struct nmk_gpio_platform_data { | |||
65 | char *name; | 65 | char *name; |
66 | int first_gpio; | 66 | int first_gpio; |
67 | int first_irq; | 67 | int first_irq; |
68 | int parent_irq; | ||
69 | }; | 68 | }; |
70 | 69 | ||
71 | #endif /* __ASM_PLAT_GPIO_H */ | 70 | #endif /* __ASM_PLAT_GPIO_H */ |