From patchwork Tue Dec 1 04:25:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nishanth Menon X-Patchwork-Id: 57476 Delivered-To: patch@linaro.org Received: by 10.112.155.196 with SMTP id vy4csp1936579lbb; Mon, 30 Nov 2015 20:27:41 -0800 (PST) X-Received: by 10.98.10.197 with SMTP id 66mr75726474pfk.37.1448944061868; Mon, 30 Nov 2015 20:27:41 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id da6si14641958pad.156.2015.11.30.20.27.41; Mon, 30 Nov 2015 20:27:41 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753545AbbLAE1j (ORCPT + 28 others); Mon, 30 Nov 2015 23:27:39 -0500 Received: from arroyo.ext.ti.com ([192.94.94.40]:49743 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752014AbbLAE1i (ORCPT ); Mon, 30 Nov 2015 23:27:38 -0500 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id tB14Q8dg005123; Mon, 30 Nov 2015 22:26:08 -0600 Received: from DFLE73.ent.ti.com (dfle73.ent.ti.com [128.247.5.110]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id tB14Q8Ke027383; Mon, 30 Nov 2015 22:26:08 -0600 Received: from dlep33.itg.ti.com (157.170.170.75) by DFLE73.ent.ti.com (128.247.5.110) with Microsoft SMTP Server id 14.3.224.2; Mon, 30 Nov 2015 22:26:07 -0600 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id tB14Q7xx025140; Mon, 30 Nov 2015 22:26:07 -0600 From: Nishanth Menon To: Guenter Roeck , Jean Delvare CC: , , , , Nishanth Menon , Eduardo Valentin Subject: [PATCH] hwmon: (tmp102) Force wait for conversion time for the first valid data Date: Mon, 30 Nov 2015 22:25:55 -0600 Message-ID: <1448943955-2385-1-git-send-email-nm@ti.com> X-Mailer: git-send-email 2.6.2.402.g2635c2b MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org TMP102 works based on conversions done periodically. However, as per the TMP102 data sheet[1] the first conversion is triggered immediately after we program the configuration register. The temperature data registers do not reflect proper data until the first conversion is complete (in our case HZ/4). The driver currently sets the last_update to be jiffies - HZ, just after the configuration is complete. When tmp102 driver registers with the thermal framework, it immediately tries to read the sensor temperature data. This takes place even before the conversion on the TMP102 is complete and results in an invalid temperature read. Depending on the value read, this may cause thermal framework to assume that a critical temperature event has occurred and attempts to shutdown the system. Instead of causing an invalid mid-conversion value to be read erroneously, we mark the last_update to be in-line with the current jiffies. This allows the tmp102_update_device function to skip update until the required conversion time is complete. Further, we ensure to return -EAGAIN result instead of returning spurious temperature (such as 0C) values to the caller to prevent any wrong decisions made with such values. A simpler alternative approach could be to sleep in the probe for the duration required, but that will result in latency that is undesirable that can delay boot sequence un-necessarily. [1] http://www.ti.com/lit/ds/symlink/tmp102.pdf Cc: Eduardo Valentin Reported-by: Aparna Balasubramanian Reported-by: Elvita Lobo Reported-by: Yan Liu Signed-off-by: Nishanth Menon --- Example case (from Beagleboard-x15 using an older kernel revision): http://pastebin.ubuntu.com/13591711/ Notice the thermal shutdown trigger: thermal thermal_zone3: critical temperature reached(108 C),shutting down drivers/hwmon/tmp102.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) -- 2.6.2.402.g2635c2b -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 65482624ea2c..145f69108f23 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -50,6 +50,9 @@ #define TMP102_TLOW_REG 0x02 #define TMP102_THIGH_REG 0x03 +/* TMP102 range is -55 to 150C -> we use -128 as a default invalid value */ +#define TMP102_NOTREADY -128 + struct tmp102 { struct i2c_client *client; struct device *hwmon_dev; @@ -102,6 +105,12 @@ static int tmp102_read_temp(void *dev, int *temp) { struct tmp102 *tmp102 = tmp102_update_device(dev); + /* Is it too early even to return a conversion? */ + if (tmp102->temp[0] == TMP102_NOTREADY) { + dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); + return -EAGAIN; + } + *temp = tmp102->temp[0]; return 0; @@ -114,6 +123,10 @@ static ssize_t tmp102_show_temp(struct device *dev, struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); struct tmp102 *tmp102 = tmp102_update_device(dev); + /* Is it too early even to return a read? */ + if (tmp102->temp[sda->index] == TMP102_NOTREADY) + return -EAGAIN; + return sprintf(buf, "%d\n", tmp102->temp[sda->index]); } @@ -207,7 +220,11 @@ static int tmp102_probe(struct i2c_client *client, status = -ENODEV; goto fail_restore_config; } - tmp102->last_update = jiffies - HZ; + tmp102->last_update = jiffies; + /* Mark that we are not ready with data until conversion is complete */ + tmp102->temp[0] = TMP102_NOTREADY; + tmp102->temp[1] = TMP102_NOTREADY; + tmp102->temp[2] = TMP102_NOTREADY; mutex_init(&tmp102->lock); hwmon_dev = hwmon_device_register_with_groups(dev, client->name,