aboutsummaryrefslogtreecommitdiff
path: root/drivers/sbus/char/envctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sbus/char/envctrl.c')
-rw-r--r--drivers/sbus/char/envctrl.c262
1 files changed, 126 insertions, 136 deletions
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index b0cc3c2588f..af15a2fdab5 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -1,5 +1,4 @@
-/* $Id: envctrl.c,v 1.25 2002/01/15 09:01:26 davem Exp $
- * envctrl.c: Temperature and Fan monitoring on Machines providing it.
+/* envctrl.c: Temperature and Fan monitoring on Machines providing it.
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com)
@@ -19,25 +18,23 @@
* Daniele Bellucci <bellucda@tiscali.it>
*/
-#define __KERNEL_SYSCALLS__
-static int errno;
-
-#include <linux/config.h>
#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/kthread.h>
-#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/ioport.h>
-#include <linux/init.h>
#include <linux/miscdevice.h>
-#include <linux/mm.h>
+#include <linux/kmod.h>
+#include <linux/reboot.h>
#include <linux/slab.h>
-#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
-#include <asm/ebus.h>
#include <asm/uaccess.h>
#include <asm/envctrl.h>
+#include <asm/io.h>
+
+#define DRIVER_NAME "envctrl"
+#define PFX DRIVER_NAME ": "
#define ENVCTRL_MINOR 162
@@ -94,11 +91,11 @@ static int errno;
#define ENVCTRL_CPUTEMP_MON 1 /* cpu temperature monitor */
#define ENVCTRL_CPUVOLTAGE_MON 2 /* voltage monitor */
#define ENVCTRL_FANSTAT_MON 3 /* fan status monitor */
-#define ENVCTRL_ETHERTEMP_MON 4 /* ethernet temperarture */
+#define ENVCTRL_ETHERTEMP_MON 4 /* ethernet temperature */
/* monitor */
#define ENVCTRL_VOLTAGESTAT_MON 5 /* voltage status monitor */
#define ENVCTRL_MTHRBDTEMP_MON 6 /* motherboard temperature */
-#define ENVCTRL_SCSITEMP_MON 7 /* scsi temperarture */
+#define ENVCTRL_SCSITEMP_MON 7 /* scsi temperature */
#define ENVCTRL_GLOBALADDR_MON 8 /* global address */
/* Child device type.
@@ -198,7 +195,7 @@ static void envtrl_i2c_test_pin(void)
}
if (limit <= 0)
- printk(KERN_INFO "envctrl: Pin status will not clear.\n");
+ printk(KERN_INFO PFX "Pin status will not clear.\n");
}
/* Function Description: Test busy bit.
@@ -216,7 +213,7 @@ static void envctrl_i2c_test_bb(void)
}
if (limit <= 0)
- printk(KERN_INFO "envctrl: Busy bit will not clear.\n");
+ printk(KERN_INFO PFX "Busy bit will not clear.\n");
}
/* Function Description: Send the address for a read access.
@@ -355,7 +352,7 @@ static int envctrl_i2c_data_translate(unsigned char data, int translate_type,
default:
break;
- };
+ }
return len;
}
@@ -646,7 +643,7 @@ envctrl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
default:
break;
- };
+ }
return ret;
}
@@ -654,9 +651,8 @@ envctrl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
/* Function Description: Command what to read. Mapped to user ioctl().
* Return: Gives 0 for implemented commands, -EINVAL otherwise.
*/
-static int
-envctrl_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long
+envctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
char __user *infobuf;
@@ -690,7 +686,7 @@ envctrl_ioctl(struct inode *inode, struct file *file,
default:
return -EINVAL;
- };
+ }
return 0;
}
@@ -714,12 +710,16 @@ envctrl_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations envctrl_fops = {
- .owner = THIS_MODULE,
- .read = envctrl_read,
- .ioctl = envctrl_ioctl,
- .open = envctrl_open,
- .release = envctrl_release,
+static const struct file_operations envctrl_fops = {
+ .owner = THIS_MODULE,
+ .read = envctrl_read,
+ .unlocked_ioctl = envctrl_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = envctrl_ioctl,
+#endif
+ .open = envctrl_open,
+ .release = envctrl_release,
+ .llseek = noop_llseek,
};
static struct miscdevice envctrl_dev = {
@@ -732,7 +732,7 @@ static struct miscdevice envctrl_dev = {
* Return: None.
*/
static void envctrl_set_mon(struct i2c_child_t *pchild,
- char *chnl_desc,
+ const char *chnl_desc,
int chnl_no)
{
/* Firmware only has temperature type. It does not distinguish
@@ -766,16 +766,14 @@ static void envctrl_set_mon(struct i2c_child_t *pchild,
* decoding tables, monitor type, optional properties.
* Return: None.
*/
-static void envctrl_init_adc(struct i2c_child_t *pchild, int node)
+static void envctrl_init_adc(struct i2c_child_t *pchild, struct device_node *dp)
{
- char chnls_desc[CHANNEL_DESC_SZ];
int i = 0, len;
- char *pos = chnls_desc;
+ const char *pos;
+ const unsigned int *pval;
/* Firmware describe channels into a stream separated by a '\0'. */
- len = prom_getproperty(node, "channels-description", chnls_desc,
- CHANNEL_DESC_SZ);
- chnls_desc[CHANNEL_DESC_SZ - 1] = '\0';
+ pos = of_get_property(dp, "channels-description", &len);
while (len > 0) {
int l = strlen(pos) + 1;
@@ -785,10 +783,13 @@ static void envctrl_init_adc(struct i2c_child_t *pchild, int node)
}
/* Get optional properties. */
- len = prom_getproperty(node, "warning-temp", (char *)&warning_temperature,
- sizeof(warning_temperature));
- len = prom_getproperty(node, "shutdown-temp", (char *)&shutdown_temperature,
- sizeof(shutdown_temperature));
+ pval = of_get_property(dp, "warning-temp", NULL);
+ if (pval)
+ warning_temperature = *pval;
+
+ pval = of_get_property(dp, "shutdown-temp", NULL);
+ if (pval)
+ shutdown_temperature = *pval;
}
/* Function Description: Initialize child device monitoring fan status.
@@ -859,24 +860,20 @@ static void envctrl_init_voltage_status(struct i2c_child_t *pchild)
/* Function Description: Initialize i2c child device.
* Return: None.
*/
-static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
+static void envctrl_init_i2c_child(struct device_node *dp,
struct i2c_child_t *pchild)
{
- int node, len, i, tbls_size = 0;
-
- node = edev_child->prom_node;
+ int len, i, tbls_size = 0;
+ const void *pval;
/* Get device address. */
- len = prom_getproperty(node, "reg",
- (char *) &(pchild->addr),
- sizeof(pchild->addr));
+ pval = of_get_property(dp, "reg", &len);
+ memcpy(&pchild->addr, pval, len);
/* Get tables property. Read firmware temperature tables. */
- len = prom_getproperty(node, "translation",
- (char *) pchild->tblprop_array,
- (PCF8584_MAX_CHANNELS *
- sizeof(struct pcf8584_tblprop)));
- if (len > 0) {
+ pval = of_get_property(dp, "translation", &len);
+ if (pval && len > 0) {
+ memcpy(pchild->tblprop_array, pval, len);
pchild->total_tbls = len / sizeof(struct pcf8584_tblprop);
for (i = 0; i < pchild->total_tbls; i++) {
if ((pchild->tblprop_array[i].size + pchild->tblprop_array[i].offset) > tbls_size) {
@@ -886,15 +883,15 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
pchild->tables = kmalloc(tbls_size, GFP_KERNEL);
if (pchild->tables == NULL){
- printk("envctrl: Failed to allocate table.\n");
+ printk(KERN_ERR PFX "Failed to allocate table.\n");
return;
}
- len = prom_getproperty(node, "tables",
- (char *) pchild->tables, tbls_size);
- if (len <= 0) {
- printk("envctrl: Failed to get table.\n");
+ pval = of_get_property(dp, "tables", &len);
+ if (!pval || len <= 0) {
+ printk(KERN_ERR PFX "Failed to get table.\n");
return;
}
+ memcpy(pchild->tables, pval, len);
}
/* SPARCengine ASM Reference Manual (ref. SMI doc 805-7581-04)
@@ -905,12 +902,11 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
* 'NULL' monitor type.
*/
if (ENVCTRL_CPCI_IGNORED_NODE == pchild->addr) {
+ struct device_node *root_node;
int len;
- char prop[56];
- len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
- if (0 < len && (0 == strncmp(prop, "SUNW,UltraSPARC-IIi-cEngine", len)))
- {
+ root_node = of_find_node_by_path("/");
+ if (!strcmp(root_node->name, "SUNW,UltraSPARC-IIi-cEngine")) {
for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) {
pchild->mon_type[len] = ENVCTRL_NOMON;
}
@@ -919,16 +915,14 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
}
/* Get the monitor channels. */
- len = prom_getproperty(node, "channels-in-use",
- (char *) pchild->chnl_array,
- (PCF8584_MAX_CHANNELS *
- sizeof(struct pcf8584_channel)));
+ pval = of_get_property(dp, "channels-in-use", &len);
+ memcpy(pchild->chnl_array, pval, len);
pchild->total_chnls = len / sizeof(struct pcf8584_channel);
for (i = 0; i < pchild->total_chnls; i++) {
switch (pchild->chnl_array[i].type) {
case PCF8584_TEMP_TYPE:
- envctrl_init_adc(pchild, node);
+ envctrl_init_adc(pchild, dp);
break;
case PCF8584_GLOBALADDR_TYPE:
@@ -943,7 +937,7 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
case PCF8584_VOLTAGE_TYPE:
if (pchild->i2ctype == I2C_ADC) {
- envctrl_init_adc(pchild,node);
+ envctrl_init_adc(pchild,dp);
} else {
envctrl_init_voltage_status(pchild);
}
@@ -952,7 +946,7 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
default:
break;
- };
+ }
}
}
@@ -976,17 +970,15 @@ static struct i2c_child_t *envctrl_get_i2c_child(unsigned char mon_type)
static void envctrl_do_shutdown(void)
{
static int inprog = 0;
- static char *envp[] = {
- "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
- char *argv[] = {
- "/sbin/shutdown", "-h", "now", NULL };
+ int ret;
if (inprog != 0)
return;
inprog = 1;
printk(KERN_CRIT "kenvctrld: WARNING: Shutting down the system now.\n");
- if (0 > execve("/sbin/shutdown", argv, envp)) {
+ ret = orderly_poweroff(true);
+ if (ret < 0) {
printk(KERN_CRIT "kenvctrld: WARNING: system shutdown failed!\n");
inprog = 0; /* unlikely to succeed, but we could try again */
}
@@ -1002,14 +994,14 @@ static int kenvctrld(void *__unused)
struct i2c_child_t *cputemp;
if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) {
- printk(KERN_ERR
- "envctrl: kenvctrld unable to monitor CPU temp-- exiting\n");
+ printk(KERN_ERR PFX
+ "kenvctrld unable to monitor CPU temp-- exiting\n");
return -ENODEV;
}
poll_interval = 5000; /* TODO env_mon_interval */
- printk(KERN_INFO "envctrl: %s starting...\n", current->comm);
+ printk(KERN_INFO PFX "%s starting...\n", current->comm);
for (;;) {
msleep_interruptible(poll_interval);
@@ -1031,54 +1023,34 @@ static int kenvctrld(void *__unused)
}
}
}
- printk(KERN_INFO "envctrl: %s exiting...\n", current->comm);
+ printk(KERN_INFO PFX "%s exiting...\n", current->comm);
return 0;
}
-static int __init envctrl_init(void)
+static int envctrl_probe(struct platform_device *op)
{
- struct linux_ebus *ebus = NULL;
- struct linux_ebus_device *edev = NULL;
- struct linux_ebus_child *edev_child = NULL;
- int err, i = 0;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_name, "bbc")) {
- /* If we find a boot-bus controller node,
- * then this envctrl driver is not for us.
- */
- return -ENODEV;
- }
- }
- }
+ struct device_node *dp;
+ int index, err;
- /* Traverse through ebus and ebus device list for i2c device and
- * adc and gpio nodes.
- */
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_name, "i2c")) {
- i2c = ioremap(edev->resource[0].start, 0x2);
- for_each_edevchild(edev, edev_child) {
- if (!strcmp("gpio", edev_child->prom_name)) {
- i2c_childlist[i].i2ctype = I2C_GPIO;
- envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
- }
- if (!strcmp("adc", edev_child->prom_name)) {
- i2c_childlist[i].i2ctype = I2C_ADC;
- envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
- }
- }
- goto done;
- }
+ if (i2c)
+ return -EINVAL;
+
+ i2c = of_ioremap(&op->resource[0], 0, 0x2, DRIVER_NAME);
+ if (!i2c)
+ return -ENOMEM;
+
+ index = 0;
+ dp = op->dev.of_node->child;
+ while (dp) {
+ if (!strcmp(dp->name, "gpio")) {
+ i2c_childlist[index].i2ctype = I2C_GPIO;
+ envctrl_init_i2c_child(dp, &(i2c_childlist[index++]));
+ } else if (!strcmp(dp->name, "adc")) {
+ i2c_childlist[index].i2ctype = I2C_ADC;
+ envctrl_init_i2c_child(dp, &(i2c_childlist[index++]));
}
- }
-done:
- if (!edev) {
- printk("envctrl: I2C device not found.\n");
- return -ENODEV;
+ dp = dp->sibling;
}
/* Set device address. */
@@ -1096,7 +1068,7 @@ done:
/* Register the device as a minor miscellaneous device. */
err = misc_register(&envctrl_dev);
if (err) {
- printk("envctrl: Unable to get misc minor %d\n",
+ printk(KERN_ERR PFX "Unable to get misc minor %d\n",
envctrl_dev.minor);
goto out_iounmap;
}
@@ -1105,12 +1077,12 @@ done:
* a next child device, so we decrement before reverse-traversal of
* child devices.
*/
- printk("envctrl: initialized ");
- for (--i; i >= 0; --i) {
+ printk(KERN_INFO PFX "Initialized ");
+ for (--index; index >= 0; --index) {
printk("[%s 0x%lx]%s",
- (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") :
- ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")),
- i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
+ (I2C_ADC == i2c_childlist[index].i2ctype) ? "adc" :
+ ((I2C_GPIO == i2c_childlist[index].i2ctype) ? "gpio" : "unknown"),
+ i2c_childlist[index].addr, (0 == index) ? "\n" : " ");
}
kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
@@ -1124,29 +1096,47 @@ done:
out_deregister:
misc_deregister(&envctrl_dev);
out_iounmap:
- iounmap(i2c);
- for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) {
- if (i2c_childlist[i].tables)
- kfree(i2c_childlist[i].tables);
- }
+ of_iounmap(&op->resource[0], i2c, 0x2);
+ for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++)
+ kfree(i2c_childlist[index].tables);
+
return err;
}
-static void __exit envctrl_cleanup(void)
+static int envctrl_remove(struct platform_device *op)
{
- int i;
+ int index;
kthread_stop(kenvctrld_task);
- iounmap(i2c);
+ of_iounmap(&op->resource[0], i2c, 0x2);
misc_deregister(&envctrl_dev);
- for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) {
- if (i2c_childlist[i].tables)
- kfree(i2c_childlist[i].tables);
- }
+ for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++)
+ kfree(i2c_childlist[index].tables);
+
+ return 0;
}
-module_init(envctrl_init);
-module_exit(envctrl_cleanup);
+static const struct of_device_id envctrl_match[] = {
+ {
+ .name = "i2c",
+ .compatible = "i2cpcf,8584",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, envctrl_match);
+
+static struct platform_driver envctrl_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = envctrl_match,
+ },
+ .probe = envctrl_probe,
+ .remove = envctrl_remove,
+};
+
+module_platform_driver(envctrl_driver);
+
MODULE_LICENSE("GPL");