aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sbus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sbus')
-rw-r--r--drivers/sbus/char/envctrl.c147
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 */
861static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, 864static 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
1029static int __init envctrl_init(void) 1031static 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
1069done: 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:
1115out_deregister: 1098out_deregister:
1116 misc_deregister(&envctrl_dev); 1099 misc_deregister(&envctrl_dev);
1117out_iounmap: 1100out_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
1125static void __exit envctrl_cleanup(void) 1108static 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
1123static struct of_device_id envctrl_match[] = {
1124 {
1125 .name = "i2c",
1126 .compatible = "i2cpcf,8584",
1127 },
1128 {},
1129};
1130MODULE_DEVICE_TABLE(of, envctrl_match);
1131
1132static 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
1139static int __init envctrl_init(void)
1140{
1141 return of_register_driver(&envctrl_driver, &of_bus_type);
1142}
1143
1144static void __exit envctrl_exit(void)
1145{
1146 of_unregister_driver(&envctrl_driver);
1136} 1147}
1137 1148
1138module_init(envctrl_init); 1149module_init(envctrl_init);
1139module_exit(envctrl_cleanup); 1150module_exit(envctrl_exit);
1140MODULE_LICENSE("GPL"); 1151MODULE_LICENSE("GPL");