From patchwork Mon Nov 5 20:48:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10669119 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7564C13BF for ; Mon, 5 Nov 2018 20:49:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5F04C29E72 for ; Mon, 5 Nov 2018 20:49:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5353C29EB0; Mon, 5 Nov 2018 20:49:15 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 05C8A29E72 for ; Mon, 5 Nov 2018 20:49:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726902AbeKFGKW (ORCPT ); Tue, 6 Nov 2018 01:10:22 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:41700 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727329AbeKFGKV (ORCPT ); Tue, 6 Nov 2018 01:10:21 -0500 Received: by mail-pf1-f193.google.com with SMTP id e22-v6so4990798pfn.8; Mon, 05 Nov 2018 12:48:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8ADAr5AQOBKf5xqeLGhSnQ4E/XqcDmKpYJgabGVmIJo=; b=BodiFLFauFXWxpl33rPnpQhlyR3FOO2W8zwfoU+ztyLUlvxIYEGtqfDwQlUyyMDLvP pEdlyAuU4SqKMg45oL5RON/H6f2pBUaKMqmeg4NOoo9LhQNiP6/n+vwaSeUCTjPGk5rW VfKIGM8vHAlfi25U3QIPFaML1PntcJ7muVtAMt9qv5nx18trKGG7xpKfSV9FoG/m7zGy 7qsj3bYpJr29rKuq80M8Uwpir9GVSD66K734Fw4x4YbD85i57vZnf9jVFnn91IPZ2zH2 s5JUJApNkS/i/Tmt59zEXQJM0PqKigspPZ0hD/KeVm30icFYL2fsMMoFeqxqsnM0PSI6 +W3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8ADAr5AQOBKf5xqeLGhSnQ4E/XqcDmKpYJgabGVmIJo=; b=pVOGDs4Jy9HxFUbmhUuQFy1oG5oN6BqaVmgT2DDir0ayPkeBlYSdvNPVLwj1bC/zKo NzOkcS12UfQybjDuokRKiPJv3bPr6feV6xmMT9vmaWceRE7looSpYaciv5R6RTDyOx40 sl6rKW00AORrYIUMbWPw6YZROtC8+1cnB/10/457uoCV8ZAUtV8EylJBmNSQjvvBrOZU wAvbxeOMQZB996tf7lrpwt26g6vdPWp6xEKagWWV3eU40jd0VOiIDkfxNpmXxgeBbPiV /QCpE0FKFkGAki/zO1++V9TNS7XCAQha0G7B6X6WRbDoSdc3jnoU/9BV5WuCXBJzFw8V Q57g== X-Gm-Message-State: AGRZ1gJFz08U1Izn6lztqUnFWb+2s+1xgmo7umhArIvVet8PECaK7f2J jwfQWCfEmDdAkwTr/if/eXq9LUQD X-Google-Smtp-Source: AJdET5cOIVpiz0npjVa1cOGfyWdzUk19+BrqQyamZJ3aU/+Fe3THCARym4BTr/5I2NMZjDBJsdOpGQ== X-Received: by 2002:a63:1342:: with SMTP id 2-v6mr21175929pgt.19.1541450931063; Mon, 05 Nov 2018 12:48:51 -0800 (PST) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id q1sm25569257pgs.14.2018.11.05.12.48.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 12:48:50 -0800 (PST) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 1/4] hwmon: (ina3221) Check channel status for alarms attribute read Date: Mon, 5 Nov 2018 12:48:40 -0800 Message-Id: <20181105204843.4081-2-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181105204843.4081-1-nicoleotsuka@gmail.com> References: <20181105204843.4081-1-nicoleotsuka@gmail.com> 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 There is nothing critically wrong to read these two attributes without having a is_enabled() check at this point. But reading the MASK_ENABLE register would clear the CVRF bit according to the datasheet. So it'd be safer to fence for disabled channels in order to add pm runtime feature. Signed-off-by: Nicolin Chen --- Changelog v2->v5: * N/A v1->v2: * Returned 0 for alert flags instead of -ENODATA drivers/hwmon/ina3221.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index d61688f04594..26cdf3342d80 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -200,6 +200,12 @@ static int ina3221_read_curr(struct device *dev, u32 attr, return 0; case hwmon_curr_crit_alarm: case hwmon_curr_max_alarm: + /* No actual register read if channel is disabled */ + if (!ina3221_is_enabled(ina, channel)) { + /* Return 0 for alert flags */ + *val = 0; + return 0; + } ret = regmap_field_read(ina->fields[reg], ®val); if (ret) return ret; From patchwork Mon Nov 5 20:48:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10669115 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 279C015E9 for ; Mon, 5 Nov 2018 20:49:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0FE5229E26 for ; Mon, 5 Nov 2018 20:49:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 03D2229E72; Mon, 5 Nov 2018 20:49:05 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 889F729E26 for ; Mon, 5 Nov 2018 20:49:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387577AbeKFGKY (ORCPT ); Tue, 6 Nov 2018 01:10:24 -0500 Received: from mail-pg1-f195.google.com ([209.85.215.195]:34303 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730258AbeKFGKX (ORCPT ); Tue, 6 Nov 2018 01:10:23 -0500 Received: by mail-pg1-f195.google.com with SMTP id k1-v6so4769292pgq.1; Mon, 05 Nov 2018 12:48:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ag7ymbQUhUKOFa848vV76yrTHubxL26VbSmRYSD6E5o=; b=XcjRnrXPpxcsMqUdCr8f7cAF7y33Zkp8CB+dmEIIhPBZbYjX6c9PZKqisMDsYG0zM6 lMBQsGtsMKeHSL8MVuH9yFF0rjpUAN5NzAQESuCgkovdOurvMR33qUXukeygTkmPM0nK d6JbMwf6+1u4G7V3xGDrJmuTNAxsySxCIUIlcgQU+V1zaI8fUAo7u1CISFmMtOMr3YfC cXruxWnBbxBKpFbzNsH70+aAPZJxB9Hgs7fO3iCsginVDObNiNCQuRQpWPunlM5JTN7A VkaQmhLYjOuptjfsqBwpOEWIsn4/1GDMKEfam6DjXZE0obyxGH1sUgolhge/ATs/KRpO wwEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ag7ymbQUhUKOFa848vV76yrTHubxL26VbSmRYSD6E5o=; b=PbYxfe8cm53tjAkS3+B6dXpX0B6B5/+FNq1BHCzOZIQr28FOLTmRwwPncxLxxnR252 drWMbAdgoR0qf/zo7P/zq+qJS8E25xVH0QQPGyy2SwciOg+tVAtXbG3zbdcCgBNQ9Qyz GuXWordDIl+wrulTC/82eIgq0hjid4B0OvkxQNsUQcLZA7sxKHEHmBFaSF2qNCTGNJMs FjnZR0N5G3EbE/T8HXqBNoSVCZ7tWA6eSay+lNCa7BVx84OeaHAecoXSRR3mFGS+X6z9 F6Lm0HtTnPFXe+VTAjCHYD8DfxwxXbUZEv3lGXLSFFNy6zu8t49yOk9dq4JvUqEtSR5J iOYQ== X-Gm-Message-State: AGRZ1gIQHVvY7VOW375n/CE1DYpDKA1b4L/ZNWoK9R8WLCjfWfFpS7fg dqUNjIO+ea7VldPnBRIyjCk= X-Google-Smtp-Source: AJdET5cb3DdawMH/ihPKA9eB08+bmb+cPs5VyC0th4co4WXNIcu+DWnc1wqvwaFWZgtUTVMtbpMGsw== X-Received: by 2002:a62:1cc6:: with SMTP id c189-v6mr8294804pfc.49.1541450931753; Mon, 05 Nov 2018 12:48:51 -0800 (PST) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id q1sm25569257pgs.14.2018.11.05.12.48.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 12:48:51 -0800 (PST) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 2/4] hwmon: (ina3221) Serialize sysfs ABI accesses Date: Mon, 5 Nov 2018 12:48:41 -0800 Message-Id: <20181105204843.4081-3-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181105204843.4081-1-nicoleotsuka@gmail.com> References: <20181105204843.4081-1-nicoleotsuka@gmail.com> 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 This change adds a mutex to serialize accesses of sysfs attributes. This is required when polling CVRF bit of the MASK/ENABLE register because this bit is cleared on a read of this MASK/ENABLE register or a write to CONFIG register, which means that this bit might be accidentally cleared by reading other fields like alert flags. So this patch adds a mutex lock to protect the write() and read() callbacks. The read_string() callback won't need the lock since it just returns the label without touching any hardware register. Signed-off-by: Nicolin Chen --- Changlog v1->v5: * N/A drivers/hwmon/ina3221.c | 51 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 26cdf3342d80..10e8347a3c80 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -94,12 +95,14 @@ struct ina3221_input { * @regmap: Register map of the device * @fields: Register fields of the device * @inputs: Array of channel input source specific structures + * @lock: mutex lock to serialize sysfs attribute accesses * @reg_config: Register value of INA3221_CONFIG */ struct ina3221_data { struct regmap *regmap; struct regmap_field *fields[F_MAX_FIELDS]; struct ina3221_input inputs[INA3221_NUM_CHANNELS]; + struct mutex lock; u32 reg_config; }; @@ -265,29 +268,53 @@ static int ina3221_write_enable(struct device *dev, int channel, bool enable) static int ina3221_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { + struct ina3221_data *ina = dev_get_drvdata(dev); + int ret; + + mutex_lock(&ina->lock); + switch (type) { case hwmon_in: /* 0-align channel ID */ - return ina3221_read_in(dev, attr, channel - 1, val); + ret = ina3221_read_in(dev, attr, channel - 1, val); + break; case hwmon_curr: - return ina3221_read_curr(dev, attr, channel, val); + ret = ina3221_read_curr(dev, attr, channel, val); + break; default: - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + break; } + + mutex_unlock(&ina->lock); + + return ret; } static int ina3221_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long val) { + struct ina3221_data *ina = dev_get_drvdata(dev); + int ret; + + mutex_lock(&ina->lock); + switch (type) { case hwmon_in: /* 0-align channel ID */ - return ina3221_write_enable(dev, channel - 1, val); + ret = ina3221_write_enable(dev, channel - 1, val); + break; case hwmon_curr: - return ina3221_write_curr(dev, attr, channel, val); + ret = ina3221_write_curr(dev, attr, channel, val); + break; default: - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + break; } + + mutex_unlock(&ina->lock); + + return ret; } static int ina3221_read_string(struct device *dev, enum hwmon_sensor_types type, @@ -582,6 +609,7 @@ static int ina3221_probe(struct i2c_client *client, if (ret) return ret; + mutex_init(&ina->lock); dev_set_drvdata(dev, ina); hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, ina, @@ -589,12 +617,22 @@ static int ina3221_probe(struct i2c_client *client, ina3221_groups); if (IS_ERR(hwmon_dev)) { dev_err(dev, "Unable to register hwmon device\n"); + mutex_destroy(&ina->lock); return PTR_ERR(hwmon_dev); } return 0; } +static int ina3221_remove(struct i2c_client *client) +{ + struct ina3221_data *ina = dev_get_drvdata(&client->dev); + + mutex_destroy(&ina->lock); + + return 0; +} + static int __maybe_unused ina3221_suspend(struct device *dev) { struct ina3221_data *ina = dev_get_drvdata(dev); @@ -663,6 +701,7 @@ MODULE_DEVICE_TABLE(i2c, ina3221_ids); static struct i2c_driver ina3221_i2c_driver = { .probe = ina3221_probe, + .remove = ina3221_remove, .driver = { .name = INA3221_DRIVER_NAME, .of_match_table = ina3221_of_match_table, From patchwork Mon Nov 5 20:48:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10669117 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C899213BF for ; Mon, 5 Nov 2018 20:49:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B1A7829E72 for ; Mon, 5 Nov 2018 20:49:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A3A1B29E5F; Mon, 5 Nov 2018 20:49:09 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 2688729E5F for ; Mon, 5 Nov 2018 20:49:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387722AbeKFGKf (ORCPT ); Tue, 6 Nov 2018 01:10:35 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:39368 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727329AbeKFGKX (ORCPT ); Tue, 6 Nov 2018 01:10:23 -0500 Received: by mail-pf1-f193.google.com with SMTP id n11-v6so4994545pfb.6; Mon, 05 Nov 2018 12:48:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=py2saqwnL0jJ4Sun7/vf2GxVpITa6mnrjAiJg1FsXec=; b=BprR4N7rR215A9dR1RcYyKb6e/6dzxI3wQEUfMbUe+6TgG5d7AzFmLekWowT++iUQD H+pj/LZ4EMGoaoZgzZQHH+BiJToWrbistv4GRrRSwqi3gzHNqS3Q/Drw54ykQGIGYPSS 4y2G6SS3u+F1UGDi2dDNc2TIQPS+OZ8amjksDTfvULFRhkQNqacX+tutfFOhzVcP++CH nr2OSNi2gCbbiWienBm9czyMbCKCSHmlynC7i5zDRsOUhoHXb1Yivix6OS1+ZW/an6/e CfLjkjEtzYXpOkzb7RLFuhPzjj3gevdZq3O+AbzcKVLO7rZolA/VJJqW8Nyy92Y/PsSi t6dA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=py2saqwnL0jJ4Sun7/vf2GxVpITa6mnrjAiJg1FsXec=; b=QYIGh/gGbo2JJazXEr7YOf53CY839bWl91GYSpYkiEDTkiuOn+tSczFXLjuBDJAbXf jBUZEAUz89Q4cahTyzy9y7QfPaqh+Tgbo5yv3dlAKmxC87VVVdfw7sbBAcgiVJvZQLHQ gJF7wyEoENsk8POSsyuhbi4OqEgYtYMf99zb9krmmBgSDrpHV4SJx8Rn6j+aDpO65lP7 DFJbXxuYigHmHgZkKl2zTZ5lzckEp82iZRfbgEUOb1mLK8FsS6JNlJPVbojrasSvRKlb cYxaHkspToIkLbhc9j1pch/ZNV1Hn/MpQES+EfJjObDfo1PfxA4kxXVr08RW9/kmpKRD 22Ig== X-Gm-Message-State: AGRZ1gJ4rUZ8e3efn0pqkGvESH0oJOGkYyXDArU4MgGDUs4IAIalpbb+ R5ioL5IGAKMC+jXciGMTWl0= X-Google-Smtp-Source: AJdET5dw8kn9cERxbLrnNAege2ZZaz2JDyNv4rUWxFCTsTWAwisZTx7ZYiYsOkiIT9mKKEVEKu8WJQ== X-Received: by 2002:a62:4816:: with SMTP id v22-v6mr14857525pfa.233.1541450932543; Mon, 05 Nov 2018 12:48:52 -0800 (PST) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id q1sm25569257pgs.14.2018.11.05.12.48.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 12:48:52 -0800 (PST) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 3/4] hwmon: (ina3221) Make sure data is ready before reading Date: Mon, 5 Nov 2018 12:48:42 -0800 Message-Id: <20181105204843.4081-4-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181105204843.4081-1-nicoleotsuka@gmail.com> References: <20181105204843.4081-1-nicoleotsuka@gmail.com> 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 data might need some time to get ready after channel enabling, although the data register is always readable. The CVRF bit is to indicate that data conversion is finished, so polling the CVRF bit before data reading could ensure the result being valid. An alternative way could be to wait for expected time between the channel enabling and the data reading. And this could avoid extra I2C communications. However, INA3221 seemly takes longer time than what's stated in the datasheet. Test results show that sometimes it couldn't finish data conversion in time. So this patch plays safe by adding a CVRF polling to make sure the data register is updated with the new data. Signed-off-by: Nicolin Chen --- Changelog v3->v5: * N/A v2->v3: * Dropped timeout dev_err messages as it's indicated in the errno v1->v2: * Moved CVRF polling to data read routine * Added calculation of wait time based on conversion time setting drivers/hwmon/ina3221.c | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 10e8347a3c80..07dd6ef58d3e 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -44,6 +44,13 @@ #define INA3221_CONFIG_MODE_SHUNT BIT(0) #define INA3221_CONFIG_MODE_BUS BIT(1) #define INA3221_CONFIG_MODE_CONTINUOUS BIT(2) +#define INA3221_CONFIG_VSH_CT_SHIFT 3 +#define INA3221_CONFIG_VSH_CT_MASK GENMASK(5, 3) +#define INA3221_CONFIG_VSH_CT(x) (((x) & GENMASK(5, 3)) >> 3) +#define INA3221_CONFIG_VBUS_CT_SHIFT 6 +#define INA3221_CONFIG_VBUS_CT_MASK GENMASK(8, 6) +#define INA3221_CONFIG_VBUS_CT(x) (((x) & GENMASK(8, 6)) >> 6) +#define INA3221_CONFIG_CHs_EN_MASK GENMASK(14, 12) #define INA3221_CONFIG_CHx_EN(x) BIT(14 - (x)) #define INA3221_RSHUNT_DEFAULT 10000 @@ -52,6 +59,9 @@ enum ina3221_fields { /* Configuration */ F_RST, + /* Status Flags */ + F_CVRF, + /* Alert Flags */ F_WF3, F_WF2, F_WF1, F_CF3, F_CF2, F_CF1, @@ -63,6 +73,7 @@ enum ina3221_fields { static const struct reg_field ina3221_reg_fields[] = { [F_RST] = REG_FIELD(INA3221_CONFIG, 15, 15), + [F_CVRF] = REG_FIELD(INA3221_MASK_ENABLE, 0, 0), [F_WF3] = REG_FIELD(INA3221_MASK_ENABLE, 3, 3), [F_WF2] = REG_FIELD(INA3221_MASK_ENABLE, 4, 4), [F_WF1] = REG_FIELD(INA3221_MASK_ENABLE, 5, 5), @@ -111,6 +122,28 @@ static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel) return ina->reg_config & INA3221_CONFIG_CHx_EN(channel); } +/* Lookup table for Bus and Shunt conversion times in usec */ +static const u16 ina3221_conv_time[] = { + 140, 204, 332, 588, 1100, 2116, 4156, 8244, +}; + +static inline int ina3221_wait_for_data(struct ina3221_data *ina) +{ + u32 channels = hweight16(ina->reg_config & INA3221_CONFIG_CHs_EN_MASK); + u32 vbus_ct_idx = INA3221_CONFIG_VBUS_CT(ina->reg_config); + u32 vsh_ct_idx = INA3221_CONFIG_VSH_CT(ina->reg_config); + u32 vbus_ct = ina3221_conv_time[vbus_ct_idx]; + u32 vsh_ct = ina3221_conv_time[vsh_ct_idx]; + u32 wait, cvrf; + + /* Calculate total conversion time */ + wait = channels * (vbus_ct + vsh_ct); + + /* Polling the CVRF bit to make sure read data is ready */ + return regmap_field_read_poll_timeout(ina->fields[F_CVRF], + cvrf, cvrf, wait, 100000); +} + static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg, int *val) { @@ -150,6 +183,10 @@ static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val) if (!ina3221_is_enabled(ina, channel)) return -ENODATA; + ret = ina3221_wait_for_data(ina); + if (ret) + return ret; + ret = ina3221_read_value(ina, reg, ®val); if (ret) return ret; @@ -189,6 +226,11 @@ static int ina3221_read_curr(struct device *dev, u32 attr, case hwmon_curr_input: if (!ina3221_is_enabled(ina, channel)) return -ENODATA; + + ret = ina3221_wait_for_data(ina); + if (ret) + return ret; + /* fall through */ case hwmon_curr_crit: case hwmon_curr_max: From patchwork Mon Nov 5 20:48:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10669113 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 89DCE15E9 for ; Mon, 5 Nov 2018 20:49:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 71A5A29E26 for ; Mon, 5 Nov 2018 20:49:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 63DDF29E76; Mon, 5 Nov 2018 20:49:01 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 BD23529E26 for ; Mon, 5 Nov 2018 20:49:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387670AbeKFGKZ (ORCPT ); Tue, 6 Nov 2018 01:10:25 -0500 Received: from mail-pg1-f194.google.com ([209.85.215.194]:36175 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387580AbeKFGKY (ORCPT ); Tue, 6 Nov 2018 01:10:24 -0500 Received: by mail-pg1-f194.google.com with SMTP id z17-v6so4764967pgv.3; Mon, 05 Nov 2018 12:48:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4p2prooMrBuBN4DjqsFBoeT3ZNXy+n4g0jtJQCtamEY=; b=KxXp5O3nlFzH394M8iOijRUV4ze0v0Sq12AIemSnlkXkhvGj9mQg+fwckBIbH1YV33 j4AFPyY4Zl9d1RDgOwY+2f2Rlw6FKGauMeniuZjweP1qCeIVFFWikkxXhV7yTLxLDjAr jXemXkRGntoAbaRSsYwFfQUcI/v9dFaH5OPZfhjr0poZrd5IJ8eFhtuUGV2t8fQrSBYA lLyvh9+ALOkUBaiajSlNtaTTb5IaobkfhFQi9bzXJMosj9PeLAAviHcF0DUDEsV/mjK3 rr3n9tCoA0HRY6BIaEcSCyhyBS7fnUuQYSvClTPEQZVh24LapL9o6Lo8oJVJdIaEvDpy XAng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4p2prooMrBuBN4DjqsFBoeT3ZNXy+n4g0jtJQCtamEY=; b=FJn4d19Zgj0qdOYVIGrVmIt6OZMRxwY31qKHtFwxHTlto6aO2KOxCcr0jTqepyUl/g i9e3XNBeatxrTKpy4seso6aAVE9Py028UxWLSy97QeGlpEKwObuPl6mcLZNDLb6rbc2v 8JG44E0pbratrhSh7jBYLQ2Gd34hL3BTYQBQrVgWhl00cI0t4zgrCRCAv4T7bHuLFljj zzDBvuRtVJrQu5j0I9anxx55a53NMQcPtNnIdiCTXgzVjWKUseY0S+8Q+ozjalo3VqpG HF8bIZa6JXEXUnVRHGVlKAeoRnI/Fr73ODO5Cu6PkXHfL9f6pfaeK6LBATC64HmZJibx yR2A== X-Gm-Message-State: AGRZ1gKnNnh5FxGhuSx+nevDhoNJT8OkeezQ7Pag2Z12r6jZlbl4HfI0 0iBs/cfV1LkaosktjepSNSI= X-Google-Smtp-Source: AJdET5fjqjSB6oZS+Mn3Cmw1GPHduZZkGC+b+pTIHWI3/bulXXQuNaIPjnRe0N5gJwv+0Xn4HalrgA== X-Received: by 2002:a63:1a0c:: with SMTP id a12mr1328600pga.157.1541450933245; Mon, 05 Nov 2018 12:48:53 -0800 (PST) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id q1sm25569257pgs.14.2018.11.05.12.48.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 12:48:52 -0800 (PST) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 4/4] hwmon: (ina3221) Add PM runtime support Date: Mon, 5 Nov 2018 12:48:43 -0800 Message-Id: <20181105204843.4081-5-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181105204843.4081-1-nicoleotsuka@gmail.com> References: <20181105204843.4081-1-nicoleotsuka@gmail.com> 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 If all three channels are disabled via in[123]_enable ABI, the driver could suspend the chip for power saving purpose. So this patch adds the PM runtime support in order to gain more power control than system suspend and resume use case. For PM runtime, there are a few related changes happening: 1) Added a new pm_dev device pointer for all the PM runtime callbacks. This is because hwmon core registers a child device for each hwmon driver and passes it back to each driver. So there might be a mismatch between two device pointers in the driver if mixing using them. 2) Added a check in ina3221_is_enabled() to make sure that the chip is resumed. 3) Bypassed the unchanged status in ina3221_write_enable() in order to keep the PM runtime refcount being matched. 4) Removed the reset routine in the probe() by calling the resume() via pm_runtime_get_sync() instead, as they're similar. It's also necessary to do so to match initial PM refcount with the number of enabled channels. Signed-off-by: Nicolin Chen --- Changelog v4->v5: * Dropped the code of passing pm pointer via _info API ** Moved all changes back to the status of v3 * Used i2c_client dev pointer for pm runtime callbacks v3->v4: * Passed pm pointer via _with_info API instead the i2c driver v2->v3: * Improved a dev_err message * Added comments at pm_runtime_put_noidle() callbacks * Added pm_runtime header file in an alphabetical order v1->v2: * Bypassed i2c_client->dev in suspend/resume() * Added a missing '\n' in one dev_err() drivers/hwmon/ina3221.c | 93 ++++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 19 deletions(-) diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 07dd6ef58d3e..17a57dbc0424 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #define INA3221_DRIVER_NAME "ina3221" @@ -53,6 +54,7 @@ #define INA3221_CONFIG_CHs_EN_MASK GENMASK(14, 12) #define INA3221_CONFIG_CHx_EN(x) BIT(14 - (x)) +#define INA3221_CONFIG_DEFAULT 0x7127 #define INA3221_RSHUNT_DEFAULT 10000 enum ina3221_fields { @@ -103,6 +105,7 @@ struct ina3221_input { /** * struct ina3221_data - device specific information + * @pm_dev: Device pointer for pm runtime * @regmap: Register map of the device * @fields: Register fields of the device * @inputs: Array of channel input source specific structures @@ -110,6 +113,7 @@ struct ina3221_input { * @reg_config: Register value of INA3221_CONFIG */ struct ina3221_data { + struct device *pm_dev; struct regmap *regmap; struct regmap_field *fields[F_MAX_FIELDS]; struct ina3221_input inputs[INA3221_NUM_CHANNELS]; @@ -119,7 +123,8 @@ struct ina3221_data { static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel) { - return ina->reg_config & INA3221_CONFIG_CHx_EN(channel); + return pm_runtime_active(ina->pm_dev) && + (ina->reg_config & INA3221_CONFIG_CHx_EN(channel)); } /* Lookup table for Bus and Shunt conversion times in usec */ @@ -290,21 +295,48 @@ static int ina3221_write_enable(struct device *dev, int channel, bool enable) { struct ina3221_data *ina = dev_get_drvdata(dev); u16 config, mask = INA3221_CONFIG_CHx_EN(channel); + u16 config_old = ina->reg_config & mask; int ret; config = enable ? mask : 0; + /* Bypass if enable status is not being changed */ + if (config_old == config) + return 0; + + /* For enabling routine, increase refcount and resume() at first */ + if (enable) { + ret = pm_runtime_get_sync(ina->pm_dev); + if (ret < 0) { + dev_err(dev, "Failed to get PM runtime\n"); + return ret; + } + } + /* Enable or disable the channel */ ret = regmap_update_bits(ina->regmap, INA3221_CONFIG, mask, config); if (ret) - return ret; + goto fail; /* Cache the latest config register value */ ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config); if (ret) - return ret; + goto fail; + + /* For disabling routine, decrease refcount or suspend() at last */ + if (!enable) + pm_runtime_put_sync(ina->pm_dev); return 0; + +fail: + if (enable) { + dev_err(dev, "Failed to enable channel %d: error %d\n", + channel, ret); + pm_runtime_put_sync(ina->pm_dev); + } + + return ret; } static int ina3221_read(struct device *dev, enum hwmon_sensor_types type, @@ -631,44 +663,65 @@ static int ina3221_probe(struct i2c_client *client, return ret; } - ret = regmap_field_write(ina->fields[F_RST], true); - if (ret) { - dev_err(dev, "Unable to reset device\n"); - return ret; - } - - /* Sync config register after reset */ - ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config); - if (ret) - return ret; + /* The driver will be reset, so use reset value */ + ina->reg_config = INA3221_CONFIG_DEFAULT; /* Disable channels if their inputs are disconnected */ for (i = 0; i < INA3221_NUM_CHANNELS; i++) { if (ina->inputs[i].disconnected) ina->reg_config &= ~INA3221_CONFIG_CHx_EN(i); } - ret = regmap_write(ina->regmap, INA3221_CONFIG, ina->reg_config); - if (ret) - return ret; + ina->pm_dev = dev; mutex_init(&ina->lock); dev_set_drvdata(dev, ina); + /* Enable PM runtime -- status is suspended by default */ + pm_runtime_enable(ina->pm_dev); + + /* Initialize (resume) the device */ + for (i = 0; i < INA3221_NUM_CHANNELS; i++) { + if (ina->inputs[i].disconnected) + continue; + /* Match the refcount with number of enabled channels */ + ret = pm_runtime_get_sync(ina->pm_dev); + if (ret < 0) + goto fail; + } + hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, ina, &ina3221_chip_info, ina3221_groups); if (IS_ERR(hwmon_dev)) { dev_err(dev, "Unable to register hwmon device\n"); - mutex_destroy(&ina->lock); - return PTR_ERR(hwmon_dev); + ret = PTR_ERR(hwmon_dev); + goto fail; } return 0; + +fail: + pm_runtime_disable(ina->pm_dev); + pm_runtime_set_suspended(ina->pm_dev); + /* pm_runtime_put_noidle() will decrease the PM refcount until 0 */ + for (i = 0; i < INA3221_NUM_CHANNELS; i++) + pm_runtime_put_noidle(ina->pm_dev); + mutex_destroy(&ina->lock); + + return ret; } static int ina3221_remove(struct i2c_client *client) { struct ina3221_data *ina = dev_get_drvdata(&client->dev); + int i; + + pm_runtime_disable(ina->pm_dev); + pm_runtime_set_suspended(ina->pm_dev); + + /* pm_runtime_put_noidle() will decrease the PM refcount until 0 */ + for (i = 0; i < INA3221_NUM_CHANNELS; i++) + pm_runtime_put_noidle(ina->pm_dev); mutex_destroy(&ina->lock); @@ -726,7 +779,9 @@ static int __maybe_unused ina3221_resume(struct device *dev) } static const struct dev_pm_ops ina3221_pm = { - SET_SYSTEM_SLEEP_PM_OPS(ina3221_suspend, ina3221_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(ina3221_suspend, ina3221_resume, NULL) }; static const struct of_device_id ina3221_of_match_table[] = {