diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-07 15:15:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-07 15:15:36 -0500 |
commit | fbce1c234feedb5270468aa4b1770c1cab58a960 (patch) | |
tree | 7391d7bcce50eab43c750c4055b056ab1892d6b2 /drivers | |
parent | 7affca3537d74365128e477b40c529d6f2fe86c8 (diff) | |
parent | d0ad5e89256c351ddd40167152c24a88efcb0f6d (diff) |
Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6
Changes queued in gpio/next for the start of the 3.3 merge window
* tag 'gpio-for-linus-20120104' of git://git.secretlab.ca/git/linux-2.6:
gpio: Add decode of WM8994 GPIO configuration
gpio: Convert GPIO drivers to module_platform_driver
gpio: Fix typo in comment in Samsung driver
gpio: Explicitly index samsung_gpio_cfgs
gpio: Add Linus Walleij as gpio co-maintainer
of: Add device tree selftests
of: create of_phandle_args to simplify return of phandle parsing data
gpio/powerpc: Eliminate duplication of of_get_named_gpio_flags()
gpio/microblaze: Eliminate duplication of of_get_named_gpio_flags()
gpiolib: output basic details and consolidate gpio device drivers
pch_gpio: Change company name OKI SEMICONDUCTOR to LAPIS Semiconductor
pch_gpio: Support new device LAPIS Semiconductor ML7831 IOH
spi/pl022: make the chip deselect handling thread safe
spi/pl022: add support for pm_runtime autosuspend
spi/pl022: disable the PL022 block when unused
spi/pl022: move device disable to workqueue thread
spi/pl022: skip default configuration before suspending
spi/pl022: fix build warnings
spi/pl022: only enable RX interrupts when TX is complete
Diffstat (limited to 'drivers')
27 files changed, 456 insertions, 319 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8482a23887dc..4e04157a3683 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -387,7 +387,7 @@ config GPIO_LANGWELL | |||
387 | Say Y here to support Intel Langwell/Penwell GPIO. | 387 | Say Y here to support Intel Langwell/Penwell GPIO. |
388 | 388 | ||
389 | config GPIO_PCH | 389 | config GPIO_PCH |
390 | tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO" | 390 | tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO" |
391 | depends on PCI && X86 | 391 | depends on PCI && X86 |
392 | select GENERIC_IRQ_CHIP | 392 | select GENERIC_IRQ_CHIP |
393 | help | 393 | help |
@@ -395,11 +395,12 @@ config GPIO_PCH | |||
395 | which is an IOH(Input/Output Hub) for x86 embedded processor. | 395 | which is an IOH(Input/Output Hub) for x86 embedded processor. |
396 | This driver can access PCH GPIO device. | 396 | This driver can access PCH GPIO device. |
397 | 397 | ||
398 | This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ | 398 | This driver also can be used for LAPIS Semiconductor IOH(Input/ |
399 | Output Hub), ML7223. | 399 | Output Hub), ML7223 and ML7831. |
400 | ML7223 IOH is for MP(Media Phone) use. | 400 | ML7223 IOH is for MP(Media Phone) use. |
401 | ML7223 is companion chip for Intel Atom E6xx series. | 401 | ML7831 IOH is for general purpose use. |
402 | ML7223 is completely compatible for Intel EG20T PCH. | 402 | ML7223/ML7831 is companion chip for Intel Atom E6xx series. |
403 | ML7223/ML7831 is completely compatible for Intel EG20T PCH. | ||
403 | 404 | ||
404 | config GPIO_ML_IOH | 405 | config GPIO_ML_IOH |
405 | tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" | 406 | tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" |
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index 9f2781537001..2f263cc32561 100644 --- a/drivers/gpio/gpio-adp5520.c +++ b/drivers/gpio/gpio-adp5520.c | |||
@@ -193,17 +193,7 @@ static struct platform_driver adp5520_gpio_driver = { | |||
193 | .remove = __devexit_p(adp5520_gpio_remove), | 193 | .remove = __devexit_p(adp5520_gpio_remove), |
194 | }; | 194 | }; |
195 | 195 | ||
196 | static int __init adp5520_gpio_init(void) | 196 | module_platform_driver(adp5520_gpio_driver); |
197 | { | ||
198 | return platform_driver_register(&adp5520_gpio_driver); | ||
199 | } | ||
200 | module_init(adp5520_gpio_init); | ||
201 | |||
202 | static void __exit adp5520_gpio_exit(void) | ||
203 | { | ||
204 | platform_driver_unregister(&adp5520_gpio_driver); | ||
205 | } | ||
206 | module_exit(adp5520_gpio_exit); | ||
207 | 197 | ||
208 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 198 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
209 | MODULE_DESCRIPTION("GPIO ADP5520 Driver"); | 199 | MODULE_DESCRIPTION("GPIO ADP5520 Driver"); |
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index 3525ad918771..9ad1703d1408 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c | |||
@@ -418,9 +418,8 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client, | |||
418 | if (ret) | 418 | if (ret) |
419 | goto err_irq; | 419 | goto err_irq; |
420 | 420 | ||
421 | dev_info(&client->dev, "gpios %d..%d (IRQ Base %d) on a %s Rev. %d\n", | 421 | dev_info(&client->dev, "IRQ Base: %d Rev.: %d\n", |
422 | gc->base, gc->base + gc->ngpio - 1, | 422 | pdata->irq_base, revid); |
423 | pdata->irq_base, client->name, revid); | ||
424 | 423 | ||
425 | if (pdata->setup) { | 424 | if (pdata->setup) { |
426 | ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); | 425 | ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); |
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index ec57936aef62..5ca4098ba092 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c | |||
@@ -223,9 +223,6 @@ static int bt8xxgpio_probe(struct pci_dev *dev, | |||
223 | goto err_release_mem; | 223 | goto err_release_mem; |
224 | } | 224 | } |
225 | 225 | ||
226 | printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n", | ||
227 | bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1); | ||
228 | |||
229 | return 0; | 226 | return 0; |
230 | 227 | ||
231 | err_release_mem: | 228 | err_release_mem: |
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c index 6e16cba56ad2..19eda1bbe343 100644 --- a/drivers/gpio/gpio-cs5535.c +++ b/drivers/gpio/gpio-cs5535.c | |||
@@ -347,7 +347,6 @@ static int __devinit cs5535_gpio_probe(struct platform_device *pdev) | |||
347 | if (err) | 347 | if (err) |
348 | goto release_region; | 348 | goto release_region; |
349 | 349 | ||
350 | dev_info(&pdev->dev, "GPIO support successfully loaded.\n"); | ||
351 | return 0; | 350 | return 0; |
352 | 351 | ||
353 | release_region: | 352 | release_region: |
@@ -382,18 +381,7 @@ static struct platform_driver cs5535_gpio_driver = { | |||
382 | .remove = __devexit_p(cs5535_gpio_remove), | 381 | .remove = __devexit_p(cs5535_gpio_remove), |
383 | }; | 382 | }; |
384 | 383 | ||
385 | static int __init cs5535_gpio_init(void) | 384 | module_platform_driver(cs5535_gpio_driver); |
386 | { | ||
387 | return platform_driver_register(&cs5535_gpio_driver); | ||
388 | } | ||
389 | |||
390 | static void __exit cs5535_gpio_exit(void) | ||
391 | { | ||
392 | platform_driver_unregister(&cs5535_gpio_driver); | ||
393 | } | ||
394 | |||
395 | module_init(cs5535_gpio_init); | ||
396 | module_exit(cs5535_gpio_exit); | ||
397 | 385 | ||
398 | MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); | 386 | MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); |
399 | MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver"); | 387 | MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver"); |
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index f8ce29ef9f88..56dd047d5844 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c | |||
@@ -254,17 +254,7 @@ static struct platform_driver da9052_gpio_driver = { | |||
254 | }, | 254 | }, |
255 | }; | 255 | }; |
256 | 256 | ||
257 | static int __init da9052_gpio_init(void) | 257 | module_platform_driver(da9052_gpio_driver); |
258 | { | ||
259 | return platform_driver_register(&da9052_gpio_driver); | ||
260 | } | ||
261 | module_init(da9052_gpio_init); | ||
262 | |||
263 | static void __exit da9052_gpio_exit(void) | ||
264 | { | ||
265 | return platform_driver_unregister(&da9052_gpio_driver); | ||
266 | } | ||
267 | module_exit(da9052_gpio_exit); | ||
268 | 258 | ||
269 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | 259 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); |
270 | MODULE_DESCRIPTION("DA9052 GPIO Device Driver"); | 260 | MODULE_DESCRIPTION("DA9052 GPIO Device Driver"); |
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index 4e24436b0f82..e38dd0c31973 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c | |||
@@ -524,17 +524,7 @@ static struct platform_driver bgpio_driver = { | |||
524 | .remove = __devexit_p(bgpio_pdev_remove), | 524 | .remove = __devexit_p(bgpio_pdev_remove), |
525 | }; | 525 | }; |
526 | 526 | ||
527 | static int __init bgpio_platform_init(void) | 527 | module_platform_driver(bgpio_driver); |
528 | { | ||
529 | return platform_driver_register(&bgpio_driver); | ||
530 | } | ||
531 | module_init(bgpio_platform_init); | ||
532 | |||
533 | static void __exit bgpio_platform_exit(void) | ||
534 | { | ||
535 | platform_driver_unregister(&bgpio_driver); | ||
536 | } | ||
537 | module_exit(bgpio_platform_exit); | ||
538 | 528 | ||
539 | #endif /* CONFIG_GPIO_GENERIC_PLATFORM */ | 529 | #endif /* CONFIG_GPIO_GENERIC_PLATFORM */ |
540 | 530 | ||
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c index 813ac077e5d7..f2f000dd70b3 100644 --- a/drivers/gpio/gpio-janz-ttl.c +++ b/drivers/gpio/gpio-janz-ttl.c | |||
@@ -201,8 +201,6 @@ static int __devinit ttl_probe(struct platform_device *pdev) | |||
201 | goto out_iounmap_regs; | 201 | goto out_iounmap_regs; |
202 | } | 202 | } |
203 | 203 | ||
204 | dev_info(&pdev->dev, "module %d: registered GPIO device\n", | ||
205 | pdata->modno); | ||
206 | return 0; | 204 | return 0; |
207 | 205 | ||
208 | out_iounmap_regs: | 206 | out_iounmap_regs: |
@@ -239,20 +237,9 @@ static struct platform_driver ttl_driver = { | |||
239 | .remove = __devexit_p(ttl_remove), | 237 | .remove = __devexit_p(ttl_remove), |
240 | }; | 238 | }; |
241 | 239 | ||
242 | static int __init ttl_init(void) | 240 | module_platform_driver(ttl_driver); |
243 | { | ||
244 | return platform_driver_register(&ttl_driver); | ||
245 | } | ||
246 | |||
247 | static void __exit ttl_exit(void) | ||
248 | { | ||
249 | platform_driver_unregister(&ttl_driver); | ||
250 | } | ||
251 | 241 | ||
252 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); | 242 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); |
253 | MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver"); | 243 | MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver"); |
254 | MODULE_LICENSE("GPL"); | 244 | MODULE_LICENSE("GPL"); |
255 | MODULE_ALIAS("platform:janz-ttl"); | 245 | MODULE_ALIAS("platform:janz-ttl"); |
256 | |||
257 | module_init(ttl_init); | ||
258 | module_exit(ttl_exit); | ||
diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index 1ebedfb6d46d..839624f9fe6a 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c | |||
@@ -1150,8 +1150,8 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) | |||
1150 | 1150 | ||
1151 | nmk_gpio_init_irq(nmk_chip); | 1151 | nmk_gpio_init_irq(nmk_chip); |
1152 | 1152 | ||
1153 | dev_info(&dev->dev, "Bits %i-%i at address %p\n", | 1153 | dev_info(&dev->dev, "at address %p\n", |
1154 | nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); | 1154 | nmk_chip->addr); |
1155 | return 0; | 1155 | return 0; |
1156 | 1156 | ||
1157 | out_free: | 1157 | out_free: |
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 3e1f1ecd07be..2d1de9e7e9bd 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c | |||
@@ -290,10 +290,7 @@ static int pcf857x_probe(struct i2c_client *client, | |||
290 | * methods can't be called from sleeping contexts. | 290 | * methods can't be called from sleeping contexts. |
291 | */ | 291 | */ |
292 | 292 | ||
293 | dev_info(&client->dev, "gpios %d..%d on a %s%s\n", | 293 | dev_info(&client->dev, "%s\n", |
294 | gpio->chip.base, | ||
295 | gpio->chip.base + gpio->chip.ngpio - 1, | ||
296 | client->name, | ||
297 | client->irq ? " (irq ignored)" : ""); | 294 | client->irq ? " (irq ignored)" : ""); |
298 | 295 | ||
299 | /* Let platform code set up the GPIOs and their users. | 296 | /* Let platform code set up the GPIOs and their users. |
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index a6008e123d04..f0603297f829 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. | 2 | * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
@@ -49,8 +49,8 @@ struct pch_regs { | |||
49 | 49 | ||
50 | enum pch_type_t { | 50 | enum pch_type_t { |
51 | INTEL_EG20T_PCH, | 51 | INTEL_EG20T_PCH, |
52 | OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */ | 52 | OKISEMI_ML7223m_IOH, /* LAPIS Semiconductor ML7223 IOH PCIe Bus-m */ |
53 | OKISEMI_ML7223n_IOH /* OKISEMI ML7223 IOH PCIe Bus-n */ | 53 | OKISEMI_ML7223n_IOH /* LAPIS Semiconductor ML7223 IOH PCIe Bus-n */ |
54 | }; | 54 | }; |
55 | 55 | ||
56 | /* Specifies number of GPIO PINS */ | 56 | /* Specifies number of GPIO PINS */ |
@@ -524,6 +524,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { | |||
524 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, | 524 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, |
525 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) }, | 525 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) }, |
526 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) }, | 526 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) }, |
527 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803) }, | ||
527 | { 0, } | 528 | { 0, } |
528 | }; | 529 | }; |
529 | MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); | 530 | MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); |
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c index 2762698e0204..e97016af6443 100644 --- a/drivers/gpio/gpio-rdc321x.c +++ b/drivers/gpio/gpio-rdc321x.c | |||
@@ -227,18 +227,7 @@ static struct platform_driver rdc321x_gpio_driver = { | |||
227 | .remove = __devexit_p(rdc321x_gpio_remove), | 227 | .remove = __devexit_p(rdc321x_gpio_remove), |
228 | }; | 228 | }; |
229 | 229 | ||
230 | static int __init rdc321x_gpio_init(void) | 230 | module_platform_driver(rdc321x_gpio_driver); |
231 | { | ||
232 | return platform_driver_register(&rdc321x_gpio_driver); | ||
233 | } | ||
234 | |||
235 | static void __exit rdc321x_gpio_exit(void) | ||
236 | { | ||
237 | platform_driver_unregister(&rdc321x_gpio_driver); | ||
238 | } | ||
239 | |||
240 | module_init(rdc321x_gpio_init); | ||
241 | module_exit(rdc321x_gpio_exit); | ||
242 | 231 | ||
243 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | 232 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); |
244 | MODULE_DESCRIPTION("RDC321x GPIO driver"); | 233 | MODULE_DESCRIPTION("RDC321x GPIO driver"); |
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index dcbe4541fe49..ab098ba9f1dd 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c | |||
@@ -230,7 +230,7 @@ static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip, | |||
230 | * @chip: The gpio chip that is being configured. | 230 | * @chip: The gpio chip that is being configured. |
231 | * @off: The offset for the GPIO being configured. | 231 | * @off: The offset for the GPIO being configured. |
232 | * | 232 | * |
233 | * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg | 233 | * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which |
234 | * could be directly passed back to samsung_gpio_setcfg_2bit(), from the | 234 | * could be directly passed back to samsung_gpio_setcfg_2bit(), from the |
235 | * S3C_GPIO_SPECIAL() macro. | 235 | * S3C_GPIO_SPECIAL() macro. |
236 | */ | 236 | */ |
@@ -467,33 +467,42 @@ static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = { | |||
467 | #endif | 467 | #endif |
468 | 468 | ||
469 | static struct samsung_gpio_cfg samsung_gpio_cfgs[] = { | 469 | static struct samsung_gpio_cfg samsung_gpio_cfgs[] = { |
470 | { | 470 | [0] = { |
471 | .cfg_eint = 0x0, | 471 | .cfg_eint = 0x0, |
472 | }, { | 472 | }, |
473 | [1] = { | ||
473 | .cfg_eint = 0x3, | 474 | .cfg_eint = 0x3, |
474 | }, { | 475 | }, |
476 | [2] = { | ||
475 | .cfg_eint = 0x7, | 477 | .cfg_eint = 0x7, |
476 | }, { | 478 | }, |
479 | [3] = { | ||
477 | .cfg_eint = 0xF, | 480 | .cfg_eint = 0xF, |
478 | }, { | 481 | }, |
482 | [4] = { | ||
479 | .cfg_eint = 0x0, | 483 | .cfg_eint = 0x0, |
480 | .set_config = samsung_gpio_setcfg_2bit, | 484 | .set_config = samsung_gpio_setcfg_2bit, |
481 | .get_config = samsung_gpio_getcfg_2bit, | 485 | .get_config = samsung_gpio_getcfg_2bit, |
482 | }, { | 486 | }, |
487 | [5] = { | ||
483 | .cfg_eint = 0x2, | 488 | .cfg_eint = 0x2, |
484 | .set_config = samsung_gpio_setcfg_2bit, | 489 | .set_config = samsung_gpio_setcfg_2bit, |
485 | .get_config = samsung_gpio_getcfg_2bit, | 490 | .get_config = samsung_gpio_getcfg_2bit, |
486 | }, { | 491 | }, |
492 | [6] = { | ||
487 | .cfg_eint = 0x3, | 493 | .cfg_eint = 0x3, |
488 | .set_config = samsung_gpio_setcfg_2bit, | 494 | .set_config = samsung_gpio_setcfg_2bit, |
489 | .get_config = samsung_gpio_getcfg_2bit, | 495 | .get_config = samsung_gpio_getcfg_2bit, |
490 | }, { | 496 | }, |
497 | [7] = { | ||
491 | .set_config = samsung_gpio_setcfg_2bit, | 498 | .set_config = samsung_gpio_setcfg_2bit, |
492 | .get_config = samsung_gpio_getcfg_2bit, | 499 | .get_config = samsung_gpio_getcfg_2bit, |
493 | }, { | 500 | }, |
501 | [8] = { | ||
494 | .set_pull = exynos4_gpio_setpull, | 502 | .set_pull = exynos4_gpio_setpull, |
495 | .get_pull = exynos4_gpio_getpull, | 503 | .get_pull = exynos4_gpio_getpull, |
496 | }, { | 504 | }, |
505 | [9] = { | ||
497 | .cfg_eint = 0x3, | 506 | .cfg_eint = 0x3, |
498 | .set_pull = exynos4_gpio_setpull, | 507 | .set_pull = exynos4_gpio_setpull, |
499 | .get_pull = exynos4_gpio_getpull, | 508 | .get_pull = exynos4_gpio_getpull, |
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 163515845494..8cadf4d683a8 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c | |||
@@ -297,18 +297,7 @@ static struct platform_driver sch_gpio_driver = { | |||
297 | .remove = __devexit_p(sch_gpio_remove), | 297 | .remove = __devexit_p(sch_gpio_remove), |
298 | }; | 298 | }; |
299 | 299 | ||
300 | static int __init sch_gpio_init(void) | 300 | module_platform_driver(sch_gpio_driver); |
301 | { | ||
302 | return platform_driver_register(&sch_gpio_driver); | ||
303 | } | ||
304 | |||
305 | static void __exit sch_gpio_exit(void) | ||
306 | { | ||
307 | platform_driver_unregister(&sch_gpio_driver); | ||
308 | } | ||
309 | |||
310 | module_init(sch_gpio_init); | ||
311 | module_exit(sch_gpio_exit); | ||
312 | 301 | ||
313 | MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); | 302 | MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); |
314 | MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH"); | 303 | MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH"); |
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index c593bd46bfb6..031c6adf5b65 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c | |||
@@ -359,18 +359,7 @@ static struct platform_driver timbgpio_platform_driver = { | |||
359 | 359 | ||
360 | /*--------------------------------------------------------------------------*/ | 360 | /*--------------------------------------------------------------------------*/ |
361 | 361 | ||
362 | static int __init timbgpio_init(void) | 362 | module_platform_driver(timbgpio_platform_driver); |
363 | { | ||
364 | return platform_driver_register(&timbgpio_platform_driver); | ||
365 | } | ||
366 | |||
367 | static void __exit timbgpio_exit(void) | ||
368 | { | ||
369 | platform_driver_unregister(&timbgpio_platform_driver); | ||
370 | } | ||
371 | |||
372 | module_init(timbgpio_init); | ||
373 | module_exit(timbgpio_exit); | ||
374 | 363 | ||
375 | MODULE_DESCRIPTION("Timberdale GPIO driver"); | 364 | MODULE_DESCRIPTION("Timberdale GPIO driver"); |
376 | MODULE_LICENSE("GPL v2"); | 365 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c index 50e6bd1392ce..26405efe0f9f 100644 --- a/drivers/gpio/gpio-ucb1400.c +++ b/drivers/gpio/gpio-ucb1400.c | |||
@@ -103,23 +103,12 @@ static struct platform_driver ucb1400_gpio_driver = { | |||
103 | }, | 103 | }, |
104 | }; | 104 | }; |
105 | 105 | ||
106 | static int __init ucb1400_gpio_init(void) | ||
107 | { | ||
108 | return platform_driver_register(&ucb1400_gpio_driver); | ||
109 | } | ||
110 | |||
111 | static void __exit ucb1400_gpio_exit(void) | ||
112 | { | ||
113 | platform_driver_unregister(&ucb1400_gpio_driver); | ||
114 | } | ||
115 | |||
116 | void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data) | 106 | void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data) |
117 | { | 107 | { |
118 | ucbdata = data; | 108 | ucbdata = data; |
119 | } | 109 | } |
120 | 110 | ||
121 | module_init(ucb1400_gpio_init); | 111 | module_platform_driver(ucb1400_gpio_driver); |
122 | module_exit(ucb1400_gpio_exit); | ||
123 | 112 | ||
124 | MODULE_DESCRIPTION("Philips UCB1400 GPIO driver"); | 113 | MODULE_DESCRIPTION("Philips UCB1400 GPIO driver"); |
125 | MODULE_LICENSE("GPL"); | 114 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c index 98723cb9ac68..82d5c20ad3cb 100644 --- a/drivers/gpio/gpio-vr41xx.c +++ b/drivers/gpio/gpio-vr41xx.c | |||
@@ -571,15 +571,4 @@ static struct platform_driver giu_device_driver = { | |||
571 | }, | 571 | }, |
572 | }; | 572 | }; |
573 | 573 | ||
574 | static int __init vr41xx_giu_init(void) | 574 | module_platform_driver(giu_device_driver); |
575 | { | ||
576 | return platform_driver_register(&giu_device_driver); | ||
577 | } | ||
578 | |||
579 | static void __exit vr41xx_giu_exit(void) | ||
580 | { | ||
581 | platform_driver_unregister(&giu_device_driver); | ||
582 | } | ||
583 | |||
584 | module_init(vr41xx_giu_init); | ||
585 | module_exit(vr41xx_giu_exit); | ||
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c index ef5aabd8b8b7..76ebfe5ff702 100644 --- a/drivers/gpio/gpio-vx855.c +++ b/drivers/gpio/gpio-vx855.c | |||
@@ -315,17 +315,7 @@ static struct platform_driver vx855gpio_driver = { | |||
315 | .remove = __devexit_p(vx855gpio_remove), | 315 | .remove = __devexit_p(vx855gpio_remove), |
316 | }; | 316 | }; |
317 | 317 | ||
318 | static int vx855gpio_init(void) | 318 | module_platform_driver(vx855gpio_driver); |
319 | { | ||
320 | return platform_driver_register(&vx855gpio_driver); | ||
321 | } | ||
322 | module_init(vx855gpio_init); | ||
323 | |||
324 | static void vx855gpio_exit(void) | ||
325 | { | ||
326 | platform_driver_unregister(&vx855gpio_driver); | ||
327 | } | ||
328 | module_exit(vx855gpio_exit); | ||
329 | 319 | ||
330 | MODULE_LICENSE("GPL"); | 320 | MODULE_LICENSE("GPL"); |
331 | MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>"); | 321 | MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>"); |
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index 96198f3fab73..92ea5350dfe9 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c | |||
@@ -117,6 +117,60 @@ static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
117 | 117 | ||
118 | 118 | ||
119 | #ifdef CONFIG_DEBUG_FS | 119 | #ifdef CONFIG_DEBUG_FS |
120 | static const char *wm8994_gpio_fn(u16 fn) | ||
121 | { | ||
122 | switch (fn) { | ||
123 | case WM8994_GP_FN_PIN_SPECIFIC: | ||
124 | return "pin-specific"; | ||
125 | case WM8994_GP_FN_GPIO: | ||
126 | return "GPIO"; | ||
127 | case WM8994_GP_FN_SDOUT: | ||
128 | return "SDOUT"; | ||
129 | case WM8994_GP_FN_IRQ: | ||
130 | return "IRQ"; | ||
131 | case WM8994_GP_FN_TEMPERATURE: | ||
132 | return "Temperature"; | ||
133 | case WM8994_GP_FN_MICBIAS1_DET: | ||
134 | return "MICBIAS1 detect"; | ||
135 | case WM8994_GP_FN_MICBIAS1_SHORT: | ||
136 | return "MICBIAS1 short"; | ||
137 | case WM8994_GP_FN_MICBIAS2_DET: | ||
138 | return "MICBIAS2 detect"; | ||
139 | case WM8994_GP_FN_MICBIAS2_SHORT: | ||
140 | return "MICBIAS2 short"; | ||
141 | case WM8994_GP_FN_FLL1_LOCK: | ||
142 | return "FLL1 lock"; | ||
143 | case WM8994_GP_FN_FLL2_LOCK: | ||
144 | return "FLL2 lock"; | ||
145 | case WM8994_GP_FN_SRC1_LOCK: | ||
146 | return "SRC1 lock"; | ||
147 | case WM8994_GP_FN_SRC2_LOCK: | ||
148 | return "SRC2 lock"; | ||
149 | case WM8994_GP_FN_DRC1_ACT: | ||
150 | return "DRC1 activity"; | ||
151 | case WM8994_GP_FN_DRC2_ACT: | ||
152 | return "DRC2 activity"; | ||
153 | case WM8994_GP_FN_DRC3_ACT: | ||
154 | return "DRC3 activity"; | ||
155 | case WM8994_GP_FN_WSEQ_STATUS: | ||
156 | return "Write sequencer"; | ||
157 | case WM8994_GP_FN_FIFO_ERROR: | ||
158 | return "FIFO error"; | ||
159 | case WM8994_GP_FN_OPCLK: | ||
160 | return "OPCLK"; | ||
161 | case WM8994_GP_FN_THW: | ||
162 | return "Thermal warning"; | ||
163 | case WM8994_GP_FN_DCS_DONE: | ||
164 | return "DC servo"; | ||
165 | case WM8994_GP_FN_FLL1_OUT: | ||
166 | return "FLL1 output"; | ||
167 | case WM8994_GP_FN_FLL2_OUT: | ||
168 | return "FLL1 output"; | ||
169 | default: | ||
170 | return "Unknown"; | ||
171 | } | ||
172 | } | ||
173 | |||
120 | static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 174 | static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
121 | { | 175 | { |
122 | struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); | 176 | struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); |
@@ -148,8 +202,29 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
148 | continue; | 202 | continue; |
149 | } | 203 | } |
150 | 204 | ||
151 | /* No decode yet; note that GPIO2 is special */ | 205 | if (reg & WM8994_GPN_DIR) |
152 | seq_printf(s, "(%x)\n", reg); | 206 | seq_printf(s, "in "); |
207 | else | ||
208 | seq_printf(s, "out "); | ||
209 | |||
210 | if (reg & WM8994_GPN_PU) | ||
211 | seq_printf(s, "pull up "); | ||
212 | |||
213 | if (reg & WM8994_GPN_PD) | ||
214 | seq_printf(s, "pull down "); | ||
215 | |||
216 | if (reg & WM8994_GPN_POL) | ||
217 | seq_printf(s, "inverted "); | ||
218 | else | ||
219 | seq_printf(s, "noninverted "); | ||
220 | |||
221 | if (reg & WM8994_GPN_OP_CFG) | ||
222 | seq_printf(s, "open drain "); | ||
223 | else | ||
224 | seq_printf(s, "CMOS "); | ||
225 | |||
226 | seq_printf(s, "%s (%x)\n", | ||
227 | wm8994_gpio_fn(reg & WM8994_GPN_FN_MASK), reg); | ||
153 | } | 228 | } |
154 | } | 229 | } |
155 | #else | 230 | #else |
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 0ce6ac9898b1..79b0fe8a7253 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c | |||
@@ -206,7 +206,6 @@ static int __devinit xgpio_of_probe(struct device_node *np) | |||
206 | np->full_name, status); | 206 | np->full_name, status); |
207 | return status; | 207 | return status; |
208 | } | 208 | } |
209 | pr_info("XGpio: %s: registered\n", np->full_name); | ||
210 | return 0; | 209 | return 0; |
211 | } | 210 | } |
212 | 211 | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index a971e3d043ba..17fdf4b6af93 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -114,7 +114,7 @@ static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset) | |||
114 | } | 114 | } |
115 | 115 | ||
116 | /* caller holds gpio_lock *OR* gpio is marked as requested */ | 116 | /* caller holds gpio_lock *OR* gpio is marked as requested */ |
117 | static inline struct gpio_chip *gpio_to_chip(unsigned gpio) | 117 | struct gpio_chip *gpio_to_chip(unsigned gpio) |
118 | { | 118 | { |
119 | return gpio_desc[gpio].chip; | 119 | return gpio_desc[gpio].chip; |
120 | } | 120 | } |
@@ -1089,6 +1089,10 @@ unlock: | |||
1089 | if (status) | 1089 | if (status) |
1090 | goto fail; | 1090 | goto fail; |
1091 | 1091 | ||
1092 | pr_info("gpiochip_add: registered GPIOs %d to %d on device: %s\n", | ||
1093 | chip->base, chip->base + chip->ngpio - 1, | ||
1094 | chip->label ? : "generic"); | ||
1095 | |||
1092 | return 0; | 1096 | return 0; |
1093 | fail: | 1097 | fail: |
1094 | /* failures here can mean systems won't boot... */ | 1098 | /* failures here can mean systems won't boot... */ |
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index cac63c9f49ae..268163dd71c7 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -15,6 +15,15 @@ config PROC_DEVICETREE | |||
15 | an image of the device tree that the kernel copies from Open | 15 | an image of the device tree that the kernel copies from Open |
16 | Firmware or other boot firmware. If unsure, say Y here. | 16 | Firmware or other boot firmware. If unsure, say Y here. |
17 | 17 | ||
18 | config OF_SELFTEST | ||
19 | bool "Device Tree Runtime self tests" | ||
20 | help | ||
21 | This option builds in test cases for the device tree infrastructure | ||
22 | that are executed one at boot time, and the results dumped to the | ||
23 | console. | ||
24 | |||
25 | If unsure, say N here, but this option is safe to enable. | ||
26 | |||
18 | config OF_FLATTREE | 27 | config OF_FLATTREE |
19 | bool | 28 | bool |
20 | select DTC | 29 | select DTC |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index dccb1176be57..a73f5a51ff4c 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_OF_GPIO) += gpio.o | |||
8 | obj-$(CONFIG_OF_I2C) += of_i2c.o | 8 | obj-$(CONFIG_OF_I2C) += of_i2c.o |
9 | obj-$(CONFIG_OF_NET) += of_net.o | 9 | obj-$(CONFIG_OF_NET) += of_net.o |
10 | obj-$(CONFIG_OF_SPI) += of_spi.o | 10 | obj-$(CONFIG_OF_SPI) += of_spi.o |
11 | obj-$(CONFIG_OF_SELFTEST) += selftest.o | ||
11 | obj-$(CONFIG_OF_MDIO) += of_mdio.o | 12 | obj-$(CONFIG_OF_MDIO) += of_mdio.o |
12 | obj-$(CONFIG_OF_PCI) += of_pci.o | 13 | obj-$(CONFIG_OF_PCI) += of_pci.o |
13 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o | 14 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 9b6588ef0673..c6db9ab9046e 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -824,17 +824,19 @@ of_parse_phandle(struct device_node *np, const char *phandle_name, int index) | |||
824 | EXPORT_SYMBOL(of_parse_phandle); | 824 | EXPORT_SYMBOL(of_parse_phandle); |
825 | 825 | ||
826 | /** | 826 | /** |
827 | * of_parse_phandles_with_args - Find a node pointed by phandle in a list | 827 | * of_parse_phandle_with_args() - Find a node pointed by phandle in a list |
828 | * @np: pointer to a device tree node containing a list | 828 | * @np: pointer to a device tree node containing a list |
829 | * @list_name: property name that contains a list | 829 | * @list_name: property name that contains a list |
830 | * @cells_name: property name that specifies phandles' arguments count | 830 | * @cells_name: property name that specifies phandles' arguments count |
831 | * @index: index of a phandle to parse out | 831 | * @index: index of a phandle to parse out |
832 | * @out_node: optional pointer to device_node struct pointer (will be filled) | 832 | * @out_args: optional pointer to output arguments structure (will be filled) |
833 | * @out_args: optional pointer to arguments pointer (will be filled) | ||
834 | * | 833 | * |
835 | * This function is useful to parse lists of phandles and their arguments. | 834 | * This function is useful to parse lists of phandles and their arguments. |
836 | * Returns 0 on success and fills out_node and out_args, on error returns | 835 | * Returns 0 on success and fills out_args, on error returns appropriate |
837 | * appropriate errno value. | 836 | * errno value. |
837 | * | ||
838 | * Caller is responsible to call of_node_put() on the returned out_args->node | ||
839 | * pointer. | ||
838 | * | 840 | * |
839 | * Example: | 841 | * Example: |
840 | * | 842 | * |
@@ -851,94 +853,96 @@ EXPORT_SYMBOL(of_parse_phandle); | |||
851 | * } | 853 | * } |
852 | * | 854 | * |
853 | * To get a device_node of the `node2' node you may call this: | 855 | * To get a device_node of the `node2' node you may call this: |
854 | * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args); | 856 | * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); |
855 | */ | 857 | */ |
856 | int of_parse_phandles_with_args(struct device_node *np, const char *list_name, | 858 | int of_parse_phandle_with_args(struct device_node *np, const char *list_name, |
857 | const char *cells_name, int index, | 859 | const char *cells_name, int index, |
858 | struct device_node **out_node, | 860 | struct of_phandle_args *out_args) |
859 | const void **out_args) | ||
860 | { | 861 | { |
861 | int ret = -EINVAL; | 862 | const __be32 *list, *list_end; |
862 | const __be32 *list; | 863 | int size, cur_index = 0; |
863 | const __be32 *list_end; | 864 | uint32_t count = 0; |
864 | int size; | ||
865 | int cur_index = 0; | ||
866 | struct device_node *node = NULL; | 865 | struct device_node *node = NULL; |
867 | const void *args = NULL; | 866 | phandle phandle; |
868 | 867 | ||
868 | /* Retrieve the phandle list property */ | ||
869 | list = of_get_property(np, list_name, &size); | 869 | list = of_get_property(np, list_name, &size); |
870 | if (!list) { | 870 | if (!list) |
871 | ret = -ENOENT; | 871 | return -EINVAL; |
872 | goto err0; | ||
873 | } | ||
874 | list_end = list + size / sizeof(*list); | 872 | list_end = list + size / sizeof(*list); |
875 | 873 | ||
874 | /* Loop over the phandles until all the requested entry is found */ | ||
876 | while (list < list_end) { | 875 | while (list < list_end) { |
877 | const __be32 *cells; | 876 | count = 0; |
878 | phandle phandle; | ||
879 | 877 | ||
878 | /* | ||
879 | * If phandle is 0, then it is an empty entry with no | ||
880 | * arguments. Skip forward to the next entry. | ||
881 | */ | ||
880 | phandle = be32_to_cpup(list++); | 882 | phandle = be32_to_cpup(list++); |
881 | args = list; | 883 | if (phandle) { |
882 | 884 | /* | |
883 | /* one cell hole in the list = <>; */ | 885 | * Find the provider node and parse the #*-cells |
884 | if (!phandle) | 886 | * property to determine the argument length |
885 | goto next; | 887 | */ |
886 | 888 | node = of_find_node_by_phandle(phandle); | |
887 | node = of_find_node_by_phandle(phandle); | 889 | if (!node) { |
888 | if (!node) { | 890 | pr_err("%s: could not find phandle\n", |
889 | pr_debug("%s: could not find phandle\n", | 891 | np->full_name); |
890 | np->full_name); | 892 | break; |
891 | goto err0; | 893 | } |
892 | } | 894 | if (of_property_read_u32(node, cells_name, &count)) { |
895 | pr_err("%s: could not get %s for %s\n", | ||
896 | np->full_name, cells_name, | ||
897 | node->full_name); | ||
898 | break; | ||
899 | } | ||
893 | 900 | ||
894 | cells = of_get_property(node, cells_name, &size); | 901 | /* |
895 | if (!cells || size != sizeof(*cells)) { | 902 | * Make sure that the arguments actually fit in the |
896 | pr_debug("%s: could not get %s for %s\n", | 903 | * remaining property data length |
897 | np->full_name, cells_name, node->full_name); | 904 | */ |
898 | goto err1; | 905 | if (list + count > list_end) { |
906 | pr_err("%s: arguments longer than property\n", | ||
907 | np->full_name); | ||
908 | break; | ||
909 | } | ||
899 | } | 910 | } |
900 | 911 | ||
901 | list += be32_to_cpup(cells); | 912 | /* |
902 | if (list > list_end) { | 913 | * All of the error cases above bail out of the loop, so at |
903 | pr_debug("%s: insufficient arguments length\n", | 914 | * this point, the parsing is successful. If the requested |
904 | np->full_name); | 915 | * index matches, then fill the out_args structure and return, |
905 | goto err1; | 916 | * or return -ENOENT for an empty entry. |
917 | */ | ||
918 | if (cur_index == index) { | ||
919 | if (!phandle) | ||
920 | return -ENOENT; | ||
921 | |||
922 | if (out_args) { | ||
923 | int i; | ||
924 | if (WARN_ON(count > MAX_PHANDLE_ARGS)) | ||
925 | count = MAX_PHANDLE_ARGS; | ||
926 | out_args->np = node; | ||
927 | out_args->args_count = count; | ||
928 | for (i = 0; i < count; i++) | ||
929 | out_args->args[i] = be32_to_cpup(list++); | ||
930 | } | ||
931 | return 0; | ||
906 | } | 932 | } |
907 | next: | ||
908 | if (cur_index == index) | ||
909 | break; | ||
910 | 933 | ||
911 | of_node_put(node); | 934 | of_node_put(node); |
912 | node = NULL; | 935 | node = NULL; |
913 | args = NULL; | 936 | list += count; |
914 | cur_index++; | 937 | cur_index++; |
915 | } | 938 | } |
916 | 939 | ||
917 | if (!node) { | 940 | /* Loop exited without finding a valid entry; return an error */ |
918 | /* | 941 | if (node) |
919 | * args w/o node indicates that the loop above has stopped at | 942 | of_node_put(node); |
920 | * the 'hole' cell. Report this differently. | 943 | return -EINVAL; |
921 | */ | ||
922 | if (args) | ||
923 | ret = -EEXIST; | ||
924 | else | ||
925 | ret = -ENOENT; | ||
926 | goto err0; | ||
927 | } | ||
928 | |||
929 | if (out_node) | ||
930 | *out_node = node; | ||
931 | if (out_args) | ||
932 | *out_args = args; | ||
933 | |||
934 | return 0; | ||
935 | err1: | ||
936 | of_node_put(node); | ||
937 | err0: | ||
938 | pr_debug("%s failed with status %d\n", __func__, ret); | ||
939 | return ret; | ||
940 | } | 944 | } |
941 | EXPORT_SYMBOL(of_parse_phandles_with_args); | 945 | EXPORT_SYMBOL(of_parse_phandle_with_args); |
942 | 946 | ||
943 | /** | 947 | /** |
944 | * prom_add_property - Add a property to a node | 948 | * prom_add_property - Add a property to a node |
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index ef0105fa52b1..7e62d15d60f6 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c | |||
@@ -35,32 +35,27 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, | |||
35 | int index, enum of_gpio_flags *flags) | 35 | int index, enum of_gpio_flags *flags) |
36 | { | 36 | { |
37 | int ret; | 37 | int ret; |
38 | struct device_node *gpio_np; | ||
39 | struct gpio_chip *gc; | 38 | struct gpio_chip *gc; |
40 | int size; | 39 | struct of_phandle_args gpiospec; |
41 | const void *gpio_spec; | ||
42 | const __be32 *gpio_cells; | ||
43 | 40 | ||
44 | ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index, | 41 | ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index, |
45 | &gpio_np, &gpio_spec); | 42 | &gpiospec); |
46 | if (ret) { | 43 | if (ret) { |
47 | pr_debug("%s: can't parse gpios property\n", __func__); | 44 | pr_debug("%s: can't parse gpios property\n", __func__); |
48 | goto err0; | 45 | goto err0; |
49 | } | 46 | } |
50 | 47 | ||
51 | gc = of_node_to_gpiochip(gpio_np); | 48 | gc = of_node_to_gpiochip(gpiospec.np); |
52 | if (!gc) { | 49 | if (!gc) { |
53 | pr_debug("%s: gpio controller %s isn't registered\n", | 50 | pr_debug("%s: gpio controller %s isn't registered\n", |
54 | np->full_name, gpio_np->full_name); | 51 | np->full_name, gpiospec.np->full_name); |
55 | ret = -ENODEV; | 52 | ret = -ENODEV; |
56 | goto err1; | 53 | goto err1; |
57 | } | 54 | } |
58 | 55 | ||
59 | gpio_cells = of_get_property(gpio_np, "#gpio-cells", &size); | 56 | if (gpiospec.args_count != gc->of_gpio_n_cells) { |
60 | if (!gpio_cells || size != sizeof(*gpio_cells) || | ||
61 | be32_to_cpup(gpio_cells) != gc->of_gpio_n_cells) { | ||
62 | pr_debug("%s: wrong #gpio-cells for %s\n", | 57 | pr_debug("%s: wrong #gpio-cells for %s\n", |
63 | np->full_name, gpio_np->full_name); | 58 | np->full_name, gpiospec.np->full_name); |
64 | ret = -EINVAL; | 59 | ret = -EINVAL; |
65 | goto err1; | 60 | goto err1; |
66 | } | 61 | } |
@@ -69,13 +64,13 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, | |||
69 | if (flags) | 64 | if (flags) |
70 | *flags = 0; | 65 | *flags = 0; |
71 | 66 | ||
72 | ret = gc->of_xlate(gc, np, gpio_spec, flags); | 67 | ret = gc->of_xlate(gc, &gpiospec, flags); |
73 | if (ret < 0) | 68 | if (ret < 0) |
74 | goto err1; | 69 | goto err1; |
75 | 70 | ||
76 | ret += gc->base; | 71 | ret += gc->base; |
77 | err1: | 72 | err1: |
78 | of_node_put(gpio_np); | 73 | of_node_put(gpiospec.np); |
79 | err0: | 74 | err0: |
80 | pr_debug("%s exited with status %d\n", __func__, ret); | 75 | pr_debug("%s exited with status %d\n", __func__, ret); |
81 | return ret; | 76 | return ret; |
@@ -105,8 +100,8 @@ unsigned int of_gpio_count(struct device_node *np) | |||
105 | do { | 100 | do { |
106 | int ret; | 101 | int ret; |
107 | 102 | ||
108 | ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", | 103 | ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells", |
109 | cnt, NULL, NULL); | 104 | cnt, NULL); |
110 | /* A hole in the gpios = <> counts anyway. */ | 105 | /* A hole in the gpios = <> counts anyway. */ |
111 | if (ret < 0 && ret != -EEXIST) | 106 | if (ret < 0 && ret != -EEXIST) |
112 | break; | 107 | break; |
@@ -127,12 +122,9 @@ EXPORT_SYMBOL(of_gpio_count); | |||
127 | * gpio chips. This function performs only one sanity check: whether gpio | 122 | * gpio chips. This function performs only one sanity check: whether gpio |
128 | * is less than ngpios (that is specified in the gpio_chip). | 123 | * is less than ngpios (that is specified in the gpio_chip). |
129 | */ | 124 | */ |
130 | int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np, | 125 | int of_gpio_simple_xlate(struct gpio_chip *gc, |
131 | const void *gpio_spec, u32 *flags) | 126 | const struct of_phandle_args *gpiospec, u32 *flags) |
132 | { | 127 | { |
133 | const __be32 *gpio = gpio_spec; | ||
134 | const u32 n = be32_to_cpup(gpio); | ||
135 | |||
136 | /* | 128 | /* |
137 | * We're discouraging gpio_cells < 2, since that way you'll have to | 129 | * We're discouraging gpio_cells < 2, since that way you'll have to |
138 | * write your own xlate function (that will have to retrive the GPIO | 130 | * write your own xlate function (that will have to retrive the GPIO |
@@ -144,13 +136,16 @@ int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np, | |||
144 | return -EINVAL; | 136 | return -EINVAL; |
145 | } | 137 | } |
146 | 138 | ||
147 | if (n > gc->ngpio) | 139 | if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) |
140 | return -EINVAL; | ||
141 | |||
142 | if (gpiospec->args[0] > gc->ngpio) | ||
148 | return -EINVAL; | 143 | return -EINVAL; |
149 | 144 | ||
150 | if (flags) | 145 | if (flags) |
151 | *flags = be32_to_cpu(gpio[1]); | 146 | *flags = gpiospec->args[1]; |
152 | 147 | ||
153 | return n; | 148 | return gpiospec->args[0]; |
154 | } | 149 | } |
155 | EXPORT_SYMBOL(of_gpio_simple_xlate); | 150 | EXPORT_SYMBOL(of_gpio_simple_xlate); |
156 | 151 | ||
@@ -198,8 +193,6 @@ int of_mm_gpiochip_add(struct device_node *np, | |||
198 | if (ret) | 193 | if (ret) |
199 | goto err2; | 194 | goto err2; |
200 | 195 | ||
201 | pr_debug("%s: registered as generic GPIO chip, base is %d\n", | ||
202 | np->full_name, gc->base); | ||
203 | return 0; | 196 | return 0; |
204 | err2: | 197 | err2: |
205 | iounmap(mm_gc->regs); | 198 | iounmap(mm_gc->regs); |
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c new file mode 100644 index 000000000000..9d2b4803a9d6 --- /dev/null +++ b/drivers/of/selftest.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Self tests for device tree subsystem | ||
3 | */ | ||
4 | |||
5 | #define pr_fmt(fmt) "### %s(): " fmt, __func__ | ||
6 | |||
7 | #include <linux/clk.h> | ||
8 | #include <linux/err.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/of.h> | ||
12 | #include <linux/list.h> | ||
13 | #include <linux/mutex.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/device.h> | ||
16 | |||
17 | static bool selftest_passed = true; | ||
18 | #define selftest(result, fmt, ...) { \ | ||
19 | selftest_passed &= (result); \ | ||
20 | if (!(result)) \ | ||
21 | pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ | ||
22 | } | ||
23 | |||
24 | static void __init of_selftest_parse_phandle_with_args(void) | ||
25 | { | ||
26 | struct device_node *np; | ||
27 | struct of_phandle_args args; | ||
28 | int rc, i; | ||
29 | bool passed_all = true; | ||
30 | |||
31 | pr_info("start\n"); | ||
32 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); | ||
33 | if (!np) { | ||
34 | pr_err("missing testcase data\n"); | ||
35 | return; | ||
36 | } | ||
37 | |||
38 | for (i = 0; i < 7; i++) { | ||
39 | bool passed = true; | ||
40 | rc = of_parse_phandle_with_args(np, "phandle-list", | ||
41 | "#phandle-cells", i, &args); | ||
42 | |||
43 | /* Test the values from tests-phandle.dtsi */ | ||
44 | switch (i) { | ||
45 | case 0: | ||
46 | passed &= !rc; | ||
47 | passed &= (args.args_count == 1); | ||
48 | passed &= (args.args[0] == (i + 1)); | ||
49 | break; | ||
50 | case 1: | ||
51 | passed &= !rc; | ||
52 | passed &= (args.args_count == 2); | ||
53 | passed &= (args.args[0] == (i + 1)); | ||
54 | passed &= (args.args[1] == 0); | ||
55 | break; | ||
56 | case 2: | ||
57 | passed &= (rc == -ENOENT); | ||
58 | break; | ||
59 | case 3: | ||
60 | passed &= !rc; | ||
61 | passed &= (args.args_count == 3); | ||
62 | passed &= (args.args[0] == (i + 1)); | ||
63 | passed &= (args.args[1] == 4); | ||
64 | passed &= (args.args[2] == 3); | ||
65 | break; | ||
66 | case 4: | ||
67 | passed &= !rc; | ||
68 | passed &= (args.args_count == 2); | ||
69 | passed &= (args.args[0] == (i + 1)); | ||
70 | passed &= (args.args[1] == 100); | ||
71 | break; | ||
72 | case 5: | ||
73 | passed &= !rc; | ||
74 | passed &= (args.args_count == 0); | ||
75 | break; | ||
76 | case 6: | ||
77 | passed &= !rc; | ||
78 | passed &= (args.args_count == 1); | ||
79 | passed &= (args.args[0] == (i + 1)); | ||
80 | break; | ||
81 | case 7: | ||
82 | passed &= (rc == -EINVAL); | ||
83 | break; | ||
84 | default: | ||
85 | passed = false; | ||
86 | } | ||
87 | |||
88 | if (!passed) { | ||
89 | int j; | ||
90 | pr_err("index %i - data error on node %s rc=%i regs=[", | ||
91 | i, args.np->full_name, rc); | ||
92 | for (j = 0; j < args.args_count; j++) | ||
93 | printk(" %i", args.args[j]); | ||
94 | printk(" ]\n"); | ||
95 | |||
96 | passed_all = false; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* Check for missing list property */ | ||
101 | rc = of_parse_phandle_with_args(np, "phandle-list-missing", | ||
102 | "#phandle-cells", 0, &args); | ||
103 | passed_all &= (rc == -EINVAL); | ||
104 | |||
105 | /* Check for missing cells property */ | ||
106 | rc = of_parse_phandle_with_args(np, "phandle-list", | ||
107 | "#phandle-cells-missing", 0, &args); | ||
108 | passed_all &= (rc == -EINVAL); | ||
109 | |||
110 | /* Check for bad phandle in list */ | ||
111 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", | ||
112 | "#phandle-cells", 0, &args); | ||
113 | passed_all &= (rc == -EINVAL); | ||
114 | |||
115 | /* Check for incorrectly formed argument list */ | ||
116 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", | ||
117 | "#phandle-cells", 1, &args); | ||
118 | passed_all &= (rc == -EINVAL); | ||
119 | |||
120 | pr_info("end - %s\n", passed_all ? "PASS" : "FAIL"); | ||
121 | } | ||
122 | |||
123 | static int __init of_selftest(void) | ||
124 | { | ||
125 | struct device_node *np; | ||
126 | |||
127 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); | ||
128 | if (!np) { | ||
129 | pr_info("No testcase data in device tree; not running tests\n"); | ||
130 | return 0; | ||
131 | } | ||
132 | of_node_put(np); | ||
133 | |||
134 | pr_info("start of selftest - you will see error messages\n"); | ||
135 | of_selftest_parse_phandle_with_args(); | ||
136 | pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL"); | ||
137 | return 0; | ||
138 | } | ||
139 | late_initcall(of_selftest); | ||
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 7026af195683..f1f5efbc3404 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c | |||
@@ -340,6 +340,10 @@ struct vendor_data { | |||
340 | * @cur_msg: Pointer to current spi_message being processed | 340 | * @cur_msg: Pointer to current spi_message being processed |
341 | * @cur_transfer: Pointer to current spi_transfer | 341 | * @cur_transfer: Pointer to current spi_transfer |
342 | * @cur_chip: pointer to current clients chip(assigned from controller_state) | 342 | * @cur_chip: pointer to current clients chip(assigned from controller_state) |
343 | * @next_msg_cs_active: the next message in the queue has been examined | ||
344 | * and it was found that it uses the same chip select as the previous | ||
345 | * message, so we left it active after the previous transfer, and it's | ||
346 | * active already. | ||
343 | * @tx: current position in TX buffer to be read | 347 | * @tx: current position in TX buffer to be read |
344 | * @tx_end: end position in TX buffer to be read | 348 | * @tx_end: end position in TX buffer to be read |
345 | * @rx: current position in RX buffer to be written | 349 | * @rx: current position in RX buffer to be written |
@@ -373,6 +377,7 @@ struct pl022 { | |||
373 | struct spi_message *cur_msg; | 377 | struct spi_message *cur_msg; |
374 | struct spi_transfer *cur_transfer; | 378 | struct spi_transfer *cur_transfer; |
375 | struct chip_data *cur_chip; | 379 | struct chip_data *cur_chip; |
380 | bool next_msg_cs_active; | ||
376 | void *tx; | 381 | void *tx; |
377 | void *tx_end; | 382 | void *tx_end; |
378 | void *rx; | 383 | void *rx; |
@@ -445,23 +450,9 @@ static void giveback(struct pl022 *pl022) | |||
445 | struct spi_transfer *last_transfer; | 450 | struct spi_transfer *last_transfer; |
446 | unsigned long flags; | 451 | unsigned long flags; |
447 | struct spi_message *msg; | 452 | struct spi_message *msg; |
448 | void (*curr_cs_control) (u32 command); | 453 | pl022->next_msg_cs_active = false; |
449 | 454 | ||
450 | /* | 455 | last_transfer = list_entry(pl022->cur_msg->transfers.prev, |
451 | * This local reference to the chip select function | ||
452 | * is needed because we set curr_chip to NULL | ||
453 | * as a step toward termininating the message. | ||
454 | */ | ||
455 | curr_cs_control = pl022->cur_chip->cs_control; | ||
456 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
457 | msg = pl022->cur_msg; | ||
458 | pl022->cur_msg = NULL; | ||
459 | pl022->cur_transfer = NULL; | ||
460 | pl022->cur_chip = NULL; | ||
461 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
462 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
463 | |||
464 | last_transfer = list_entry(msg->transfers.prev, | ||
465 | struct spi_transfer, | 456 | struct spi_transfer, |
466 | transfer_list); | 457 | transfer_list); |
467 | 458 | ||
@@ -473,18 +464,13 @@ static void giveback(struct pl022 *pl022) | |||
473 | */ | 464 | */ |
474 | udelay(last_transfer->delay_usecs); | 465 | udelay(last_transfer->delay_usecs); |
475 | 466 | ||
476 | /* | 467 | if (!last_transfer->cs_change) { |
477 | * Drop chip select UNLESS cs_change is true or we are returning | ||
478 | * a message with an error, or next message is for another chip | ||
479 | */ | ||
480 | if (!last_transfer->cs_change) | ||
481 | curr_cs_control(SSP_CHIP_DESELECT); | ||
482 | else { | ||
483 | struct spi_message *next_msg; | 468 | struct spi_message *next_msg; |
484 | 469 | ||
485 | /* Holding of cs was hinted, but we need to make sure | 470 | /* |
486 | * the next message is for the same chip. Don't waste | 471 | * cs_change was not set. We can keep the chip select |
487 | * time with the following tests unless this was hinted. | 472 | * enabled if there is message in the queue and it is |
473 | * for the same spi device. | ||
488 | * | 474 | * |
489 | * We cannot postpone this until pump_messages, because | 475 | * We cannot postpone this until pump_messages, because |
490 | * after calling msg->complete (below) the driver that | 476 | * after calling msg->complete (below) the driver that |
@@ -501,19 +487,29 @@ static void giveback(struct pl022 *pl022) | |||
501 | struct spi_message, queue); | 487 | struct spi_message, queue); |
502 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 488 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
503 | 489 | ||
504 | /* see if the next and current messages point | 490 | /* |
505 | * to the same chip | 491 | * see if the next and current messages point |
492 | * to the same spi device. | ||
506 | */ | 493 | */ |
507 | if (next_msg && next_msg->spi != msg->spi) | 494 | if (next_msg && next_msg->spi != pl022->cur_msg->spi) |
508 | next_msg = NULL; | 495 | next_msg = NULL; |
509 | if (!next_msg || msg->state == STATE_ERROR) | 496 | if (!next_msg || pl022->cur_msg->state == STATE_ERROR) |
510 | curr_cs_control(SSP_CHIP_DESELECT); | 497 | pl022->cur_chip->cs_control(SSP_CHIP_DESELECT); |
498 | else | ||
499 | pl022->next_msg_cs_active = true; | ||
511 | } | 500 | } |
501 | |||
502 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
503 | msg = pl022->cur_msg; | ||
504 | pl022->cur_msg = NULL; | ||
505 | pl022->cur_transfer = NULL; | ||
506 | pl022->cur_chip = NULL; | ||
507 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
508 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
509 | |||
512 | msg->state = NULL; | 510 | msg->state = NULL; |
513 | if (msg->complete) | 511 | if (msg->complete) |
514 | msg->complete(msg->context); | 512 | msg->complete(msg->context); |
515 | /* This message is completed, so let's turn off the clocks & power */ | ||
516 | pm_runtime_put(&pl022->adev->dev); | ||
517 | } | 513 | } |
518 | 514 | ||
519 | /** | 515 | /** |
@@ -1244,9 +1240,9 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) | |||
1244 | 1240 | ||
1245 | if ((pl022->tx == pl022->tx_end) && (flag == 0)) { | 1241 | if ((pl022->tx == pl022->tx_end) && (flag == 0)) { |
1246 | flag = 1; | 1242 | flag = 1; |
1247 | /* Disable Transmit interrupt */ | 1243 | /* Disable Transmit interrupt, enable receive interrupt */ |
1248 | writew(readw(SSP_IMSC(pl022->virtbase)) & | 1244 | writew((readw(SSP_IMSC(pl022->virtbase)) & |
1249 | (~SSP_IMSC_MASK_TXIM), | 1245 | ~SSP_IMSC_MASK_TXIM) | SSP_IMSC_MASK_RXIM, |
1250 | SSP_IMSC(pl022->virtbase)); | 1246 | SSP_IMSC(pl022->virtbase)); |
1251 | } | 1247 | } |
1252 | 1248 | ||
@@ -1352,7 +1348,7 @@ static void pump_transfers(unsigned long data) | |||
1352 | */ | 1348 | */ |
1353 | udelay(previous->delay_usecs); | 1349 | udelay(previous->delay_usecs); |
1354 | 1350 | ||
1355 | /* Drop chip select only if cs_change is requested */ | 1351 | /* Reselect chip select only if cs_change was requested */ |
1356 | if (previous->cs_change) | 1352 | if (previous->cs_change) |
1357 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | 1353 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); |
1358 | } else { | 1354 | } else { |
@@ -1379,15 +1375,22 @@ static void pump_transfers(unsigned long data) | |||
1379 | } | 1375 | } |
1380 | 1376 | ||
1381 | err_config_dma: | 1377 | err_config_dma: |
1382 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | 1378 | /* enable all interrupts except RX */ |
1379 | writew(ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM, SSP_IMSC(pl022->virtbase)); | ||
1383 | } | 1380 | } |
1384 | 1381 | ||
1385 | static void do_interrupt_dma_transfer(struct pl022 *pl022) | 1382 | static void do_interrupt_dma_transfer(struct pl022 *pl022) |
1386 | { | 1383 | { |
1387 | u32 irqflags = ENABLE_ALL_INTERRUPTS; | 1384 | /* |
1385 | * Default is to enable all interrupts except RX - | ||
1386 | * this will be enabled once TX is complete | ||
1387 | */ | ||
1388 | u32 irqflags = ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM; | ||
1389 | |||
1390 | /* Enable target chip, if not already active */ | ||
1391 | if (!pl022->next_msg_cs_active) | ||
1392 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
1388 | 1393 | ||
1389 | /* Enable target chip */ | ||
1390 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
1391 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { | 1394 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { |
1392 | /* Error path */ | 1395 | /* Error path */ |
1393 | pl022->cur_msg->state = STATE_ERROR; | 1396 | pl022->cur_msg->state = STATE_ERROR; |
@@ -1442,7 +1445,8 @@ static void do_polling_transfer(struct pl022 *pl022) | |||
1442 | } else { | 1445 | } else { |
1443 | /* STATE_START */ | 1446 | /* STATE_START */ |
1444 | message->state = STATE_RUNNING; | 1447 | message->state = STATE_RUNNING; |
1445 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | 1448 | if (!pl022->next_msg_cs_active) |
1449 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
1446 | } | 1450 | } |
1447 | 1451 | ||
1448 | /* Configuration Changing Per Transfer */ | 1452 | /* Configuration Changing Per Transfer */ |
@@ -1504,14 +1508,28 @@ static void pump_messages(struct work_struct *work) | |||
1504 | struct pl022 *pl022 = | 1508 | struct pl022 *pl022 = |
1505 | container_of(work, struct pl022, pump_messages); | 1509 | container_of(work, struct pl022, pump_messages); |
1506 | unsigned long flags; | 1510 | unsigned long flags; |
1511 | bool was_busy = false; | ||
1507 | 1512 | ||
1508 | /* Lock queue and check for queue work */ | 1513 | /* Lock queue and check for queue work */ |
1509 | spin_lock_irqsave(&pl022->queue_lock, flags); | 1514 | spin_lock_irqsave(&pl022->queue_lock, flags); |
1510 | if (list_empty(&pl022->queue) || !pl022->running) { | 1515 | if (list_empty(&pl022->queue) || !pl022->running) { |
1516 | if (pl022->busy) { | ||
1517 | /* nothing more to do - disable spi/ssp and power off */ | ||
1518 | writew((readw(SSP_CR1(pl022->virtbase)) & | ||
1519 | (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); | ||
1520 | |||
1521 | if (pl022->master_info->autosuspend_delay > 0) { | ||
1522 | pm_runtime_mark_last_busy(&pl022->adev->dev); | ||
1523 | pm_runtime_put_autosuspend(&pl022->adev->dev); | ||
1524 | } else { | ||
1525 | pm_runtime_put(&pl022->adev->dev); | ||
1526 | } | ||
1527 | } | ||
1511 | pl022->busy = false; | 1528 | pl022->busy = false; |
1512 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 1529 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
1513 | return; | 1530 | return; |
1514 | } | 1531 | } |
1532 | |||
1515 | /* Make sure we are not already running a message */ | 1533 | /* Make sure we are not already running a message */ |
1516 | if (pl022->cur_msg) { | 1534 | if (pl022->cur_msg) { |
1517 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 1535 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
@@ -1522,7 +1540,10 @@ static void pump_messages(struct work_struct *work) | |||
1522 | list_entry(pl022->queue.next, struct spi_message, queue); | 1540 | list_entry(pl022->queue.next, struct spi_message, queue); |
1523 | 1541 | ||
1524 | list_del_init(&pl022->cur_msg->queue); | 1542 | list_del_init(&pl022->cur_msg->queue); |
1525 | pl022->busy = true; | 1543 | if (pl022->busy) |
1544 | was_busy = true; | ||
1545 | else | ||
1546 | pl022->busy = true; | ||
1526 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 1547 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
1527 | 1548 | ||
1528 | /* Initial message state */ | 1549 | /* Initial message state */ |
@@ -1532,12 +1553,14 @@ static void pump_messages(struct work_struct *work) | |||
1532 | 1553 | ||
1533 | /* Setup the SPI using the per chip configuration */ | 1554 | /* Setup the SPI using the per chip configuration */ |
1534 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); | 1555 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); |
1535 | /* | 1556 | if (!was_busy) |
1536 | * We enable the core voltage and clocks here, then the clocks | 1557 | /* |
1537 | * and core will be disabled when giveback() is called in each method | 1558 | * We enable the core voltage and clocks here, then the clocks |
1538 | * (poll/interrupt/DMA) | 1559 | * and core will be disabled when this workqueue is run again |
1539 | */ | 1560 | * and there is no more work to be done. |
1540 | pm_runtime_get_sync(&pl022->adev->dev); | 1561 | */ |
1562 | pm_runtime_get_sync(&pl022->adev->dev); | ||
1563 | |||
1541 | restore_state(pl022); | 1564 | restore_state(pl022); |
1542 | flush(pl022); | 1565 | flush(pl022); |
1543 | 1566 | ||
@@ -1582,6 +1605,7 @@ static int start_queue(struct pl022 *pl022) | |||
1582 | pl022->cur_msg = NULL; | 1605 | pl022->cur_msg = NULL; |
1583 | pl022->cur_transfer = NULL; | 1606 | pl022->cur_transfer = NULL; |
1584 | pl022->cur_chip = NULL; | 1607 | pl022->cur_chip = NULL; |
1608 | pl022->next_msg_cs_active = false; | ||
1585 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | 1609 | spin_unlock_irqrestore(&pl022->queue_lock, flags); |
1586 | 1610 | ||
1587 | queue_work(pl022->workqueue, &pl022->pump_messages); | 1611 | queue_work(pl022->workqueue, &pl022->pump_messages); |
@@ -1881,7 +1905,7 @@ static int pl022_setup(struct spi_device *spi) | |||
1881 | { | 1905 | { |
1882 | struct pl022_config_chip const *chip_info; | 1906 | struct pl022_config_chip const *chip_info; |
1883 | struct chip_data *chip; | 1907 | struct chip_data *chip; |
1884 | struct ssp_clock_params clk_freq = {0, }; | 1908 | struct ssp_clock_params clk_freq = { .cpsdvsr = 0, .scr = 0}; |
1885 | int status = 0; | 1909 | int status = 0; |
1886 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); | 1910 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); |
1887 | unsigned int bits = spi->bits_per_word; | 1911 | unsigned int bits = spi->bits_per_word; |
@@ -2231,7 +2255,17 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2231 | dev_dbg(dev, "probe succeeded\n"); | 2255 | dev_dbg(dev, "probe succeeded\n"); |
2232 | 2256 | ||
2233 | /* let runtime pm put suspend */ | 2257 | /* let runtime pm put suspend */ |
2234 | pm_runtime_put(dev); | 2258 | if (platform_info->autosuspend_delay > 0) { |
2259 | dev_info(&adev->dev, | ||
2260 | "will use autosuspend for runtime pm, delay %dms\n", | ||
2261 | platform_info->autosuspend_delay); | ||
2262 | pm_runtime_set_autosuspend_delay(dev, | ||
2263 | platform_info->autosuspend_delay); | ||
2264 | pm_runtime_use_autosuspend(dev); | ||
2265 | pm_runtime_put_autosuspend(dev); | ||
2266 | } else { | ||
2267 | pm_runtime_put(dev); | ||
2268 | } | ||
2235 | return 0; | 2269 | return 0; |
2236 | 2270 | ||
2237 | err_spi_register: | 2271 | err_spi_register: |
@@ -2305,11 +2339,6 @@ static int pl022_suspend(struct device *dev) | |||
2305 | return status; | 2339 | return status; |
2306 | } | 2340 | } |
2307 | 2341 | ||
2308 | amba_vcore_enable(pl022->adev); | ||
2309 | amba_pclk_enable(pl022->adev); | ||
2310 | load_ssp_default_config(pl022); | ||
2311 | amba_pclk_disable(pl022->adev); | ||
2312 | amba_vcore_disable(pl022->adev); | ||
2313 | dev_dbg(dev, "suspended\n"); | 2342 | dev_dbg(dev, "suspended\n"); |
2314 | return 0; | 2343 | return 0; |
2315 | } | 2344 | } |