From nobody Thu Oct 2 14:24:23 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (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 E144B305E24 for ; Tue, 16 Sep 2025 10:24:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758018265; cv=none; b=GuUZoqFUMJqJg6X7x1QxHE3aTU8liWnQW6qqjFJgPhwo5x+mHMZ5rRYTFC6h2nCUIxrPBqV31Hhr448AtNtUgN8jF0ujErn4CuqRDfsen55Fsn1YZRskwH6rhsSYCYmkPk7JhEuikMBvqu6MUm7ZUfYnXmsrvzkGM1s7xv3F40I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758018265; c=relaxed/simple; bh=eno6mobSsV0Vz477n004Idm38KpAYuuVSri+PQ/cVmg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Hl1EsQEn696uV/Wsltr8nyyk7ZybY1K5xZFBhcb+2Z0PraWw9YCrBol5xOzn3sdGpaWS8posOQ7EdX6DFaMO/buhEi9OTy/dcThurs9gmc+JQ4bNRDup/ItJE28+CPYCYhIFoMbuqRMszlv9TwWrBSWAdFtH49w1g1HphI/hpBs= 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=afZ84qiZ; arc=none smtp.client-ip=185.246.84.56 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="afZ84qiZ" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 742171A0D84; Tue, 16 Sep 2025 10:24:22 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4A5086061E; Tue, 16 Sep 2025 10:24:22 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 448C1102F16DF; Tue, 16 Sep 2025 12:24:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1758018261; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=7xH/6o5AG/ZkEV08qqD3o809y7CCiNGJ+1iwApjb1E0=; b=afZ84qiZvW+v0wFW+c7lZHQr3eOyRJFuW33zqsqor6rzpbz0wu0WoiaUVuu31jPiZ14wyZ jhuYm6fA8xj6+Wo02YvtK/AC/UKyuBzkwUXRu9+uQyqtyPQJdYKoLqTrN5VmXNsQajDT4Q NqCEpj6nf6xR6/nC7oRPRlGiUEhDyAmcCOOcUPLyIP0K8DrBmSRsJ+TmEGj/QO7A9K1CoB KicgAyHT5zpr3B4YH+sXkIh8E0fHV0wOY8fXdnL4m304OGEJy71MtKXgtbmdtKlh+bGGA7 EfGEuGYQfT4LzEfNNhxwamxwKcaG/o6z7sTtLttsE8UuQKDnENZuuWNDFrlzag== From: Romain Gantois Date: Tue, 16 Sep 2025 12:24:09 +0200 Subject: [PATCH 4/4] regulator: ltm8054: Support output current limit control 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: <20250916-ltm8054-driver-v1-4-fd4e781d33b9@bootlin.com> References: <20250916-ltm8054-driver-v1-0-fd4e781d33b9@bootlin.com> In-Reply-To: <20250916-ltm8054-driver-v1-0-fd4e781d33b9@bootlin.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: Thomas Petazzoni , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-iio@vger.kernel.org, Romain Gantois X-Mailer: b4 0.14.2 X-Last-TLS-Session-Version: TLSv1.3 The LTM8054 supports setting a fixed output current limit using a sense resistor connected to a dedicated pin. This limit can then be lowered dynamically by varying the voltage level of the CTL pin. Support controlling the LTM8054's output current limit. Signed-off-by: Romain Gantois --- drivers/regulator/Kconfig | 1 + drivers/regulator/ltm8054-regulator.c | 109 ++++++++++++++++++++++++++++++= ++++ 2 files changed, 110 insertions(+) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 15fb71193b67d0b2daa631b69778dde9323aedd2..22cf0e980351f21e3ef5b6611a3= 9cb48aeb503ea 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -579,6 +579,7 @@ config REGULATOR_LTC3676 =20 config REGULATOR_LTM8054 tristate "LTM8054 Buck-Boost voltage regulator" + depends on IIO help This driver provides support for the Linear Technology LTM8054 Buck-Boost micromodule regulator. The LTM8054 has an adjustable diff --git a/drivers/regulator/ltm8054-regulator.c b/drivers/regulator/ltm8= 054-regulator.c index e41bd95da55fb87912e2cdf70bae231133c25745..3b7b826e29cfb37415a7fb7cab6= 78cc33494d184 100644 --- a/drivers/regulator/ltm8054-regulator.c +++ b/drivers/regulator/ltm8054-regulator.c @@ -11,12 +11,27 @@ #include #include #include +#include +#include #include =20 +/* Threshold voltage between the Vout and Iout pins which triggers current + * limiting, in microvolts + */ +#define LTM8054_VOUT_IOUT_MAX 58000 + +#define LTM8054_MAX_CTL_V 1200000 +#define LTM8054_MIN_CTL_V 50000 + /* The LTM8054 regulates its FB pin to 1.2V */ #define LTM8054_FB_V 1200000 =20 struct ltm8054_priv { + struct iio_channel *ctl_dac; + + int min_uA; + int max_uA; + struct regulator_desc rdesc; }; =20 @@ -30,18 +45,105 @@ static int ltm8054_scale(unsigned int uV, u32 r1, u32 = r2) return uV + (unsigned int)tmp; } =20 +static int ltm8054_set_current_limit(struct regulator_dev *rdev, int min_u= A, int max_uA) +{ + struct ltm8054_priv *priv =3D rdev_get_drvdata(rdev); + u64 vdac_uV; + + min_uA =3D clamp_t(int, min_uA, priv->min_uA, priv->max_uA); + + /* adjusted current limit =3D Rsense current limit * CTL pin voltage / ma= x CTL pin voltage */ + vdac_uV =3D (u64)min_uA * LTM8054_MAX_CTL_V; + do_div(vdac_uV, priv->max_uA); + + dev_dbg(&rdev->dev, + "Setting current limit to %duA, CTL pin to %duV\n", min_uA, (int)vdac_uV= ); + + /* Standard IIO voltage unit is mV, scale accordingly. */ + return iio_write_channel_processed_scale(priv->ctl_dac, vdac_uV, 1000); +} + +static int ltm8054_get_current_limit(struct regulator_dev *rdev) +{ + struct ltm8054_priv *priv =3D rdev_get_drvdata(rdev); + int ret, vdac_uv; + u64 uA; + + ret =3D iio_read_channel_processed_scale(priv->ctl_dac, &vdac_uv, 1000); + if (ret < 0) { + dev_err(&rdev->dev, "failed to read CTL DAC voltage, err %d\n", ret); + return ret; + } + + uA =3D (u64)vdac_uv * priv->max_uA; + do_div(uA, LTM8054_MAX_CTL_V); + + return uA; +} + static const struct regulator_ops ltm8054_regulator_ops =3D { + .set_current_limit =3D ltm8054_set_current_limit, + .get_current_limit =3D ltm8054_get_current_limit, }; =20 +static int ltm8054_init_ctl_dac(struct platform_device *pdev, struct ltm80= 54_priv *priv) +{ + struct iio_channel *ctl_dac; + enum iio_chan_type type; + int ret; + + ctl_dac =3D devm_iio_channel_get(&pdev->dev, "ctl"); + if (IS_ERR(ctl_dac)) + return PTR_ERR(ctl_dac); + + ret =3D iio_get_channel_type(ctl_dac, &type); + if (ret < 0) + return ret; + + if (type !=3D IIO_VOLTAGE) + return -EINVAL; + + priv->ctl_dac =3D ctl_dac; + + return 0; +} + static int ltm8054_of_parse(struct device *dev, struct ltm8054_priv *priv, struct regulator_config *config) { struct device_node *np =3D dev->of_node; + u32 rsense; u32 r[2]; + u64 tmp; int ret; =20 config->of_node =3D np; =20 + ret =3D of_property_read_u32(np, "lltc,iout-rsense-micro-ohms", &rsense); + if (ret < 0) { + dev_err(dev, "failed to get sense resistor value\n"); + return ret; + } + + if (rsense =3D=3D 0) { + dev_err(dev, "invalid value zero for sense resistor\n"); + return -EINVAL; + } + + /* The maximum output current limit is the one set by the Rsense resistor= */ + tmp =3D 1000000 * (u64)LTM8054_VOUT_IOUT_MAX; + do_div(tmp, rsense); + priv->max_uA =3D tmp; + + /* Applying a voltage below LTM8054_MAX_CTL_V on the CTL pin reduces + * the output current limit. If this level drops below + * LTM8054_MIN_CTL_V the regulator stops switching + */ + + tmp =3D LTM8054_MIN_CTL_V * (u64)priv->max_uA; + do_div(tmp, (u32)LTM8054_MAX_CTL_V); + priv->min_uA =3D tmp; + ret =3D of_property_read_u32_array(np, "lltc,fb-voltage-divider", r, 2); if (ret) { dev_err(dev, "Failed to parse voltage divider\n"); @@ -52,6 +154,9 @@ static int ltm8054_of_parse(struct device *dev, struct l= tm8054_priv *priv, priv->rdesc.min_uV =3D priv->rdesc.fixed_uV; priv->rdesc.n_voltages =3D 1; =20 + dev_dbg(dev, "max_uA: %d min_uA: %d fixed_uV: %d\n", + priv->max_uA, priv->min_uA, priv->rdesc.fixed_uV); + config->init_data =3D of_get_regulator_init_data(dev, np, &priv->rdesc); @@ -92,6 +197,10 @@ static int ltm8054_probe(struct platform_device *pdev) if (ret) return dev_err_probe(&pdev->dev, ret, "failed to parse device tree\n"); =20 + ret =3D ltm8054_init_ctl_dac(pdev, priv); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to initialize CTL DAC\n"); + rdev =3D devm_regulator_register(&pdev->dev, &priv->rdesc, &config); if (IS_ERR(rdev)) return dev_err_probe(&pdev->dev, PTR_ERR(rdev), "failed to register regu= lator\n"); --=20 2.51.0