diff options
Diffstat (limited to 'drivers/sbus')
-rw-r--r-- | drivers/sbus/char/envctrl.c | 147 |
1 files changed, 79 insertions, 68 deletions
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index a408402426f8..ea8c35cbffd3 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: envctrl.c,v 1.25 2002/01/15 09:01:26 davem Exp $ | 1 | /* envctrl.c: Temperature and Fan monitoring on Machines providing it. |
2 | * envctrl.c: Temperature and Fan monitoring on Machines providing it. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) |
5 | * Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com) | 4 | * Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com) |
@@ -28,12 +27,16 @@ | |||
28 | #include <linux/kmod.h> | 27 | #include <linux/kmod.h> |
29 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
30 | #include <linux/smp_lock.h> | 29 | #include <linux/smp_lock.h> |
30 | #include <linux/of.h> | ||
31 | #include <linux/of_device.h> | ||
31 | 32 | ||
32 | #include <asm/ebus.h> | ||
33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
34 | #include <asm/envctrl.h> | 34 | #include <asm/envctrl.h> |
35 | #include <asm/io.h> | 35 | #include <asm/io.h> |
36 | 36 | ||
37 | #define DRIVER_NAME "envctrl" | ||
38 | #define PFX DRIVER_NAME ": " | ||
39 | |||
37 | #define ENVCTRL_MINOR 162 | 40 | #define ENVCTRL_MINOR 162 |
38 | 41 | ||
39 | #define PCF8584_ADDRESS 0x55 | 42 | #define PCF8584_ADDRESS 0x55 |
@@ -193,7 +196,7 @@ static void envtrl_i2c_test_pin(void) | |||
193 | } | 196 | } |
194 | 197 | ||
195 | if (limit <= 0) | 198 | if (limit <= 0) |
196 | printk(KERN_INFO "envctrl: Pin status will not clear.\n"); | 199 | printk(KERN_INFO PFX "Pin status will not clear.\n"); |
197 | } | 200 | } |
198 | 201 | ||
199 | /* Function Description: Test busy bit. | 202 | /* Function Description: Test busy bit. |
@@ -211,7 +214,7 @@ static void envctrl_i2c_test_bb(void) | |||
211 | } | 214 | } |
212 | 215 | ||
213 | if (limit <= 0) | 216 | if (limit <= 0) |
214 | printk(KERN_INFO "envctrl: Busy bit will not clear.\n"); | 217 | printk(KERN_INFO PFX "Busy bit will not clear.\n"); |
215 | } | 218 | } |
216 | 219 | ||
217 | /* Function Description: Send the address for a read access. | 220 | /* Function Description: Send the address for a read access. |
@@ -858,11 +861,10 @@ static void envctrl_init_voltage_status(struct i2c_child_t *pchild) | |||
858 | /* Function Description: Initialize i2c child device. | 861 | /* Function Description: Initialize i2c child device. |
859 | * Return: None. | 862 | * Return: None. |
860 | */ | 863 | */ |
861 | static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, | 864 | static void envctrl_init_i2c_child(struct device_node *dp, |
862 | struct i2c_child_t *pchild) | 865 | struct i2c_child_t *pchild) |
863 | { | 866 | { |
864 | int len, i, tbls_size = 0; | 867 | int len, i, tbls_size = 0; |
865 | struct device_node *dp = edev_child->prom_node; | ||
866 | const void *pval; | 868 | const void *pval; |
867 | 869 | ||
868 | /* Get device address. */ | 870 | /* Get device address. */ |
@@ -882,12 +884,12 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, | |||
882 | 884 | ||
883 | pchild->tables = kmalloc(tbls_size, GFP_KERNEL); | 885 | pchild->tables = kmalloc(tbls_size, GFP_KERNEL); |
884 | if (pchild->tables == NULL){ | 886 | if (pchild->tables == NULL){ |
885 | printk("envctrl: Failed to allocate table.\n"); | 887 | printk(KERN_ERR PFX "Failed to allocate table.\n"); |
886 | return; | 888 | return; |
887 | } | 889 | } |
888 | pval = of_get_property(dp, "tables", &len); | 890 | pval = of_get_property(dp, "tables", &len); |
889 | if (!pval || len <= 0) { | 891 | if (!pval || len <= 0) { |
890 | printk("envctrl: Failed to get table.\n"); | 892 | printk(KERN_ERR PFX "Failed to get table.\n"); |
891 | return; | 893 | return; |
892 | } | 894 | } |
893 | memcpy(pchild->tables, pval, len); | 895 | memcpy(pchild->tables, pval, len); |
@@ -993,14 +995,14 @@ static int kenvctrld(void *__unused) | |||
993 | struct i2c_child_t *cputemp; | 995 | struct i2c_child_t *cputemp; |
994 | 996 | ||
995 | if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) { | 997 | if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) { |
996 | printk(KERN_ERR | 998 | printk(KERN_ERR PFX |
997 | "envctrl: kenvctrld unable to monitor CPU temp-- exiting\n"); | 999 | "kenvctrld unable to monitor CPU temp-- exiting\n"); |
998 | return -ENODEV; | 1000 | return -ENODEV; |
999 | } | 1001 | } |
1000 | 1002 | ||
1001 | poll_interval = 5000; /* TODO env_mon_interval */ | 1003 | poll_interval = 5000; /* TODO env_mon_interval */ |
1002 | 1004 | ||
1003 | printk(KERN_INFO "envctrl: %s starting...\n", current->comm); | 1005 | printk(KERN_INFO PFX "%s starting...\n", current->comm); |
1004 | for (;;) { | 1006 | for (;;) { |
1005 | msleep_interruptible(poll_interval); | 1007 | msleep_interruptible(poll_interval); |
1006 | 1008 | ||
@@ -1022,54 +1024,35 @@ static int kenvctrld(void *__unused) | |||
1022 | } | 1024 | } |
1023 | } | 1025 | } |
1024 | } | 1026 | } |
1025 | printk(KERN_INFO "envctrl: %s exiting...\n", current->comm); | 1027 | printk(KERN_INFO PFX "%s exiting...\n", current->comm); |
1026 | return 0; | 1028 | return 0; |
1027 | } | 1029 | } |
1028 | 1030 | ||
1029 | static int __init envctrl_init(void) | 1031 | static int __devinit envctrl_probe(struct of_device *op, |
1032 | const struct of_device_id *match) | ||
1030 | { | 1033 | { |
1031 | struct linux_ebus *ebus = NULL; | 1034 | struct device_node *dp; |
1032 | struct linux_ebus_device *edev = NULL; | 1035 | int index, err; |
1033 | struct linux_ebus_child *edev_child = NULL; | ||
1034 | int err, i = 0; | ||
1035 | |||
1036 | for_each_ebus(ebus) { | ||
1037 | for_each_ebusdev(edev, ebus) { | ||
1038 | if (!strcmp(edev->prom_node->name, "bbc")) { | ||
1039 | /* If we find a boot-bus controller node, | ||
1040 | * then this envctrl driver is not for us. | ||
1041 | */ | ||
1042 | return -ENODEV; | ||
1043 | } | ||
1044 | } | ||
1045 | } | ||
1046 | 1036 | ||
1047 | /* Traverse through ebus and ebus device list for i2c device and | 1037 | if (i2c) |
1048 | * adc and gpio nodes. | 1038 | return -EINVAL; |
1049 | */ | 1039 | |
1050 | for_each_ebus(ebus) { | 1040 | i2c = of_ioremap(&op->resource[0], 0, 0x2, DRIVER_NAME); |
1051 | for_each_ebusdev(edev, ebus) { | 1041 | if (!i2c) |
1052 | if (!strcmp(edev->prom_node->name, "i2c")) { | 1042 | return -ENOMEM; |
1053 | i2c = ioremap(edev->resource[0].start, 0x2); | 1043 | |
1054 | for_each_edevchild(edev, edev_child) { | 1044 | index = 0; |
1055 | if (!strcmp("gpio", edev_child->prom_node->name)) { | 1045 | dp = op->node->child; |
1056 | i2c_childlist[i].i2ctype = I2C_GPIO; | 1046 | while (dp) { |
1057 | envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); | 1047 | if (!strcmp(dp->name, "gpio")) { |
1058 | } | 1048 | i2c_childlist[index].i2ctype = I2C_GPIO; |
1059 | if (!strcmp("adc", edev_child->prom_node->name)) { | 1049 | envctrl_init_i2c_child(dp, &(i2c_childlist[index++])); |
1060 | i2c_childlist[i].i2ctype = I2C_ADC; | 1050 | } else if (!strcmp(dp->name, "adc")) { |
1061 | envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); | 1051 | i2c_childlist[index].i2ctype = I2C_ADC; |
1062 | } | 1052 | envctrl_init_i2c_child(dp, &(i2c_childlist[index++])); |
1063 | } | ||
1064 | goto done; | ||
1065 | } | ||
1066 | } | 1053 | } |
1067 | } | ||
1068 | 1054 | ||
1069 | done: | 1055 | dp = dp->sibling; |
1070 | if (!edev) { | ||
1071 | printk("envctrl: I2C device not found.\n"); | ||
1072 | return -ENODEV; | ||
1073 | } | 1056 | } |
1074 | 1057 | ||
1075 | /* Set device address. */ | 1058 | /* Set device address. */ |
@@ -1087,7 +1070,7 @@ done: | |||
1087 | /* Register the device as a minor miscellaneous device. */ | 1070 | /* Register the device as a minor miscellaneous device. */ |
1088 | err = misc_register(&envctrl_dev); | 1071 | err = misc_register(&envctrl_dev); |
1089 | if (err) { | 1072 | if (err) { |
1090 | printk("envctrl: Unable to get misc minor %d\n", | 1073 | printk(KERN_ERR PFX "Unable to get misc minor %d\n", |
1091 | envctrl_dev.minor); | 1074 | envctrl_dev.minor); |
1092 | goto out_iounmap; | 1075 | goto out_iounmap; |
1093 | } | 1076 | } |
@@ -1096,12 +1079,12 @@ done: | |||
1096 | * a next child device, so we decrement before reverse-traversal of | 1079 | * a next child device, so we decrement before reverse-traversal of |
1097 | * child devices. | 1080 | * child devices. |
1098 | */ | 1081 | */ |
1099 | printk("envctrl: initialized "); | 1082 | printk(KERN_INFO PFX "Initialized "); |
1100 | for (--i; i >= 0; --i) { | 1083 | for (--index; index >= 0; --index) { |
1101 | printk("[%s 0x%lx]%s", | 1084 | printk("[%s 0x%lx]%s", |
1102 | (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") : | 1085 | (I2C_ADC == i2c_childlist[index].i2ctype) ? "adc" : |
1103 | ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")), | 1086 | ((I2C_GPIO == i2c_childlist[index].i2ctype) ? "gpio" : "unknown"), |
1104 | i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); | 1087 | i2c_childlist[index].addr, (0 == index) ? "\n" : " "); |
1105 | } | 1088 | } |
1106 | 1089 | ||
1107 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); | 1090 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); |
@@ -1115,26 +1098,54 @@ done: | |||
1115 | out_deregister: | 1098 | out_deregister: |
1116 | misc_deregister(&envctrl_dev); | 1099 | misc_deregister(&envctrl_dev); |
1117 | out_iounmap: | 1100 | out_iounmap: |
1118 | iounmap(i2c); | 1101 | of_iounmap(&op->resource[0], i2c, 0x2); |
1119 | for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) | 1102 | for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++) |
1120 | kfree(i2c_childlist[i].tables); | 1103 | kfree(i2c_childlist[index].tables); |
1121 | 1104 | ||
1122 | return err; | 1105 | return err; |
1123 | } | 1106 | } |
1124 | 1107 | ||
1125 | static void __exit envctrl_cleanup(void) | 1108 | static int __devexit envctrl_remove(struct of_device *op) |
1126 | { | 1109 | { |
1127 | int i; | 1110 | int index; |
1128 | 1111 | ||
1129 | kthread_stop(kenvctrld_task); | 1112 | kthread_stop(kenvctrld_task); |
1130 | 1113 | ||
1131 | iounmap(i2c); | 1114 | of_iounmap(&op->resource[0], i2c, 0x2); |
1132 | misc_deregister(&envctrl_dev); | 1115 | misc_deregister(&envctrl_dev); |
1133 | 1116 | ||
1134 | for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) | 1117 | for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++) |
1135 | kfree(i2c_childlist[i].tables); | 1118 | kfree(i2c_childlist[index].tables); |
1119 | |||
1120 | return 0; | ||
1121 | } | ||
1122 | |||
1123 | static struct of_device_id envctrl_match[] = { | ||
1124 | { | ||
1125 | .name = "i2c", | ||
1126 | .compatible = "i2cpcf,8584", | ||
1127 | }, | ||
1128 | {}, | ||
1129 | }; | ||
1130 | MODULE_DEVICE_TABLE(of, envctrl_match); | ||
1131 | |||
1132 | static struct of_platform_driver envctrl_driver = { | ||
1133 | .name = DRIVER_NAME, | ||
1134 | .match_table = envctrl_match, | ||
1135 | .probe = envctrl_probe, | ||
1136 | .remove = __devexit_p(envctrl_remove), | ||
1137 | }; | ||
1138 | |||
1139 | static int __init envctrl_init(void) | ||
1140 | { | ||
1141 | return of_register_driver(&envctrl_driver, &of_bus_type); | ||
1142 | } | ||
1143 | |||
1144 | static void __exit envctrl_exit(void) | ||
1145 | { | ||
1146 | of_unregister_driver(&envctrl_driver); | ||
1136 | } | 1147 | } |
1137 | 1148 | ||
1138 | module_init(envctrl_init); | 1149 | module_init(envctrl_init); |
1139 | module_exit(envctrl_cleanup); | 1150 | module_exit(envctrl_exit); |
1140 | MODULE_LICENSE("GPL"); | 1151 | MODULE_LICENSE("GPL"); |