diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 12:08:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 12:08:00 -0500 |
commit | 822e5215f9eef86c1dd56d5696bf55a212b0e3f0 (patch) | |
tree | 661de9888a0edef872e7366df09831bf7a5bc067 /drivers/gpio | |
parent | c1e0d97d3d63d5173baf8c39a13dc5c25b031bd4 (diff) | |
parent | 92d50a4132977b932ed830fa58c05deeb5c524f0 (diff) |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (59 commits)
mfd: ab8500-core chip version cut 2.0 support
mfd: Flag WM831x /IRQ as a wake source
mfd: Convert WM831x away from legacy I2C PM operations
regulator: Support MAX8998/LP3974 DVS-GPIO
mfd: Support LP3974 RTC
i2c: Convert SCx200 driver from using raw PCI to platform device
x86: OLPC: convert olpc-xo1 driver from pci device to platform device
mfd: MAX8998/LP3974 hibernation support
mfd/ab8500: remove spi support
mfd: Remove ARCH_U8500 dependency from AB8500
misc: Make AB8500_PWM driver depend on U8500 due to PWM breakage
mfd: Add __devexit annotation for vx855_remove
mfd: twl6030 irq_data conversion.
gpio: Fix cs5535 printk warnings
misc: Fix cs5535 printk warnings
mfd: Convert Wolfson MFD drivers to use irq_data accessor function
mfd: Convert TWL4030 to new irq_ APIs
mfd: Convert tps6586x driver to new irq_ API
mfd: Convert tc6393xb driver to new irq_ APIs
mfd: Convert t7166xb driver to new irq_ API
...
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/cs5535-gpio.c | 93 |
1 files changed, 31 insertions, 62 deletions
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index 815d98b2c1ba..0d05ea7d499b 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c | |||
@@ -11,14 +11,13 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/pci.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/gpio.h> | 15 | #include <linux/gpio.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/cs5535.h> | 17 | #include <linux/cs5535.h> |
18 | #include <asm/msr.h> | 18 | #include <asm/msr.h> |
19 | 19 | ||
20 | #define DRV_NAME "cs5535-gpio" | 20 | #define DRV_NAME "cs5535-gpio" |
21 | #define GPIO_BAR 1 | ||
22 | 21 | ||
23 | /* | 22 | /* |
24 | * Some GPIO pins | 23 | * Some GPIO pins |
@@ -47,7 +46,7 @@ static struct cs5535_gpio_chip { | |||
47 | struct gpio_chip chip; | 46 | struct gpio_chip chip; |
48 | resource_size_t base; | 47 | resource_size_t base; |
49 | 48 | ||
50 | struct pci_dev *pdev; | 49 | struct platform_device *pdev; |
51 | spinlock_t lock; | 50 | spinlock_t lock; |
52 | } cs5535_gpio_chip; | 51 | } cs5535_gpio_chip; |
53 | 52 | ||
@@ -301,10 +300,10 @@ static struct cs5535_gpio_chip cs5535_gpio_chip = { | |||
301 | }, | 300 | }, |
302 | }; | 301 | }; |
303 | 302 | ||
304 | static int __init cs5535_gpio_probe(struct pci_dev *pdev, | 303 | static int __devinit cs5535_gpio_probe(struct platform_device *pdev) |
305 | const struct pci_device_id *pci_id) | ||
306 | { | 304 | { |
307 | int err; | 305 | struct resource *res; |
306 | int err = -EIO; | ||
308 | ulong mask_orig = mask; | 307 | ulong mask_orig = mask; |
309 | 308 | ||
310 | /* There are two ways to get the GPIO base address; one is by | 309 | /* There are two ways to get the GPIO base address; one is by |
@@ -314,25 +313,23 @@ static int __init cs5535_gpio_probe(struct pci_dev *pdev, | |||
314 | * it turns out to be unreliable in the face of crappy BIOSes, we | 313 | * it turns out to be unreliable in the face of crappy BIOSes, we |
315 | * can always go back to using MSRs.. */ | 314 | * can always go back to using MSRs.. */ |
316 | 315 | ||
317 | err = pci_enable_device_io(pdev); | 316 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
318 | if (err) { | 317 | if (!res) { |
319 | dev_err(&pdev->dev, "can't enable device IO\n"); | 318 | dev_err(&pdev->dev, "can't fetch device resource info\n"); |
320 | goto done; | 319 | goto done; |
321 | } | 320 | } |
322 | 321 | ||
323 | err = pci_request_region(pdev, GPIO_BAR, DRV_NAME); | 322 | if (!request_region(res->start, resource_size(res), pdev->name)) { |
324 | if (err) { | 323 | dev_err(&pdev->dev, "can't request region\n"); |
325 | dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR); | ||
326 | goto done; | 324 | goto done; |
327 | } | 325 | } |
328 | 326 | ||
329 | /* set up the driver-specific struct */ | 327 | /* set up the driver-specific struct */ |
330 | cs5535_gpio_chip.base = pci_resource_start(pdev, GPIO_BAR); | 328 | cs5535_gpio_chip.base = res->start; |
331 | cs5535_gpio_chip.pdev = pdev; | 329 | cs5535_gpio_chip.pdev = pdev; |
332 | spin_lock_init(&cs5535_gpio_chip.lock); | 330 | spin_lock_init(&cs5535_gpio_chip.lock); |
333 | 331 | ||
334 | dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR, | 332 | dev_info(&pdev->dev, "reserved resource region %pR\n", res); |
335 | (unsigned long long) cs5535_gpio_chip.base); | ||
336 | 333 | ||
337 | /* mask out reserved pins */ | 334 | /* mask out reserved pins */ |
338 | mask &= 0x1F7FFFFF; | 335 | mask &= 0x1F7FFFFF; |
@@ -350,78 +347,49 @@ static int __init cs5535_gpio_probe(struct pci_dev *pdev, | |||
350 | if (err) | 347 | if (err) |
351 | goto release_region; | 348 | goto release_region; |
352 | 349 | ||
353 | dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n"); | 350 | dev_info(&pdev->dev, "GPIO support successfully loaded.\n"); |
354 | return 0; | 351 | return 0; |
355 | 352 | ||
356 | release_region: | 353 | release_region: |
357 | pci_release_region(pdev, GPIO_BAR); | 354 | release_region(res->start, resource_size(res)); |
358 | done: | 355 | done: |
359 | return err; | 356 | return err; |
360 | } | 357 | } |
361 | 358 | ||
362 | static void __exit cs5535_gpio_remove(struct pci_dev *pdev) | 359 | static int __devexit cs5535_gpio_remove(struct platform_device *pdev) |
363 | { | 360 | { |
361 | struct resource *r; | ||
364 | int err; | 362 | int err; |
365 | 363 | ||
366 | err = gpiochip_remove(&cs5535_gpio_chip.chip); | 364 | err = gpiochip_remove(&cs5535_gpio_chip.chip); |
367 | if (err) { | 365 | if (err) { |
368 | /* uhh? */ | 366 | /* uhh? */ |
369 | dev_err(&pdev->dev, "unable to remove gpio_chip?\n"); | 367 | dev_err(&pdev->dev, "unable to remove gpio_chip?\n"); |
368 | return err; | ||
370 | } | 369 | } |
371 | pci_release_region(pdev, GPIO_BAR); | ||
372 | } | ||
373 | |||
374 | static struct pci_device_id cs5535_gpio_pci_tbl[] = { | ||
375 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, | ||
376 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, | ||
377 | { 0, }, | ||
378 | }; | ||
379 | MODULE_DEVICE_TABLE(pci, cs5535_gpio_pci_tbl); | ||
380 | 370 | ||
381 | /* | 371 | r = platform_get_resource(pdev, IORESOURCE_IO, 0); |
382 | * We can't use the standard PCI driver registration stuff here, since | 372 | release_region(r->start, resource_size(r)); |
383 | * that allows only one driver to bind to each PCI device (and we want | 373 | return 0; |
384 | * multiple drivers to be able to bind to the device). Instead, manually | ||
385 | * scan for the PCI device, request a single region, and keep track of the | ||
386 | * devices that we're using. | ||
387 | */ | ||
388 | |||
389 | static int __init cs5535_gpio_scan_pci(void) | ||
390 | { | ||
391 | struct pci_dev *pdev; | ||
392 | int err = -ENODEV; | ||
393 | int i; | ||
394 | |||
395 | for (i = 0; i < ARRAY_SIZE(cs5535_gpio_pci_tbl); i++) { | ||
396 | pdev = pci_get_device(cs5535_gpio_pci_tbl[i].vendor, | ||
397 | cs5535_gpio_pci_tbl[i].device, NULL); | ||
398 | if (pdev) { | ||
399 | err = cs5535_gpio_probe(pdev, &cs5535_gpio_pci_tbl[i]); | ||
400 | if (err) | ||
401 | pci_dev_put(pdev); | ||
402 | |||
403 | /* we only support a single CS5535/6 southbridge */ | ||
404 | break; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | return err; | ||
409 | } | 374 | } |
410 | 375 | ||
411 | static void __exit cs5535_gpio_free_pci(void) | 376 | static struct platform_driver cs5535_gpio_drv = { |
412 | { | 377 | .driver = { |
413 | cs5535_gpio_remove(cs5535_gpio_chip.pdev); | 378 | .name = DRV_NAME, |
414 | pci_dev_put(cs5535_gpio_chip.pdev); | 379 | .owner = THIS_MODULE, |
415 | } | 380 | }, |
381 | .probe = cs5535_gpio_probe, | ||
382 | .remove = __devexit_p(cs5535_gpio_remove), | ||
383 | }; | ||
416 | 384 | ||
417 | static int __init cs5535_gpio_init(void) | 385 | static int __init cs5535_gpio_init(void) |
418 | { | 386 | { |
419 | return cs5535_gpio_scan_pci(); | 387 | return platform_driver_register(&cs5535_gpio_drv); |
420 | } | 388 | } |
421 | 389 | ||
422 | static void __exit cs5535_gpio_exit(void) | 390 | static void __exit cs5535_gpio_exit(void) |
423 | { | 391 | { |
424 | cs5535_gpio_free_pci(); | 392 | platform_driver_unregister(&cs5535_gpio_drv); |
425 | } | 393 | } |
426 | 394 | ||
427 | module_init(cs5535_gpio_init); | 395 | module_init(cs5535_gpio_init); |
@@ -430,3 +398,4 @@ module_exit(cs5535_gpio_exit); | |||
430 | MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); | 398 | MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); |
431 | MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver"); | 399 | MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver"); |
432 | MODULE_LICENSE("GPL"); | 400 | MODULE_LICENSE("GPL"); |
401 | MODULE_ALIAS("platform:" DRV_NAME); | ||