diff options
| -rw-r--r-- | drivers/i2c/busses/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-ibm_iic.c | 187 |
2 files changed, 187 insertions, 2 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 51de2ccc1519..1577bcad288a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
| @@ -246,7 +246,7 @@ config I2C_PIIX4 | |||
| 246 | 246 | ||
| 247 | config I2C_IBM_IIC | 247 | config I2C_IBM_IIC |
| 248 | tristate "IBM PPC 4xx on-chip I2C interface" | 248 | tristate "IBM PPC 4xx on-chip I2C interface" |
| 249 | depends on IBM_OCP | 249 | depends on 4xx |
| 250 | help | 250 | help |
| 251 | Say Y here if you want to use IIC peripheral found on | 251 | Say Y here if you want to use IIC peripheral found on |
| 252 | embedded IBM PPC 4xx based systems. | 252 | embedded IBM PPC 4xx based systems. |
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index b330a0c9a6a5..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"); |
| @@ -657,6 +665,7 @@ static inline u8 iic_clckdiv(unsigned int opb) | |||
| 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 | */ |
| @@ -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); |
