From patchwork Thu Apr 19 08:16:53 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Herrenschmidt X-Patchwork-Id: 153694 X-Patchwork-Delegate: benh@kernel.crashing.org Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 54374B6FF9 for ; Thu, 19 Apr 2012 18:56:30 +1000 (EST) Received: by ozlabs.org (Postfix) id EB6E0B6FC8; Thu, 19 Apr 2012 18:55:36 +1000 (EST) Delivered-To: linuxppc-dev@ozlabs.org Received: from e23smtp04.au.ibm.com (e23smtp04.au.ibm.com [202.81.31.146]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "e23smtp04.au.ibm.com", Issuer "GeoTrust SSL CA" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 949F4B6FE3 for ; Thu, 19 Apr 2012 18:55:30 +1000 (EST) Received: from /spool/local by e23smtp04.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 19 Apr 2012 08:02:55 +1000 Received: from d23relay03.au.ibm.com (202.81.31.245) by e23smtp04.au.ibm.com (202.81.31.210) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 19 Apr 2012 08:02:16 +1000 Received: from d23av01.au.ibm.com (d23av01.au.ibm.com [9.190.234.96]) by d23relay03.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q3J8JnXQ33292430 for ; Thu, 19 Apr 2012 18:19:49 +1000 Received: from d23av01.au.ibm.com (loopback [127.0.0.1]) by d23av01.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q3J8Jn5m008337 for ; Thu, 19 Apr 2012 18:19:49 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.190.163.12]) by d23av01.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q3J8JmCs008263; Thu, 19 Apr 2012 18:19:49 +1000 Received: from grosgo.ozlabs.ibm.com (haven.au.ibm.com [9.190.164.82]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.au.ibm.com (Postfix) with ESMTPSA id DE44B73A42; Thu, 19 Apr 2012 18:19:48 +1000 (EST) From: Benjamin Herrenschmidt To: linuxppc-dev@ozlabs.org Subject: [PATCH 12/15] powerpc/windfarm: Add lm87 sensor Date: Thu, 19 Apr 2012 18:16:53 +1000 Message-Id: <1334823416-9138-13-git-send-email-benh@kernel.crashing.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1334823416-9138-1-git-send-email-benh@kernel.crashing.org> References: <1334823416-9138-1-git-send-email-benh@kernel.crashing.org> x-cbid: 12041822-9264-0000-0000-00000148EC7F Cc: khali@linux-fr.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org For use by the upcoming windfarm_rm31 Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/windfarm_lm87_sensor.c | 201 ++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 drivers/macintosh/windfarm_lm87_sensor.c diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c new file mode 100644 index 0000000..c071aab --- /dev/null +++ b/drivers/macintosh/windfarm_lm87_sensor.c @@ -0,0 +1,201 @@ +/* + * Windfarm PowerMac thermal control. LM87 sensor + * + * Copyright 2012 Benjamin Herrenschmidt, IBM Corp. + * + * Released under the term of the GNU GPL v2. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windfarm.h" + +#define VERSION "1.0" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +struct wf_lm87_sensor { + struct i2c_client *i2c; + struct wf_sensor sens; +}; +#define wf_to_lm87(c) container_of(c, struct wf_lm87_sensor, sens) + + +static int wf_lm87_read_reg(struct i2c_client *chip, int reg) +{ + int rc, tries = 0; + u8 buf; + + for (;;) { + /* Set address */ + buf = (u8)reg; + rc = i2c_master_send(chip, &buf, 1); + if (rc <= 0) + goto error; + rc = i2c_master_recv(chip, &buf, 1); + if (rc <= 0) + goto error; + return (int)buf; + error: + DBG("wf_lm87: Error reading LM87, retrying...\n"); + if (++tries > 10) { + printk(KERN_ERR "wf_lm87: Error reading LM87 !\n"); + return -EIO; + } + msleep(10); + } +} + +static int wf_lm87_get(struct wf_sensor *sr, s32 *value) +{ + struct wf_lm87_sensor *lm = sr->priv; + s32 temp; + + if (lm->i2c == NULL) + return -ENODEV; + +#define LM87_INT_TEMP 0x27 + + /* Read temperature register */ + temp = wf_lm87_read_reg(lm->i2c, LM87_INT_TEMP); + if (temp < 0) + return temp; + *value = temp << 16; + + return 0; +} + +static void wf_lm87_release(struct wf_sensor *sr) +{ + struct wf_lm87_sensor *lm = wf_to_lm87(sr); + + kfree(lm); +} + +static struct wf_sensor_ops wf_lm87_ops = { + .get_value = wf_lm87_get, + .release = wf_lm87_release, + .owner = THIS_MODULE, +}; + +static int wf_lm87_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct wf_lm87_sensor *lm; + const char *name = NULL, *loc; + struct device_node *np = NULL; + int rc; + + /* + * The lm87 contains a whole pile of sensors, additionally, + * the Xserve G5 has several lm87's. However, for now we only + * care about the internal temperature sensor + */ + while ((np = of_get_next_child(client->dev.of_node, np)) != NULL) { + if (strcmp(np->name, "int-temp")) + continue; + loc = of_get_property(np, "location", NULL); + if (!loc) + continue; + if (strstr(loc, "DIMM")) + name = "dimms-temp"; + else if (strstr(loc, "Processors")) + name = "between-cpus-temp"; + if (name) { + of_node_put(np); + break; + } + } + if (!name) { + pr_warning("wf_lm87: Unsupported sensor %s\n", + client->dev.of_node->full_name); + return -ENODEV; + } + + lm = kzalloc(sizeof(struct wf_lm87_sensor), GFP_KERNEL); + if (lm == NULL) + return -ENODEV; + + lm->i2c = client; + lm->sens.name = name; + lm->sens.ops = &wf_lm87_ops; + lm->sens.priv = lm; + i2c_set_clientdata(client, lm); + + rc = wf_register_sensor(&lm->sens); + if (rc) + kfree(lm); + return rc; +} + +static int wf_lm87_remove(struct i2c_client *client) +{ + struct wf_lm87_sensor *lm = i2c_get_clientdata(client); + + DBG("wf_lm87: i2c detatch called for %s\n", lm->sens.name); + + /* Mark client detached */ + lm->i2c = NULL; + + /* release sensor */ + wf_unregister_sensor(&lm->sens); + + return 0; +} + +static const struct i2c_device_id wf_lm87_id[] = { + { "MAC,lm87cimt", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wf_lm87_id); + +static struct i2c_driver wf_lm87_driver = { + .driver = { + .name = "wf_lm87", + }, + .probe = wf_lm87_probe, + .remove = wf_lm87_remove, + .id_table = wf_lm87_id, +}; + +static int __init wf_lm87_sensor_init(void) +{ + /* We only support this on the Xserve */ + if (!of_machine_is_compatible("RackMac3,1")) + return -ENODEV; + + return i2c_add_driver(&wf_lm87_driver); +} + +static void __exit wf_lm87_sensor_exit(void) +{ + i2c_del_driver(&wf_lm87_driver); +} + + +module_init(wf_lm87_sensor_init); +module_exit(wf_lm87_sensor_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("LM87 sensor objects for PowerMacs thermal control"); +MODULE_LICENSE("GPL"); +