Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: Convert SCx200 driver from using raw PCI to platform device

The SCx200 ACB driver supports ISA hardware as well as PCI. The PCI
hardware is CS5535/CS5536 based, and the device that it grabs is handled by
the cs5535-mfd driver. This converts the SCx200 driver to use a
platform_driver rather than the previous PCI hackery.

The driver used to manually track the iface list (via linked list); now it
only does this for ISA devices. PCI ifaces are handled through standard
driver model lists.

It's unclear what happens in case of errors in the old ISA code; rather than
pretending the code actually cares, I've dropped the (implicit) ignorance
of return values and marked it with a comment.

Signed-off-by: Andres Salomon <dilinger@queued.net>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Andres Salomon and committed by
Samuel Ortiz
de8255cc 419cdc54

+85 -125
+85 -125
drivers/i2c/busses/scx200_acb.c
··· 29 29 #include <linux/init.h> 30 30 #include <linux/i2c.h> 31 31 #include <linux/pci.h> 32 + #include <linux/platform_device.h> 32 33 #include <linux/delay.h> 33 34 #include <linux/mutex.h> 34 35 #include <linux/slab.h> ··· 41 40 42 41 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); 43 42 MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver"); 43 + MODULE_ALIAS("platform:cs5535-smb"); 44 44 MODULE_LICENSE("GPL"); 45 45 46 46 #define MAX_DEVICES 4 ··· 86 84 u8 *ptr; 87 85 char needs_reset; 88 86 unsigned len; 89 - 90 - /* PCI device info */ 91 - struct pci_dev *pdev; 92 - int bar; 93 87 }; 94 88 95 89 /* Register Definitions */ ··· 389 391 static struct scx200_acb_iface *scx200_acb_list; 390 392 static DEFINE_MUTEX(scx200_acb_list_mutex); 391 393 392 - static __init int scx200_acb_probe(struct scx200_acb_iface *iface) 394 + static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface) 393 395 { 394 396 u8 val; 395 397 ··· 425 427 return 0; 426 428 } 427 429 428 - static __init struct scx200_acb_iface *scx200_create_iface(const char *text, 430 + static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text, 429 431 struct device *dev, int index) 430 432 { 431 433 struct scx200_acb_iface *iface; ··· 450 452 return iface; 451 453 } 452 454 453 - static int __init scx200_acb_create(struct scx200_acb_iface *iface) 455 + static int __devinit scx200_acb_create(struct scx200_acb_iface *iface) 454 456 { 455 457 struct i2c_adapter *adapter; 456 458 int rc; ··· 470 472 return -ENODEV; 471 473 } 472 474 473 - mutex_lock(&scx200_acb_list_mutex); 474 - iface->next = scx200_acb_list; 475 - scx200_acb_list = iface; 476 - mutex_unlock(&scx200_acb_list_mutex); 475 + if (!adapter->dev.parent) { 476 + /* If there's no dev, we're tracking (ISA) ifaces manually */ 477 + mutex_lock(&scx200_acb_list_mutex); 478 + iface->next = scx200_acb_list; 479 + scx200_acb_list = iface; 480 + mutex_unlock(&scx200_acb_list_mutex); 481 + } 477 482 478 483 return 0; 479 484 } 480 485 481 - static __init int scx200_create_pci(const char *text, struct pci_dev *pdev, 482 - int bar) 486 + static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text, 487 + unsigned long base, int index, struct device *dev) 483 488 { 484 489 struct scx200_acb_iface *iface; 485 490 int rc; 486 491 487 - iface = scx200_create_iface(text, &pdev->dev, 0); 492 + iface = scx200_create_iface(text, dev, index); 488 493 489 494 if (iface == NULL) 490 - return -ENOMEM; 491 - 492 - iface->pdev = pdev; 493 - iface->bar = bar; 494 - 495 - rc = pci_enable_device_io(iface->pdev); 496 - if (rc) 497 - goto errout_free; 498 - 499 - rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name); 500 - if (rc) { 501 - printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n", 502 - iface->bar); 503 - goto errout_free; 504 - } 505 - 506 - iface->base = pci_resource_start(iface->pdev, iface->bar); 507 - rc = scx200_acb_create(iface); 508 - 509 - if (rc == 0) 510 - return 0; 511 - 512 - pci_release_region(iface->pdev, iface->bar); 513 - pci_dev_put(iface->pdev); 514 - errout_free: 515 - kfree(iface); 516 - return rc; 517 - } 518 - 519 - static int __init scx200_create_isa(const char *text, unsigned long base, 520 - int index) 521 - { 522 - struct scx200_acb_iface *iface; 523 - int rc; 524 - 525 - iface = scx200_create_iface(text, NULL, index); 526 - 527 - if (iface == NULL) 528 - return -ENOMEM; 495 + return NULL; 529 496 530 497 if (!request_region(base, 8, iface->adapter.name)) { 531 498 printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n", 532 499 base, base + 8 - 1); 533 - rc = -EBUSY; 534 500 goto errout_free; 535 501 } 536 502 ··· 502 540 rc = scx200_acb_create(iface); 503 541 504 542 if (rc == 0) 505 - return 0; 543 + return iface; 506 544 507 545 release_region(base, 8); 508 546 errout_free: 509 547 kfree(iface); 510 - return rc; 548 + return NULL; 511 549 } 512 550 513 - /* Driver data is an index into the scx200_data array that indicates 514 - * the name and the BAR where the I/O address resource is located. ISA 515 - * devices are flagged with a bar value of -1 */ 551 + static int __devinit scx200_probe(struct platform_device *pdev) 552 + { 553 + struct scx200_acb_iface *iface; 554 + struct resource *res; 516 555 517 - static const struct pci_device_id scx200_pci[] __initconst = { 518 - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE), 519 - .driver_data = 0 }, 520 - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE), 521 - .driver_data = 0 }, 522 - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA), 523 - .driver_data = 1 }, 524 - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA), 525 - .driver_data = 2 }, 556 + res = platform_get_resource(pdev, IORESOURCE_IO, 0); 557 + if (!res) { 558 + dev_err(&pdev->dev, "can't fetch device resource info\n"); 559 + return -ENODEV; 560 + } 561 + 562 + iface = scx200_create_dev("CS5535", res->start, 0, &pdev->dev); 563 + if (!iface) 564 + return -EIO; 565 + 566 + dev_info(&pdev->dev, "SCx200 device '%s' registered\n", 567 + iface->adapter.name); 568 + platform_set_drvdata(pdev, iface); 569 + 570 + return 0; 571 + } 572 + 573 + static void __devexit scx200_cleanup_iface(struct scx200_acb_iface *iface) 574 + { 575 + i2c_del_adapter(&iface->adapter); 576 + release_region(iface->base, 8); 577 + kfree(iface); 578 + } 579 + 580 + static int __devexit scx200_remove(struct platform_device *pdev) 581 + { 582 + struct scx200_acb_iface *iface; 583 + 584 + iface = platform_get_drvdata(pdev); 585 + platform_set_drvdata(pdev, NULL); 586 + scx200_cleanup_iface(iface); 587 + 588 + return 0; 589 + } 590 + 591 + static struct platform_driver scx200_pci_drv = { 592 + .driver = { 593 + .name = "cs5535-smb", 594 + .owner = THIS_MODULE, 595 + }, 596 + .probe = scx200_probe, 597 + .remove = __devexit_p(scx200_remove), 598 + }; 599 + 600 + static const struct pci_device_id scx200_isa[] __initconst = { 601 + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, 602 + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, 526 603 { 0, } 527 604 }; 528 605 529 - static struct { 530 - const char *name; 531 - int bar; 532 - } scx200_data[] = { 533 - { "SCx200", -1 }, 534 - { "CS5535", 0 }, 535 - { "CS5536", 0 } 536 - }; 537 - 538 - static __init int scx200_scan_pci(void) 606 + static __init void scx200_scan_isa(void) 539 607 { 540 - int data, dev; 541 - int rc = -ENODEV; 542 - struct pci_dev *pdev; 608 + int i; 543 609 544 - for(dev = 0; dev < ARRAY_SIZE(scx200_pci); dev++) { 545 - pdev = pci_get_device(scx200_pci[dev].vendor, 546 - scx200_pci[dev].device, NULL); 610 + if (!pci_dev_present(scx200_isa)) 611 + return; 547 612 548 - if (pdev == NULL) 613 + for (i = 0; i < MAX_DEVICES; ++i) { 614 + if (base[i] == 0) 549 615 continue; 550 616 551 - data = scx200_pci[dev].driver_data; 552 - 553 - /* if .bar is greater or equal to zero, this is a 554 - * PCI device - otherwise, we assume 555 - that the ports are ISA based 556 - */ 557 - 558 - if (scx200_data[data].bar >= 0) 559 - rc = scx200_create_pci(scx200_data[data].name, pdev, 560 - scx200_data[data].bar); 561 - else { 562 - int i; 563 - 564 - pci_dev_put(pdev); 565 - for (i = 0; i < MAX_DEVICES; ++i) { 566 - if (base[i] == 0) 567 - continue; 568 - 569 - rc = scx200_create_isa(scx200_data[data].name, 570 - base[i], 571 - i); 572 - } 573 - } 574 - 575 - break; 617 + /* XXX: should we care about failures? */ 618 + scx200_create_dev("SCx200", base[i], i, NULL); 576 619 } 577 - 578 - return rc; 579 620 } 580 621 581 622 static int __init scx200_acb_init(void) 582 623 { 583 - int rc; 584 - 585 624 pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); 586 625 587 - rc = scx200_scan_pci(); 626 + /* First scan for ISA-based devices */ 627 + scx200_scan_isa(); /* XXX: should we care about errors? */ 588 628 589 629 /* If at least one bus was created, init must succeed */ 590 630 if (scx200_acb_list) 591 631 return 0; 592 - return rc; 632 + 633 + /* No ISA devices; register the platform driver for PCI-based devices */ 634 + return platform_driver_register(&scx200_pci_drv); 593 635 } 594 636 595 637 static void __exit scx200_acb_cleanup(void) 596 638 { 597 639 struct scx200_acb_iface *iface; 598 640 641 + platform_driver_unregister(&scx200_pci_drv); 642 + 599 643 mutex_lock(&scx200_acb_list_mutex); 600 644 while ((iface = scx200_acb_list) != NULL) { 601 645 scx200_acb_list = iface->next; 602 646 mutex_unlock(&scx200_acb_list_mutex); 603 647 604 - i2c_del_adapter(&iface->adapter); 648 + scx200_cleanup_iface(iface); 605 649 606 - if (iface->pdev) { 607 - pci_release_region(iface->pdev, iface->bar); 608 - pci_dev_put(iface->pdev); 609 - } 610 - else 611 - release_region(iface->base, 8); 612 - 613 - kfree(iface); 614 650 mutex_lock(&scx200_acb_list_mutex); 615 651 } 616 652 mutex_unlock(&scx200_acb_list_mutex);