From 936ea71f2f9a647c68ef3ea08ec5cb65b19722e1 Mon Sep 17 00:00:00 2001
From: Guido Guenther <agx@sigxcpu.org>
Date: Sun, 19 Nov 2006 02:07:20 +0100
Subject: [PATCH] support adm1030 on PowerBook6,1

parse the necessary information from the OF tree
---
 drivers/hwmon/adm1031.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 2bffcab..23ae6b7 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -30,6 +30,9 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#ifdef CONFIG_PPC_OF
+#include <linux/of.h>
+#endif
 
 /* Following macros takes channel parameter starting from 0 to 2 */
 #define ADM1031_REG_FAN_SPEED(nr)	(0x08 + (nr))
@@ -105,6 +108,13 @@ static void adm1031_init_client(struct i2c_client *client);
 static int adm1031_detach_client(struct i2c_client *client);
 static struct adm1031_data *adm1031_update_device(struct device *dev);
 
+#ifdef CONFIG_PPC_OF
+int therm_bus, therm_address;
+static char *sensor_location[2];
+static int adm1031_of_detect(void);
+#endif
+
+
 /* This is the driver that will be inserted */
 static struct i2c_driver adm1031_driver = {
 	.driver = {
@@ -695,9 +705,20 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
 
 static int adm1031_attach_adapter(struct i2c_adapter *adapter)
 {
+#ifndef CONFIG_PPC_OF
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_probe(adapter, &addr_data, adm1031_detect);
+#else
+	unsigned long bus_no;
+
+	if (strncmp(adapter->name, "uni-n", 5))
+		return -ENODEV;
+	bus_no = simple_strtoul(adapter->name + 6, NULL, 10);
+	if (bus_no != therm_bus)
+		return -ENODEV;
+	return adm1031_detect(adapter, therm_address, -1);
+#endif
 }
 
 static struct attribute *adm1031_attributes[] = {
@@ -980,8 +1001,60 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
 	return data;
 }
 
+
+#ifdef CONFIG_PPC_OF
+
+static int adm1031_of_detect()
+{
+	struct device_node* np;
+	u32 *prop;
+	int i = 0, offset = 0;
+
+	np = of_find_node_by_name(NULL, "fan");
+	if (!np)
+		return 0;
+	if (!of_device_is_compatible(np, "adm1030"))
+		return 0;
+
+	prop = (u32 *)of_get_property(np, "hwsensor-params-version", NULL);
+	printk(KERN_DEBUG "adm1030: version %d (%ssupported)\n", *prop,
+			 (*prop == 1)?"":"un");
+	if (*prop != 1)
+		return 0;
+
+	prop = (u32 *)of_get_property(np, "reg", NULL);
+	if (!prop)
+		return 0;
+	therm_bus = ((*prop) >> 8) & 0x0f;
+	therm_address = ((*prop) & 0xff) >> 1;
+
+	printk(KERN_INFO "adm1030: Thermostat bus: %d, address: 0x%02x\n",
+			 therm_bus, therm_address);
+
+	if (of_get_property(np, "hwsensor-location", NULL)) {
+		for (i = 0; i < 2; i++) {
+			sensor_location[i] = (char*)of_get_property(np,
+					"hwsensor-location", NULL) + offset;
+
+			if (sensor_location[i] == NULL)
+				sensor_location[i] = "";
+
+			printk(KERN_DEBUG "sensor %d: %s\n", i, sensor_location[i]);
+			offset += strlen(sensor_location[i]) + 1;
+		}
+	} else
+	    return 0;
+
+	return 1;
+}
+#endif
+
 static int __init sensors_adm1031_init(void)
 {
+#ifdef CONFIG_PPC_OF
+	if(!adm1031_of_detect())
+	    return -ENODEV;
+#endif
 	return i2c_add_driver(&adm1031_driver);
 }
 
-- 
1.5.6.3

