From patchwork Wed Oct 24 19:33:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10654907 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 D4A2814E2 for ; Wed, 24 Oct 2018 19:34:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C22B42839C for ; Wed, 24 Oct 2018 19:34:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B4C3F2B0B9; Wed, 24 Oct 2018 19:34:52 +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 B281D2839C for ; Wed, 24 Oct 2018 19:34:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727131AbeJYEDi (ORCPT ); Thu, 25 Oct 2018 00:03:38 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:37534 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725817AbeJYEDh (ORCPT ); Thu, 25 Oct 2018 00:03:37 -0400 Received: by mail-pf1-f196.google.com with SMTP id j23-v6so2930097pfi.4; Wed, 24 Oct 2018 12:34:16 -0700 (PDT) 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=jxA/4tYnI4eV6Lr2ToAINbnH9pilQBxyPt4EVIDdWSE=; b=VwXlbdRPfMzgpyZ0bBYA5d+ng6Z/TziXIfrohQN91Xbp2Yq9bej3HRV0MV+66kNdcN 0I6oeU3+WlL0K6e+mJDlKNbzvROIQEASsJ9KfweBPADd8FkId3U5BdJOeSSwukSou0LL P8v42TU70rCxkARmvW0ZmUJr3DFkHdfJJJvUeGDfGnc92h+HPpGhRUkv+6U1ejuZjnPo GEUMGdiQe1UZBpOIoQfd9moDF1bqENy69KK1q9A36YQZ+ButQtXHnsWXaS7opkuPsZy0 hQVwkKqnvpemQTyOeAXxPV9LqoWnjkdowSnLK1wl98boYAXNCwCPyAZEbDKD2wgr6irO lRdQ== 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=jxA/4tYnI4eV6Lr2ToAINbnH9pilQBxyPt4EVIDdWSE=; b=cewdvoLfs2p4c3Ob8g87zBFOWobKGg7xG7WAnHaS84sdsdJzhs4+h1oZm3gE0VH44O vm5mD57MQCdAG55arPRJs3tZYkTlAkdVKOKPnhpYontnk5ERxurqSh3Tz5zNhkhmwv0z yOfPL6hT6hIMqB07tvf3AWHyWpB1hNMocE+qox1ioGbOXPJ/POVkrLV/UyzRrRHm/CTj sLAFZJuDwZKd3RcVMMQT1zB7XAlhB1YPltjby/IpGC6ojy0XD54h6M79qw7a1NGnsZcR 6n3vAo76mvAKJxcMDWKMRnvMQAZDSdabwnHyGuUTf6yNpK6FPZ+QRt8TSG35vlNixto0 Rf0A== X-Gm-Message-State: AGRZ1gKCWSZXSMdDj5gc9fJy1bhEK+pOdFl77gOXWtefrdMmeqru+5sK n3ltOL9YACOox1hrWPrTBDc= X-Google-Smtp-Source: AJdET5ep81f6KzDr0rQB+6Kit4o4gtnOF0rGLh+jKXFN3vFv6QnCcSF7fCIby/TMl7ijK8wpouOh6A== X-Received: by 2002:aa7:84cc:: with SMTP id x12-v6mr3893607pfn.220.1540409656411; Wed, 24 Oct 2018 12:34:16 -0700 (PDT) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id r81-v6sm19921633pfa.110.2018.10.24.12.34.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 12:34:15 -0700 (PDT) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/5] hwmon: (core) Inherit power properties to hdev Date: Wed, 24 Oct 2018 12:33:58 -0700 Message-Id: <20181024193402.16698-2-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024193402.16698-1-nicoleotsuka@gmail.com> References: <20181024193402.16698-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 new hdev is a child device related to the original parent hwmon driver and its device. However, it doesn't support the power features, typically being defined in the parent driver. So this patch inherits three necessary power properties from the parent dev to hdev: power, pm_domain and driver pointers. Note that the dev->driver pointer is the place that contains a dev_pm_ops pointer defined in the parent device driver and the pm runtime core also checks this pointer: if (!cb && dev->driver && dev->driver->pm) Signed-off-by: Nicolin Chen --- Changelog v2->v3: * N/A v1->v2: * Added device pointers drivers/hwmon/hwmon.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 975c95169884..14cfab64649f 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -625,7 +625,12 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, hwdev->name = name; hdev->class = &hwmon_class; hdev->parent = dev; - hdev->of_node = dev ? dev->of_node : NULL; + if (dev) { + hdev->driver = dev->driver; + hdev->power = dev->power; + hdev->pm_domain = dev->pm_domain; + hdev->of_node = dev->of_node; + } hwdev->chip = chip; dev_set_drvdata(hdev, drvdata); dev_set_name(hdev, HWMON_ID_FORMAT, id); From patchwork Wed Oct 24 19:33:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10654905 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 4F2AC14E2 for ; Wed, 24 Oct 2018 19:34:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E44F2839C for ; Wed, 24 Oct 2018 19:34:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 329BF2B0B9; Wed, 24 Oct 2018 19:34:48 +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 C1EB12839C for ; Wed, 24 Oct 2018 19:34:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727161AbeJYEDj (ORCPT ); Thu, 25 Oct 2018 00:03:39 -0400 Received: from mail-pf1-f193.google.com ([209.85.210.193]:33073 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725817AbeJYEDi (ORCPT ); Thu, 25 Oct 2018 00:03:38 -0400 Received: by mail-pf1-f193.google.com with SMTP id 22-v6so2941647pfz.0; Wed, 24 Oct 2018 12:34:17 -0700 (PDT) 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=ErQIde3ytmx8BZaFyBy+CXyz9NH/Bog4bW1OGBrV7Nw=; b=exDauN6+6zYVvBCFU4vdKfTLAynQCUccVsbXBwVn05M1cAButQqRi7icqiwogzer1O pdNapF2Sddoa5jfzAPeIXoVZb/il923zOIvlWcErhLzWiei9cd2hIjpkwrI/WE+1qgTo zq6oBucVA1CTWTGuusQu3habTo7YJluT1pBTcHT18XgsGH9LstQ8kfYH/MhsYMObR3uO EPdyb0pQRQ7tlHzQ255fVJpfogyc4mBOTQmqHnlNGS9xohbi+YeFhzwu3qk92sgYd2YO 0oLvdDApIPHiRNHTKsmI9j7JtT24Eq/toqMVS1jNiUh2Uvm4hQsDhWfNeaGh5BBZ/2lh MaAg== 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=ErQIde3ytmx8BZaFyBy+CXyz9NH/Bog4bW1OGBrV7Nw=; b=iQYw2+iYZ7V2DiDZFOxK82niau95qh2hmnAc/14k63jdxVqFgxfFsZijX0Fw7WHQfe gslCwzEUYZ0N01oL7+cOzgvY3nzc8/JX0vmx7B/f3cq4M3StgQ9CTM0oM27K6kr7t7Ky XijxA69jEfFJbZuq1UNucea9DxA+DNCtTYW4cf8/AFg8jauDx6aIw+ajf9nit3EY1NrZ CxrL7esFKRgBHnHLGXBptypXgThIfgDoMaeacid2iNRZyxJKWr2PchIS03KmDbpzhBrZ 2UsDYysqqvn/GqiWA84Z7w1F+jbmVNShm+tXjRVyEOjJZ8LAmh4sfC+01jI5AQTD40eb 0pmQ== X-Gm-Message-State: AGRZ1gKyjvoQGOuY61B/lLSet7qyqYvR9vdJoyVWbXkDUw6uMWwMz63V +gpFnrRNtUMA6qY4KeQyCXY= X-Google-Smtp-Source: AJdET5dHLcfQ6LKnxKasn4Lr3vBppeaoFPyAb/S60/B9uM7BYURxrKyQuaMjHoc9AnQ2IAgtkyp+Uw== X-Received: by 2002:a63:4c6:: with SMTP id 189mr3733473pge.391.1540409657251; Wed, 24 Oct 2018 12:34:17 -0700 (PDT) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id r81-v6sm19921633pfa.110.2018.10.24.12.34.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 12:34:16 -0700 (PDT) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/5] hwmon: (ina3221) Check channel status for alarms attribute read Date: Wed, 24 Oct 2018 12:33:59 -0700 Message-Id: <20181024193402.16698-3-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024193402.16698-1-nicoleotsuka@gmail.com> References: <20181024193402.16698-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->v3: * 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 Wed Oct 24 19:34:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10654901 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 1CC6A14E2 for ; Wed, 24 Oct 2018 19:34:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0B52F2839C for ; Wed, 24 Oct 2018 19:34:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F3C0E2B0B9; Wed, 24 Oct 2018 19:34:41 +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 823E72839C for ; Wed, 24 Oct 2018 19:34:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727256AbeJYEDk (ORCPT ); Thu, 25 Oct 2018 00:03:40 -0400 Received: from mail-pg1-f195.google.com ([209.85.215.195]:45487 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727173AbeJYEDj (ORCPT ); Thu, 25 Oct 2018 00:03:39 -0400 Received: by mail-pg1-f195.google.com with SMTP id s3-v6so2789324pga.12; Wed, 24 Oct 2018 12:34:18 -0700 (PDT) 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=HYBMANsFtxTvEdz9erpZJE2vyqhPlAPNtRDSmO7XKEw=; b=nMdmMVYqB1CXISq9sWKNM8DbvIcy2wCj+DBB0YEpSH/372Yl9TZQ6/8ZVUG5P9Rz9u pWwK01nVwQubX7ELXWyjViXSi278QbXUzVrxgkd9i30KlwL/vfJLPX1aZGTpyUqXp9WU SmtKZGnlApRD4JjmIK34Yca5ffpCn0HhXyyTi8BPzm807r+/9XCWoSMxCE97m83FEGKz 4EVtZmhHZ11SGz5Zdio4uq5zzjjUqNVnTlt/C8sd1xu+bBBSm+5uWqj2dFMwQKmbCbQK iCXvXHP8YjRdm7+IE5Gu6vD/CTTBt7KXwIPEboIg2ABWsNKtiZCWqG/U51tSDLsjft4Q ob3g== 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=HYBMANsFtxTvEdz9erpZJE2vyqhPlAPNtRDSmO7XKEw=; b=UO5EF5xS5STE0LnCwtPOc9uHVPBm/dudOYn5SvCCL0jrbtWyW7FtWtY/kiexXnLHlC 8tH0m2RX56fa0k0GIwXqz+5m9Exk5gOCDyD8dlgn+cvjxwNgrN2XLBLJta0xQSgrQEAo RZHx1q17VppVwnUrkhb8KKBXtM3e7JBqp+ONTQe6/6YpjeVnptcTbhXEBVXWsJT1n3zO Xl6s2tVyGXTn9Kpdyr91ibrmE30JFhmAGyBbCvR7csS+HZuaqr1pfWitDE0UWJGiubT8 H3WZhooJm61LgMniWyqXk6Y9JRGHW/nTCxEjJrs7OKhfqnXNXfNzJ/JJQMhKSWVfyOwJ YaMA== X-Gm-Message-State: AGRZ1gKfruDfnJXXFA6z2WdwgZDFq5BqXrBjLtIzEwCD8wD2oGDx3wq0 NWrMhF2EdlMP5MlbTbR6ifE= X-Google-Smtp-Source: AJdET5eDR9ND4Neq7WlmKCTMGAtsS+1bgr4XOsnP00bvlec+h678RPYcgFJrw8biKoascrI3vxEkhw== X-Received: by 2002:a62:9f11:: with SMTP id g17-v6mr3867594pfe.144.1540409658027; Wed, 24 Oct 2018 12:34:18 -0700 (PDT) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id r81-v6sm19921633pfa.110.2018.10.24.12.34.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 12:34:17 -0700 (PDT) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 3/5] hwmon: (ina3221) Serialize sysfs ABI accesses Date: Wed, 24 Oct 2018 12:34:00 -0700 Message-Id: <20181024193402.16698-4-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024193402.16698-1-nicoleotsuka@gmail.com> References: <20181024193402.16698-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->v3: * 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 Wed Oct 24 19:34:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10654903 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 5D2AE14BB for ; Wed, 24 Oct 2018 19:34:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4C7092839C for ; Wed, 24 Oct 2018 19:34:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 409052B0B9; Wed, 24 Oct 2018 19:34:44 +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 CA5DA2839C for ; Wed, 24 Oct 2018 19:34:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727220AbeJYEDk (ORCPT ); Thu, 25 Oct 2018 00:03:40 -0400 Received: from mail-pl1-f194.google.com ([209.85.214.194]:39842 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725817AbeJYEDk (ORCPT ); Thu, 25 Oct 2018 00:03:40 -0400 Received: by mail-pl1-f194.google.com with SMTP id e67-v6so2693379plb.6; Wed, 24 Oct 2018 12:34:19 -0700 (PDT) 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=6N/GlUC27cnYsO8+zk0TomAYmkISb/0zWfW0oqqa/6k=; b=sErbTQ7otRVfVKLq5aPLqwxhH55uaCnoAeVAY049QaAS3P50WXx8Hs2Rog83cIBpFZ 382wk2YBvOnvUZCjz0EiXFmr5gORYVihL3DzoIlLcw0x7ht0DANk5rU094nEL55GUcwU NQfEg3+GAVvygjzOYq3FpFKAx686Ff083Z1++7nRHn6jXBbR0toAiGiv6/Wyv3dDD9s5 1zl+s0CtsQJiFVu3f0cKIGm40HEo7KAXuwMmu7nXCx3hIhomJLmsiRFimiUCkGzOBzby XRhFcle8in07luWoCjamKch3s9CEAXlgg3uu8SbGLXIylg0gdEmPH9glHDjCLH+bRmwC YMPQ== 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=6N/GlUC27cnYsO8+zk0TomAYmkISb/0zWfW0oqqa/6k=; b=VrZwQCDFoUtsoOvxmR+Adq3essr4pEXehS6Xjt3axTNWN6KJIDFMnW8fZLeLKVDNCf Dec5L7LlUFKZl6hdG9LNCKqtSbBBNbqrYMGAuHbdzuhEdXtWbPT1wtNtc4Zzidg215DM rCCaiPJXEgnJdnbCB0utEV+8j088ECQ5/ygrDp3SZe5fysxr2KJ4p2JDMtrchtvuGhXR Bsi8g5RpW/F6qRB/d3GYXIDP9YcpOm6GKtmuXCCHKdBCIxS3IsC+thnU8Or688l2WJmI LH5qL+q2j4goMXmMT8gNvT/sLgykPxP37+B19NJt9BhMG8bc2Q85bSaXcFYdhijB3c80 QP3A== X-Gm-Message-State: AGRZ1gIIYTsORXkGaJhQJ12QFPjd24Kxe3HpJiMvaxNL1Sgxsm8TNJoy qTcQVqtYaeIOLB2TW+4HND8= X-Google-Smtp-Source: AJdET5fxe1HMaJfd73kESiZr6J48PRLcVx8vyat77+zxJpZVSNpgwT/Ebnz2lzZirwNrauLeT+KF9Q== X-Received: by 2002:a17:902:4103:: with SMTP id e3-v6mr3660408pld.236.1540409658897; Wed, 24 Oct 2018 12:34:18 -0700 (PDT) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id r81-v6sm19921633pfa.110.2018.10.24.12.34.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 12:34:18 -0700 (PDT) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 4/5] hwmon: (ina3221) Make sure data is ready before reading Date: Wed, 24 Oct 2018 12:34:01 -0700 Message-Id: <20181024193402.16698-5-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024193402.16698-1-nicoleotsuka@gmail.com> References: <20181024193402.16698-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 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 Wed Oct 24 19:34:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10654899 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 854E014E2 for ; Wed, 24 Oct 2018 19:34:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 73CCD2839C for ; Wed, 24 Oct 2018 19:34:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 680732B0B9; Wed, 24 Oct 2018 19:34:40 +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 B42A02839C for ; Wed, 24 Oct 2018 19:34:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725821AbeJYEDx (ORCPT ); Thu, 25 Oct 2018 00:03:53 -0400 Received: from mail-pl1-f193.google.com ([209.85.214.193]:44888 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727225AbeJYEDl (ORCPT ); Thu, 25 Oct 2018 00:03:41 -0400 Received: by mail-pl1-f193.google.com with SMTP id d23-v6so2682151pls.11; Wed, 24 Oct 2018 12:34:20 -0700 (PDT) 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=jZRxRcX58vlVGx5DKWx9aAIsUJCedGMpn9hiGaSCbQE=; b=OUB6CNtYorsuxgAcf3wXfwJsSR8ugZ7jkT2kQHPJtnO4xuJ5BXcjAQ00LCVtqX9b9O AjRudzgD2Wayxuiuj4Ryjj6HMUAcxe3LzSTUrt6XyH2UI3sZR/lxf+THwgiDtvZsl5aq cWbz0sKtS4tky7YJYE2yO71qOPoQqa45dVa6XvllyuEZIY2PBGPwclm6HpQsix6llWwK JY/KZ5BEdzRmZqy7wEwGLFvmADCGlOV2V7h6zK4oGVEVPnpN3QlRzBWWNvSLJsgRydHc 36Y+LjYN7oyK347YtRwToj9uYeWjME81TB6DLsSJVl/o5a3WayFPSEhRGliQoKF9g0u0 eCFA== 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=jZRxRcX58vlVGx5DKWx9aAIsUJCedGMpn9hiGaSCbQE=; b=n/qdAkXiwM8WtuJ42I2TIiuTkv/M7WNBsLTo6d/Jg0GnxEbKQ1EOLxarjJegE7WnKA MVCXyOcw2MkPEr70dLRfe27kPZvWH8HNBte4qXXHjj+Die7/OppWTvwDGg65U4aZ/4Aj rZU71nLQSe6EL2ADIcJzf3Ny/B6GpSFmnNBJ56BrT+ZEMekUOrlC6BHeI5rflo1WpOur oj+eZZY9B/zNyiEUscY4gc6bSlYt4j1peoLndc1S8dyASDhfIGzNnI8dEy0ydccaHrCV gHO26eWpKO7+6PWU5DTu5FCLTAjSck/ePRmIhXYmvxPkebNd7sB6PMisoMaERNrxijmH fwAw== X-Gm-Message-State: AGRZ1gLD+Gia38uR5mxvcGBpQNc7p8C9IaF5alBgwA1qboHvVMyhjTbE gitG1xB6Sgv7+B+HgHwSbRk= X-Google-Smtp-Source: AJdET5dIsk7U8vC0XupwawVVtbYjOYZAw+5h1dUR8FSMAFcc8fzbQ8rvcaImGh0YGadDkLcPIF8uOw== X-Received: by 2002:a17:902:748a:: with SMTP id h10-v6mr3657913pll.187.1540409659761; Wed, 24 Oct 2018 12:34:19 -0700 (PDT) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id r81-v6sm19921633pfa.110.2018.10.24.12.34.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 12:34:19 -0700 (PDT) From: Nicolin Chen To: jdelvare@suse.com, linux@roeck-us.net Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 5/5] hwmon: (ina3221) Add PM runtime support Date: Wed, 24 Oct 2018 12:34:02 -0700 Message-Id: <20181024193402.16698-6-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024193402.16698-1-nicoleotsuka@gmail.com> References: <20181024193402.16698-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 explicit hdev device pointer for all the PM runtime callbacks. This is because hwmon core registers a child device for each hwmon 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. 5) Bypassed the system suspend/resume callbacks from the i2c_client->dev, because both the i2c_client->dev and the ina->hdev coexist and share the same pair of system suspend/resume callback functions, which means there'd be two suspend() calls during the system suspend while the second one will fail. Signed-off-by: Nicolin Chen --- Changelog 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 | 113 ++++++++++++++++++++++++++++++++-------- 1 file changed, 91 insertions(+), 22 deletions(-) diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 07dd6ef58d3e..3e7c6fac6e1b 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 + * @hdev: Device pointer of hwmon child device, used 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 *hdev; 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->hdev) && + (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->hdev); + 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->hdev); return 0; + +fail: + if (enable) { + dev_err(dev, "Failed to enable channel %d: error %d\n", + channel, ret); + pm_runtime_put_sync(ina->hdev); + } + + return ret; } static int ina3221_read(struct device *dev, enum hwmon_sensor_types type, @@ -599,7 +631,6 @@ static int ina3221_probe(struct i2c_client *client, { struct device *dev = &client->dev; struct ina3221_data *ina; - struct device *hwmon_dev; int i, ret; ina = devm_kzalloc(dev, sizeof(*ina), GFP_KERNEL); @@ -631,44 +662,72 @@ 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; mutex_init(&ina->lock); dev_set_drvdata(dev, ina); - hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, ina, + /* Fence sysfs nodes till pm_runtime is resumed */ + mutex_lock(&ina->lock); + + /* Use the returned hdev for pm_runtime */ + ina->hdev = devm_hwmon_device_register_with_info(dev, client->name, ina, &ina3221_chip_info, ina3221_groups); - if (IS_ERR(hwmon_dev)) { + if (IS_ERR(ina->hdev)) { dev_err(dev, "Unable to register hwmon device\n"); - mutex_destroy(&ina->lock); - return PTR_ERR(hwmon_dev); + ret = PTR_ERR(ina->hdev); + goto fail_lock; } + /* Enable PM runtime -- status is suspended by default */ + pm_runtime_enable(ina->hdev); + + /* 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->hdev); + if (ret < 0) + goto fail_pm; + } + + mutex_unlock(&ina->lock); + return 0; + +fail_pm: + pm_runtime_disable(ina->hdev); + pm_runtime_set_suspended(ina->hdev); + /* pm_runtime_put_noidle() will decrease the PM refcount until 0 */ + for (i = 0; i < INA3221_NUM_CHANNELS; i++) + pm_runtime_put_noidle(ina->hdev); +fail_lock: + mutex_unlock(&ina->lock); + 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->hdev); + pm_runtime_set_suspended(ina->hdev); + + /* pm_runtime_put_noidle() will decrease the PM refcount until 0 */ + for (i = 0; i < INA3221_NUM_CHANNELS; i++) + pm_runtime_put_noidle(ina->hdev); mutex_destroy(&ina->lock); @@ -680,6 +739,10 @@ static int __maybe_unused ina3221_suspend(struct device *dev) struct ina3221_data *ina = dev_get_drvdata(dev); int ret; + /* Let hdev control all PM runtime callbacks */ + if (dev != ina->hdev) + return 0; + /* Save config register value and enable cache-only */ ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config); if (ret) @@ -703,6 +766,10 @@ static int __maybe_unused ina3221_resume(struct device *dev) struct ina3221_data *ina = dev_get_drvdata(dev); int ret; + /* Let hdev control all PM runtime callbacks */ + if (dev != ina->hdev) + return 0; + regcache_cache_only(ina->regmap, false); /* Software reset the chip */ @@ -726,7 +793,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[] = {