From nobody Mon Apr 6 16:28:11 2026 Received: from mail-dy1-f182.google.com (mail-dy1-f182.google.com [74.125.82.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4634E3EE1DA for ; Wed, 18 Mar 2026 19:07:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773860830; cv=none; b=ndpheFuIDkWUALFdZOVL4zZpcuuc09n8iAnuOSLwMYnjhSEXhOS0LV9HM1p6N5VWUlytRBqKOXMxki2hC4bKmEa74q7VNECX9WqhY2z6ZmkxnALoUbaCKqrSEi0wr/1gKmdiZaIngOXd4J8ERpJSNaaqJHI1HI0Ka+aXIEYMrd0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773860830; c=relaxed/simple; bh=Ix0E+ghAlT/s3O64UalU9fFWFzeOgY7nHsaKESKcTQo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CTdxET/krnWUYbIPJIpy6MaSAr9nicyT2lrO8qqSs4CG3tTuh1OdnveK8TNcHALeHQAcj3AaWxBlVPg6xGoVAYkNgL9zoFRT7qzd/IdvEdXYD+H+/pI7fGlLIITp7r6Pfi+zcJbbS3m0RECxPEBp0Wr5EYEoeNRGtWvd5FVXkMY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=CiGicv54; arc=none smtp.client-ip=74.125.82.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="CiGicv54" Received: by mail-dy1-f182.google.com with SMTP id 5a478bee46e88-2c0cf039a45so479372eec.0 for ; Wed, 18 Mar 2026 12:07:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773860828; x=1774465628; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=OfIYfJNP2o1iQz4OXKfFq4L/Db/4rDBcPTYZVS8ZPFk=; b=CiGicv54BtArkUGnV20SURZNYLU2mhAGrj0A0RDnRXuvYImTsUL4GikCkHbHZac7IS hmTniEIYaQsTlCFr+lE8dfXytzM/LmTlmdravbmLoHIHZFfkfnMjbaJdKnN/DNU8wxVH ZuyKHVz20FMQoCyz0SPm8zYSCQslsnsVf3k77QQ67+AQFsXijXXNekAJgRCnSzeMqvSu rru/E2ApRED3Ni1latDwIdY7cnh8DX39wQO8jfsfcjNykGXJskRPTOTaYIRh+Z29gd36 8dzqSim3CnREaJfcgMHHQMqxEY2fv97kvGghDAYnSN0Fz5u+aU+zGqKR7zfmKB2gNXL1 lzIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773860828; x=1774465628; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=OfIYfJNP2o1iQz4OXKfFq4L/Db/4rDBcPTYZVS8ZPFk=; b=nbvskczVmdmxi6ivQ1R4twtgnxohFk6ZOJRKwmvVfO9bXVCSK7Woa+XOXzTGw4BDdp VYyNH2f+ygjsbE4mjqgIa2QwdXEbFhUq7f4Fz1eCkSzHaoWYXzk/K1HJtpesbKdJPnpJ LSGRt4/Ad+Wh4Lm6YPtLEBT7ROt6xSCctSziY5G6rdNseLCQP2Janwvz3Q5rG8eFUBMN 9tz9outCBmh4xJ4zUcxiKz25B8s7Hyal4n5oVriNADrj3HKRbT7jvLWcRKFCDlP8Q0Z/ aIB0PbpJ2KFjT0LlXcAeWe45ngfrmA5ctOiXnTpB8L3FzycaYvCfuaVZutLWfhuSXwmf g0oA== X-Forwarded-Encrypted: i=1; AJvYcCXDKD/rVTlnfbmlGEkL1lyImVrsN2AFehg5unjlbogW5+k23N6LZ71eiogboJdYXf7ixCUdEmhJYy7e0b0=@vger.kernel.org X-Gm-Message-State: AOJu0YyE9l3gstqwoApajw2e4vMm0rAGd4AGtO9UacSsPOAnzkB8qGHG 0B2n6zPkK8v2zITkX3v/TwOXbqjKWqMo+VfItldIZ1YzuRg3U0sfBCv88oG65zLl X-Gm-Gg: ATEYQzzmuSUDeDzo7ceCnsH9IkMgj0KUKVdhhzP/io9jAq6WALseqta3NlYaqaGIxsb quvTcrazffCV1E3kSys94X1Y3OY6kiNna/adsjdB34/ieeuZg0d16R0ayiek8ABLE9HduX2ylQJ Vf5M2+vCXyFNf1YN2Svf65JndPe/EWyr3gekO+37PMWZvTVTWoSNzJg/uWCSNPDy0+18KPYUhTm M2Sonc+RNgwOhOWQnsJ+nTDe1wFqPTA5jqomVvVAnotQATytpXqN1JJ5bZnY4/lp9rJ4VeS8Pqc bbK90A99yLmOB/R1fxIDbzSYI3QWybUbdZ80/i6kalzLRSxn3bDkSVvqT5Ihv8c5eSiFf3fEWX2 rmYwm5zspxNsra550q/FdQ+3r7MOXhxGGy4XxqNYRGVKxoorPdTr1BmSlllbeOmYwN1Fma8Ahum s6s17atHtmq0t1SKoEoS89PViY9AGzLmGgrwHJ9VMsp6H4LPu7rHJMTacnu/oFzZ/jpli4Mvty X-Received: by 2002:a05:7300:8ca2:b0:2c0:c482:7db with SMTP id 5a478bee46e88-2c0e502b25bmr2461837eec.10.1773860828137; Wed, 18 Mar 2026 12:07:08 -0700 (PDT) Received: from localhost.localdomain (c-67-164-93-214.hsd1.ca.comcast.net. [67.164.93.214]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2c0e5582dd5sm4894424eec.15.2026.03.18.12.07.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 12:07:07 -0700 (PDT) From: Sanman Pradhan X-Google-Original-From: Sanman Pradhan To: Guenter Roeck Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, Sanman Pradhan Subject: [PATCH v3 1/2] hwmon: (pmbus) export pmbus_wait and pmbus_update_ts Date: Wed, 18 Mar 2026 12:06:42 -0700 Message-Id: <20260318190643.54372-2-psanman@juniper.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260318190643.54372-1-psanman@juniper.net> References: <20260318190643.54372-1-psanman@juniper.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some PMBus devices require strict inter-transaction delays to avoid NACKs or communication faults. The PMBus core manages this automatically for standard PMBus accesses via pmbus_wait() and pmbus_update_ts(). However, when a device driver performs raw I2C/SMBus transfers (e.g., for long reads or custom commands) that bypass the PMBus core, the core's timing state machine is unaware of the transaction. This can cause the next core-mediated PMBus access to violate the device's required delay. Export pmbus_wait() and pmbus_update_ts() to the PMBUS namespace so device-specific drivers can explicitly synchronize their raw transfers with the core's delay management. Additionally, move the PMBUS_OP_WRITE and PMBUS_OP_PAGE_CHANGE bitmasks into the drivers/hwmon/pmbus/pmbus.h header so callers can accurately report the nature of their raw transactions. Signed-off-by: Sanman Pradhan --- v3: - No changes to this patch in this version. v2: - New patch in the series. - Export pmbus_wait() and pmbus_update_ts() to the PMBUS namespace. - Relocate PMBUS_OP_* bitmasks to the subsystem header. --- drivers/hwmon/pmbus/pmbus.h | 9 +++++++++ drivers/hwmon/pmbus/pmbus_core.c | 13 ++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index 3ddcb742d289..56620ed4ac9c 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -424,6 +424,13 @@ enum vrm_version { vr11 =3D 0, vr12, vr13, imvp9, amd6= 25mv, nvidia195mv }; #define PMBUS_REV_12 0x22 /* PMBus revision 1.2 */ #define PMBUS_REV_13 0x33 /* PMBus revision 1.3 */ =20 +/* + * The type of operation used for picking the delay between + * successive pmbus operations. + */ +#define PMBUS_OP_WRITE BIT(0) +#define PMBUS_OP_PAGE_CHANGE BIT(1) + struct pmbus_driver_info { int pages; /* Total number of pages */ u8 phases[PMBUS_PAGES]; /* Number of phases per page */ @@ -555,6 +562,8 @@ int pmbus_update_byte_data(struct i2c_client *client, i= nt page, u8 reg, void pmbus_clear_faults(struct i2c_client *client); bool pmbus_check_byte_register(struct i2c_client *client, int page, int re= g); bool pmbus_check_word_register(struct i2c_client *client, int page, int re= g); +void pmbus_wait(struct i2c_client *client); +void pmbus_update_ts(struct i2c_client *client, int op); int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *in= fo); const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client); diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_c= ore.c index 4d7634ee6148..b150c2ee670a 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -32,13 +32,6 @@ #define PMBUS_ATTR_ALLOC_SIZE 32 #define PMBUS_NAME_SIZE 24 =20 -/* - * The type of operation used for picking the delay between - * successive pmbus operations. - */ -#define PMBUS_OP_WRITE BIT(0) -#define PMBUS_OP_PAGE_CHANGE BIT(1) - static int wp =3D -1; module_param(wp, int, 0444); =20 @@ -173,7 +166,7 @@ void pmbus_set_update(struct i2c_client *client, u8 reg= , bool update) EXPORT_SYMBOL_NS_GPL(pmbus_set_update, "PMBUS"); =20 /* Some chips need a delay between accesses. */ -static void pmbus_wait(struct i2c_client *client) +void pmbus_wait(struct i2c_client *client) { struct pmbus_data *data =3D i2c_get_clientdata(client); s64 delay =3D ktime_us_delta(data->next_access_backoff, ktime_get()); @@ -181,9 +174,10 @@ static void pmbus_wait(struct i2c_client *client) if (delay > 0) fsleep(delay); } +EXPORT_SYMBOL_NS_GPL(pmbus_wait, "PMBUS"); =20 /* Sets the last operation timestamp for pmbus_wait */ -static void pmbus_update_ts(struct i2c_client *client, int op) +void pmbus_update_ts(struct i2c_client *client, int op) { struct pmbus_data *data =3D i2c_get_clientdata(client); const struct pmbus_driver_info *info =3D data->info; @@ -197,6 +191,7 @@ static void pmbus_update_ts(struct i2c_client *client, = int op) if (delay > 0) data->next_access_backoff =3D ktime_add_us(ktime_get(), delay); } +EXPORT_SYMBOL_NS_GPL(pmbus_update_ts, "PMBUS"); =20 int pmbus_set_page(struct i2c_client *client, int page, int phase) { --=20 2.34.1 From nobody Mon Apr 6 16:28:11 2026 Received: from mail-dy1-f174.google.com (mail-dy1-f174.google.com [74.125.82.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D8E4C3EE1E2 for ; Wed, 18 Mar 2026 19:07:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773860831; cv=none; b=MjlqfAVO3427L96rluR1bpl7azmShFXJ301dtWLNtmq3Az0WBBJ3v92P/CcyfcS4AqMhS/865w7zYgsbJNWOm40XeunQHoZoLg4szipiWuJxH31lg9vUu8i5olPvfWpEqZPjwLubXQZ2P9w3tBnuDCZCrUFiOV1bLP74kzEAb2M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773860831; c=relaxed/simple; bh=3+NzCXM7GAwCb2QumJA5MQOFjv6K6E35VQlDbrPe9do=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kx+vAFSpuvNf+dxC3uTtjoQuM88LcWbbpGBK8Gl1jpjqommnNTr7wMJxg2t5rizS0U3lL17LKNKyoughi4kxNjDfMNF17wfQxwSDo0tMLDbbDELkQIW3NDp65nsxpgRQvIuNS18qBKQIw9VD2ysSDqBa4HOO+HWU5y2OJoeWzWQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KzqvnoUR; arc=none smtp.client-ip=74.125.82.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KzqvnoUR" Received: by mail-dy1-f174.google.com with SMTP id 5a478bee46e88-2bd9a485bd6so440968eec.1 for ; Wed, 18 Mar 2026 12:07:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773860829; x=1774465629; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IUuVSITVac1PeD8ht0OmJx+BPb33jgkvU+nSink4gks=; b=KzqvnoURkK5Sf5Mqy4E3pBjM/m8y01WYgrTxuK1gxKQBfPfCL1A7Zdy7TaSK2G30VG k/Q8Lkg0l+7Tu2kmjCjn6qlj7Tf7XUjMEokPj4jPOdYgvzglrV7++P8np/pxzrTEtcAs +ipc9bap6JYr/KpuoFy96ajVkqr82VV4iIyvTTk7wUwkjD3ArqNvgj75HUK3whN4M6du AIkC1/NqTeADK49+cE7GxJu2gS9xUPCb6ryNdG4UToA+zhy7Msh7SDTLgpxTtWlW9kUe hidmMZV186XldzU0AhwSVKeSK4wHvyKKxHWtQr6inVEUFSkPEHCCrefoSjIPEAXraZzU yIAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773860829; x=1774465629; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=IUuVSITVac1PeD8ht0OmJx+BPb33jgkvU+nSink4gks=; b=SBYtqz101e+8gIcxWYuMIAhtu24XdWlhRUGbE5VVzh8hKFTfAMyfw819MWEVSP8XNc tkt3kAN/VEKl91expy8PpUlN56pSZUDXEMAQXq2IsdqUsYyaTK3LItkcq/bAD0ZZ2ZJ/ IrlwyalmLlXn+lFmprGhfPNinXhnG93JwTD2QEyDzfj/alaW+FNf3EvDDCZ4xAZsMRbl P/KhKNPZpOhSBs4YN71/zzcMCwK9tE5t5Y5gUsh1+NNFX/epuJtKZy/GWfXHiq6L2lPZ Mu8gTbsHYsQJILi2JLKPTZLwzd5GXs9XTx5CsijlO9V2FHaCAfsuXCaDhl2we2GVFOSK 1+Ig== X-Forwarded-Encrypted: i=1; AJvYcCVt/PpGmd2mlB7Fc6+04pVeMM21SY+kWmboR7kEKrMOzuB1XiftyUDNRLP4cUzLsidZ273RKvaWBh90c2M=@vger.kernel.org X-Gm-Message-State: AOJu0YyxAaao7XCaZY1hVpWjOKCoFx9rOEZyrm3wq/OIjX2K0dlYVQdD uXEnp+GpiIwmBjAHrrSRPE94GWuGlEXSHpcAicI0b/2v/y9F+tOksANX X-Gm-Gg: ATEYQzyyMpa4c/uA83+5Ab1JKILGClKgsxfpLos8g13KCBBDK6d07pIcfuR0xDOjqiS cLHxr7ZQGauVzwzQbDplpjYDHJhW+Ce0JejFRw9ZbF3rJQHJHGMJ9p33B06mtLbX4gQETZbMrs3 k614uKHxXRmGzbaYYTUl9Tshly0Gsw36G2KAhMhIx2WcXGshRSqZFEqi7aUyfHf0L3tn4VrViQ+ Jv5A0TGi5Em9q1GVEBd+md2uug0+dRGiNYq3u8/1MFk3eIbUBPS7zP5DuaRTYsPK/80vLADygHj 4jEkdQ78xTGGNyfBLlT6s1QHgpN7ImFIqn/gAVWR7xoFRf9GkYLlOpitgdlOjqpLLNEvhH18TQD uxB5KGK1lT1Z7ft5ojS04coAECGzHKTf9+7WVpJDVa1WlR1+Y1lBdb9jbIZyqQ4BK1D0ZUdxZxY cZGEXnjTa75XWI3/4hIXhHVquY9bEHLcRGsXHRc+f3vvbLz8PrdzEn7YYvJHo4gyRvDH9vlK8U X-Received: by 2002:a05:7301:1e90:b0:2ae:5bde:a5c5 with SMTP id 5a478bee46e88-2c0e505d7damr2121248eec.30.1773860828853; Wed, 18 Mar 2026 12:07:08 -0700 (PDT) Received: from localhost.localdomain (c-67-164-93-214.hsd1.ca.comcast.net. [67.164.93.214]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2c0e5582dd5sm4894424eec.15.2026.03.18.12.07.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 12:07:08 -0700 (PDT) From: Sanman Pradhan X-Google-Original-From: Sanman Pradhan To: Guenter Roeck Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, Sanman Pradhan Subject: [PATCH v3 2/2] hwmon: (pmbus/max31785) use access_delay for PMBus-mediated accesses Date: Wed, 18 Mar 2026 12:06:43 -0700 Message-Id: <20260318190643.54372-3-psanman@juniper.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260318190643.54372-1-psanman@juniper.net> References: <20260318190643.54372-1-psanman@juniper.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The MAX31785 fan controller occasionally NACKs master transactions if accesses are too tightly spaced. To avoid this, the driver currently enforces a 250us inter-access delay with a private timestamp and wrapper functions around both raw SMBus accesses and PMBus helper paths. Simplify the driver by using pmbus_driver_info.access_delay for normal PMBus-mediated accesses instead, and remove the driver-local PMBus read/write wrappers. Keep local delay handling for raw SMBus accesses used before pmbus_do_probe(). For the raw i2c_transfer() long-read path, which bypasses PMBus core timing, use pmbus_wait() and pmbus_update_ts() so the PMBus core also tracks the raw transfer timing. Update the PMBus core timestamp before checking the transfer result so failed transfers do not skip the required delay before the next PMBus access. Also update max31785_read_byte_data() so PMBUS_FAN_CONFIG_12 accesses are only remapped for virtual pages, allowing physical-page accesses to fall back to the PMBus core. With that change, use pmbus_update_fan() for fan configuration updates. Finally, use the delayed raw read helper for MFR_REVISION during probe, rename the local variable "virtual" to "vpage", drop the unused to_max31785_data() macro, and add an explicit delay before pmbus_do_probe() so the first PMBus core access is properly spaced from the last pre-probe raw access. Signed-off-by: Sanman Pradhan --- v3: - Added an explicit max31785_wait() before pmbus_do_probe() to ensure proper timing spacing during the handover to the PMBus core. v2: - Replaced local usleep_range() with core pmbus_wait() and pmbus_update_ts() in the raw long-read path. - Updated read_byte_data() to allow core fallback for physical pages. --- drivers/hwmon/pmbus/max31785.c | 182 ++++++++++----------------------- 1 file changed, 55 insertions(+), 127 deletions(-) diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c index 50073fe0c5e8..2a160eaed5ed 100644 --- a/drivers/hwmon/pmbus/max31785.c +++ b/drivers/hwmon/pmbus/max31785.c @@ -31,8 +31,6 @@ struct max31785_data { struct pmbus_driver_info info; }; =20 -#define to_max31785_data(x) container_of(x, struct max31785_data, info) - /* * MAX31785 Driver Workaround * @@ -40,9 +38,8 @@ struct max31785_data { * These issues are not indicated by the device itself, except for occasio= nal * NACK responses during master transactions. No error bits are set in STA= TUS_BYTE. * - * To address this, we introduce a delay of 250us between consecutive acce= sses - * to the fan controller. This delay helps mitigate communication problems= by - * allowing sufficient time between accesses. + * Keep minimal local delay handling for raw pre-probe SMBus accesses. + * Normal PMBus-mediated accesses use pmbus_driver_info.access_delay inste= ad. */ static inline void max31785_wait(const struct max31785_data *data) { @@ -54,87 +51,38 @@ static inline void max31785_wait(const struct max31785_= data *data) } =20 static int max31785_i2c_write_byte_data(struct i2c_client *client, - struct max31785_data *driver_data, - int command, u8 data) + struct max31785_data *data, + int command, u8 value) { int rc; =20 - max31785_wait(driver_data); - rc =3D i2c_smbus_write_byte_data(client, command, data); - driver_data->access =3D ktime_get(); + max31785_wait(data); + rc =3D i2c_smbus_write_byte_data(client, command, value); + data->access =3D ktime_get(); return rc; } =20 static int max31785_i2c_read_word_data(struct i2c_client *client, - struct max31785_data *driver_data, + struct max31785_data *data, int command) { int rc; =20 - max31785_wait(driver_data); + max31785_wait(data); rc =3D i2c_smbus_read_word_data(client, command); - driver_data->access =3D ktime_get(); - return rc; -} - -static int _max31785_read_byte_data(struct i2c_client *client, - struct max31785_data *driver_data, - int page, int command) -{ - int rc; - - max31785_wait(driver_data); - rc =3D pmbus_read_byte_data(client, page, command); - driver_data->access =3D ktime_get(); - return rc; -} - -static int _max31785_write_byte_data(struct i2c_client *client, - struct max31785_data *driver_data, - int page, int command, u16 data) -{ - int rc; - - max31785_wait(driver_data); - rc =3D pmbus_write_byte_data(client, page, command, data); - driver_data->access =3D ktime_get(); - return rc; -} - -static int _max31785_read_word_data(struct i2c_client *client, - struct max31785_data *driver_data, - int page, int phase, int command) -{ - int rc; - - max31785_wait(driver_data); - rc =3D pmbus_read_word_data(client, page, phase, command); - driver_data->access =3D ktime_get(); - return rc; -} - -static int _max31785_write_word_data(struct i2c_client *client, - struct max31785_data *driver_data, - int page, int command, u16 data) -{ - int rc; - - max31785_wait(driver_data); - rc =3D pmbus_write_word_data(client, page, command, data); - driver_data->access =3D ktime_get(); + data->access =3D ktime_get(); return rc; } =20 static int max31785_read_byte_data(struct i2c_client *client, int page, in= t reg) { - const struct pmbus_driver_info *info =3D pmbus_get_driver_info(client); - struct max31785_data *driver_data =3D to_max31785_data(info); - switch (reg) { case PMBUS_VOUT_MODE: return -ENOTSUPP; case PMBUS_FAN_CONFIG_12: - return _max31785_read_byte_data(client, driver_data, + if (page < MAX31785_NR_PAGES) + return -ENODATA; + return pmbus_read_byte_data(client, page - MAX31785_NR_PAGES, reg); } @@ -178,7 +126,21 @@ static int max31785_read_long_data(struct i2c_client *= client, int page, if (rc < 0) return rc; =20 + /* + * Ensure the raw transfer is properly spaced from the + * preceding PMBus transaction. + */ + pmbus_wait(client); + rc =3D i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + + /* + * Update PMBus core timing state for the raw transfer, even on error. + * Pass 0 as the operation mask since this is a raw read, intentionally + * neither PMBUS_OP_WRITE nor PMBUS_OP_PAGE_CHANGE. + */ + pmbus_update_ts(client, 0); + if (rc < 0) return rc; =20 @@ -203,19 +165,16 @@ static int max31785_get_pwm(struct i2c_client *client= , int page) return rv; } =20 -static int max31785_get_pwm_mode(struct i2c_client *client, - struct max31785_data *driver_data, int page) +static int max31785_get_pwm_mode(struct i2c_client *client, int page) { int config; int command; =20 - config =3D _max31785_read_byte_data(client, driver_data, page, - PMBUS_FAN_CONFIG_12); + config =3D pmbus_read_byte_data(client, page, PMBUS_FAN_CONFIG_12); if (config < 0) return config; =20 - command =3D _max31785_read_word_data(client, driver_data, page, 0xff, - PMBUS_FAN_COMMAND_1); + command =3D pmbus_read_word_data(client, page, 0xff, PMBUS_FAN_COMMAND_1); if (command < 0) return command; =20 @@ -233,8 +192,6 @@ static int max31785_get_pwm_mode(struct i2c_client *cli= ent, static int max31785_read_word_data(struct i2c_client *client, int page, int phase, int reg) { - const struct pmbus_driver_info *info =3D pmbus_get_driver_info(client); - struct max31785_data *driver_data =3D to_max31785_data(info); u32 val; int rv; =20 @@ -263,7 +220,7 @@ static int max31785_read_word_data(struct i2c_client *c= lient, int page, rv =3D max31785_get_pwm(client, page); break; case PMBUS_VIRT_PWM_ENABLE_1: - rv =3D max31785_get_pwm_mode(client, driver_data, page); + rv =3D max31785_get_pwm_mode(client, page); break; default: rv =3D -ENODATA; @@ -294,36 +251,7 @@ static inline u32 max31785_scale_pwm(u32 sensor_val) return (sensor_val * 100) / 255; } =20 -static int max31785_update_fan(struct i2c_client *client, - struct max31785_data *driver_data, int page, - u8 config, u8 mask, u16 command) -{ - int from, rv; - u8 to; - - from =3D _max31785_read_byte_data(client, driver_data, page, - PMBUS_FAN_CONFIG_12); - if (from < 0) - return from; - - to =3D (from & ~mask) | (config & mask); - - if (to !=3D from) { - rv =3D _max31785_write_byte_data(client, driver_data, page, - PMBUS_FAN_CONFIG_12, to); - if (rv < 0) - return rv; - } - - rv =3D _max31785_write_word_data(client, driver_data, page, - PMBUS_FAN_COMMAND_1, command); - - return rv; -} - -static int max31785_pwm_enable(struct i2c_client *client, - struct max31785_data *driver_data, int page, - u16 word) +static int max31785_pwm_enable(struct i2c_client *client, int page, u16 wo= rd) { int config =3D 0; int rate; @@ -351,23 +279,20 @@ static int max31785_pwm_enable(struct i2c_client *cli= ent, return -EINVAL; } =20 - return max31785_update_fan(client, driver_data, page, config, + return pmbus_update_fan(client, page, 0, config, PB_FAN_1_RPM, rate); } =20 static int max31785_write_word_data(struct i2c_client *client, int page, int reg, u16 word) { - const struct pmbus_driver_info *info =3D pmbus_get_driver_info(client); - struct max31785_data *driver_data =3D to_max31785_data(info); - switch (reg) { case PMBUS_VIRT_PWM_1: - return max31785_update_fan(client, driver_data, page, 0, + return pmbus_update_fan(client, page, 0, 0, PB_FAN_1_RPM, max31785_scale_pwm(word)); case PMBUS_VIRT_PWM_ENABLE_1: - return max31785_pwm_enable(client, driver_data, page, word); + return max31785_pwm_enable(client, page, word); default: break; } @@ -391,6 +316,7 @@ static const struct pmbus_driver_info max31785_info =3D= { .read_byte_data =3D max31785_read_byte_data, .read_word_data =3D max31785_read_word_data, .write_byte =3D max31785_write_byte, + .access_delay =3D MAX31785_WAIT_DELAY_US, =20 /* RPM */ .format[PSC_FAN] =3D direct, @@ -438,29 +364,29 @@ static const struct pmbus_driver_info max31785_info = =3D { }; =20 static int max31785_configure_dual_tach(struct i2c_client *client, - struct pmbus_driver_info *info) + struct max31785_data *data) { + struct pmbus_driver_info *info =3D &data->info; int ret; int i; - struct max31785_data *driver_data =3D to_max31785_data(info); =20 for (i =3D 0; i < MAX31785_NR_FAN_PAGES; i++) { - ret =3D max31785_i2c_write_byte_data(client, driver_data, + ret =3D max31785_i2c_write_byte_data(client, data, PMBUS_PAGE, i); if (ret < 0) return ret; =20 - ret =3D max31785_i2c_read_word_data(client, driver_data, + ret =3D max31785_i2c_read_word_data(client, data, MFR_FAN_CONFIG); if (ret < 0) return ret; =20 if (ret & MFR_FAN_CONFIG_DUAL_TACH) { - int virtual =3D MAX31785_NR_PAGES + i; + int vpage =3D MAX31785_NR_PAGES + i; =20 - info->pages =3D virtual + 1; - info->func[virtual] |=3D PMBUS_HAVE_FAN12; - info->func[virtual] |=3D PMBUS_PAGE_VIRTUAL; + info->pages =3D vpage + 1; + info->func[vpage] |=3D PMBUS_HAVE_FAN12; + info->func[vpage] |=3D PMBUS_PAGE_VIRTUAL; } } =20 @@ -471,7 +397,7 @@ static int max31785_probe(struct i2c_client *client) { struct device *dev =3D &client->dev; struct pmbus_driver_info *info; - struct max31785_data *driver_data; + struct max31785_data *data; bool dual_tach =3D false; int ret; =20 @@ -480,20 +406,20 @@ static int max31785_probe(struct i2c_client *client) I2C_FUNC_SMBUS_WORD_DATA)) return -ENODEV; =20 - driver_data =3D devm_kzalloc(dev, sizeof(struct max31785_data), GFP_KERNE= L); - if (!driver_data) + data =3D devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) return -ENOMEM; =20 - info =3D &driver_data->info; - driver_data->access =3D ktime_get(); + data->access =3D ktime_get(); + info =3D &data->info; *info =3D max31785_info; =20 - ret =3D max31785_i2c_write_byte_data(client, driver_data, - PMBUS_PAGE, 255); + ret =3D max31785_i2c_write_byte_data(client, data, + PMBUS_PAGE, 0xff); if (ret < 0) return ret; =20 - ret =3D i2c_smbus_read_word_data(client, MFR_REVISION); + ret =3D max31785_i2c_read_word_data(client, data, MFR_REVISION); if (ret < 0) return ret; =20 @@ -509,11 +435,13 @@ static int max31785_probe(struct i2c_client *client) } =20 if (dual_tach) { - ret =3D max31785_configure_dual_tach(client, info); + ret =3D max31785_configure_dual_tach(client, data); if (ret < 0) return ret; } =20 + max31785_wait(data); + return pmbus_do_probe(client, info); } =20 --=20 2.34.1