* [PATCH v2 0/2] regulator: add new PMIC PF0900 support
@ 2025-07-21 7:11 Joy Zou
2025-07-21 7:11 ` [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml Joy Zou
2025-07-21 7:11 ` [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support Joy Zou
0 siblings, 2 replies; 10+ messages in thread
From: Joy Zou @ 2025-07-21 7:11 UTC (permalink / raw)
To: Joy Zou, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, imx, Frank Li, Ye Li, Jacky Bai,
Dong Aisheng, kernel test robot
Add binding document and driver.
Signed-off-by: Joy Zou <joy.zou@nxp.com>
---
Changes in v2:
binding part
- modify the binding file name to match compatible string.
- add one space for dt_binding_check warning.
- remove unnecessary quotes from "VAON".
- remove the unnecessary empty line.
- move unevaluatedProperties after the $ref.
- move additionalProperties after regulator type.
- remove unnecessary regulator description
driver part
- modify the copyright comment block to C++ style.
- add reg_read/write for regmap_bus.
- remove original pf0900_pmic_read/write.
- remove many regulator operations.
- use regmap_read replace pf0900_pmic_read.
- use regmap_update_bits and regmap_write_bits replace pf0900_pmic_write.
- move the code from pf0900.h to pf0900-regulator.c and delete the header file.
- remove unmask status interrupts and add unmask regulator interrupts.
- remove many interrupts check warning print from irq_handler.
- add notifier for regulator event.
- remove unused macro define.
- add PF0900 prefix for IRQ macro define in order to avoid duplication.
- use GENMASK() and BIT() to replace mask marco define
- remove redundant enum pf0900_chip_type.
- remove redundant print info and comments.
- add dvs property present check because this property is optional.
- remove ret == -EINVAL check from sw_set_dvs() function.
- Link to v1: https://lore.kernel.org/imx/20250617102025.3455544-1-joy.zou@nxp.com/
---
Joy Zou (2):
dt-bindings: regulator: add PF0900 regulator yaml
regulator: pf0900: Add PMIC PF0900 support
.../devicetree/bindings/regulator/nxp,pf0900.yaml | 169 ++++
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/pf0900-regulator.c | 1028 ++++++++++++++++++++
4 files changed, 1206 insertions(+)
---
base-commit: d086c886ceb9f59dea6c3a9dae7eb89e780a20c9
change-id: 20250714-b4-pf09-v2-91cdee6d1272
Best regards,
--
Joy Zou <joy.zou@nxp.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml
2025-07-21 7:11 [PATCH v2 0/2] regulator: add new PMIC PF0900 support Joy Zou
@ 2025-07-21 7:11 ` Joy Zou
2025-07-21 7:28 ` Krzysztof Kozlowski
2025-07-21 7:11 ` [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support Joy Zou
1 sibling, 1 reply; 10+ messages in thread
From: Joy Zou @ 2025-07-21 7:11 UTC (permalink / raw)
To: Joy Zou, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, imx, Frank Li, Ye Li, Jacky Bai,
Dong Aisheng
Add device binding doc for PF0900 PMIC driver.
Signed-off-by: Joy Zou <joy.zou@nxp.com>
---
Changes for v2:
1. modify the binding file name to match compatible string.
2. add one space for dt_binding_check warning.
3. remove unnecessary quotes from "VAON".
4. remove the unnecessary empty line.
5. move unevaluatedProperties after the $ref.
6. move additionalProperties after regulator type.
7. remove unnecessary regulator description
---
.../devicetree/bindings/regulator/nxp,pf0900.yaml | 169 +++++++++++++++++++++
1 file changed, 169 insertions(+)
diff --git a/Documentation/devicetree/bindings/regulator/nxp,pf0900.yaml b/Documentation/devicetree/bindings/regulator/nxp,pf0900.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..55cfe9ad5c5c24b47d5a806985e092e279755064
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/nxp,pf0900.yaml
@@ -0,0 +1,169 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/nxp,pf0900.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PF0900 Power Management Integrated Circuit regulators
+
+maintainers:
+ - Joy Zou <joy.zou@nxp.com>
+
+description:
+ The PF0900 is a power management integrated circuit (PMIC) optimized
+ for high performance i.MX9x based applications. It features five high
+ efficiency buck converters, three linear and one vaon regulators. It
+ provides low quiescent current in Standby and low power off Modes.
+
+properties:
+ compatible:
+ enum:
+ - nxp,pf0900
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ regulators:
+ type: object
+ additionalProperties: false
+
+ properties:
+ VAON:
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ patternProperties:
+ "^LDO[1-3]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^SW[1-5]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ nxp,dvs-run-microvolt:
+ minimum: 300000
+ maximum: 1350000
+ description:
+ PMIC default "RUN" state voltage in uV.
+
+ nxp,dvs-standby-microvolt:
+ minimum: 300000
+ maximum: 1350000
+ description:
+ PMIC default "STANDBY" state voltage in uV.
+
+ nxp,i2c-crc-enable:
+ type: boolean
+ description: If the PMIC OTP_I2C_CRC_EN is enable, you need to add this property.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@8 {
+ compatible = "nxp,pf0900";
+ reg = <0x08>;
+ interrupt-parent = <&pcal6524>;
+ interrupts = <89 IRQ_TYPE_LEVEL_LOW>;
+ nxp,i2c-crc-enable;
+
+ regulators {
+ VAON {
+ regulator-name = "VAON";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ SW1 {
+ regulator-name = "SW1";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1950>;
+ };
+
+ SW2 {
+ regulator-name = "SW2";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1950>;
+ };
+
+ SW3 {
+ regulator-name = "SW3";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1950>;
+ };
+
+ SW4 {
+ regulator-name = "SW4";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1950>;
+ };
+
+ SW5 {
+ regulator-name = "SW5";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1950>;
+ };
+
+ LDO1 {
+ regulator-name = "LDO1";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO2 {
+ regulator-name = "LDO2";
+ regulator-min-microvolt = <650000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO3 {
+ regulator-name = "LDO3";
+ regulator-min-microvolt = <650000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+ };
--
2.37.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support
2025-07-21 7:11 [PATCH v2 0/2] regulator: add new PMIC PF0900 support Joy Zou
2025-07-21 7:11 ` [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml Joy Zou
@ 2025-07-21 7:11 ` Joy Zou
2025-07-21 7:30 ` Krzysztof Kozlowski
` (2 more replies)
1 sibling, 3 replies; 10+ messages in thread
From: Joy Zou @ 2025-07-21 7:11 UTC (permalink / raw)
To: Joy Zou, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, imx, Frank Li, Ye Li, Jacky Bai,
Dong Aisheng, kernel test robot
The PF0900 is a power management integrated circuit (PMIC) optimized
for high performance i.MX9x based applications. It features five high
efficiency buck converters, three linear and one vaon regulators.
It provides low quiescent current in Standby and low power off Modes.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202506181134.0Hkvy7CK-lkp@intel.com/
Signed-off-by: Joy Zou <joy.zou@nxp.com>
Changes for v2:
1. modify the copyright comment block to C++ style.
2. add reg_read/write for regmap_bus.
3. remove original pf0900_pmic_read/write.
4. remove many regulator operations.
5. use regmap_read replace pf0900_pmic_read.
6. use regmap_update_bits and regmap_write_bits replace pf0900_pmic_write.
7. move the code from pf0900.h to pf0900-regulator.c and delete the header file.
8. remove unmask status interrupts and add unmask regulator interrupts.
9. remove many interrupts check warning print from irq_handler.
10. add notifier for regulator event.
11. remove unused macro define.
12. add PF0900 prefix for IRQ macro define in order to avoid duplication.
13. use GENMASK() and BIT() to replace mask marco define.
14. remove redundant enum pf0900_chip_type.
15. remove redundant print info and comments.
16. add dvs property present check because this property is optional.
17. remove ret == -EINVAL check from sw_set_dvs() function.
---
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/pf0900-regulator.c | 1028 ++++++++++++++++++++++++++++++++++
3 files changed, 1037 insertions(+)
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 7423954153b07f55d2a618fcc4a78bfd631db774..cc0f86c374886261844004071067da263a4f3f01 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1006,6 +1006,14 @@ config REGULATOR_PCAP
This driver provides support for the voltage regulators of the
PCAP2 PMIC.
+config REGULATOR_PF0900
+ tristate "NXP PF0900/PF0901/PF09XX regulator driver"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say y here to support the NXP PF0900/PF0901/PF09XX PMIC
+ regulator driver.
+
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 be98b29d6675d8be1ca984c2d137bdfc4ba2de87..74b029d29a8b7faf79f3f82bb848eab65568753f 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -124,6 +124,7 @@ obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_USB_VBUS) += qcom_usb_vbus-regulator.o
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
obj-$(CONFIG_REGULATOR_PCA9450) += pca9450-regulator.o
+obj-$(CONFIG_REGULATOR_PF0900) += pf0900-regulator.o
obj-$(CONFIG_REGULATOR_PF9453) += pf9453-regulator.o
obj-$(CONFIG_REGULATOR_PF8X00) += pf8x00-regulator.o
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
diff --git a/drivers/regulator/pf0900-regulator.c b/drivers/regulator/pf0900-regulator.c
new file mode 100644
index 0000000000000000000000000000000000000000..7310fec3e66ea30b4a961666f48eb9889aae98b8
--- /dev/null
+++ b/drivers/regulator/pf0900-regulator.c
@@ -0,0 +1,1028 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2025 NXP.
+// NXP PF0900 pmic driver
+
+#include <linux/crc8.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+enum pf0900_regulators {
+ PF0900_SW1 = 0,
+ PF0900_SW2,
+ PF0900_SW3,
+ PF0900_SW4,
+ PF0900_SW5,
+ PF0900_LDO1,
+ PF0900_LDO2,
+ PF0900_LDO3,
+ PF0900_VAON,
+ PF0900_REGULATOR_CNT,
+};
+
+enum {
+ PF0900_DVS_LEVEL_RUN = 0,
+ PF0900_DVS_LEVEL_STANDBY,
+ PF0900_DVS_LEVEL_MAX,
+};
+
+
+#define PF0900_VAON_VOLTAGE_NUM 0x03
+#define PF0900_SW_VOLTAGE_NUM 0x100
+#define PF0900_LDO_VOLTAGE_NUM 0x20
+
+#define REGU_SW_CNT 0x5
+#define REGU_LDO_VAON_CNT 0x4
+
+enum {
+ PF0900_REG_DEV_ID = 0x00,
+ PF0900_REG_DEV_FAM = 0x01,
+ PF0900_REG_REV_ID = 0x02,
+ PF0900_REG_PROG_ID1 = 0x03,
+ PF0900_REG_PROG_ID2 = 0x04,
+ PF0900_REG_SYSTEM_INT = 0x05,
+ PF0900_REG_STATUS1_INT = 0x06,
+ PF0900_REG_STATUS1_MSK = 0x07,
+ PF0900_REG_STATUS1_SNS = 0x08,
+ PF0900_REG_STATUS2_INT = 0x09,
+ PF0900_REG_STATUS2_MSK = 0x0A,
+ PF0900_REG_STATUS2_SNS = 0x0B,
+ PF0900_REG_STATUS3_INT = 0x0C,
+ PF0900_REG_STATUS3_MSK = 0x0D,
+ PF0900_REG_SW_MODE_INT = 0x0E,
+ PF0900_REG_SW_MODE_MSK = 0x0F,
+ PF0900_REG_SW_ILIM_INT = 0x10,
+ PF0900_REG_SW_ILIM_MSK = 0x11,
+ PF0900_REG_SW_ILIM_SNS = 0x12,
+ PF0900_REG_LDO_ILIM_INT = 0x13,
+ PF0900_REG_LDO_ILIM_MSK = 0x14,
+ PF0900_REG_LDO_ILIM_SNS = 0x15,
+ PF0900_REG_SW_UV_INT = 0x16,
+ PF0900_REG_SW_UV_MSK = 0x17,
+ PF0900_REG_SW_UV_SNS = 0x18,
+ PF0900_REG_SW_OV_INT = 0x19,
+ PF0900_REG_SW_OV_MSK = 0x1A,
+ PF0900_REG_SW_OV_SNS = 0x1B,
+ PF0900_REG_LDO_UV_INT = 0x1C,
+ PF0900_REG_LDO_UV_MSK = 0x1D,
+ PF0900_REG_LDO_UV_SNS = 0x1E,
+ PF0900_REG_LDO_OV_INT = 0x1F,
+ PF0900_REG_LDO_OV_MSK = 0x20,
+ PF0900_REG_LDO_OV_SNS = 0x21,
+ PF0900_REG_PWRON_INT = 0x22,
+ PF0900_REG_IO_INT = 0x24,
+ PF0900_REG_IO_MSK = 0x25,
+ PF0900_REG_IO_SNS = 0x26,
+ PF0900_REG_IOSHORT_SNS = 0x27,
+ PF0900_REG_ABIST_OV1 = 0x28,
+ PF0900_REG_ABIST_OV2 = 0x29,
+ PF0900_REG_ABIST_UV1 = 0x2A,
+ PF0900_REG_ABIST_UV2 = 0x2B,
+ PF0900_REG_ABIST_IO = 0x2C,
+ PF0900_REG_TEST_FLAGS = 0x2D,
+ PF0900_REG_HFAULT_FLAGS = 0x2E,
+ PF0900_REG_FAULT_FLAGS = 0x2F,
+ PF0900_REG_FS0B_CFG = 0x30,
+ PF0900_REG_FCCU_CFG = 0x31,
+ PF0900_REG_RSTB_CFG1 = 0x32,
+ PF0900_REG_SYSTEM_CMD = 0x33,
+ PF0900_REG_FS0B_CMD = 0x34,
+ PF0900_REG_SECURE_WR1 = 0x35,
+ PF0900_REG_SECURE_WR2 = 0x36,
+ PF0900_REG_VMON_CFG1 = 0x37,
+ PF0900_REG_SYS_CFG1 = 0x38,
+ PF0900_REG_GPO_CFG = 0x39,
+ PF0900_REG_GPO_CTRL = 0x3A,
+ PF0900_REG_PWRUP_CFG = 0x3B,
+ PF0900_REG_RSTB_PWRUP = 0x3C,
+ PF0900_REG_GPIO1_PWRUP = 0x3D,
+ PF0900_REG_GPIO2_PWRUP = 0x3E,
+ PF0900_REG_GPIO3_PWRUP = 0x3F,
+ PF0900_REG_GPIO4_PWRUP = 0x40,
+ PF0900_REG_VMON1_PWRUP = 0x41,
+ PF0900_REG_VMON2_PWRUP = 0x42,
+ PF0900_REG_SW1_PWRUP = 0x43,
+ PF0900_REG_SW2_PWRUP = 0x44,
+ PF0900_REG_SW3_PWRUP = 0x45,
+ PF0900_REG_SW4_PWRUP = 0x46,
+ PF0900_REG_SW5_PWRUP = 0x47,
+ PF0900_REG_LDO1_PWRUP = 0x48,
+ PF0900_REG_LDO2_PWRUP = 0x49,
+ PF0900_REG_LDO3_PWRUP = 0x4A,
+ PF0900_REG_VAON_PWRUP = 0x4B,
+ PF0900_REG_FREQ_CTRL = 0x4C,
+ PF0900_REG_PWRON_CFG = 0x4D,
+ PF0900_REG_WD_CTRL1 = 0x4E,
+ PF0900_REG_WD_CTRL2 = 0x4F,
+ PF0900_REG_WD_CFG1 = 0x50,
+ PF0900_REG_WD_CFG2 = 0x51,
+ PF0900_REG_WD_CNT1 = 0x52,
+ PF0900_REG_WD_CNT2 = 0x53,
+ PF0900_REG_FAULT_CFG = 0x54,
+ PF0900_REG_FAULT_CNT = 0x55,
+ PF0900_REG_DFS_CNT = 0x56,
+ PF0900_REG_AMUX_CFG = 0x57,
+ PF0900_REG_VMON1_RUN_CFG = 0x58,
+ PF0900_REG_VMON1_STBY_CFG = 0x59,
+ PF0900_REG_VMON1_CTRL = 0x5A,
+ PF0900_REG_VMON2_RUN_CFG = 0x5B,
+ PF0900_REG_VMON2_STBY_CFG = 0x5C,
+ PF0900_REG_VMON2_CTRL = 0x5D,
+ PF0900_REG_SW1_VRUN = 0x5E,
+ PF0900_REG_SW1_VSTBY = 0x5F,
+ PF0900_REG_SW1_MODE = 0x60,
+ PF0900_REG_SW1_CFG1 = 0x61,
+ PF0900_REG_SW1_CFG2 = 0x62,
+ PF0900_REG_SW2_VRUN = 0x63,
+ PF0900_REG_SW2_VSTBY = 0x64,
+ PF0900_REG_SW2_MODE = 0x65,
+ PF0900_REG_SW2_CFG1 = 0x66,
+ PF0900_REG_SW2_CFG2 = 0x67,
+ PF0900_REG_SW3_VRUN = 0x68,
+ PF0900_REG_SW3_VSTBY = 0x69,
+ PF0900_REG_SW3_MODE = 0x6A,
+ PF0900_REG_SW3_CFG1 = 0x6B,
+ PF0900_REG_SW3_CFG2 = 0x6C,
+ PF0900_REG_SW4_VRUN = 0x6D,
+ PF0900_REG_SW4_VSTBY = 0x6E,
+ PF0900_REG_SW4_MODE = 0x6F,
+ PF0900_REG_SW4_CFG1 = 0x70,
+ PF0900_REG_SW4_CFG2 = 0x71,
+ PF0900_REG_SW5_VRUN = 0x72,
+ PF0900_REG_SW5_VSTBY = 0x73,
+ PF0900_REG_SW5_MODE = 0x74,
+ PF0900_REG_SW5_CFG1 = 0x75,
+ PF0900_REG_SW5_CFG2 = 0x76,
+ PF0900_REG_LDO1_RUN = 0x77,
+ PF0900_REG_LDO1_STBY = 0x78,
+ PF0900_REG_LDO1_CFG2 = 0x79,
+ PF0900_REG_LDO2_RUN = 0x7A,
+ PF0900_REG_LDO2_STBY = 0x7B,
+ PF0900_REG_LDO2_CFG2 = 0x7C,
+ PF0900_REG_LDO3_RUN = 0x7D,
+ PF0900_REG_LDO3_STBY = 0x7E,
+ PF0900_REG_LDO3_CFG2 = 0x7F,
+ PF0900_REG_VAON_CFG1 = 0x80,
+ PF0900_REG_VAON_CFG2 = 0x81,
+ PF0900_REG_SYS_DIAG = 0x82,
+ PF0900_MAX_REGISTER,
+};
+
+/* PF0900 SW MODE */
+#define SW_RUN_MODE_OFF 0x00
+#define SW_RUN_MODE_PWM 0x01
+#define SW_RUN_MODE_PFM 0x02
+#define SW_STBY_MODE_OFF 0x00
+#define SW_STBY_MODE_PWM 0x04
+#define SW_STBY_MODE_PFM 0x08
+
+/* PF0900 SW MODE MASK */
+#define SW_RUN_MODE_MASK GENMASK(1, 0)
+#define SW_STBY_MODE_MASK GENMASK(3, 2)
+
+/* PF0900 SW VRUN MASK */
+#define SW_VRUN_MASK GENMASK(7, 0)
+
+/* PF0900 SW STBY MASK */
+#define SW_STBY_MASK GENMASK(7, 0)
+
+/* PF0900_REG_VAON_CFG1 bits */
+#define VAON_1P8V 0x01
+
+#define VAON_MASK GENMASK(1, 0)
+
+/* PF0900_REG_SWX_CFG1 MASK */
+#define SW_DVS_MASK GENMASK(4, 3)
+
+/* PF0900_REG_LDO_RUN MASK */
+#define VLDO_RUN_MASK GENMASK(4, 0)
+#define LDO_RUN_EN_MASK BIT(5)
+
+/* PF0900_REG_STATUS1_INT bits */
+#define PF0900_IRQ_PWRUP BIT(3)
+
+/* PF0900_REG_ILIM_INT bits */
+#define PF0900_IRQ_SW1_IL BIT(0)
+#define PF0900_IRQ_SW2_IL BIT(1)
+#define PF0900_IRQ_SW3_IL BIT(2)
+#define PF0900_IRQ_SW4_IL BIT(3)
+#define PF0900_IRQ_SW5_IL BIT(4)
+
+#define PF0900_IRQ_LDO1_IL BIT(0)
+#define PF0900_IRQ_LDO2_IL BIT(1)
+#define PF0900_IRQ_LDO3_IL BIT(2)
+
+/* PF0900_REG_UV_INT bits */
+#define PF0900_IRQ_SW1_UV BIT(0)
+#define PF0900_IRQ_SW2_UV BIT(1)
+#define PF0900_IRQ_SW3_UV BIT(2)
+#define PF0900_IRQ_SW4_UV BIT(3)
+#define PF0900_IRQ_SW5_UV BIT(4)
+
+#define PF0900_IRQ_LDO1_UV BIT(0)
+#define PF0900_IRQ_LDO2_UV BIT(1)
+#define PF0900_IRQ_LDO3_UV BIT(2)
+#define PF0900_IRQ_VAON_UV BIT(3)
+
+/* PF0900_REG_OV_INT bits */
+#define PF0900_IRQ_SW1_OV BIT(0)
+#define PF0900_IRQ_SW2_OV BIT(1)
+#define PF0900_IRQ_SW3_OV BIT(2)
+#define PF0900_IRQ_SW4_OV BIT(3)
+#define PF0900_IRQ_SW5_OV BIT(4)
+
+#define PF0900_IRQ_LDO1_OV BIT(0)
+#define PF0900_IRQ_LDO2_OV BIT(1)
+#define PF0900_IRQ_LDO3_OV BIT(2)
+#define PF0900_IRQ_VAON_OV BIT(3)
+
+struct pf0900_dvs_config {
+ unsigned int run_reg;
+ unsigned int run_mask;
+ unsigned int standby_reg;
+ unsigned int standby_mask;
+};
+
+struct pf0900_regulator_desc {
+ struct regulator_desc desc;
+ const struct pf0900_dvs_config dvs;
+};
+
+struct pf0900_drvdata {
+ const struct pf0900_regulator_desc *desc;
+ unsigned int rcnt;
+};
+
+struct pf0900 {
+ struct device *dev;
+ struct regmap *regmap;
+ const struct pf0900_drvdata *drvdata;
+ struct regulator_dev *rdevs[PF0900_REGULATOR_CNT];
+ int irq;
+ unsigned short addr;
+ bool crc_en;
+};
+
+enum pf0900_regulator_type {
+ PF0900_SW = 0,
+ PF0900_LDO,
+};
+
+#define PF0900_REGU_IRQ(_reg, _type, _event) \
+ { \
+ .reg = _reg, \
+ .type = _type, \
+ .event = _event, \
+ }
+
+struct pf0900_regulator_irq {
+ unsigned int reg;
+ unsigned int type;
+ unsigned int event;
+};
+
+static const struct regmap_range pf0900_range = {
+ .range_min = PF0900_REG_DEV_ID,
+ .range_max = PF0900_REG_SYS_DIAG,
+};
+
+static const struct regmap_access_table pf0900_volatile_regs = {
+ .yes_ranges = &pf0900_range,
+ .n_yes_ranges = 1,
+};
+
+static const struct regmap_config pf0900_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &pf0900_volatile_regs,
+ .max_register = PF0900_MAX_REGISTER - 1,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static uint8_t crc8_j1850(unsigned short addr, unsigned int reg,
+ unsigned int val)
+{
+ uint8_t crcBuf[3];
+ uint8_t t_crc;
+ uint8_t i, j;
+
+ crcBuf[0] = addr;
+ crcBuf[1] = reg;
+ crcBuf[2] = val;
+ t_crc = 0xFF;
+
+ /*
+ * The CRC calculation is based on the standard CRC-8-SAE as
+ * defined in the SAE-J1850 specification with the following
+ * characteristics.
+ * Polynomial = 0x1D
+ * Initial Value = 0xFF
+ * The CRC byte is calculated by shifting 24-bit data through
+ * the CRC polynomial.The 24-bits package is built as follows:
+ * DEVICE_ADDR[b8] + REGISTER_ADDR [b8] +DATA[b8]
+ * The DEVICE_ADDR is calculated as the 7-bit slave address
+ * shifted left one space plus the corresponding read/write bit.
+ * (7Bit Address [b7] << 1 ) + R/W = DEVICE_ADDR[b8]
+ */
+ for (i = 0; i < sizeof(crcBuf); i++) {
+ t_crc ^= crcBuf[i];
+ for (j = 0; j < 8; j++) {
+ if ((t_crc & 0x80) != 0) {
+ t_crc <<= 1;
+ t_crc ^= 0x1D;
+ } else {
+ t_crc <<= 1;
+ }
+ }
+ }
+
+ return t_crc;
+}
+
+static int pf0900_regmap_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ struct device *dev = context;
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct pf0900 *pf0900 = dev_get_drvdata(dev);
+ int ret;
+ u8 crc;
+
+ if (!pf0900 || !pf0900->dev)
+ return -EINVAL;
+
+ if (reg >= PF0900_MAX_REGISTER) {
+ dev_err(pf0900->dev, "Invalid register address: 0x%x\n", reg);
+ return -EINVAL;
+ }
+
+ if (pf0900->crc_en) {
+ ret = i2c_smbus_read_word_data(i2c, reg);
+ if (ret < 0) {
+ dev_err(pf0900->dev, "Read error at reg=0x%x: %d\n", reg, ret);
+ return ret;
+ }
+
+ *val = (u16)ret;
+ crc = crc8_j1850(pf0900->addr << 1 | 0x1, reg, FIELD_GET(GENMASK(7, 0), *val));
+ if (crc != FIELD_GET(GENMASK(15, 8), *val)) {
+ dev_err(pf0900->dev, "Crc check error!\n");
+ return -EINVAL;
+ }
+ *val = FIELD_GET(GENMASK(7, 0), *val);
+ } else {
+ ret = i2c_smbus_read_byte_data(i2c, reg);
+ if (ret < 0) {
+ dev_err(pf0900->dev, "Read error at reg=0x%x: %d\n", reg, ret);
+ return ret;
+ }
+ *val = ret;
+ }
+
+ return 0;
+}
+
+static int pf0900_regmap_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ struct device *dev = context;
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct pf0900 *pf0900 = dev_get_drvdata(dev);
+ uint8_t data[2];
+ int ret;
+
+ if (!pf0900 || !pf0900->dev)
+ return -EINVAL;
+
+ if (reg >= PF0900_MAX_REGISTER) {
+ dev_err(pf0900->dev, "Invalid register address: 0x%x\n", reg);
+ return -EINVAL;
+ }
+
+ data[0] = val;
+ if (pf0900->crc_en) {
+ /* Get CRC */
+ data[1] = crc8_j1850(pf0900->addr << 1, reg, data[0]);
+ val = FIELD_PREP(GENMASK(15, 8), data[1]) | data[0];
+ ret = i2c_smbus_write_word_data(i2c, reg, val);
+ } else {
+ ret = i2c_smbus_write_byte_data(i2c, reg, data[0]);
+ }
+
+ if (ret) {
+ dev_err(pf0900->dev, "Write reg=0x%x error!\n", reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct regmap_bus pf0900_regmap_bus = {
+ .reg_read = pf0900_regmap_read,
+ .reg_write = pf0900_regmap_write,
+};
+
+static const struct regulator_ops pf0900_avon_regulator_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_ops pf0900_dvs_sw_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_ramp_delay = regulator_set_ramp_delay_regmap,
+};
+
+static const struct regulator_ops pf0900_ldo_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+/*
+ * SW1/2/3/4/5
+ * SW1_DVS[1:0] SW1 DVS ramp rate setting
+ * 00: 15.6mV/8usec
+ * 01: 15.6mV/4usec
+ * 10: 15.6mV/2usec
+ * 11: 15.6mV/1usec
+ */
+static const unsigned int pf0900_dvs_sw_ramp_table[] = {
+ 1950, 3900, 7800, 15600
+};
+
+/* VAON 1.8V, 3.0V, or 3.3V */
+static const int pf0900_vaon_voltages[] = {
+ 0, 1800000, 3000000, 3300000,
+};
+
+/*
+ * SW1 0.5V to 3.3V
+ * 0.5V to 1.35V (6.25mV step)
+ * 1.8V to 2.5V (125mV step)
+ * 2.8V to 3.3V (250mV step)
+ */
+static const struct linear_range pf0900_dvs_sw1_volts[] = {
+ REGULATOR_LINEAR_RANGE(0, 0x00, 0x08, 0),
+ REGULATOR_LINEAR_RANGE(500000, 0x09, 0x91, 6250),
+ REGULATOR_LINEAR_RANGE(0, 0x92, 0x9E, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 0x9F, 0x9F, 0),
+ REGULATOR_LINEAR_RANGE(1800000, 0xA0, 0xD8, 12500),
+ REGULATOR_LINEAR_RANGE(0, 0xD9, 0xDF, 0),
+ REGULATOR_LINEAR_RANGE(2800000, 0xE0, 0xF4, 25000),
+ REGULATOR_LINEAR_RANGE(0, 0xF5, 0xFF, 0),
+};
+
+/*
+ * SW2/3/4/5 0.3V to 3.3V
+ * 0.45V to 1.35V (6.25mV step)
+ * 1.8V to 2.5V (125mV step)
+ * 2.8V to 3.3V (250mV step)
+ */
+static const struct linear_range pf0900_dvs_sw2345_volts[] = {
+ REGULATOR_LINEAR_RANGE(300000, 0x00, 0x00, 0),
+ REGULATOR_LINEAR_RANGE(450000, 0x01, 0x91, 6250),
+ REGULATOR_LINEAR_RANGE(0, 0x92, 0x9E, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 0x9F, 0x9F, 0),
+ REGULATOR_LINEAR_RANGE(1800000, 0xA0, 0xD8, 12500),
+ REGULATOR_LINEAR_RANGE(0, 0xD9, 0xDF, 0),
+ REGULATOR_LINEAR_RANGE(2800000, 0xE0, 0xF4, 25000),
+ REGULATOR_LINEAR_RANGE(0, 0xF5, 0xFF, 0),
+};
+
+/*
+ * LDO1
+ * 0.75V to 3.3V
+ */
+static const struct linear_range pf0900_ldo1_volts[] = {
+ REGULATOR_LINEAR_RANGE(750000, 0x00, 0x0F, 50000),
+ REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1F, 100000),
+};
+
+/*
+ * LDO2/3
+ * 0.65V to 3.3V (50mV step)
+ */
+static const struct linear_range pf0900_ldo23_volts[] = {
+ REGULATOR_LINEAR_RANGE(650000, 0x00, 0x0D, 50000),
+ REGULATOR_LINEAR_RANGE(1400000, 0x0E, 0x0F, 100000),
+ REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1F, 100000),
+};
+
+/* SW1 dvs 0.5v to 1.35v
+ * SW2-5 dvs 0.3v to 1.35v
+ */
+static int sw_set_dvs(const struct regulator_desc *desc, struct pf0900 *pf0900,
+ struct device_node *np, char *prop, unsigned int reg,
+ unsigned int mask)
+{
+ uint32_t uv;
+ int ret, i;
+
+ if (!desc || !pf0900 || !np || !prop)
+ return -EINVAL;
+
+ ret = of_property_read_u32(np, prop, &uv);
+ if (ret)
+ return dev_err_probe(pf0900->dev, ret, "Failed to read property %s\n", prop);
+
+ for (i = 0; i < desc->n_voltages; i++) {
+ ret = regulator_desc_list_voltage_linear_range(desc, i);
+ if (ret < 0)
+ continue;
+ if (ret == uv) {
+ i <<= ffs(desc->vsel_mask) - 1;
+ ret = regmap_update_bits(pf0900->regmap, reg, mask, i);
+ if (ret)
+ return dev_err_probe(pf0900->dev, ret,
+ "Failed to write voltage to register 0x%x\n",
+ reg);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int pf0900_set_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ struct pf0900_regulator_desc *data = container_of(desc,
+ struct pf0900_regulator_desc, desc);
+ struct pf0900 *pf0900 = dev_get_drvdata(cfg->dev);
+ const struct pf0900_dvs_config *dvs = &data->dvs;
+ unsigned int reg, mask;
+ int i, ret = 0;
+ char *prop;
+
+ for (i = 0; i < PF0900_DVS_LEVEL_MAX; i++) {
+ switch (i) {
+ case PF0900_DVS_LEVEL_RUN:
+ prop = "nxp,dvs-run-microvolt";
+ reg = dvs->run_reg;
+ mask = dvs->run_mask;
+ break;
+ case PF0900_DVS_LEVEL_STANDBY:
+ prop = "nxp,dvs-standby-microvolt";
+ reg = dvs->standby_reg;
+ mask = dvs->standby_mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (of_property_present(np, prop)) {
+ ret = sw_set_dvs(desc, pf0900, np, prop, reg, mask);
+ if (ret)
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static const struct pf0900_regulator_desc pf0900_regulators[] = {
+ {
+ .desc = {
+ .name = "sw1",
+ .of_match = of_match_ptr("SW1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_SW1,
+ .ops = &pf0900_dvs_sw_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_SW_VOLTAGE_NUM,
+ .linear_ranges = pf0900_dvs_sw1_volts,
+ .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw1_volts),
+ .vsel_reg = PF0900_REG_SW1_VRUN,
+ .vsel_mask = SW_VRUN_MASK,
+ .enable_reg = PF0900_REG_SW1_MODE,
+ .enable_mask = SW_RUN_MODE_MASK,
+ .enable_val = SW_RUN_MODE_PWM,
+ .ramp_reg = PF0900_REG_SW1_CFG1,
+ .ramp_mask = SW_DVS_MASK,
+ .ramp_delay_table = pf0900_dvs_sw_ramp_table,
+ .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
+ .owner = THIS_MODULE,
+ .of_parse_cb = pf0900_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PF0900_REG_SW1_VRUN,
+ .run_mask = SW_VRUN_MASK,
+ .standby_reg = PF0900_REG_SW1_VSTBY,
+ .standby_mask = SW_STBY_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "sw2",
+ .of_match = of_match_ptr("SW2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_SW2,
+ .ops = &pf0900_dvs_sw_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_SW_VOLTAGE_NUM,
+ .linear_ranges = pf0900_dvs_sw2345_volts,
+ .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts),
+ .vsel_reg = PF0900_REG_SW2_VRUN,
+ .vsel_mask = SW_VRUN_MASK,
+ .enable_reg = PF0900_REG_SW2_MODE,
+ .enable_mask = SW_RUN_MODE_MASK,
+ .enable_val = SW_RUN_MODE_PWM,
+ .ramp_reg = PF0900_REG_SW2_CFG1,
+ .ramp_mask = SW_DVS_MASK,
+ .ramp_delay_table = pf0900_dvs_sw_ramp_table,
+ .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
+ .owner = THIS_MODULE,
+ .of_parse_cb = pf0900_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PF0900_REG_SW2_VRUN,
+ .run_mask = SW_VRUN_MASK,
+ .standby_reg = PF0900_REG_SW2_VSTBY,
+ .standby_mask = SW_STBY_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "sw3",
+ .of_match = of_match_ptr("SW3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_SW3,
+ .ops = &pf0900_dvs_sw_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_SW_VOLTAGE_NUM,
+ .linear_ranges = pf0900_dvs_sw2345_volts,
+ .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts),
+ .vsel_reg = PF0900_REG_SW3_VRUN,
+ .vsel_mask = SW_VRUN_MASK,
+ .enable_reg = PF0900_REG_SW3_MODE,
+ .enable_mask = SW_RUN_MODE_MASK,
+ .enable_val = SW_RUN_MODE_PWM,
+ .ramp_reg = PF0900_REG_SW3_CFG1,
+ .ramp_mask = SW_DVS_MASK,
+ .ramp_delay_table = pf0900_dvs_sw_ramp_table,
+ .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
+ .owner = THIS_MODULE,
+ .of_parse_cb = pf0900_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PF0900_REG_SW3_VRUN,
+ .run_mask = SW_VRUN_MASK,
+ .standby_reg = PF0900_REG_SW3_VSTBY,
+ .standby_mask = SW_STBY_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "sw4",
+ .of_match = of_match_ptr("SW4"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_SW5,
+ .ops = &pf0900_dvs_sw_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_SW_VOLTAGE_NUM,
+ .linear_ranges = pf0900_dvs_sw2345_volts,
+ .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts),
+ .vsel_reg = PF0900_REG_SW4_VRUN,
+ .vsel_mask = SW_VRUN_MASK,
+ .enable_reg = PF0900_REG_SW4_MODE,
+ .enable_mask = SW_RUN_MODE_MASK,
+ .enable_val = SW_RUN_MODE_PWM,
+ .ramp_reg = PF0900_REG_SW4_CFG1,
+ .ramp_mask = SW_DVS_MASK,
+ .ramp_delay_table = pf0900_dvs_sw_ramp_table,
+ .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
+ .owner = THIS_MODULE,
+ .of_parse_cb = pf0900_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PF0900_REG_SW4_VRUN,
+ .run_mask = SW_VRUN_MASK,
+ .standby_reg = PF0900_REG_SW4_VSTBY,
+ .standby_mask = SW_STBY_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "sw5",
+ .of_match = of_match_ptr("SW5"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_SW5,
+ .ops = &pf0900_dvs_sw_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_SW_VOLTAGE_NUM,
+ .linear_ranges = pf0900_dvs_sw2345_volts,
+ .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts),
+ .vsel_reg = PF0900_REG_SW5_VRUN,
+ .vsel_mask = SW_VRUN_MASK,
+ .enable_reg = PF0900_REG_SW5_MODE,
+ .enable_mask = SW_RUN_MODE_MASK,
+ .enable_val = SW_RUN_MODE_PWM,
+ .ramp_reg = PF0900_REG_SW5_CFG1,
+ .ramp_mask = SW_DVS_MASK,
+ .ramp_delay_table = pf0900_dvs_sw_ramp_table,
+ .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table),
+ .owner = THIS_MODULE,
+ .of_parse_cb = pf0900_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PF0900_REG_SW5_VRUN,
+ .run_mask = SW_VRUN_MASK,
+ .standby_reg = PF0900_REG_SW5_VSTBY,
+ .standby_mask = SW_STBY_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo1",
+ .of_match = of_match_ptr("LDO1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_LDO1,
+ .ops = &pf0900_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_LDO_VOLTAGE_NUM,
+ .linear_ranges = pf0900_ldo1_volts,
+ .n_linear_ranges = ARRAY_SIZE(pf0900_ldo1_volts),
+ .vsel_reg = PF0900_REG_LDO1_RUN,
+ .vsel_mask = VLDO_RUN_MASK,
+ .enable_reg = PF0900_REG_LDO1_RUN,
+ .enable_mask = LDO_RUN_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo2",
+ .of_match = of_match_ptr("LDO2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_LDO2,
+ .ops = &pf0900_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_LDO_VOLTAGE_NUM,
+ .linear_ranges = pf0900_ldo23_volts,
+ .n_linear_ranges = ARRAY_SIZE(pf0900_ldo23_volts),
+ .vsel_reg = PF0900_REG_LDO2_RUN,
+ .vsel_mask = VLDO_RUN_MASK,
+ .enable_reg = PF0900_REG_LDO2_RUN,
+ .enable_mask = LDO_RUN_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo3",
+ .of_match = of_match_ptr("LDO3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_LDO3,
+ .ops = &pf0900_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_LDO_VOLTAGE_NUM,
+ .linear_ranges = pf0900_ldo23_volts,
+ .n_linear_ranges = ARRAY_SIZE(pf0900_ldo23_volts),
+ .vsel_reg = PF0900_REG_LDO3_RUN,
+ .vsel_mask = VLDO_RUN_MASK,
+ .enable_reg = PF0900_REG_LDO3_RUN,
+ .enable_mask = LDO_RUN_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "vaon",
+ .of_match = of_match_ptr("VAON"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PF0900_VAON,
+ .ops = &pf0900_avon_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PF0900_VAON_VOLTAGE_NUM,
+ .volt_table = pf0900_vaon_voltages,
+ .enable_reg = PF0900_REG_VAON_CFG1,
+ .enable_mask = VAON_MASK,
+ .enable_val = VAON_1P8V,
+ .vsel_reg = PF0900_REG_VAON_CFG1,
+ .vsel_mask = VAON_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+};
+
+struct pf0900_regulator_irq regu_irqs[] = {
+ PF0900_REGU_IRQ(PF0900_REG_SW_ILIM_INT, PF0900_SW, REGULATOR_ERROR_OVER_CURRENT_WARN),
+ PF0900_REGU_IRQ(PF0900_REG_LDO_ILIM_INT, PF0900_LDO, REGULATOR_ERROR_OVER_CURRENT_WARN),
+ PF0900_REGU_IRQ(PF0900_REG_SW_UV_INT, PF0900_SW, REGULATOR_ERROR_UNDER_VOLTAGE_WARN),
+ PF0900_REGU_IRQ(PF0900_REG_LDO_UV_INT, PF0900_LDO, REGULATOR_ERROR_UNDER_VOLTAGE_WARN),
+ PF0900_REGU_IRQ(PF0900_REG_SW_OV_INT, PF0900_SW, REGULATOR_ERROR_OVER_VOLTAGE_WARN),
+ PF0900_REGU_IRQ(PF0900_REG_LDO_OV_INT, PF0900_LDO, REGULATOR_ERROR_OVER_VOLTAGE_WARN),
+};
+
+static irqreturn_t pf0900_irq_handler(int irq, void *data)
+{
+ unsigned int val, regu, i, index;
+ struct pf0900 *pf0900 = data;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(regu_irqs); i++) {
+ ret = regmap_read(pf0900->regmap, regu_irqs[i].reg, &val);
+ if (ret < 0) {
+ dev_err(pf0900->dev, "Failed to read %d\n", ret);
+ return IRQ_NONE;
+ }
+ if (val) {
+ ret = regmap_write_bits(pf0900->regmap, regu_irqs[i].reg, val, val);
+ if (ret < 0) {
+ dev_err(pf0900->dev, "Failed to update %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ if (regu_irqs[i].type == PF0900_SW) {
+ for (index = 0; index < REGU_SW_CNT; index++) {
+ if (val & BIT(index)) {
+ regu = (enum pf0900_regulators)index;
+ regulator_notifier_call_chain(pf0900->rdevs[regu],
+ regu_irqs[i].event,
+ NULL);
+ }
+ }
+ } else if (regu_irqs[i].type == PF0900_LDO) {
+ for (index = 0; index < REGU_LDO_VAON_CNT; index++) {
+ if (val & BIT(index)) {
+ regu = (enum pf0900_regulators)index + PF0900_LDO1;
+ regulator_notifier_call_chain(pf0900->rdevs[regu],
+ regu_irqs[i].event,
+ NULL);
+ }
+ }
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int pf0900_i2c_probe(struct i2c_client *i2c)
+{
+ const struct pf0900_regulator_desc *regulator_desc;
+ const struct pf0900_drvdata *drvdata = NULL;
+ struct device_node *np = i2c->dev.of_node;
+ unsigned int device_id, device_fam, i;
+ struct regulator_config config = { };
+ struct pf0900 *pf0900;
+ int ret;
+
+ if (!i2c->irq)
+ return dev_err_probe(&i2c->dev, -EINVAL, "No IRQ configured?\n");
+
+ pf0900 = devm_kzalloc(&i2c->dev, sizeof(struct pf0900), GFP_KERNEL);
+ if (!pf0900)
+ return -ENOMEM;
+
+ drvdata = device_get_match_data(&i2c->dev);
+ if (!drvdata)
+ return dev_err_probe(&i2c->dev, -EINVAL, "unable to find driver data\n");
+
+ regulator_desc = drvdata->desc;
+ pf0900->drvdata = drvdata;
+ pf0900->crc_en = of_property_read_bool(np, "nxp,i2c-crc-enable");
+ pf0900->irq = i2c->irq;
+ pf0900->dev = &i2c->dev;
+ pf0900->addr = i2c->addr;
+
+ dev_set_drvdata(&i2c->dev, pf0900);
+
+ pf0900->regmap = devm_regmap_init(&i2c->dev, &pf0900_regmap_bus, &i2c->dev,
+ &pf0900_regmap_config);
+ if (IS_ERR(pf0900->regmap))
+ return dev_err_probe(&i2c->dev, PTR_ERR(pf0900->regmap),
+ "regmap initialization failed\n");
+ ret = regmap_read(pf0900->regmap, PF0900_REG_DEV_ID, &device_id);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Read device id error\n");
+
+ ret = regmap_read(pf0900->regmap, PF0900_REG_DEV_FAM, &device_fam);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Read device fam error\n");
+
+ /* Check your board and dts for match the right pmic */
+ if (device_fam == 0x09 && (device_id & 0x1F) != 0x0)
+ return dev_err_probe(&i2c->dev, -EINVAL, "Device id(%x) mismatched\n",
+ device_id >> 4);
+
+ for (i = 0; i < drvdata->rcnt; i++) {
+ const struct regulator_desc *desc;
+ const struct pf0900_regulator_desc *r;
+
+ r = ®ulator_desc[i];
+ desc = &r->desc;
+ config.regmap = pf0900->regmap;
+ config.dev = pf0900->dev;
+
+ pf0900->rdevs[i] = devm_regulator_register(pf0900->dev, desc, &config);
+ if (IS_ERR(pf0900->rdevs[i]))
+ return dev_err_probe(pf0900->dev, PTR_ERR(pf0900->rdevs[i]),
+ "Failed to register regulator(%s)\n", desc->name);
+ }
+
+ ret = devm_request_threaded_irq(pf0900->dev, pf0900->irq, NULL,
+ pf0900_irq_handler,
+ (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
+ "pf0900-irq", pf0900);
+
+ if (ret != 0)
+ return dev_err_probe(pf0900->dev, ret, "Failed to request IRQ: %d\n",
+ pf0900->irq);
+ /*
+ * The PWRUP_M is unmasked by default. When the device enter in RUN state,
+ * it will assert the PWRUP_I interrupt and assert the INTB pin to inform
+ * the MCU that it has finished the power up sequence properly.
+ */
+ ret = regmap_write_bits(pf0900->regmap, PF0900_REG_STATUS1_INT, PF0900_IRQ_PWRUP,
+ PF0900_IRQ_PWRUP);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Clean PWRUP_I error\n");
+
+ /* mask interrupt PWRUP */
+ ret = regmap_update_bits(pf0900->regmap, PF0900_REG_STATUS1_MSK, PF0900_IRQ_PWRUP,
+ PF0900_IRQ_PWRUP);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
+
+ ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_ILIM_MSK, PF0900_IRQ_SW1_IL |
+ PF0900_IRQ_SW2_IL | PF0900_IRQ_SW3_IL | PF0900_IRQ_SW4_IL |
+ PF0900_IRQ_SW5_IL, 0);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
+
+ ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_UV_MSK, PF0900_IRQ_SW1_UV |
+ PF0900_IRQ_SW2_UV | PF0900_IRQ_SW3_UV | PF0900_IRQ_SW4_UV |
+ PF0900_IRQ_SW5_UV, 0);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
+
+ ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_OV_MSK, PF0900_IRQ_SW1_OV |
+ PF0900_IRQ_SW2_OV | PF0900_IRQ_SW3_OV | PF0900_IRQ_SW4_OV |
+ PF0900_IRQ_SW5_OV, 0);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
+
+ ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_ILIM_MSK, PF0900_IRQ_LDO1_IL |
+ PF0900_IRQ_LDO2_IL | PF0900_IRQ_LDO3_IL, 0);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
+
+ ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_UV_MSK, PF0900_IRQ_LDO1_UV |
+ PF0900_IRQ_LDO2_UV | PF0900_IRQ_LDO3_UV | PF0900_IRQ_VAON_UV, 0);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
+
+ ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_OV_MSK, PF0900_IRQ_LDO1_OV |
+ PF0900_IRQ_LDO2_OV | PF0900_IRQ_LDO3_OV | PF0900_IRQ_VAON_OV, 0);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
+
+ return 0;
+}
+
+static struct pf0900_drvdata pf0900_drvdata = {
+ .desc = pf0900_regulators,
+ .rcnt = ARRAY_SIZE(pf0900_regulators),
+};
+
+static const struct of_device_id pf0900_of_match[] = {
+ { .compatible = "nxp,pf0900", .data = &pf0900_drvdata},
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, pf0900_of_match);
+
+static struct i2c_driver pf0900_i2c_driver = {
+ .driver = {
+ .name = "nxp-pf0900",
+ .of_match_table = pf0900_of_match,
+ },
+ .probe = pf0900_i2c_probe,
+};
+
+module_i2c_driver(pf0900_i2c_driver);
+
+MODULE_AUTHOR("Joy Zou <joy.zou@nxp.com>");
+MODULE_DESCRIPTION("NXP PF0900 Power Management IC driver");
+MODULE_LICENSE("GPL");
--
2.37.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml
2025-07-21 7:11 ` [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml Joy Zou
@ 2025-07-21 7:28 ` Krzysztof Kozlowski
2025-07-21 12:00 ` Mark Brown
2025-07-24 10:51 ` Joy Zou
0 siblings, 2 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2025-07-21 7:28 UTC (permalink / raw)
To: Joy Zou, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, imx, Frank Li, Ye Li, Jacky Bai,
Dong Aisheng
On 21/07/2025 09:11, Joy Zou wrote:
Subject: Reverse prefixes.
Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
> +
> + regulators:
> + type: object
> + additionalProperties: false
> +
> + properties:
> + VAON:
Lowercase names.
> + type: object
> + $ref: regulator.yaml#
> + unevaluatedProperties: false
> +
> + patternProperties:
> + "^LDO[1-3]$":
> + type: object
> + $ref: regulator.yaml#
> + unevaluatedProperties: false
> +
> + "^SW[1-5]$":
> + type: object
> + $ref: regulator.yaml#
> + unevaluatedProperties: false
> +
> + properties:
> + nxp,dvs-run-microvolt:
> + minimum: 300000
> + maximum: 1350000
> + description:
> + PMIC default "RUN" state voltage in uV.
Why existing properties are not suitable?
> +
> + nxp,dvs-standby-microvolt:
Why existing standby state bindings are not suitable?
> + minimum: 300000
> + maximum: 1350000
> + description:
> + PMIC default "STANDBY" state voltage in uV.
> +
> + nxp,i2c-crc-enable:
> + type: boolean
> + description: If the PMIC OTP_I2C_CRC_EN is enable, you need to add this property.
1. Why you cannot just read registers to check for this?
2. You need anyway proper description what is this about and then wrap
according to Linux coding style.
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - regulators
> +
> +additionalProperties: false
> +
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support
2025-07-21 7:11 ` [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support Joy Zou
@ 2025-07-21 7:30 ` Krzysztof Kozlowski
2025-07-21 12:26 ` Mark Brown
2025-07-22 10:19 ` kernel test robot
2 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2025-07-21 7:30 UTC (permalink / raw)
To: Joy Zou, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, devicetree, imx, Frank Li, Ye Li, Jacky Bai,
Dong Aisheng, kernel test robot
On 21/07/2025 09:11, Joy Zou wrote:
> The PF0900 is a power management integrated circuit (PMIC) optimized
> for high performance i.MX9x based applications. It features five high
> efficiency buck converters, three linear and one vaon regulators.
> It provides low quiescent current in Standby and low power off Modes.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202506181134.0Hkvy7CK-lkp@intel.com/
> Signed-off-by: Joy Zou <joy.zou@nxp.com>
Missing separator. See submitting patches.
>
> Changes for v2:
> 1. modify the copyright comment block to C++ style.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml
2025-07-21 7:28 ` Krzysztof Kozlowski
@ 2025-07-21 12:00 ` Mark Brown
2025-07-24 10:51 ` Joy Zou
1 sibling, 0 replies; 10+ messages in thread
From: Mark Brown @ 2025-07-21 12:00 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Joy Zou, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-kernel, devicetree, imx, Frank Li, Ye Li,
Jacky Bai, Dong Aisheng
[-- Attachment #1: Type: text/plain, Size: 448 bytes --]
On Mon, Jul 21, 2025 at 09:28:59AM +0200, Krzysztof Kozlowski wrote:
> > + nxp,i2c-crc-enable:
> > + type: boolean
> > + description: If the PMIC OTP_I2C_CRC_EN is enable, you need to add this property.
> 1. Why you cannot just read registers to check for this?
> 2. You need anyway proper description what is this about and then wrap
> according to Linux coding style.
Looking at the driver code the CRCs are also done on reads as well.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support
2025-07-21 7:11 ` [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support Joy Zou
2025-07-21 7:30 ` Krzysztof Kozlowski
@ 2025-07-21 12:26 ` Mark Brown
2025-07-22 10:19 ` kernel test robot
2 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2025-07-21 12:26 UTC (permalink / raw)
To: Joy Zou
Cc: Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-kernel, devicetree, imx, Frank Li, Ye Li, Jacky Bai,
Dong Aisheng, kernel test robot
[-- Attachment #1: Type: text/plain, Size: 803 bytes --]
On Mon, Jul 21, 2025 at 03:11:28PM +0800, Joy Zou wrote:
> The PF0900 is a power management integrated circuit (PMIC) optimized
> for high performance i.MX9x based applications. It features five high
> efficiency buck converters, three linear and one vaon regulators.
> It provides low quiescent current in Standby and low power off Modes.
This looks basically fine, one very minor issue since it looks like you
need to resubmit for the bindings:
> +static const struct regmap_config pf0900_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .volatile_table = &pf0900_volatile_regs,
> + .max_register = PF0900_MAX_REGISTER - 1,
> + .cache_type = REGCACHE_RBTREE,
> +};
Unless you've got a strong reason to do something else new drivers
should use _MAPLE, it's a more modern data structure.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support
2025-07-21 7:11 ` [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support Joy Zou
2025-07-21 7:30 ` Krzysztof Kozlowski
2025-07-21 12:26 ` Mark Brown
@ 2025-07-22 10:19 ` kernel test robot
2 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2025-07-22 10:19 UTC (permalink / raw)
To: Joy Zou, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: oe-kbuild-all, linux-kernel, devicetree, imx, Frank Li, Ye Li,
Jacky Bai, Dong Aisheng, kernel test robot
Hi Joy,
kernel test robot noticed the following build errors:
[auto build test ERROR on d086c886ceb9f59dea6c3a9dae7eb89e780a20c9]
url: https://github.com/intel-lab-lkp/linux/commits/Joy-Zou/dt-bindings-regulator-add-PF0900-regulator-yaml/20250721-151818
base: d086c886ceb9f59dea6c3a9dae7eb89e780a20c9
patch link: https://lore.kernel.org/r/20250721-b4-pf09-v2-v2-2-e2c568548032%40nxp.com
patch subject: [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20250722/202507221720.jxsGRfcE-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250722/202507221720.jxsGRfcE-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507221720.jxsGRfcE-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/regulator/pf0900-regulator.c: In function 'pf0900_regmap_read':
>> drivers/regulator/pf0900-regulator.c:377:64: error: implicit declaration of function 'FIELD_GET' [-Wimplicit-function-declaration]
377 | crc = crc8_j1850(pf0900->addr << 1 | 0x1, reg, FIELD_GET(GENMASK(7, 0), *val));
| ^~~~~~~~~
drivers/regulator/pf0900-regulator.c: In function 'pf0900_regmap_write':
>> drivers/regulator/pf0900-regulator.c:416:23: error: implicit declaration of function 'FIELD_PREP' [-Wimplicit-function-declaration]
416 | val = FIELD_PREP(GENMASK(15, 8), data[1]) | data[0];
| ^~~~~~~~~~
vim +/FIELD_GET +377 drivers/regulator/pf0900-regulator.c
351
352 static int pf0900_regmap_read(void *context, unsigned int reg,
353 unsigned int *val)
354 {
355 struct device *dev = context;
356 struct i2c_client *i2c = to_i2c_client(dev);
357 struct pf0900 *pf0900 = dev_get_drvdata(dev);
358 int ret;
359 u8 crc;
360
361 if (!pf0900 || !pf0900->dev)
362 return -EINVAL;
363
364 if (reg >= PF0900_MAX_REGISTER) {
365 dev_err(pf0900->dev, "Invalid register address: 0x%x\n", reg);
366 return -EINVAL;
367 }
368
369 if (pf0900->crc_en) {
370 ret = i2c_smbus_read_word_data(i2c, reg);
371 if (ret < 0) {
372 dev_err(pf0900->dev, "Read error at reg=0x%x: %d\n", reg, ret);
373 return ret;
374 }
375
376 *val = (u16)ret;
> 377 crc = crc8_j1850(pf0900->addr << 1 | 0x1, reg, FIELD_GET(GENMASK(7, 0), *val));
378 if (crc != FIELD_GET(GENMASK(15, 8), *val)) {
379 dev_err(pf0900->dev, "Crc check error!\n");
380 return -EINVAL;
381 }
382 *val = FIELD_GET(GENMASK(7, 0), *val);
383 } else {
384 ret = i2c_smbus_read_byte_data(i2c, reg);
385 if (ret < 0) {
386 dev_err(pf0900->dev, "Read error at reg=0x%x: %d\n", reg, ret);
387 return ret;
388 }
389 *val = ret;
390 }
391
392 return 0;
393 }
394
395 static int pf0900_regmap_write(void *context, unsigned int reg,
396 unsigned int val)
397 {
398 struct device *dev = context;
399 struct i2c_client *i2c = to_i2c_client(dev);
400 struct pf0900 *pf0900 = dev_get_drvdata(dev);
401 uint8_t data[2];
402 int ret;
403
404 if (!pf0900 || !pf0900->dev)
405 return -EINVAL;
406
407 if (reg >= PF0900_MAX_REGISTER) {
408 dev_err(pf0900->dev, "Invalid register address: 0x%x\n", reg);
409 return -EINVAL;
410 }
411
412 data[0] = val;
413 if (pf0900->crc_en) {
414 /* Get CRC */
415 data[1] = crc8_j1850(pf0900->addr << 1, reg, data[0]);
> 416 val = FIELD_PREP(GENMASK(15, 8), data[1]) | data[0];
417 ret = i2c_smbus_write_word_data(i2c, reg, val);
418 } else {
419 ret = i2c_smbus_write_byte_data(i2c, reg, data[0]);
420 }
421
422 if (ret) {
423 dev_err(pf0900->dev, "Write reg=0x%x error!\n", reg);
424 return ret;
425 }
426
427 return 0;
428 }
429
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml
2025-07-21 7:28 ` Krzysztof Kozlowski
2025-07-21 12:00 ` Mark Brown
@ 2025-07-24 10:51 ` Joy Zou
2025-07-24 18:58 ` Krzysztof Kozlowski
1 sibling, 1 reply; 10+ messages in thread
From: Joy Zou @ 2025-07-24 10:51 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-kernel, devicetree, imx, Frank Li, Ye Li,
Jacky Bai, Dong Aisheng
On Mon, Jul 21, 2025 at 09:28:59AM +0200, Krzysztof Kozlowski wrote:
> On 21/07/2025 09:11, Joy Zou wrote:
>
> Subject: Reverse prefixes.
>
> Please use subject prefixes matching the subsystem. You can get them for
> example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
> your patch is touching. For bindings, the preferred subjects are
> explained here:
> https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
>
> > +
> > + regulators:
> > + type: object
> > + additionalProperties: false
> > +
> > + properties:
> > + VAON:
>
> Lowercase names.
>
> > + type: object
> > + $ref: regulator.yaml#
> > + unevaluatedProperties: false
> > +
> > + patternProperties:
> > + "^LDO[1-3]$":
> > + type: object
> > + $ref: regulator.yaml#
> > + unevaluatedProperties: false
> > +
> > + "^SW[1-5]$":
> > + type: object
> > + $ref: regulator.yaml#
> > + unevaluatedProperties: false
> > +
> > + properties:
> > + nxp,dvs-run-microvolt:
> > + minimum: 300000
> > + maximum: 1350000
> > + description:
> > + PMIC default "RUN" state voltage in uV.
>
> Why existing properties are not suitable?
Have not found the property that can set run state voltage in regulator.yaml.
Can we add a property for run state such as regulator-suspend-microvolt?
>
> > +
> > + nxp,dvs-standby-microvolt:
>
> Why existing standby state bindings are not suitable?
Have found regulator-suspend-microvolt property that can set standby state voltage.
But the regulator-suspend-microvolt property is now deprecated. Can we use it?
>
> > + minimum: 300000
> > + maximum: 1350000
> > + description:
> > + PMIC default "STANDBY" state voltage in uV.
> > +
> > + nxp,i2c-crc-enable:
> > + type: boolean
> > + description: If the PMIC OTP_I2C_CRC_EN is enable, you need to add this property.
>
>
> 1. Why you cannot just read registers to check for this?
> 2. You need anyway proper description what is this about and then wrap
> according to Linux coding style.
Controlled by customer unviewable fuse bits OTP_I2C_CRC_EN. Check chip part number.
So can not get the I2C_CRC_EN config by reading register.
BR
Joy Zou
>
>
>
> > +
> > +required:
> > + - compatible
> > + - reg
> > + - interrupts
> > + - regulators
> > +
> > +additionalProperties: false
> > +
>
>
>
> Best regards,
> Krzysztof
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml
2025-07-24 10:51 ` Joy Zou
@ 2025-07-24 18:58 ` Krzysztof Kozlowski
0 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2025-07-24 18:58 UTC (permalink / raw)
To: Joy Zou
Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-kernel, devicetree, imx, Frank Li, Ye Li,
Jacky Bai, Dong Aisheng
On 24/07/2025 12:51, Joy Zou wrote:
>>> + type: object
>>> + $ref: regulator.yaml#
>>> + unevaluatedProperties: false
>>> +
>>> + patternProperties:
>>> + "^LDO[1-3]$":
>>> + type: object
>>> + $ref: regulator.yaml#
>>> + unevaluatedProperties: false
>>> +
>>> + "^SW[1-5]$":
>>> + type: object
>>> + $ref: regulator.yaml#
>>> + unevaluatedProperties: false
>>> +
>>> + properties:
>>> + nxp,dvs-run-microvolt:
>>> + minimum: 300000
>>> + maximum: 1350000
>>> + description:
>>> + PMIC default "RUN" state voltage in uV.
>>
>> Why existing properties are not suitable?
> Have not found the property that can set run state voltage in regulator.yaml.
> Can we add a property for run state such as regulator-suspend-microvolt?
>>
>>> +
>>> + nxp,dvs-standby-microvolt:
>>
>> Why existing standby state bindings are not suitable?
> Have found regulator-suspend-microvolt property that can set standby state voltage.
> But the regulator-suspend-microvolt property is now deprecated. Can we use it?
You have regulator-min/max properties for that. Please check with
bindings and other existing code how this looks like. I feel like you
did not try enough to solve it with existing code.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-07-24 18:58 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-21 7:11 [PATCH v2 0/2] regulator: add new PMIC PF0900 support Joy Zou
2025-07-21 7:11 ` [PATCH v2 1/2] dt-bindings: regulator: add PF0900 regulator yaml Joy Zou
2025-07-21 7:28 ` Krzysztof Kozlowski
2025-07-21 12:00 ` Mark Brown
2025-07-24 10:51 ` Joy Zou
2025-07-24 18:58 ` Krzysztof Kozlowski
2025-07-21 7:11 ` [PATCH v2 2/2] regulator: pf0900: Add PMIC PF0900 support Joy Zou
2025-07-21 7:30 ` Krzysztof Kozlowski
2025-07-21 12:26 ` Mark Brown
2025-07-22 10:19 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).