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