From patchwork Fri Jan 26 23:37:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Danilo Bargen X-Patchwork-Id: 10187185 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 89E9060383 for ; Fri, 26 Jan 2018 23:37:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 736002A3F9 for ; Fri, 26 Jan 2018 23:37:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 65B092A532; Fri, 26 Jan 2018 23:37:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AAB482A3F9 for ; Fri, 26 Jan 2018 23:37:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751431AbeAZXhf (ORCPT ); Fri, 26 Jan 2018 18:37:35 -0500 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:56297 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751408AbeAZXhf (ORCPT ); Fri, 26 Jan 2018 18:37:35 -0500 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 9C2FA20E58; Fri, 26 Jan 2018 18:37:34 -0500 (EST) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Fri, 26 Jan 2018 18:37:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dbrgn.ch; h=cc :content-transfer-encoding:content-type:date:from:message-id :mime-version:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= mesmtp; bh=9LYqSj8wQs/e30821DZ7Brd1DfBNrnL7B1V5DqrVJgY=; b=DFGqu F28IiEsLpvZktQ9oLeoZBoRso/Q4WQHLMhP3kO6l+hksLtVKgtw+kOhaEf09KpPT lXpRd2HYQf+kAaxOynPeEAvLSPaa/Lte1eWS0EHjMbCwllfZRe+1cKflu/VrKNdP msXtCOZhainYnWuPSh870oIEH/GXSsudR4mE0g= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:message-id:mime-version:subject:to:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; bh=9LYqSj8wQs/e30821DZ7Brd1DfBNr nL7B1V5DqrVJgY=; b=WRKishdfpfHoceEBVgbXATod7trEnD5WU8bL+25z47Av6 E8xsfEZjvt1QSEL7ZTPhEXp0iUX9O5+1JoSl0lCTkHev9MEDy4VwEYOHWmYohuMM WhbgshCHogUs1wI4NFAdw16kaF/nmwMoOHDVUXrBR1ozLU0xcOflzLRsoLKY/3cQ gzQd3HUjpJtoT2qjE8q+ep8heM4Fzif88YODq/YM6DT7ruz/ZtbnDnzW+1LLTAdn gysraYznN914e0klDO4vH0FsCD/Inbc/1ObluQlBYFHvePS1/cG5RgNDH09F5xKE vxf7smneJk4HhSDE2RTTvDXpt6lV6o97xYVWEDJ+A== X-ME-Sender: Received: from dbrgn.ch (46-127-132-187.dynamic.hispeed.ch [46.127.132.187]) by mail.messagingengine.com (Postfix) with ESMTPA id BC9257E0FD; Fri, 26 Jan 2018 18:37:32 -0500 (EST) Received: by dbrgn.ch (sSMTP sendmail emulation); Sat, 27 Jan 2018 00:37:31 +0100 From: Danilo Bargen To: linux-hwmon@vger.kernel.org Cc: jdelvare@suse.com, linux@roeck-us.net, andreas.brauchli@sensirion.com, Danilo Bargen Subject: [PATCH] hwmon: (sht21) Don't use clock stretching Date: Sat, 27 Jan 2018 00:37:31 +0100 Message-Id: <20180126233731.19127-1-mail@dbrgn.ch> X-Mailer: git-send-email 2.15.1 MIME-Version: 1.0 Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The current driver uses clock stretching (hold master) mode to retrieve the measurements. This blocks the bus and may cause problems on some systems like the BCM2835 (Raspberry Pi) that have buggy I2C hardware¹. ¹ http://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html Signed-off-by: Danilo Bargen Reviewed-by: Andreas Brauchli --- drivers/hwmon/sht21.c | 79 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index 984f14b3e89a..56aa13b15682 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c @@ -25,15 +25,24 @@ #include #include #include +#include -/* I2C command bytes */ -#define SHT21_TRIG_T_MEASUREMENT_HM 0xe3 -#define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5 +/* I2C commands */ +static const char sht21_trig_t_measurement_nh[] = { 0xf3 }; +static const char sht21_trig_rh_measurement_nh[] = { 0xf5 }; #define SHT21_READ_SNB_CMD1 0xFA #define SHT21_READ_SNB_CMD2 0x0F #define SHT21_READ_SNAC_CMD1 0xFC #define SHT21_READ_SNAC_CMD2 0xC9 +/* I2C lengths */ +#define SHT21_CMD_LENGTH 1 +#define SHT21_RESPONSE_LENGTH 3 + +/* Max waiting times in ms at max resolution, datasheet table 7 */ +#define SHT21_WAIT_T 85 +#define SHT21_WAIT_RH 29 + /** * struct sht21 - SHT21 device specific data * @hwmon_dev: device registered with hwmon @@ -93,6 +102,7 @@ static inline int sht21_rh_ticks_to_per_cent_mille(int ticks) static int sht21_update_measurements(struct device *dev) { int ret = 0; + unsigned char buf[SHT21_RESPONSE_LENGTH]; struct sht21 *sht21 = dev_get_drvdata(dev); struct i2c_client *client = sht21->client; @@ -103,22 +113,60 @@ static int sht21_update_measurements(struct device *dev) * maximum two measurements per second at 12bit accuracy shall be made. */ if (time_after(jiffies, sht21->last_update + HZ / 2) || !sht21->valid) { - ret = i2c_smbus_read_word_swapped(client, - SHT21_TRIG_T_MEASUREMENT_HM); - if (ret < 0) + /* + * Read from the SHT21 in non blocking mode + * (no clock stretching). + */ + + /* Trigger temperature measurement */ + ret = i2c_master_send(client, + sht21_trig_t_measurement_nh, + SHT21_CMD_LENGTH); + if (ret != SHT21_CMD_LENGTH) { + dev_err(dev, "failed to send command: %d\n", ret); + ret = -EIO; + goto out; + } + msleep(SHT21_WAIT_T); + + /* Read temperature data */ + ret = i2c_master_recv(client, buf, sizeof(buf)); + if (ret != SHT21_RESPONSE_LENGTH) { + dev_err(dev, "failed to read values: %d\n", ret); + ret = -EIO; + goto out; + } + sht21->temperature = sht21_temp_ticks_to_millicelsius( + (buf[0] << 8) | buf[1] + ); + + /* Trigger humidity measurement */ + ret = i2c_master_send(client, + sht21_trig_rh_measurement_nh, + SHT21_CMD_LENGTH); + if (ret != SHT21_CMD_LENGTH) { + dev_err(dev, "failed to send command: %d\n", ret); + ret = -EIO; goto out; - sht21->temperature = sht21_temp_ticks_to_millicelsius(ret); - ret = i2c_smbus_read_word_swapped(client, - SHT21_TRIG_RH_MEASUREMENT_HM); - if (ret < 0) + } + msleep(SHT21_WAIT_RH); + + /* Read humidity data */ + ret = i2c_master_recv(client, buf, sizeof(buf)); + if (ret != SHT21_RESPONSE_LENGTH) { + dev_err(dev, "failed to read values: %d\n", ret); + ret = -EIO; goto out; - sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret); + } + sht21->humidity = sht21_rh_ticks_to_per_cent_mille( + (buf[0] << 8) | buf[1] + ); + sht21->last_update = jiffies; sht21->valid = 1; } out: mutex_unlock(&sht21->lock); - return ret >= 0 ? 0 : ret; } @@ -269,13 +317,6 @@ static int sht21_probe(struct i2c_client *client, struct device *hwmon_dev; struct sht21 *sht21; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WORD_DATA)) { - dev_err(&client->dev, - "adapter does not support SMBus word transactions\n"); - return -ENODEV; - } - sht21 = devm_kzalloc(dev, sizeof(*sht21), GFP_KERNEL); if (!sht21) return -ENOMEM;