diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-ibm_iic.c')
-rw-r--r-- | drivers/i2c/busses/i2c-ibm_iic.c | 197 |
1 files changed, 191 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 22bb247d0e60..85dbf34382e1 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c | |||
@@ -6,6 +6,9 @@ | |||
6 | * Copyright (c) 2003, 2004 Zultys Technologies. | 6 | * Copyright (c) 2003, 2004 Zultys Technologies. |
7 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | 7 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> |
8 | * | 8 | * |
9 | * Copyright (c) 2008 PIKA Technologies | ||
10 | * Sean MacLennan <smaclennan@pikatech.com> | ||
11 | * | ||
9 | * Based on original work by | 12 | * Based on original work by |
10 | * Ian DaSilva <idasilva@mvista.com> | 13 | * Ian DaSilva <idasilva@mvista.com> |
11 | * Armin Kuster <akuster@mvista.com> | 14 | * Armin Kuster <akuster@mvista.com> |
@@ -39,12 +42,17 @@ | |||
39 | #include <asm/io.h> | 42 | #include <asm/io.h> |
40 | #include <linux/i2c.h> | 43 | #include <linux/i2c.h> |
41 | #include <linux/i2c-id.h> | 44 | #include <linux/i2c-id.h> |
45 | |||
46 | #ifdef CONFIG_IBM_OCP | ||
42 | #include <asm/ocp.h> | 47 | #include <asm/ocp.h> |
43 | #include <asm/ibm4xx.h> | 48 | #include <asm/ibm4xx.h> |
49 | #else | ||
50 | #include <linux/of_platform.h> | ||
51 | #endif | ||
44 | 52 | ||
45 | #include "i2c-ibm_iic.h" | 53 | #include "i2c-ibm_iic.h" |
46 | 54 | ||
47 | #define DRIVER_VERSION "2.1" | 55 | #define DRIVER_VERSION "2.2" |
48 | 56 | ||
49 | MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); | 57 | MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); |
50 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
@@ -650,13 +658,14 @@ static inline u8 iic_clckdiv(unsigned int opb) | |||
650 | opb /= 1000000; | 658 | opb /= 1000000; |
651 | 659 | ||
652 | if (opb < 20 || opb > 150){ | 660 | if (opb < 20 || opb > 150){ |
653 | printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n", | 661 | printk(KERN_WARNING "ibm-iic: invalid OPB clock frequency %u MHz\n", |
654 | opb); | 662 | opb); |
655 | opb = opb < 20 ? 20 : 150; | 663 | opb = opb < 20 ? 20 : 150; |
656 | } | 664 | } |
657 | return (u8)((opb + 9) / 10 - 1); | 665 | return (u8)((opb + 9) / 10 - 1); |
658 | } | 666 | } |
659 | 667 | ||
668 | #ifdef CONFIG_IBM_OCP | ||
660 | /* | 669 | /* |
661 | * Register single IIC interface | 670 | * Register single IIC interface |
662 | */ | 671 | */ |
@@ -672,7 +681,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){ | |||
672 | ocp->def->index); | 681 | ocp->def->index); |
673 | 682 | ||
674 | if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) { | 683 | if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) { |
675 | printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n", | 684 | printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n", |
676 | ocp->def->index); | 685 | ocp->def->index); |
677 | return -ENOMEM; | 686 | return -ENOMEM; |
678 | } | 687 | } |
@@ -687,7 +696,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){ | |||
687 | } | 696 | } |
688 | 697 | ||
689 | if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){ | 698 | if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){ |
690 | printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n", | 699 | printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n", |
691 | dev->idx); | 700 | dev->idx); |
692 | ret = -ENXIO; | 701 | ret = -ENXIO; |
693 | goto fail2; | 702 | goto fail2; |
@@ -745,7 +754,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){ | |||
745 | adap->nr = dev->idx >= 0 ? dev->idx : 0; | 754 | adap->nr = dev->idx >= 0 ? dev->idx : 0; |
746 | 755 | ||
747 | if ((ret = i2c_add_numbered_adapter(adap)) < 0) { | 756 | if ((ret = i2c_add_numbered_adapter(adap)) < 0) { |
748 | printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n", | 757 | printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n", |
749 | dev->idx); | 758 | dev->idx); |
750 | goto fail; | 759 | goto fail; |
751 | } | 760 | } |
@@ -778,7 +787,7 @@ static void __devexit iic_remove(struct ocp_device *ocp) | |||
778 | struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp); | 787 | struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp); |
779 | BUG_ON(dev == NULL); | 788 | BUG_ON(dev == NULL); |
780 | if (i2c_del_adapter(&dev->adap)){ | 789 | if (i2c_del_adapter(&dev->adap)){ |
781 | printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n", | 790 | printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n", |
782 | dev->idx); | 791 | dev->idx); |
783 | /* That's *very* bad, just shutdown IRQ ... */ | 792 | /* That's *very* bad, just shutdown IRQ ... */ |
784 | if (dev->irq >= 0){ | 793 | if (dev->irq >= 0){ |
@@ -828,5 +837,181 @@ static void __exit iic_exit(void) | |||
828 | ocp_unregister_driver(&ibm_iic_driver); | 837 | ocp_unregister_driver(&ibm_iic_driver); |
829 | } | 838 | } |
830 | 839 | ||
840 | #else /* !CONFIG_IBM_OCP */ | ||
841 | |||
842 | static int __devinit iic_request_irq(struct of_device *ofdev, | ||
843 | struct ibm_iic_private *dev) | ||
844 | { | ||
845 | struct device_node *np = ofdev->node; | ||
846 | int irq; | ||
847 | |||
848 | if (iic_force_poll) | ||
849 | return NO_IRQ; | ||
850 | |||
851 | irq = irq_of_parse_and_map(np, 0); | ||
852 | if (irq == NO_IRQ) { | ||
853 | dev_err(&ofdev->dev, "irq_of_parse_and_map failed\n"); | ||
854 | return NO_IRQ; | ||
855 | } | ||
856 | |||
857 | /* Disable interrupts until we finish initialization, assumes | ||
858 | * level-sensitive IRQ setup... | ||
859 | */ | ||
860 | iic_interrupt_mode(dev, 0); | ||
861 | if (request_irq(irq, iic_handler, 0, "IBM IIC", dev)) { | ||
862 | dev_err(&ofdev->dev, "request_irq %d failed\n", irq); | ||
863 | /* Fallback to the polling mode */ | ||
864 | return NO_IRQ; | ||
865 | } | ||
866 | |||
867 | return irq; | ||
868 | } | ||
869 | |||
870 | /* | ||
871 | * Register single IIC interface | ||
872 | */ | ||
873 | static int __devinit iic_probe(struct of_device *ofdev, | ||
874 | const struct of_device_id *match) | ||
875 | { | ||
876 | struct device_node *np = ofdev->node; | ||
877 | struct ibm_iic_private *dev; | ||
878 | struct i2c_adapter *adap; | ||
879 | const u32 *indexp, *freq; | ||
880 | int ret; | ||
881 | |||
882 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
883 | if (!dev) { | ||
884 | dev_err(&ofdev->dev, "failed to allocate device data\n"); | ||
885 | return -ENOMEM; | ||
886 | } | ||
887 | |||
888 | dev_set_drvdata(&ofdev->dev, dev); | ||
889 | |||
890 | indexp = of_get_property(np, "index", NULL); | ||
891 | if (!indexp) { | ||
892 | dev_err(&ofdev->dev, "no index specified\n"); | ||
893 | ret = -EINVAL; | ||
894 | goto error_cleanup; | ||
895 | } | ||
896 | dev->idx = *indexp; | ||
897 | |||
898 | dev->vaddr = of_iomap(np, 0); | ||
899 | if (dev->vaddr == NULL) { | ||
900 | dev_err(&ofdev->dev, "failed to iomap device\n"); | ||
901 | ret = -ENXIO; | ||
902 | goto error_cleanup; | ||
903 | } | ||
904 | |||
905 | init_waitqueue_head(&dev->wq); | ||
906 | |||
907 | dev->irq = iic_request_irq(ofdev, dev); | ||
908 | if (dev->irq == NO_IRQ) | ||
909 | dev_warn(&ofdev->dev, "using polling mode\n"); | ||
910 | |||
911 | /* Board specific settings */ | ||
912 | if (iic_force_fast || of_get_property(np, "fast-mode", NULL)) | ||
913 | dev->fast_mode = 1; | ||
914 | |||
915 | freq = of_get_property(np, "clock-frequency", NULL); | ||
916 | if (freq == NULL) { | ||
917 | freq = of_get_property(np->parent, "clock-frequency", NULL); | ||
918 | if (freq == NULL) { | ||
919 | dev_err(&ofdev->dev, "Unable to get bus frequency\n"); | ||
920 | ret = -EINVAL; | ||
921 | goto error_cleanup; | ||
922 | } | ||
923 | } | ||
924 | |||
925 | dev->clckdiv = iic_clckdiv(*freq); | ||
926 | dev_dbg(&ofdev->dev, "clckdiv = %d\n", dev->clckdiv); | ||
927 | |||
928 | /* Initialize IIC interface */ | ||
929 | iic_dev_init(dev); | ||
930 | |||
931 | /* Register it with i2c layer */ | ||
932 | adap = &dev->adap; | ||
933 | adap->dev.parent = &ofdev->dev; | ||
934 | strlcpy(adap->name, "IBM IIC", sizeof(adap->name)); | ||
935 | i2c_set_adapdata(adap, dev); | ||
936 | adap->id = I2C_HW_OCP; | ||
937 | adap->class = I2C_CLASS_HWMON; | ||
938 | adap->algo = &iic_algo; | ||
939 | adap->timeout = 1; | ||
940 | adap->nr = dev->idx; | ||
941 | |||
942 | ret = i2c_add_numbered_adapter(adap); | ||
943 | if (ret < 0) { | ||
944 | dev_err(&ofdev->dev, "failed to register i2c adapter\n"); | ||
945 | goto error_cleanup; | ||
946 | } | ||
947 | |||
948 | dev_info(&ofdev->dev, "using %s mode\n", | ||
949 | dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); | ||
950 | |||
951 | return 0; | ||
952 | |||
953 | error_cleanup: | ||
954 | if (dev->irq != NO_IRQ) { | ||
955 | iic_interrupt_mode(dev, 0); | ||
956 | free_irq(dev->irq, dev); | ||
957 | } | ||
958 | |||
959 | if (dev->vaddr) | ||
960 | iounmap(dev->vaddr); | ||
961 | |||
962 | dev_set_drvdata(&ofdev->dev, NULL); | ||
963 | kfree(dev); | ||
964 | return ret; | ||
965 | } | ||
966 | |||
967 | /* | ||
968 | * Cleanup initialized IIC interface | ||
969 | */ | ||
970 | static int __devexit iic_remove(struct of_device *ofdev) | ||
971 | { | ||
972 | struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); | ||
973 | |||
974 | dev_set_drvdata(&ofdev->dev, NULL); | ||
975 | |||
976 | i2c_del_adapter(&dev->adap); | ||
977 | |||
978 | if (dev->irq != NO_IRQ) { | ||
979 | iic_interrupt_mode(dev, 0); | ||
980 | free_irq(dev->irq, dev); | ||
981 | } | ||
982 | |||
983 | iounmap(dev->vaddr); | ||
984 | kfree(dev); | ||
985 | |||
986 | return 0; | ||
987 | } | ||
988 | |||
989 | static const struct of_device_id ibm_iic_match[] = { | ||
990 | { .compatible = "ibm,iic-405ex", }, | ||
991 | { .compatible = "ibm,iic-405gp", }, | ||
992 | { .compatible = "ibm,iic-440gp", }, | ||
993 | { .compatible = "ibm,iic-440gpx", }, | ||
994 | { .compatible = "ibm,iic-440grx", }, | ||
995 | {} | ||
996 | }; | ||
997 | |||
998 | static struct of_platform_driver ibm_iic_driver = { | ||
999 | .name = "ibm-iic", | ||
1000 | .match_table = ibm_iic_match, | ||
1001 | .probe = iic_probe, | ||
1002 | .remove = __devexit_p(iic_remove), | ||
1003 | }; | ||
1004 | |||
1005 | static int __init iic_init(void) | ||
1006 | { | ||
1007 | return of_register_platform_driver(&ibm_iic_driver); | ||
1008 | } | ||
1009 | |||
1010 | static void __exit iic_exit(void) | ||
1011 | { | ||
1012 | of_unregister_platform_driver(&ibm_iic_driver); | ||
1013 | } | ||
1014 | #endif /* CONFIG_IBM_OCP */ | ||
1015 | |||
831 | module_init(iic_init); | 1016 | module_init(iic_init); |
832 | module_exit(iic_exit); | 1017 | module_exit(iic_exit); |