imx.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [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 = &regulator_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).