From nobody Wed Sep 10 05:39:08 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 7E98A34F486; Fri, 5 Sep 2025 12:40:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757076003; cv=none; b=KZ+HvlZhlucYltUf94H4apu3KXzqCBt9+AQVSlEhdVN7cC/E+D0pIJlu6z7W9nvBHNUBJ9PG/z8eJ/D0E6YoXnxW8jqtzSbeOGhajxtj6QarYUEDUuvMG8NKHSK+51Bc6qNoYsLv2Pm/VSn4+S3vGLzs08TQ+V0qhmmEq9wRFQs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757076003; c=relaxed/simple; bh=dnjRpNqUHpCCqmEgd85I4QFT6pOpZkdtOu7seS3QRUc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WanHy5AjDlPBFCh5pr6GCZ2ubWUwc3BH7wXPpJacaHJIqi2B1rXMTQTR79SIWqW89j1v0HiP6r3hcqsdsvs2vPuLJHZMGh178+CkRrag6EAhTbe2WC3Y4aQZYTyBM9mX/KcLHkaIqgvHCFBZdOosabOftzmtikYlO0EzaTjhZHY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oDtrSrjb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oDtrSrjb" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0F616C4CEF8; Fri, 5 Sep 2025 12:40:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757076002; bh=dnjRpNqUHpCCqmEgd85I4QFT6pOpZkdtOu7seS3QRUc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=oDtrSrjb/KUUxLaKU2ClfX94QXSWBl4PBvKEIznBNYdEeI0fzKo9ABS9f1XR/dEZy 1B19YA1Ngolj767KZbitAN/pA8Aua7HEHtglhY6j8QfPSE37G1pXSZvrLymPOgrBMv nCWrcGQA7TY8fOprbZ+2M0PUN89nVnv1wj0hERriiT3aeDSYOElDI1xfoHElY5vOk+ hmggRFH1fPg1GsXX62/PyDY7JfBkHFcin32l9Ff1k49DCM5cZ60haekm987dYogRyE PhBFMB1Y1dVOUOkXIKbbw0/AsKoe7Cc/+Qw4zyiTT5wCRVSyxopMAGDhQncf5oD1X7 LoX8lKbDDj10A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id EAC3ACA1013; Fri, 5 Sep 2025 12:40:01 +0000 (UTC) From: Woodrow Douglass via B4 Relay Date: Fri, 05 Sep 2025 08:39:42 -0400 Subject: [PATCH v7 1/2] regulator: dt-bindings: nxp,pf530x: Add NXP PF5300/PF5301/PF5302 PMICs 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: <20250902-pf530x-v7-1-10eb2542f944@carnegierobotics.com> References: <20250902-pf530x-v7-0-10eb2542f944@carnegierobotics.com> In-Reply-To: <20250902-pf530x-v7-0-10eb2542f944@carnegierobotics.com> To: Liam Girdwood , Mark Brown , Woodrow Douglass , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Krzysztof Kozlowski X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2021; i=wdouglass@carnegierobotics.com; h=from:subject:message-id; bh=GD/QKOeIwH6rbORAuBGoRr4qUHkMzXDClFHYwzK9aEo=; b=owEBbQGS/pANAwAKAewLuLlPNh4UAcsmYgBoutohx0/o4FKRg04xIhoXtqGt+27lNHYVpW1JX 3H4P5K3WbCJATMEAAEKAB0WIQSIUqjrbDLQw0mgxHLsC7i5TzYeFAUCaLraIQAKCRDsC7i5TzYe FI/dCACW0IxiwITRW1ui2rqoV6KRQAW894ZHeskC9UF9YeYKhmKK8VmMm/AGeH8Vc0wxG8sL/wh CvktFGvZp36fXeHSIbbFCHB80o2e0QS74qyw/Pi5klColoZEXLwtEFCdUZNudwX9tRXKPVDUTSc dH/XwJH9vo2RjQlfYltjeyp3AT/AB2GyhK/6xDCOCSqMiNKWutKLW93PumnF3mRnzFPat5ojZaM Qj3xep1a2WAjhVjTldcHwsVHElyucESvujLeZA9Gn1Q87X9kcQOdwIB0b8/O/87AnQg2zIn7ymX JZ5g/65o8mHa0Zrew9iWy2K96v1ptySWSZum7N+v+Md+/g7I X-Developer-Key: i=wdouglass@carnegierobotics.com; a=openpgp; fpr=8852A8EB6C32D0C349A0C472EC0BB8B94F361E14 X-Endpoint-Received: by B4 Relay for wdouglass@carnegierobotics.com/default with auth_id=514 X-Original-From: Woodrow Douglass Reply-To: wdouglass@carnegierobotics.com From: Woodrow Douglass Bindings for the pf530x series of voltage regulators Signed-off-by: Woodrow Douglass Reviewed-by: Krzysztof Kozlowski --- .../devicetree/bindings/regulator/nxp,pf5300.yaml | 54 ++++++++++++++++++= ++++ 1 file changed, 54 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/nxp,pf5300.yaml b/= Documentation/devicetree/bindings/regulator/nxp,pf5300.yaml new file mode 100644 index 000000000000..5b9d5d4e48d0 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/nxp,pf5300.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/nxp,pf5300.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP PF5300/PF5301/PF5302 PMIC regulators + +maintainers: + - Woodrow Douglass + +description: | + The PF5300, PF5301, and PF5302 integrate high-performance buck converter= s, + 12 A, 8 A, and 15 A, respectively, to power high-end automotive and indu= strial + processors. With adaptive voltage positioning and a high-bandwidth loop,= they + offer transient regulation to minimize capacitor requirements. + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + oneOf: + - const: nxp,pf5300 + - items: + - enum: + - nxp,pf5301 + - nxp,pf5302 + - const: nxp,pf5300 + reg: + maxItems: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + + regulator@28 { + compatible =3D "nxp,pf5302", "nxp,pf5300"; + reg =3D <0x28>; + + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt =3D <1200000>; + regulator-min-microvolt =3D <500000>; + }; + }; --=20 2.39.5 From nobody Wed Sep 10 05:39:08 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 52B7A1F1513; Fri, 5 Sep 2025 12:40:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757076002; cv=none; b=NMaIJ/c0rx8YLnI5SF7GC7nr1H3NcxBYifBIOMNe5oOV4HKwTFcxrW/EPzxaEyWV8PhQdU1Pikt1KDWB0oIEz1i8/okXj5PKoAEFEGQujrwS1aDiywH/aBizz7mevPcIfbGAre1j6paVKquzZlWzaul0KQOu28enf61uITbWPjo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757076002; c=relaxed/simple; bh=9tc7MPBFZtryo7G7sX61tLUWL+OEWvCi5g2YTsIJHuo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gMEPG694WfgoQIpjYTaMX+5RiHuFsBWA0yTiUdEe2E3RK8Ec/M96+69KdD+yRc+UGxQDaDCpR6uTS2+VGitjaDHUVdSQSb1qyWLqXSfYMm3dl2XmBujiPyf+rFWRHVfrwGuB2SFrT1UJFVBUxjQJu7aO2jY06ytDtdQ1yi5XhZg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GWUEi87d; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GWUEi87d" Received: by smtp.kernel.org (Postfix) with ESMTPS id 17327C4CEFB; Fri, 5 Sep 2025 12:40:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757076002; bh=9tc7MPBFZtryo7G7sX61tLUWL+OEWvCi5g2YTsIJHuo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=GWUEi87dGNIxwBi+m+B6/alGLS+OcGqTLkvjSdqAY5uaksDXwr6kiQsQmBiCA0KgJ MMhDdl3cUvTh47g74JLn+jiYGrUv3AtviRgh6Rpu1Uuqbp2fjiv5xVy67fjsqnzXw8 k+bz4YDX5cuhxPB0BVBx7Zsjh9LuEt+4v3XPY1xZgA49BBr10rZno9Tb5fu0h5k84g YUYGaP6q/d3WJ1usR8LO0KwY+Mt2FWAPcim8BVtagiGorQd3ucU5oAM+Ox59YbpkoT kpxW4TqXbQ0QFsfrSWXvdepyh/sW5VE9hsPo8IVrId+OJxL/cvWRoWGSedNfIJZa3d vy/WkG8COcRBQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 065CDCA101F; Fri, 5 Sep 2025 12:40:02 +0000 (UTC) From: Woodrow Douglass via B4 Relay Date: Fri, 05 Sep 2025 08:39:43 -0400 Subject: [PATCH v7 2/2] regulator: pf530x: Add a driver for the NXP PF5300 Regulator 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: <20250902-pf530x-v7-2-10eb2542f944@carnegierobotics.com> References: <20250902-pf530x-v7-0-10eb2542f944@carnegierobotics.com> In-Reply-To: <20250902-pf530x-v7-0-10eb2542f944@carnegierobotics.com> To: Liam Girdwood , Mark Brown , Woodrow Douglass , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=12776; i=wdouglass@carnegierobotics.com; h=from:subject:message-id; bh=Ap+q4aaKJdGlVQuy67tgUbt9LfF2bYxDb+Lne2W48co=; b=owEBbQGS/pANAwAKAewLuLlPNh4UAcsmYgBoutohuwXvz3y7/rvx9Gr5X03iVOTXG1BOCSn14 AxetvcABEaJATMEAAEKAB0WIQSIUqjrbDLQw0mgxHLsC7i5TzYeFAUCaLraIQAKCRDsC7i5TzYe FAMEB/4+jCO9rRWMUgeyNkKyGH62sHWks/YQf2OY5VU31veBlJXCKQeLyfZeOfcHL6N/6I3R1kt r2pS7xeLNhUxtuywQrPjhMDqGXnlFLmg+7YJPfFMEa3SZJ3/7yt+Wb4AXxi0njUqgBGsDCF0SjD xEmD1PTfMKIMWylKGiI/ueLRSdB8N55jXxIOwEWiib1LZ6Gh/171GePY50LYLQONwzBnhEE6BnI paXq98fr9ZUxU9r8rMmTx+gNlG1K29sEJIv9gnr8+h0UWv0xGQSxWY0RkLMTAagMwiy3Z1WEzIj NxZyFuqUKtUlFL7L6XqGG4m12bchmfNl/+107stxKwbuR5YN X-Developer-Key: i=wdouglass@carnegierobotics.com; a=openpgp; fpr=8852A8EB6C32D0C349A0C472EC0BB8B94F361E14 X-Endpoint-Received: by B4 Relay for wdouglass@carnegierobotics.com/default with auth_id=514 X-Original-From: Woodrow Douglass Reply-To: wdouglass@carnegierobotics.com From: Woodrow Douglass This driver allows reading some regulator settings and adjusting output voltage. It is based on information from the datasheet at https://www.nxp.com/docs/en/data-sheet/PF5300.pdf Signed-off-by: Woodrow Douglass --- MAINTAINERS | 6 + drivers/regulator/Kconfig | 12 ++ drivers/regulator/Makefile | 1 + drivers/regulator/pf530x-regulator.c | 375 +++++++++++++++++++++++++++++++= ++++ 4 files changed, 394 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6dcfbd11efef..7374cb0ae5d4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18291,6 +18291,12 @@ F: Documentation/devicetree/bindings/clock/*imx* F: drivers/clk/imx/ F: include/dt-bindings/clock/*imx* =20 +NXP PF5300/PF5301/PF5302 PMIC REGULATOR DEVICE DRIVER +M: Woodrow Douglass +S: Maintained +F: Documentation/devicetree/bindings/regulator/nxp,pf5300.yaml +F: drivers/regulator/pf530x-regulator.c + NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER M: Jagan Teki S: Maintained diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index eaa6df1c9f80..611356bea09d 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1006,6 +1006,18 @@ config REGULATOR_PCAP This driver provides support for the voltage regulators of the PCAP2 PMIC. =20 +config REGULATOR_PF530X + tristate "NXP PF5300/PF5301/PF5302 regulator driver" + depends on I2C && OF + select REGMAP_I2C + help + Say y here to support the regulators found on the NXP + PF5300/PF5301/PF5302 PMIC. + + Say M here if you want to support for the regulators found + on the NXP PF5300/PF5301/PF5302 PMIC. The module will be named + "pf530x-regulator". + config REGULATOR_PF8X00 tristate "NXP PF8100/PF8121A/PF8200 regulator driver" depends on I2C && OF diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index be98b29d6675..60ca55d04aef 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -125,6 +125,7 @@ obj-$(CONFIG_REGULATOR_QCOM_USB_VBUS) +=3D qcom_usb_vbu= s-regulator.o obj-$(CONFIG_REGULATOR_PALMAS) +=3D palmas-regulator.o obj-$(CONFIG_REGULATOR_PCA9450) +=3D pca9450-regulator.o obj-$(CONFIG_REGULATOR_PF9453) +=3D pf9453-regulator.o +obj-$(CONFIG_REGULATOR_PF530X) +=3D pf530x-regulator.o obj-$(CONFIG_REGULATOR_PF8X00) +=3D pf8x00-regulator.o obj-$(CONFIG_REGULATOR_PFUZE100) +=3D pfuze100-regulator.o obj-$(CONFIG_REGULATOR_PV88060) +=3D pv88060-regulator.o diff --git a/drivers/regulator/pf530x-regulator.c b/drivers/regulator/pf530= x-regulator.c new file mode 100644 index 000000000000..f789c4b6a499 --- /dev/null +++ b/drivers/regulator/pf530x-regulator.c @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: GPL-2.0+ + +// documentation of this device is available at +// https://www.nxp.com/docs/en/data-sheet/PF5300.pdf + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* registers */ +#define PF530X_DEVICEID 0x00 +#define PF530X_REV 0x01 +#define PF530X_EMREV 0x02 +#define PF530X_PROGID 0x03 +#define PF530X_CONFIG1 0x04 +#define PF530X_INT_STATUS1 0x05 +#define PF530X_INT_SENSE1 0x06 +#define PF530X_INT_STATUS2 0x07 +#define PF530X_INT_SENSE2 0x08 +#define PF530X_BIST_STAT1 0x09 +#define PF530X_BIST_CTRL 0x0a +#define PF530X_STATE 0x0b +#define PF530X_STATE_CTRL 0x0c +#define PF530X_SW1_VOLT 0x0d +#define PF530X_SW1_STBY_VOLT 0x0e +#define PF530X_SW1_CTRL1 0x0f +#define PF530X_SW1_CTRL2 0x10 +#define PF530X_CLK_CTRL 0x11 +#define PF530X_SEQ_CTRL1 0x12 +#define PF530X_SEQ_CTRL2 0x13 +#define PF530X_RANDOM_CHK 0x14 +#define PF530X_RANDOM_GEN 0x15 +#define PF530X_WD_CTRL1 0x16 +#define PF530X_WD_SEED 0x17 +#define PF530X_WD_ANSWER 0x18 +#define PF530X_FLT_CNT1 0x19 +#define PF530X_FLT_CNT2 0x1a +#define PF530X_OTP_MODE 0x2f + +enum pf530x_states { + PF530X_STATE_POF, + PF530X_STATE_FUSE_LOAD, + PF530X_STATE_LP_OFF, + PF530X_STATE_SELF_TEST, + PF530X_STATE_POWER_UP, + PF530X_STATE_INIT, + PF530X_STATE_IO_RELEASE, + PF530X_STATE_RUN, + PF530X_STATE_STANDBY, + PF530X_STATE_FAULT, + PF530X_STATE_FAILSAFE, + PF530X_STATE_POWER_DOWN, + PF530X_STATE_2MS_SELFTEST_RETRY, + PF530X_STATE_OFF_DLY, +}; + +#define PF530_FAM 0x50 +enum pf530x_devid { + PF5300 =3D 0x3, + PF5301 =3D 0x4, + PF5302 =3D 0x5, +}; + +#define PF530x_FAM 0x50 +#define PF530x_DEVICE_FAM_MASK GENMASK(7, 4) +#define PF530x_DEVICE_ID_MASK GENMASK(3, 0) + +#define PF530x_STATE_MASK GENMASK(3, 0) +#define PF530x_STATE_RUN 0x07 +#define PF530x_STATE_STANDBY 0x08 +#define PF530x_STATE_LP_OFF 0x02 + +#define PF530X_OTP_STBY_MODE GENMASK(3, 2) +#define PF530X_OTP_RUN_MODE GENMASK(1, 0) + +#define PF530X_INT_STATUS_OV BIT(1) +#define PF530X_INT_STATUS_UV BIT(2) +#define PF530X_INT_STATUS_ILIM BIT(3) + +#define SW1_ILIM_S BIT(0) +#define VMON_UV_S BIT(1) +#define VMON_OV_S BIT(2) +#define VIN_OVLO_S BIT(3) +#define BG_ERR_S BIT(6) + +#define THERM_155_S BIT(3) +#define THERM_140_S BIT(2) +#define THERM_125_S BIT(1) +#define THERM_110_S BIT(0) + +struct pf530x_chip { + struct regmap *regmap; + struct device *dev; +}; + +static const struct regmap_config pf530x_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .max_register =3D PF530X_OTP_MODE, + .cache_type =3D REGCACHE_MAPLE, +}; + +static int pf530x_get_status(struct regulator_dev *rdev) +{ + unsigned int state; + int ret; + + ret =3D regmap_read(rdev->regmap, PF530X_INT_SENSE1, &state); + if (ret !=3D 0) + return ret; + + if ((state & (BG_ERR_S | SW1_ILIM_S | VMON_UV_S | VMON_OV_S | VIN_OVLO_S)) + !=3D 0) + return REGULATOR_STATUS_ERROR; + + // no errors, check if what non-error state we're in + ret =3D regmap_read(rdev->regmap, PF530X_STATE, &state); + if (ret !=3D 0) + return ret; + + state &=3D PF530x_STATE_MASK; + + switch (state) { + case PF530x_STATE_RUN: + ret =3D REGULATOR_STATUS_NORMAL; + break; + case PF530x_STATE_STANDBY: + ret =3D REGULATOR_STATUS_STANDBY; + break; + case PF530x_STATE_LP_OFF: + ret =3D REGULATOR_STATUS_OFF; + break; + default: + ret =3D REGULATOR_STATUS_ERROR; + break; + } + return ret; +} + +static int pf530x_get_error_flags(struct regulator_dev *rdev, unsigned int= *flags) +{ + unsigned int status; + int ret; + + ret =3D regmap_read(rdev->regmap, PF530X_INT_STATUS1, &status); + + if (ret !=3D 0) + return ret; + + *flags =3D 0; + + if (status & PF530X_INT_STATUS_OV) + *flags |=3D REGULATOR_ERROR_OVER_VOLTAGE_WARN; + + if (status & PF530X_INT_STATUS_UV) + *flags |=3D REGULATOR_ERROR_UNDER_VOLTAGE; + + if (status & PF530X_INT_STATUS_ILIM) + *flags |=3D REGULATOR_ERROR_OVER_CURRENT; + + ret =3D regmap_read(rdev->regmap, PF530X_INT_SENSE2, &status); + + if (ret !=3D 0) + return ret; + + if ((status & (THERM_155_S | + THERM_140_S | + THERM_125_S | + THERM_110_S)) !=3D 0) + *flags |=3D REGULATOR_ERROR_OVER_TEMP_WARN; + + return 0; +} + +static const struct regulator_ops pf530x_regulator_ops =3D { + .enable =3D regulator_enable_regmap, + .disable =3D regulator_disable_regmap, + .is_enabled =3D regulator_is_enabled_regmap, + .map_voltage =3D regulator_map_voltage_linear_range, + .list_voltage =3D regulator_list_voltage_linear_range, + .set_voltage_sel =3D regulator_set_voltage_sel_regmap, + .get_voltage_sel =3D regulator_get_voltage_sel_regmap, + .get_status =3D pf530x_get_status, + .get_error_flags =3D pf530x_get_error_flags, + .set_bypass =3D regulator_set_bypass_regmap, + .get_bypass =3D regulator_get_bypass_regmap, +}; + +static const struct linear_range vrange =3D REGULATOR_LINEAR_RANGE(500000,= 0, 140, 5000); + +static const struct regulator_desc pf530x_reg_desc =3D { + .name =3D "SW1", + .ops =3D &pf530x_regulator_ops, + .linear_ranges =3D &vrange, + .n_linear_ranges =3D 1, + .type =3D REGULATOR_VOLTAGE, + .id =3D 0, + .owner =3D THIS_MODULE, + .vsel_reg =3D PF530X_SW1_VOLT, + .vsel_mask =3D 0xFF, + .bypass_reg =3D PF530X_SW1_CTRL2, + .bypass_mask =3D 0x07, + .bypass_val_on =3D 0x07, + .bypass_val_off =3D 0x00, + .enable_reg =3D PF530X_SW1_CTRL1, + .enable_mask =3D GENMASK(5, 2), + .enable_val =3D GENMASK(5, 2), + .disable_val =3D 0, +}; + +static int pf530x_identify(struct pf530x_chip *chip) +{ + unsigned int value; + u8 dev_fam, dev_id, full_layer_rev, metal_layer_rev, prog_idh, prog_idl, = emrev; + const char *name =3D NULL; + int ret; + + ret =3D regmap_read(chip->regmap, PF530X_DEVICEID, &value); + if (ret) { + dev_err(chip->dev, "failed to read chip family\n"); + return ret; + } + + dev_fam =3D value & PF530x_DEVICE_FAM_MASK; + switch (dev_fam) { + case PF530x_FAM: + break; + default: + dev_err(chip->dev, + "Chip 0x%x is not from PF530X family\n", dev_fam); + return ret; + } + + dev_id =3D value & PF530x_DEVICE_ID_MASK; + switch (dev_id) { + case PF5300: + name =3D "PF5300"; + break; + case PF5301: + name =3D "PF5301"; + break; + case PF5302: + name =3D "PF5302"; + break; + default: + dev_err(chip->dev, "Unknown pf530x device id 0x%x\n", dev_id); + return -ENODEV; + } + + ret =3D regmap_read(chip->regmap, PF530X_REV, &value); + if (ret) { + dev_err(chip->dev, "failed to read chip rev\n"); + return ret; + } + + full_layer_rev =3D ((value & 0xF0) =3D=3D 0) ? '0' : ((((value & 0xF0) >>= 4) - 1) + 'A'); + metal_layer_rev =3D value & 0xF; + + ret =3D regmap_read(chip->regmap, PF530X_EMREV, &value); + if (ret) { + dev_err(chip->dev, "failed to read chip emrev register\n"); + return ret; + } + + prog_idh =3D (value >> 4) + 'A'; + // prog_idh skips 'O', per page 96 of the datasheet + if (prog_idh >=3D 'O') + prog_idh +=3D 1; + + emrev =3D value & 0x7; + + ret =3D regmap_read(chip->regmap, PF530X_PROGID, &value); + if (ret) { + dev_err(chip->dev, "failed to read chip progid register\n"); + return ret; + } + + if (value >=3D 0x22) { + dev_err(chip->dev, "invalid value for progid register\n"); + return -ENODEV; + } else if (value < 10) { + prog_idl =3D value + '0'; + } else { + prog_idl =3D (value - 10) + 'A'; + // prog_idh skips 'O', per page 97 of the datasheet + if (prog_idl >=3D 'O') + prog_idl +=3D 1; + } + + dev_info(chip->dev, "%s Regulator found (Rev %c%d ProgID %c%c EMREV %x).\= n", + name, full_layer_rev, metal_layer_rev, prog_idh, prog_idl, emrev); + + return 0; +} + +static int pf530x_i2c_probe(struct i2c_client *client) +{ + struct regulator_config config =3D { NULL, }; + struct pf530x_chip *chip; + int ret; + struct regulator_dev *rdev; + struct regulator_init_data *init_data; + + chip =3D devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + i2c_set_clientdata(client, chip); + chip->dev =3D &client->dev; + + chip->regmap =3D devm_regmap_init_i2c(client, &pf530x_regmap_config); + if (IS_ERR(chip->regmap)) { + ret =3D PTR_ERR(chip->regmap); + dev_err(&client->dev, + "regmap allocation failed with err %d\n", ret); + return ret; + } + + ret =3D pf530x_identify(chip); + if (ret) + return ret; + + init_data =3D of_get_regulator_init_data(chip->dev, chip->dev->of_node, &= pf530x_reg_desc); + if (!init_data) + return -ENODATA; + + config.dev =3D chip->dev; + config.of_node =3D chip->dev->of_node; + config.regmap =3D chip->regmap; + config.init_data =3D init_data; + + // the config parameter gets copied, it's ok to pass a pointer on the sta= ck here + rdev =3D devm_regulator_register(&client->dev, &pf530x_reg_desc, &config); + if (IS_ERR(rdev)) { + dev_err(&client->dev, "failed to register %s regulator\n", pf530x_reg_de= sc.name); + return PTR_ERR(rdev); + } + + return 0; +} + +static const struct of_device_id pf530x_dt_ids[] =3D { + { .compatible =3D "nxp,pf5300",}, + { } +}; +MODULE_DEVICE_TABLE(of, pf530x_dt_ids); + +static const struct i2c_device_id pf530x_i2c_id[] =3D { + { "pf5300", 0 }, + { "pf5301", 0 }, + { "pf5302", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, pf530x_i2c_id); + +static struct i2c_driver pf530x_regulator_driver =3D { + .id_table =3D pf530x_i2c_id, + .driver =3D { + .name =3D "pf530x", + .of_match_table =3D pf530x_dt_ids, + }, + .probe =3D pf530x_i2c_probe, +}; +module_i2c_driver(pf530x_regulator_driver); + +MODULE_AUTHOR("Woodrow Douglass "); +MODULE_DESCRIPTION("Regulator Driver for NXP's PF5300/PF5301/PF5302 PMIC"); +MODULE_LICENSE("GPL"); --=20 2.39.5