From nobody Mon Oct 6 17:06:50 2025 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A045414F9D6 for ; Fri, 18 Jul 2025 14:11:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.199 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752847908; cv=none; b=fH5NWCYNcd8HppaJ/YFYYpmNiok3ZJq01PrC/KSi/PBerXYsxDxkZXdPNEVbGXzKp1iwRKM4kCN4Hpj51+sKQQEa76hrzqws7mboybGf8++DZNqGwdbCj0Mi/cLuHYEJ2wO4ufnJcRol4/Ow3gYcR+vGwIyTPWgPCqxG64jDRks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752847908; c=relaxed/simple; bh=zZ9mXmVdECw64awav1nucDoLXi3Yps28PrrgGWyJoAE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=W78mHfyhcql/EO8qXcmwpFgHpzVP6BnmC90Wl4VA3t9Sf93TlB2Ajb2S0sVzLngrX5mWWC6rXtvtYmWMG3W5VR/ETC5J9dvgfdR0OYhNAiRJx7Hv5I4HV1SRZxQber26+OnxOCvMim61Rl1zMLAOTvqN2kw6ESemZY+wIZPAymc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=ggcELmm4; arc=none smtp.client-ip=217.70.183.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="ggcELmm4" Received: by mail.gandi.net (Postfix) with ESMTPSA id 918D341C7C; Fri, 18 Jul 2025 14:11:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1752847904; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=zn2pQNPeeXR6OUDPtKeWRnpx4O5RYxIkZexIwUhRIPI=; b=ggcELmm4vMPb6OdHDgfQx3Tc6mVX5cK/NNKO8Fdt1ER+veEoe5SAWulz5Jpo0gZWZsqDEg 9g+1RveUspAfHVDPk2GiuhMh12VR1hXsBlnw7wwaB58PDuv04hxshsQMNzTEZkkq3Hjx8b CKY1fm1mSy96iTaTK5ojJ/9Tkzr3f4Db7WFyE55XPI7tq8AzJjNXYvb462uwBBa7VgzpW1 dPB3TWVIX5b68S6tl/ZtsYXhTi+IUmxe9E0BbvNZSPijuipJcg9l68zCX4Dov2Gjc/XSkP V5wkxyg05GGYiGH+Hxy9mjk0zhugOe3BaAz1R9oDj7dnrWyad/GZR2woOPKbgQ== From: Romain Gantois Date: Fri, 18 Jul 2025 16:11:36 +0200 Subject: [PATCH v2] regulator: core: repeat voltage setting request for stepped regulators Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250718-regulator-stepping-v2-1-e28c9ac5d54a@bootlin.com> X-B4-Tracking: v=1; b=H4sIABhWemgC/23MsQ7CIBCA4VdpbhYDxFLr5HsYB0qP9pIWyIGNS dN3l7i4OH7D/++QkQkz3JodGDfKFEOFPjXgZhsmFDRWg5a6lZ26CsbptdgSWeSCKVGYhJPKmt6 Mg/UOapgYPb2/08ez2nNcRZkZ7W/VavNvtSmhBA5td5GmHzvp70OMZaFwdnGF4/gAO+sjULAAA AA= X-Change-ID: 20250718-regulator-stepping-c01a696dbafc To: Liam Girdwood , Mark Brown Cc: Thomas Petazzoni , linux-kernel@vger.kernel.org, Romain Gantois X-Mailer: b4 0.14.2 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdefgdeifeeiiecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfitefpfffkpdcuggftfghnshhusghstghrihgsvgenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephfffufggtgfgkffvvefosehtjeertdertdejnecuhfhrohhmpeftohhmrghinhcuifgrnhhtohhishcuoehrohhmrghinhdrghgrnhhtohhishessghoohhtlhhinhdrtghomheqnecuggftrfgrthhtvghrnhepfeekudeihffhfeeiffdvtdduhfegudehiedvgfeuveekgeekjeduvdeljeduteeinecukfhppeeltddrkeelrdduieefrdduvdejnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepledtrdekledrudeifedruddvjedphhgvlhhopegludelvddrudeikedrtddrudefngdpmhgrihhlfhhrohhmpehrohhmrghinhdrghgrnhhtohhishessghoohhtlhhinhdrtghomhdpnhgspghrtghpthhtohephedprhgtphhtthhopehthhhomhgrshdrphgvthgriiiiohhnihessghoohhtlhhinhdrtghomhdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopegsrhhoohhnihgvsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehrohhmrghinhdrghgrnhhtohhishessghoohhtlhhinhdrtghomhdprhgtphhtthhopehlghhirhguf ihoohgusehgmhgrihhlrdgtohhm X-GND-Sasl: romain.gantois@bootlin.com The regulator_set_voltage() function may exhibit unexpected behavior if the target regulator has a maximum voltage step constraint. With such a constraint, the regulator core may clamp the requested voltage to a lesser value, to ensure that the voltage delta stays under the specified limit. This means that the resulting regulator voltage depends on the current voltage, as well as the requested range, which invalidates the assumption that a repeated request for a specific voltage range will amount to a noop. Considering the case of a regulator with a maximum voltage step constraint of 1V: initial voltage: 2.5V consumer requests 4V expected result: 3.5V resulting voltage: 3.5V consumer requests 4V again expected result: 4V actual result: 3.5V Correct this by repeating attempts to balance the regulator voltage until the result converges. Signed-off-by: Romain Gantois --- drivers/regulator/core.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index cbd6d53ebfb5ef21b5dfc8b0f1f1f033772a886c..8ed9b96518cf5186c0db147a689= 5a92bc59fae4e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3797,6 +3797,16 @@ static int _regulator_do_set_suspend_voltage(struct = regulator_dev *rdev, return 0; } =20 +static int regulator_get_voltage_delta(struct regulator_dev *rdev, int uV) +{ + int current_uV =3D regulator_get_voltage_rdev(rdev); + + if (current_uV < 0) + return current_uV; + + return abs(current_uV - uV); +} + static int regulator_set_voltage_unlocked(struct regulator *regulator, int min_uV, int max_uV, suspend_state_t state) @@ -3804,8 +3814,8 @@ static int regulator_set_voltage_unlocked(struct regu= lator *regulator, struct regulator_dev *rdev =3D regulator->rdev; struct regulator_voltage *voltage =3D ®ulator->voltage[state]; int ret =3D 0; + int current_uV, delta, new_delta; int old_min_uV, old_max_uV; - int current_uV; =20 /* If we're setting the same range as last time the change * should be a noop (some cpufreq implementations use the same @@ -3852,6 +3862,37 @@ static int regulator_set_voltage_unlocked(struct reg= ulator *regulator, voltage->max_uV =3D old_max_uV; } =20 + if (rdev->constraints->max_uV_step > 0) { + /* For regulators with a maximum voltage step, reaching the desired + * voltage might take a few retries. + */ + ret =3D regulator_get_voltage_delta(rdev, min_uV); + if (ret < 0) + goto out; + + delta =3D ret; + + while (delta > 0) { + ret =3D regulator_balance_voltage(rdev, state); + if (ret < 0) + goto out; + + ret =3D regulator_get_voltage_delta(rdev, min_uV); + if (ret < 0) + goto out; + + new_delta =3D ret; + + /* check that voltage is converging quickly enough */ + if (new_delta - delta > rdev->constraints->max_uV_step) { + ret =3D -EWOULDBLOCK; + goto out; + } + + delta =3D new_delta; + } + } + out: return ret; } --- base-commit: ef616b9763e374454957a8785a068479fa5665a6 change-id: 20250718-regulator-stepping-c01a696dbafc Best regards, --=20 Romain Gantois