From nobody Fri Dec 19 06:12:13 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 936AFC7EE21 for ; Thu, 4 May 2023 08:33:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230099AbjEDIdn (ORCPT ); Thu, 4 May 2023 04:33:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229959AbjEDIdX (ORCPT ); Thu, 4 May 2023 04:33:23 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C607A61A9; Thu, 4 May 2023 01:30:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683189060; x=1714725060; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=n/SyerxwxFMTmXmN/OA8MgfA2PcxKOBAQ2mIXdeS1oI=; b=jyQ67FfkrhU5B5SWg6F8I10JyBqyRtomUu4UprxAFmIIc8AvwPFq8/xn kghiNYWFxw9zn8vLxN3rZJJep8tWUFVJnkihqEZ4HLVzQ+e3t//XSZORH lbCel5SwUn8qIAC5VcheOXCUowmQsVJ8zTowxLdv7LaQ/T7KNjx+y0WOK +sWc/7k8xfpn4W5gYEReH8y0n98HwDrdYDeh3+oUpK3+Gd4h6q+0SPkmR E5sRz3E03Kv9OyliYSS2s4VjCCK2YqnC1wUV4tBWVxUhebpnvFTMGtXlB FPzFsq0UafZjG5uR9X9VjGWIWN6vgh/Ho5Axn/SNY7mE+aBz5RRaR1+zZ w==; From: =?utf-8?q?M=C3=A5rten_Lindahl?= Date: Thu, 4 May 2023 10:30:26 +0200 Subject: [PATCH v2 1/2] regulator: Add bindings for TPS6287x MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20230502-tps6287x-driver-v2-1-fb5419d46c49@axis.com> References: <20230502-tps6287x-driver-v2-0-fb5419d46c49@axis.com> In-Reply-To: <20230502-tps6287x-driver-v2-0-fb5419d46c49@axis.com> To: Liam Girdwood , Mark Brown , "Rob Herring" , Krzysztof Kozlowski CC: , , , =?utf-8?q?M=C3=A5rten_Lindahl?= X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1683189034; l=1836; i=marten.lindahl@axis.com; s=20230329; h=from:subject:message-id; bh=4aeTCaWo/RTTY36JuX2Zpeu7oe4DVZX7ahi9lgZVubM=; b=xCkCxU+jf4s0sABAeOhqYfs/cvI+dUupZQzy50IEuG9vdG6aHVVAMRwnIltl2WRQx2lv1eCzg qgGiK/lmFajBkU+tM2DELMWMsHy0nOqUDAeYD5r/1kbWizBz+VV8lpP X-Developer-Key: i=marten.lindahl@axis.com; a=ed25519; pk=JfbjqFPJnIDIQOkJBeatC8+S3Ax3N0RIdmN+fL3wXgw= Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add bindings for the TPS62870/TPS62871/TPS62872/TPS62873 voltage regulators. Signed-off-by: M=C3=A5rten Lindahl --- .../devicetree/bindings/regulator/ti,tps62870.yaml | 62 ++++++++++++++++++= ++++ 1 file changed, 62 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/ti,tps62870.yaml b= /Documentation/devicetree/bindings/regulator/ti,tps62870.yaml new file mode 100644 index 000000000000..32f259f16314 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/ti,tps62870.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/ti,tps62870.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI TPS62870/TPS62871/TPS62872/TPS62873 voltage regulator + +maintainers: + - M=C3=A5rten Lindahl + +properties: + compatible: + enum: + - ti,tps62870 + - ti,tps62871 + - ti,tps62872 + - ti,tps62873 + + reg: + maxItems: 1 + + regulators: + type: object + + properties: + "vout": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + additionalProperties: false + +required: + - compatible + - reg + - regulators + +additionalProperties: false + +examples: + - | + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + + regulator@41 { + compatible =3D "ti,tps62873"; + reg =3D <0x41>; + + regulators { + vout { + regulator-name =3D "+0.75V"; + regulator-min-microvolt =3D <400000>; + regulator-max-microvolt =3D <1675000>; + regulator-initial-mode =3D <2>; + }; + }; + }; + }; + +... --=20 2.30.2 From nobody Fri Dec 19 06:12:13 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8BC6FC7EE21 for ; Thu, 4 May 2023 08:34:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230353AbjEDIeL (ORCPT ); Thu, 4 May 2023 04:34:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45320 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229886AbjEDIdg (ORCPT ); Thu, 4 May 2023 04:33:36 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BE5949D1; Thu, 4 May 2023 01:31:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683189083; x=1714725083; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=+1mD+2G/YQf+1sysUFKbadN741GOKVAcFB3DDi0P978=; b=I/YyRhyJGLpTzXIE5Eq8ILvVjFRGIC0GxiLJ7RbnS+pcIMRAejbwisIS kmi921/5BUUgf2BU/Mk3cUKZ8DjUAtw+lTO5uHDQ++RtWEhuSH2GK+Qh+ IjftYrGoKpsa4RFjsRJZLiyr5kEWZk0pKoYchhAYE8IiKffALNGEfLq7/ 3j28T0apWt/QeFE8jS0WqdtU6PaPH/Refv1WHtM73aB7xPjVrgdL6ClAF NXQovhwGu1gfCfSByta7gIF/Ry74HYTZXylq/af6LEiqi+n2L8FCLa/R+ eJRXdNyH1BN18lhxoLR5rl0yYmIjQ4agr6X2uAVgKYDrfTEa26KSrK0yG g==; From: =?utf-8?q?M=C3=A5rten_Lindahl?= Date: Thu, 4 May 2023 10:30:27 +0200 Subject: [PATCH v2 2/2] regulator: Add support for TI TPS6287x regulators MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20230502-tps6287x-driver-v2-2-fb5419d46c49@axis.com> References: <20230502-tps6287x-driver-v2-0-fb5419d46c49@axis.com> In-Reply-To: <20230502-tps6287x-driver-v2-0-fb5419d46c49@axis.com> To: Liam Girdwood , Mark Brown , "Rob Herring" , Krzysztof Kozlowski CC: , , , =?utf-8?q?M=C3=A5rten_Lindahl?= X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1683189034; l=9815; i=marten.lindahl@axis.com; s=20230329; h=from:subject:message-id; bh=9aHD25qFdvOpdJ3aJnbh13Wp3O397F9k/dHxjJw1ekE=; b=uUspr+o0FcQli3o+2+Ekr7hx9P/n1mI4POKO8l4jgYOaavvHGoK+71ZSyBe14+8+nyBz9/nzY ItLornvWLzCAH785OYtbfVBKaTCuC+JWUBiI0KuULQS6mBjhdw+PH9A X-Developer-Key: i=marten.lindahl@axis.com; a=ed25519; pk=JfbjqFPJnIDIQOkJBeatC8+S3Ax3N0RIdmN+fL3wXgw= Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support for Texas Instruments TPS6287x, single-channel synchronous step-down converters with four output voltage ranges. Signed-off-by: M=C3=A5rten Lindahl --- drivers/regulator/Kconfig | 11 ++ drivers/regulator/Makefile | 1 + drivers/regulator/tps6287x-regulator.c | 289 +++++++++++++++++++++++++++++= ++++ 3 files changed, 301 insertions(+) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index aae28d0a489c..d7923ac53f53 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1374,6 +1374,17 @@ config REGULATOR_TPS6286X high-frequency synchronous step-down converters with an I2C interface. =20 +config REGULATOR_TPS6287X + tristate "TI TPS6287x Power Regulator" + depends on I2C && OF + select REGMAP_I2C + help + This driver supports TPS6287x voltage regulator chips. These are + pin-to-pin high-frequency synchronous step-down dc-dc converters + with an I2C interface. + + If built as a module it will be called tps6287x-regulator. + config REGULATOR_TPS65023 tristate "TI TPS65023 Power regulators" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index ee383d8fc835..857995db3fa4 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -161,6 +161,7 @@ obj-$(CONFIG_REGULATOR_TI_ABB) +=3D ti-abb-regulator.o obj-$(CONFIG_REGULATOR_TPS6105X) +=3D tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) +=3D tps62360-regulator.o obj-$(CONFIG_REGULATOR_TPS6286X) +=3D tps6286x-regulator.o +obj-$(CONFIG_REGULATOR_TPS6287X) +=3D tps6287x-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) +=3D tps65023-regulator.o obj-$(CONFIG_REGULATOR_TPS6507X) +=3D tps6507x-regulator.o obj-$(CONFIG_REGULATOR_TPS65086) +=3D tps65086-regulator.o diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps= 6287x-regulator.c new file mode 100644 index 000000000000..644549b6856e --- /dev/null +++ b/drivers/regulator/tps6287x-regulator.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Axis Communications AB + * + * Driver for Texas Instruments TPS6287x PMIC. + * Datasheet: https://www.ti.com/lit/ds/symlink/tps62873.pdf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TPS6287X_VSET 0x00 +#define TPS6287X_CTRL1 0x01 +#define TPS6287X_CTRL1_VRAMP GENMASK(1, 0) +#define TPS6287X_CTRL1_FPWMEN BIT(4) +#define TPS6287X_CTRL1_SWEN BIT(5) +#define TPS6287X_CTRL2 0x02 +#define TPS6287X_CTRL2_VRANGE GENMASK(3, 2) +#define TPS6287X_CTRL3 0x03 +#define TPS6287X_STATUS 0x04 + +#define TPS6287X_VRANGE_DFLT 2 +#define TPS6287X_MIN_UV_DFLT 400000 +#define TPS6287X_MAX_UV_DFLT 1675000 +#define TPS6287X_STEP_UV_DFLT 5000 + +struct tps6287x_chip { + struct regulator_dev *rdev; + struct regmap *regmap; + unsigned int uv_step; +}; + +static const struct regmap_config tps6287x_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .max_register =3D TPS6287X_STATUS, +}; + +/* min_uv, max_uv, uv_step */ +static const unsigned int tps6287x_voltage_table[][3] =3D { + { 400000, 718750, 1250 }, + { 400000, 1037500, 2500 }, + { 400000, 1675000, 5000 }, + { 800000, 3350000, 10000 }, +}; + +static const unsigned int tps6287x_ramp_table[] =3D { + 10000, 5000, 1250, 500 +}; + +static int tps6287x_get_voltage(struct regulator_dev *rdev) +{ + struct device *dev =3D rdev_get_dev(rdev); + struct tps6287x_chip *chip =3D + i2c_get_clientdata(to_i2c_client(dev->parent)); + unsigned int val; + int ret; + + ret =3D regmap_read(rdev->regmap, TPS6287X_VSET, &val); + if (ret !=3D 0) + return -ENOTRECOVERABLE; + + return (val * chip->uv_step) + rdev->constraints->min_uV; +} + +static int tps6287x_set_voltage(struct regulator_dev *rdev, int min_uv, + int max_uv, unsigned int *selector) +{ + struct device *dev =3D rdev_get_dev(rdev); + struct tps6287x_chip *chip =3D + i2c_get_clientdata(to_i2c_client(dev->parent)); + int val =3D min_uv; + + *selector =3D 0; + + if (val < rdev->constraints->min_uV) + val =3D rdev->constraints->min_uV; + if (val > rdev->constraints->max_uV) + val =3D rdev->constraints->max_uV; + + val -=3D rdev->constraints->min_uV; + val =3D DIV_ROUND_CLOSEST(val, chip->uv_step); + + return regmap_write(rdev->regmap, TPS6287X_VSET, val); +} + +static int tps6287x_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + unsigned int val; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val =3D 0; + break; + case REGULATOR_MODE_FAST: + val =3D TPS6287X_CTRL1_FPWMEN; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, TPS6287X_CTRL1, + TPS6287X_CTRL1_FPWMEN, val); +} + +static unsigned int tps6287x_get_mode(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret =3D regmap_read(rdev->regmap, TPS6287X_CTRL1, &val); + if (ret < 0) + return 0; + + return (val & TPS6287X_CTRL1_FPWMEN) ? REGULATOR_MODE_FAST : + REGULATOR_MODE_NORMAL; +} + +static unsigned int tps6287x_of_map_mode(unsigned int mode) +{ + switch (mode) { + case REGULATOR_MODE_NORMAL: + case REGULATOR_MODE_FAST: + return mode; + default: + return REGULATOR_MODE_INVALID; + } +} + +static const struct regulator_ops tps6287x_regulator_ops =3D { + .enable =3D regulator_enable_regmap, + .disable =3D regulator_disable_regmap, + .set_mode =3D tps6287x_set_mode, + .get_mode =3D tps6287x_get_mode, + .is_enabled =3D regulator_is_enabled_regmap, + .get_voltage =3D tps6287x_get_voltage, + .set_voltage =3D tps6287x_set_voltage, + .set_ramp_delay =3D regulator_set_ramp_delay_regmap, +}; + +static struct regulator_desc tps6287x_reg =3D { + .name =3D "tps6287x", + .of_match =3D of_match_ptr("vout"), + .owner =3D THIS_MODULE, + .ops =3D &tps6287x_regulator_ops, + .of_map_mode =3D tps6287x_of_map_mode, + .regulators_node =3D of_match_ptr("regulators"), + .type =3D REGULATOR_VOLTAGE, + .enable_reg =3D TPS6287X_CTRL1, + .enable_mask =3D TPS6287X_CTRL1_SWEN, + .ramp_reg =3D TPS6287X_CTRL1, + .ramp_mask =3D TPS6287X_CTRL1_VRAMP, + .ramp_delay_table =3D tps6287x_ramp_table, + .n_ramp_values =3D ARRAY_SIZE(tps6287x_ramp_table), +}; + +static int tps6287x_setup_vrange(struct tps6287x_chip *chip) +{ + struct regulator_dev *rdev =3D chip->rdev; + unsigned int val, r; + bool found =3D false; + int ret; + + /* + * Match DT voltage range to one of the predefined ranges, + * and configure the regulator with the selected range. + */ + for (r =3D 0; r < ARRAY_SIZE(tps6287x_voltage_table); r++) { + if (tps6287x_voltage_table[r][0] =3D=3D rdev->constraints->min_uV && + tps6287x_voltage_table[r][1] =3D=3D rdev->constraints->max_uV) { + found =3D true; + break; + } + } + + if (!found) { + dev_warn(rdev_get_dev(rdev)->parent, "Missing or invalid voltage range. = Using default.\n"); + rdev->constraints->min_uV =3D TPS6287X_MIN_UV_DFLT; + rdev->constraints->max_uV =3D TPS6287X_MAX_UV_DFLT; + return 0; + } + + if (r =3D=3D TPS6287X_VRANGE_DFLT) + return 0; + + ret =3D regmap_update_bits(chip->regmap, TPS6287X_CTRL2, + TPS6287X_CTRL2_VRANGE, + FIELD_PREP(TPS6287X_CTRL2_VRANGE, r)); + if (ret < 0) + return ret; + + chip->uv_step =3D tps6287x_voltage_table[r][2]; + + /* + * When voltage range is changed the setpoint register must be cleared + * and rewritten to make the regulator start using the new range. + */ + ret =3D regmap_read(rdev->regmap, TPS6287X_VSET, &val); + if (ret !=3D 0) + return ret; + + ret =3D regmap_write(rdev->regmap, TPS6287X_VSET, 0); + if (ret !=3D 0) + return ret; + + return regmap_write(rdev->regmap, TPS6287X_VSET, val); +} + +static int tps6287x_i2c_probe(struct i2c_client *i2c) +{ + struct device *dev =3D &i2c->dev; + struct regulator_config config =3D {}; + struct tps6287x_chip *chip; + int ret; + + chip =3D devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->uv_step =3D TPS6287X_STEP_UV_DFLT; + + chip->regmap =3D devm_regmap_init_i2c(i2c, &tps6287x_regmap_config); + if (IS_ERR(chip->regmap)) { + dev_err(dev, "Failed to init i2c\n"); + return PTR_ERR(chip->regmap); + } + + i2c_set_clientdata(i2c, chip); + + config.dev =3D dev; + config.of_node =3D dev->of_node; + config.regmap =3D chip->regmap; + + chip->rdev =3D devm_regulator_register(dev, &tps6287x_reg, &config); + if (IS_ERR(chip->rdev)) { + dev_err(dev, "Failed to register regulator\n"); + return PTR_ERR(chip->rdev); + } + + ret =3D tps6287x_setup_vrange(chip); + if (ret) + return ret; + + dev_dbg(dev, "Probed regulator\n"); + + return 0; +} + +static const struct of_device_id tps6287x_dt_ids[] =3D { + { .compatible =3D "ti,tps62870", }, + { .compatible =3D "ti,tps62871", }, + { .compatible =3D "ti,tps62872", }, + { .compatible =3D "ti,tps62873", }, + { } +}; + +MODULE_DEVICE_TABLE(of, tps6287x_dt_ids); + +static const struct i2c_device_id tps6287x_i2c_id[] =3D { + { "tps62870", 0 }, + { "tps62871", 0 }, + { "tps62872", 0 }, + { "tps62873", 0 }, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id); + +static struct i2c_driver tps6287x_regulator_driver =3D { + .driver =3D { + .name =3D "tps6287x", + .of_match_table =3D tps6287x_dt_ids, + }, + .probe_new =3D tps6287x_i2c_probe, + .id_table =3D tps6287x_i2c_id, +}; + +module_i2c_driver(tps6287x_regulator_driver); + +MODULE_AUTHOR("M=C3=A5rten Lindahl "); +MODULE_DESCRIPTION("Regulator driver for TI TPS6287X PMIC"); +MODULE_LICENSE("GPL"); --=20 2.30.2