Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v5 0/9] Add MAX77714 PMIC minimal driver (RTC and watchdog only)
From: Luca Ceresoli @ 2022-01-29  8:40 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-rtc, linux-watchdog, devicetree, Rob Herring, Chanwoo Choi,
	Krzysztof Kozlowski, Alessandro Zummo, Alexandre Belloni,
	Wim Van Sebroeck, Guenter Roeck, Chiwoong Byun, Laxman Dewangan,
	Randy Dunlap, linux-kernel
In-Reply-To: <d8aacb8a-5e41-fd96-daac-e9257358ca71@lucaceresoli.net>

Hi Lee, all,

On 11/01/22 11:10, Luca Ceresoli wrote:
> Hi All,
> 
> On 11/12/21 18:59, Luca Ceresoli wrote:
>> Hi,
>>
>> this series adds minimal drivers for the Maxim Semiconductor MAX77714
>> (https://www.maximintegrated.com/en/products/power/power-management-ics/MAX77714.html).
>> Only RTC and watchdog are implemented by these patches.
>>
>> All implemented functionality is tested and working: RTC read/write,
>> watchdog start/stop/ping/set_timeout.
>>
>> Patches 1-3 + 6 are trivial cleanups to the max77686 drivers and Kconfig
>> indentation and can probably be applied easily.
>>
>> Patches 4, 5, 7, 8 and 9 add: dt bindings, mfd driver, watchdog driver and
>> rtc driver.
> 
> A gentle ping about this series. It's at v5, all patches have at least
> one ack/review tag and most patches are unchanged since ~v2. It applies
> cleanly on current master.
> 
> Is there anything I should do to help making progress?

Apologies for pinging again... but as I got no further comments about
these patches I guess I can really do nothing at the moment.

Lee, is this series completely in charge to you or should it be applied
by the respective subsystem maintainers?

Thanks.
-- 
Luca

^ permalink raw reply

* [PATCH 2/2] arm64: dts: freescale: Use overlay target for simplicity
From: Shawn Guo @ 2022-01-29  7:09 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree, Rob Herring, Li Yang, Vladimir Oltean, Shawn Guo
In-Reply-To: <20220129070912.9836-1-shawnguo@kernel.org>

With commit 15d16d6dadf6 ("kbuild: Add generic rule to apply
fdtoverlay"), overlay target can be used to simplify the build of DTB
overlays.  It also performs a cross check to ensure base DT and overlay
actually match.

Signed-off-by: Shawn Guo <shawnguo@kernel.org>
---
 arch/arm64/boot/dts/freescale/Makefile | 29 +++++++++++++-------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 6d8f0a532587..c521ac2b00ca 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -1,14 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
-# required for overlay support
-DTC_FLAGS_fsl-ls1028a-qds := -@
-DTC_FLAGS_fsl-ls1028a-qds-13bb := -@
-DTC_FLAGS_fsl-ls1028a-qds-65bb := -@
-DTC_FLAGS_fsl-ls1028a-qds-7777 := -@
-DTC_FLAGS_fsl-ls1028a-qds-85bb := -@
-DTC_FLAGS_fsl-ls1028a-qds-899b := -@
-DTC_FLAGS_fsl-ls1028a-qds-9999 := -@
-
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-frdm.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-frwy.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-oxalis.dtb
@@ -21,12 +12,6 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-sl28-var2.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-sl28-var3-ads2.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-sl28-var4.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds.dtb
-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-13bb.dtb
-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-65bb.dtb
-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-7777.dtb
-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-85bb.dtb
-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-899b.dtb
-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-9999.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb
@@ -49,6 +34,20 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2162a-qds.dtb
 
+fsl-ls1028a-qds-13bb-dtbs := fsl-ls1028a-qds.dtb fsl-ls1028a-qds-13bb.dtbo
+fsl-ls1028a-qds-65bb-dtbs := fsl-ls1028a-qds.dtb fsl-ls1028a-qds-65bb.dtbo
+fsl-ls1028a-qds-7777-dtbs := fsl-ls1028a-qds.dtb fsl-ls1028a-qds-7777.dtbo
+fsl-ls1028a-qds-85bb-dtbs := fsl-ls1028a-qds.dtb fsl-ls1028a-qds-85bb.dtbo
+fsl-ls1028a-qds-899b-dtbs := fsl-ls1028a-qds.dtb fsl-ls1028a-qds-899b.dtbo
+fsl-ls1028a-qds-9999-dtbs := fsl-ls1028a-qds.dtb fsl-ls1028a-qds-9999.dtbo
+
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-13bb.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-65bb.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-7777.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-85bb.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-899b.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds-9999.dtb
+
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-beacon-kit.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-ddr4-evk.dtb
-- 
2.17.1


^ permalink raw reply related

* [PATCH 1/2] arm64: dts: fsl-ls1028a-qds: Drop overlay syntax hard coding
From: Shawn Guo @ 2022-01-29  7:09 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree, Rob Herring, Li Yang, Vladimir Oltean, Shawn Guo
In-Reply-To: <20220129070912.9836-1-shawnguo@kernel.org>

As suggested by commit 9ae8578b517a ("of: Documentation: change overlay
example to use current syntax"), there is no need to have overlay syntax
be hard coded in the device tree source file any more.

Signed-off-by: Shawn Guo <shawnguo@kernel.org>
---
 .../dts/freescale/fsl-ls1028a-qds-13bb.dts    | 146 ++++++++----------
 .../dts/freescale/fsl-ls1028a-qds-65bb.dts    | 138 +++++++----------
 .../dts/freescale/fsl-ls1028a-qds-7777.dts    |  99 ++++++------
 .../dts/freescale/fsl-ls1028a-qds-85bb.dts    | 134 +++++++---------
 .../dts/freescale/fsl-ls1028a-qds-899b.dts    |  86 +++++------
 .../dts/freescale/fsl-ls1028a-qds-9999.dts    |  97 ++++++------
 6 files changed, 299 insertions(+), 401 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts
index f748a2c12a70..f826392c23fa 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts
@@ -12,102 +12,80 @@
 /dts-v1/;
 /plugin/;
 
-/ {
-	fragment@0 {
-		target = <&mdio_slot1>;
-
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			slot1_sgmii: ethernet-phy@2 {
-				/* AQR112 */
-				reg = <0x2>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
-		};
-	};
-
-	fragment@1 {
-		target = <&enetc_port0>;
-
-		__overlay__ {
-			phy-handle = <&slot1_sgmii>;
-			phy-mode = "usxgmii";
-			managed = "in-band-status";
-			status = "okay";
-		};
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	slot1_sgmii: ethernet-phy@2 {
+		/* AQR112 */
+		reg = <0x2>;
+		compatible = "ethernet-phy-ieee802.3-c45";
 	};
+};
 
-	fragment@2 {
-		target = <&mdio_slot2>;
-
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			/* 4 ports on AQR412 */
-			slot2_qxgmii0: ethernet-phy@0 {
-				reg = <0x0>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
-
-			slot2_qxgmii1: ethernet-phy@1 {
-				reg = <0x1>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
+&enetc_port0 {
+	phy-handle = <&slot1_sgmii>;
+	phy-mode = "usxgmii";
+	managed = "in-band-status";
+	status = "okay";
+};
 
-			slot2_qxgmii2: ethernet-phy@2 {
-				reg = <0x2>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
+&mdio_slot2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 
-			slot2_qxgmii3: ethernet-phy@3 {
-				reg = <0x3>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
-		};
+	/* 4 ports on AQR412 */
+	slot2_qxgmii0: ethernet-phy@0 {
+		reg = <0x0>;
+		compatible = "ethernet-phy-ieee802.3-c45";
 	};
 
-	fragment@3 {
-		target = <&mscc_felix_ports>;
+	slot2_qxgmii1: ethernet-phy@1 {
+		reg = <0x1>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
 
-		__overlay__ {
-			port@0 {
-				status = "okay";
-				phy-handle = <&slot2_qxgmii0>;
-				phy-mode = "usxgmii";
-				managed = "in-band-status";
-			};
+	slot2_qxgmii2: ethernet-phy@2 {
+		reg = <0x2>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
 
-			port@1 {
-				status = "okay";
-				phy-handle = <&slot2_qxgmii1>;
-				phy-mode = "usxgmii";
-				managed = "in-band-status";
-			};
+	slot2_qxgmii3: ethernet-phy@3 {
+		reg = <0x3>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+};
 
-			port@2 {
-				status = "okay";
-				phy-handle = <&slot2_qxgmii2>;
-				phy-mode = "usxgmii";
-				managed = "in-band-status";
-			};
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot2_qxgmii0>;
+		phy-mode = "usxgmii";
+		managed = "in-band-status";
+	};
 
-			port@3 {
-				status = "okay";
-				phy-handle = <&slot2_qxgmii3>;
-				phy-mode = "usxgmii";
-				managed = "in-band-status";
-			};
-		};
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot2_qxgmii1>;
+		phy-mode = "usxgmii";
+		managed = "in-band-status";
 	};
 
-	fragment@4 {
-		target = <&mscc_felix>;
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot2_qxgmii2>;
+		phy-mode = "usxgmii";
+		managed = "in-band-status";
+	};
 
-		__overlay__ {
-			status = "okay";
-		};
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot2_qxgmii3>;
+		phy-mode = "usxgmii";
+		managed = "in-band-status";
 	};
 };
+
+&mscc_felix {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts
index 8ffb707a1576..bd88438c2ecd 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts
@@ -11,98 +11,78 @@
 /dts-v1/;
 /plugin/;
 
-/ {
-	fragment@0 {
-		target = <&mdio_slot1>;
-
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			slot1_sgmii: ethernet-phy@2 {
-				/* AQR112 */
-				reg = <0x2>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
-		};
-	};
+&mdio_slot1 {
 
-	fragment@1 {
-		target = <&enetc_port0>;
+	#address-cells = <1>;
+	#size-cells = <0>;
 
-		__overlay__ {
-			phy-handle = <&slot1_sgmii>;
-			phy-mode = "2500base-x";
-			managed = "in-band-status";
-			status = "okay";
-		};
+	slot1_sgmii: ethernet-phy@2 {
+		/* AQR112 */
+		reg = <0x2>;
+		compatible = "ethernet-phy-ieee802.3-c45";
 	};
+};
 
-	fragment@2 {
-		target = <&mdio_slot2>;
+&enetc_port0 {
+	phy-handle = <&slot1_sgmii>;
+	phy-mode = "2500base-x";
+	managed = "in-band-status";
+	status = "okay";
+};
 
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
+&mdio_slot2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 
-			/* 4 ports on VSC8514 */
-			slot2_qsgmii0: ethernet-phy@8 {
-				reg = <0x8>;
-			};
+	/* 4 ports on VSC8514 */
+	slot2_qsgmii0: ethernet-phy@8 {
+		reg = <0x8>;
+	};
 
-			slot2_qsgmii1: ethernet-phy@9 {
-				reg = <0x9>;
-			};
+	slot2_qsgmii1: ethernet-phy@9 {
+		reg = <0x9>;
+	};
 
-			slot2_qsgmii2: ethernet-phy@a {
-				reg = <0xa>;
-			};
+	slot2_qsgmii2: ethernet-phy@a {
+		reg = <0xa>;
+	};
 
-			slot2_qsgmii3: ethernet-phy@b {
-				reg = <0xb>;
-			};
-		};
+	slot2_qsgmii3: ethernet-phy@b {
+		reg = <0xb>;
 	};
+};
 
-	fragment@3 {
-		target = <&mscc_felix_ports>;
-
-		__overlay__ {
-			port@0 {
-				status = "okay";
-				phy-handle = <&slot2_qsgmii0>;
-				phy-mode = "qsgmii";
-				managed = "in-band-status";
-			};
-
-			port@1 {
-				status = "okay";
-				phy-handle = <&slot2_qsgmii1>;
-				phy-mode = "qsgmii";
-				managed = "in-band-status";
-			};
-
-			port@2 {
-				status = "okay";
-				phy-handle = <&slot2_qsgmii2>;
-				phy-mode = "qsgmii";
-				managed = "in-band-status";
-			};
-
-			port@3 {
-				status = "okay";
-				phy-handle = <&slot2_qsgmii3>;
-				phy-mode = "qsgmii";
-				managed = "in-band-status";
-			};
-		};
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii0>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
 	};
 
-	fragment@4 {
-		target = <&mscc_felix>;
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii1>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii2>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
 
-		__overlay__ {
-			status = "okay";
-		};
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii3>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
 	};
 };
+
+&mscc_felix {
+
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts
index eb6a1e674f10..1dff68d7484b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts
@@ -12,71 +12,58 @@
 /dts-v1/;
 /plugin/;
 
-/ {
-	fragment@0 {
-		target = <&mdio_slot1>;
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			/* 4 ports on AQR412 */
-			slot1_sxgmii0: ethernet-phy@0 {
-				reg = <0x0>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
-
-			slot1_sxgmii1: ethernet-phy@1 {
-				reg = <0x1>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
-
-			slot1_sxgmii2: ethernet-phy@2 {
-				reg = <0x2>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
+	/* 4 ports on AQR412 */
+	slot1_sxgmii0: ethernet-phy@0 {
+		reg = <0x0>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
 
-			slot1_sxgmii3: ethernet-phy@3 {
-				reg = <0x3>;
-				compatible = "ethernet-phy-ieee802.3-c45";
-			};
-		};
+	slot1_sxgmii1: ethernet-phy@1 {
+		reg = <0x1>;
+		compatible = "ethernet-phy-ieee802.3-c45";
 	};
 
-	fragment@1 {
-		target = <&mscc_felix_ports>;
+	slot1_sxgmii2: ethernet-phy@2 {
+		reg = <0x2>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
 
-		__overlay__ {
-			port@0 {
-				status = "okay";
-				phy-handle = <&slot1_sxgmii0>;
-				phy-mode = "2500base-x";
-			};
+	slot1_sxgmii3: ethernet-phy@3 {
+		reg = <0x3>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+};
 
-			port@1 {
-				status = "okay";
-				phy-handle = <&slot1_sxgmii1>;
-				phy-mode = "2500base-x";
-			};
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot1_sxgmii0>;
+		phy-mode = "2500base-x";
+	};
 
-			port@2 {
-				status = "okay";
-				phy-handle = <&slot1_sxgmii2>;
-				phy-mode = "2500base-x";
-			};
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot1_sxgmii1>;
+		phy-mode = "2500base-x";
+	};
 
-			port@3 {
-				status = "okay";
-				phy-handle = <&slot1_sxgmii3>;
-				phy-mode = "2500base-x";
-			};
-		};
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot1_sxgmii2>;
+		phy-mode = "2500base-x";
 	};
 
-	fragment@2 {
-		target = <&mscc_felix>;
-		__overlay__ {
-			status = "okay";
-		};
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot1_sxgmii3>;
+		phy-mode = "2500base-x";
 	};
 };
+
+&mscc_felix {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts
index 8e90c3088ba1..19424d349713 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts
@@ -11,97 +11,75 @@
 /dts-v1/;
 /plugin/;
 
-/ {
-	fragment@0 {
-		target = <&mdio_slot1>;
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			slot1_sgmii: ethernet-phy@1c {
-				/* 1st port on VSC8234 */
-				reg = <0x1c>;
-			};
-		};
+	slot1_sgmii: ethernet-phy@1c {
+		/* 1st port on VSC8234 */
+		reg = <0x1c>;
 	};
+};
 
-	fragment@1 {
-		target = <&enetc_port0>;
-
-		__overlay__ {
-			phy-handle = <&slot1_sgmii>;
-			phy-mode = "sgmii";
-			managed = "in-band-status";
-			status = "okay";
-		};
-	};
-
-	fragment@2 {
-		target = <&mdio_slot2>;
-
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			/* 4 ports on VSC8514 */
-			slot2_qsgmii0: ethernet-phy@8 {
-				reg = <0x8>;
-			};
-
-			slot2_qsgmii1: ethernet-phy@9 {
-				reg = <0x9>;
-			};
+&enetc_port0 {
+	phy-handle = <&slot1_sgmii>;
+	phy-mode = "sgmii";
+	managed = "in-band-status";
+	status = "okay";
+};
 
-			slot2_qsgmii2: ethernet-phy@a {
-				reg = <0xa>;
-			};
+&mdio_slot2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 
-			slot2_qsgmii3: ethernet-phy@b {
-				reg = <0xb>;
-			};
-		};
+	/* 4 ports on VSC8514 */
+	slot2_qsgmii0: ethernet-phy@8 {
+		reg = <0x8>;
 	};
 
-	fragment@3 {
-		target = <&mscc_felix_ports>;
+	slot2_qsgmii1: ethernet-phy@9 {
+		reg = <0x9>;
+	};
 
-		__overlay__ {
-			port@0 {
-				status = "okay";
-				phy-handle = <&slot2_qsgmii0>;
-				phy-mode = "qsgmii";
-				managed = "in-band-status";
-			};
+	slot2_qsgmii2: ethernet-phy@a {
+		reg = <0xa>;
+	};
 
-			port@1 {
-				status = "okay";
-				phy-handle = <&slot2_qsgmii1>;
-				phy-mode = "qsgmii";
-				managed = "in-band-status";
-			};
+	slot2_qsgmii3: ethernet-phy@b {
+		reg = <0xb>;
+	};
+};
 
-			port@2 {
-				status = "okay";
-				phy-handle = <&slot2_qsgmii2>;
-				phy-mode = "qsgmii";
-				managed = "in-band-status";
-			};
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii0>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
 
-			port@3 {
-				status = "okay";
-				phy-handle = <&slot2_qsgmii3>;
-				phy-mode = "qsgmii";
-				managed = "in-band-status";
-			};
-		};
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii1>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
 	};
 
-	fragment@4 {
-		target = <&mscc_felix>;
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii2>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
 
-		__overlay__ {
-			status = "okay";
-		};
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii3>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
 	};
 };
+
+&mscc_felix {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts
index 5d0a094e6c44..fb85847f778f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts
@@ -11,65 +11,51 @@
 /dts-v1/;
 /plugin/;
 
-/ {
-	fragment@0 {
-		target = <&mdio_slot1>;
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 
-			/* VSC8234 */
-			slot1_sgmii0: ethernet-phy@1c {
-				reg = <0x1c>;
-			};
-
-			slot1_sgmii1: ethernet-phy@1d {
-				reg = <0x1d>;
-			};
+	/* VSC8234 */
+	slot1_sgmii0: ethernet-phy@1c {
+		reg = <0x1c>;
+	};
 
-			slot1_sgmii2: ethernet-phy@1e {
-				reg = <0x1e>;
-			};
+	slot1_sgmii1: ethernet-phy@1d {
+		reg = <0x1d>;
+	};
 
-			slot1_sgmii3: ethernet-phy@1f {
-				reg = <0x1f>;
-			};
-		};
+	slot1_sgmii2: ethernet-phy@1e {
+		reg = <0x1e>;
 	};
 
-	fragment@1 {
-		target = <&enetc_port0>;
-		__overlay__ {
-			phy-handle = <&slot1_sgmii0>;
-			phy-mode = "sgmii";
-			managed = "in-band-status";
-			status = "okay";
-		};
+	slot1_sgmii3: ethernet-phy@1f {
+		reg = <0x1f>;
 	};
+};
 
-	fragment@2 {
-		target = <&mscc_felix_ports>;
-		__overlay__ {
-			port@1 {
-				status = "okay";
-				phy-handle = <&slot1_sgmii1>;
-				phy-mode = "sgmii";
-				managed = "in-band-status";
-			};
+&enetc_port0 {
+	phy-handle = <&slot1_sgmii0>;
+	phy-mode = "sgmii";
+	managed = "in-band-status";
+	status = "okay";
+};
 
-			port@2 {
-				status = "okay";
-				phy-handle = <&slot1_sgmii2>;
-				phy-mode = "sgmii";
-				managed = "in-band-status";
-			};
-		};
+&mscc_felix_ports {
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii1>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
 	};
 
-	fragment@3 {
-		target = <&mscc_felix>;
-		__overlay__ {
-			status = "okay";
-		};
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii2>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
 	};
 };
+
+&mscc_felix {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts
index 1ef743c48e84..63e46fad22bd 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts
@@ -11,69 +11,58 @@
 /dts-v1/;
 /plugin/;
 
-/ {
-	fragment@0 {
-		target = <&mdio_slot1>;
-		__overlay__ {
-			#address-cells = <1>;
-			#size-cells = <0>;
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 
-			/* VSC8234 */
-			slot1_sgmii0: ethernet-phy@1c {
-				reg = <0x1c>;
-			};
-
-			slot1_sgmii1: ethernet-phy@1d {
-				reg = <0x1d>;
-			};
+	/* VSC8234 */
+	slot1_sgmii0: ethernet-phy@1c {
+		reg = <0x1c>;
+	};
 
-			slot1_sgmii2: ethernet-phy@1e {
-				reg = <0x1e>;
-			};
+	slot1_sgmii1: ethernet-phy@1d {
+		reg = <0x1d>;
+	};
 
-			slot1_sgmii3: ethernet-phy@1f {
-				reg = <0x1f>;
-			};
-		};
+	slot1_sgmii2: ethernet-phy@1e {
+		reg = <0x1e>;
 	};
 
-	fragment@1 {
-		target = <&mscc_felix_ports>;
-		__overlay__ {
-			port@0 {
-				status = "okay";
-				phy-handle = <&slot1_sgmii0>;
-				phy-mode = "sgmii";
-				managed = "in-band-status";
-			};
+	slot1_sgmii3: ethernet-phy@1f {
+		reg = <0x1f>;
+	};
+};
 
-			port@1 {
-				status = "okay";
-				phy-handle = <&slot1_sgmii1>;
-				phy-mode = "sgmii";
-				managed = "in-band-status";
-			};
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii0>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
+	};
 
-			port@2 {
-				status = "okay";
-				phy-handle = <&slot1_sgmii2>;
-				phy-mode = "sgmii";
-				managed = "in-band-status";
-			};
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii1>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
+	};
 
-			port@3 {
-				status = "okay";
-				phy-handle = <&slot1_sgmii3>;
-				phy-mode = "sgmii";
-				managed = "in-band-status";
-			};
-		};
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii2>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
 	};
 
-	fragment@2 {
-		target = <&mscc_felix>;
-		__overlay__ {
-			status = "okay";
-		};
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii3>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
 	};
 };
+
+&mscc_felix {
+	status = "okay";
+};
-- 
2.17.1


^ permalink raw reply related

* [PATCH 0/2] Improve fsl-ls1028a-qds device tree overlay build
From: Shawn Guo @ 2022-01-29  7:09 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree, Rob Herring, Li Yang, Vladimir Oltean, Shawn Guo

It makes a couple of improvments on fsl-ls1028a-qds device tree overlay
build.  Compile tested only.

Shawn Guo (2):
  arm64: dts: fsl-ls1028a-qds: Drop overlay syntax hard coding
  arm64: dts: freescale: Use overlay target for simplicity

 arch/arm64/boot/dts/freescale/Makefile        |  29 ++--
 .../dts/freescale/fsl-ls1028a-qds-13bb.dts    | 146 ++++++++----------
 .../dts/freescale/fsl-ls1028a-qds-65bb.dts    | 138 +++++++----------
 .../dts/freescale/fsl-ls1028a-qds-7777.dts    |  99 ++++++------
 .../dts/freescale/fsl-ls1028a-qds-85bb.dts    | 134 +++++++---------
 .../dts/freescale/fsl-ls1028a-qds-899b.dts    |  86 +++++------
 .../dts/freescale/fsl-ls1028a-qds-9999.dts    |  97 ++++++------
 7 files changed, 313 insertions(+), 416 deletions(-)

-- 
2.17.1


^ permalink raw reply

* Re: [PATCH v2] arm64: dts: imx8m{m,n}_venice*: add gpio-line-names
From: Shawn Guo @ 2022-01-29  6:59 UTC (permalink / raw)
  To: Tim Harvey
  Cc: Rob Herring, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20220128010603.17620-1-tharvey@gateworks.com>

On Thu, Jan 27, 2022 at 05:06:03PM -0800, Tim Harvey wrote:
> Add gpio-line-names for the various GPIO's used on Gateworks Venice
> boards. Note that these GPIO's are typically 'configured' in Boot
> Firmware via gpio-hog therefore we only configure line names to keep the
> boot firmware configuration from changing on kernel init.
> 
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>

Applied, thanks!

^ permalink raw reply

* Re: [PATCH 1/1] arm64: dts: imx8mq: fix lcdif port node
From: Shawn Guo @ 2022-01-29  6:40 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Rob Herring, Sascha Hauer, Fabio Estevam, Peng Fan,
	Guido Günther, devicetree, linux-arm-kernel
In-Reply-To: <20220125091646.2845111-1-alexander.stein@ew.tq-group.com>

On Tue, Jan 25, 2022 at 10:16:46AM +0100, Alexander Stein wrote:
> The port node does not have a unit-address, remove it.
> This fixes the warnings:
> lcd-controller@30320000: 'port' is a required property
> lcd-controller@30320000: 'port@0' does not match any of the regexes:
> 'pinctrl-[0-9]+'
> 
> Fixes: commit d0081bd02a03 ("arm64: dts: imx8mq: Add NWL MIPI DSI controller")
> Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>

Applied, thanks!

^ permalink raw reply

* Re: [PATCH v1 0/2] arm64: dts: imx8mq: fix mipi_csi port numbering
From: Shawn Guo @ 2022-01-29  6:30 UTC (permalink / raw)
  To: Martin Kepplinger
  Cc: robh, kernel, linux-imx, devicetree, linux-arm-kernel,
	phone-devel, linux-kernel
In-Reply-To: <20220121093326.2388251-1-martin.kepplinger@puri.sm>

On Fri, Jan 21, 2022 at 10:33:24AM +0100, Martin Kepplinger wrote:
> hi Shawn and all interested,
> 
> This is a fix for an embarrassing bug that slipped into commit
> bcadd5f66c2a ("arm64: dts: imx8mq: add mipi csi phy and csi bridge descriptions")
> and commit fed7603597fa ("arm64: dts: imx8mq-librem5: describe the selfie cam").
> 
> When preparing the imx8mq.dtsi description I only tested with port@1
> being connected to the csi bridge, but what I sent said port@0.
> 
> I have this on my list for a while and want to sort this out now. I'm
> sorry for the inconvenience. Until now imx8mq-librem5 is the only user
> (maybe because of this :).
> 
> thank you,
> 
>                               martin
> 
> 
> Martin Kepplinger (2):
>   arm64: dts: imx8mq: fix mipi_csi bidirectional port numbers
>   arm64: dts: imx8mq-librem5: fix mipi_csi1 port number to sensor

Applied both, thanks!

^ permalink raw reply

* Re: [PATCH] ARM: dts: imx7ulp: Fix 'assigned-clocks-parents' typo
From: Shawn Guo @ 2022-01-29  6:23 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20220120172355.1629650-1-robh@kernel.org>

On Thu, Jan 20, 2022 at 11:23:55AM -0600, Rob Herring wrote:
> The correct property name is 'assigned-clock-parents', not
> 'assigned-clocks-parents'. Though if the platform works with the typo, one
> has to wonder if the property is even needed.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>

Applied, thanks!

^ permalink raw reply

* Re: [PATCH 2/2] arm64: dts: imx8qxp-ss-adma: Drop fsl,imx7ulp-lpuart comaptible
From: Shawn Guo @ 2022-01-29  6:15 UTC (permalink / raw)
  To: Abel Vesa
  Cc: Greg Kroah-Hartman, Rob Herring, Sascha Hauer, Fabio Estevam,
	Dong Aisheng, Peng Fan, Pengutronix Kernel Team, linux-arm-kernel,
	Alexander Stein, linux-serial, devicetree,
	Linux Kernel Mailing List, NXP Linux Team
In-Reply-To: <20220118135918.2126010-2-abel.vesa@nxp.com>

On Tue, Jan 18, 2022 at 03:59:18PM +0200, Abel Vesa wrote:
> The driver differs from clocks point of view, so the i.MX8QXP
> is not backwards compatible with i.MX7ULP.
> 
> Signed-off-by: Abel Vesa <abel.vesa@nxp.com>

Applied, thanks!

^ permalink raw reply

* Re: [PATCH] arm64: dts: imx8mp-evk: add PCA6416 interrupt controller mode
From: Shawn Guo @ 2022-01-29  6:08 UTC (permalink / raw)
  To: Hugo Villeneuve
  Cc: Rob Herring, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Hugo Villeneuve, devicetree, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20220117230639.1257549-1-hugo@hugovil.com>

On Mon, Jan 17, 2022 at 06:06:39PM -0500, Hugo Villeneuve wrote:
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> Add interrupt controller mode for the pca6416 on i.MX8MP EVK board's.
> 
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>

It doesn't apply to my branch.  Could you rebase?

Shawn

> ---
>  arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
> index 66437b659f3a..00e1e1342162 100755
> --- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
> +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
> @@ -526,6 +526,12 @@ pca6416: gpio@20 {
>  		reg = <0x20>;
>  		gpio-controller;
>  		#gpio-cells = <2>;
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_pca6416_int>;
> +		interrupt-parent = <&gpio1>;
> +		interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
>  	};
>  
>  	codec: wm8960@1a {
> @@ -1209,6 +1215,12 @@ pinctrl_csi_mclk: csi_mclk_grp {
>  			MX8MP_IOMUXC_GPIO1_IO15__CCM_CLKO2	0x59
>  		>;
>  	};
> +
> +	pinctrl_pca6416_int: pca6416_int_grp {
> +		fsl,pins = <
> +			MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12	0x146 /* Input pull-up. */
> +		>;
> +	};
>  };
>  
>  &vpu_g1 {
> -- 
> 2.30.2
> 

^ permalink raw reply

* Re: [RFC PATCH v3 1/4] ARM: dts: imx28: reparent gpmi clock to ref_gpmi
From: Shawn Guo @ 2022-01-29  5:46 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, Michael Trimarchi, Fabio Estevam, NXP Linux Team,
	Pengutronix Kernel Team, Rob Herring, Sascha Hauer, Stephen Boyd,
	devicetree, linux-arm-kernel
In-Reply-To: <20220117161755.1863579-2-dario.binacchi@amarulasolutions.com>

On Mon, Jan 17, 2022 at 05:17:52PM +0100, Dario Binacchi wrote:
> Since ref_gpmi is sourced from pll0 (480MHz), It allows the GPMI
> controller to manage High-Speed ​​NAND Timing (edo mode 3,4 and 5).
> 
> Co-developed-by: Michael Trimarchi <michael@amarulasolutions.com>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

Applied, thanks!

^ permalink raw reply

* Re: [PATCH 2/2] Revert "arm64: dts: ls1028a: add flextimer based pwm nodes"
From: Shawn Guo @ 2022-01-29  5:42 UTC (permalink / raw)
  To: Michael Walle
  Cc: linux-arm-kernel, devicetree, linux-kernel, Li Yang, Rob Herring,
	Biwen Li
In-Reply-To: <20220115210907.451189-2-michael@walle.cc>

On Sat, Jan 15, 2022 at 10:09:07PM +0100, Michael Walle wrote:
> The changes to the device tree look very wrong. There are now two
> devices with the same base address: pwm0 and ftm_alarm0. Both are using
> the Flex Timer Module. It seems like this should either be one driver or
> and MFD driver. Either way, there should only be one node in the device
> tree. Revert the offending changes to avoid getting a broken device tree
> in circulation.

Why not just fix the conflicting nodes?

Shawn

> 
> This reverts commit 71799672ea24d2935322d655d2407c1ccd7db9ff.
> 
> Fixes: 71799672ea24 ("arm64: dts: ls1028a: add flextimer based pwm nodes")
> Signed-off-by: Michael Walle <michael@walle.cc>
> ---
> 
> Btw, the nodes are also not sorted by the address. Otherwise it should have
> been spotted easily.
> 
>  .../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 95 -------------------
>  1 file changed, 95 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
> index 1ef26cbc79cb..d3cc8cbaf768 100644
> --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
> +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
> @@ -66,13 +66,6 @@ CPU_PW20: cpu-pw20 {
>  		};
>  	};
>  
> -	rtc_clk: rtc-clk {
> -		compatible = "fixed-clock";
> -		#clock-cells = <0>;
> -		clock-frequency = <32768>;
> -		clock-output-names = "rtc_clk";
> -	};
> -
>  	sysclk: sysclk {
>  		compatible = "fixed-clock";
>  		#clock-cells = <0>;
> @@ -1245,94 +1238,6 @@ ierb@1f0800000 {
>  			reg = <0x01 0xf0800000 0x0 0x10000>;
>  		};
>  
> -		pwm0: pwm@2800000 {
> -			compatible = "fsl,vf610-ftm-pwm";
> -			#pwm-cells = <3>;
> -			reg = <0x0 0x2800000 0x0 0x10000>;
> -			clock-names = "ftm_sys", "ftm_ext",
> -				      "ftm_fix", "ftm_cnt_clk_en";
> -			clocks = <&clockgen 4 1>, <&clockgen 4 1>,
> -				 <&rtc_clk>, <&clockgen 4 1>;
> -			status = "disabled";
> -		};
> -
> -		pwm1: pwm@2810000 {
> -			compatible = "fsl,vf610-ftm-pwm";
> -			#pwm-cells = <3>;
> -			reg = <0x0 0x2810000 0x0 0x10000>;
> -			clock-names = "ftm_sys", "ftm_ext",
> -				      "ftm_fix", "ftm_cnt_clk_en";
> -			clocks = <&clockgen 4 1>, <&clockgen 4 1>,
> -				 <&rtc_clk>, <&clockgen 4 1>;
> -			status = "disabled";
> -		};
> -
> -		pwm2: pwm@2820000 {
> -			compatible = "fsl,vf610-ftm-pwm";
> -			#pwm-cells = <3>;
> -			reg = <0x0 0x2820000 0x0 0x10000>;
> -			clock-names = "ftm_sys", "ftm_ext",
> -				      "ftm_fix", "ftm_cnt_clk_en";
> -			clocks = <&clockgen 4 1>, <&clockgen 4 1>,
> -				 <&rtc_clk>, <&clockgen 4 1>;
> -			status = "disabled";
> -		};
> -
> -		pwm3: pwm@2830000 {
> -			compatible = "fsl,vf610-ftm-pwm";
> -			#pwm-cells = <3>;
> -			reg = <0x0 0x2830000 0x0 0x10000>;
> -			clock-names = "ftm_sys", "ftm_ext",
> -				      "ftm_fix", "ftm_cnt_clk_en";
> -			clocks = <&clockgen 4 1>, <&clockgen 4 1>,
> -				 <&rtc_clk>, <&clockgen 4 1>;
> -			status = "disabled";
> -		};
> -
> -		pwm4: pwm@2840000 {
> -			compatible = "fsl,vf610-ftm-pwm";
> -			#pwm-cells = <3>;
> -			reg = <0x0 0x2840000 0x0 0x10000>;
> -			clock-names = "ftm_sys", "ftm_ext",
> -				      "ftm_fix", "ftm_cnt_clk_en";
> -			clocks = <&clockgen 4 1>, <&clockgen 4 1>,
> -				 <&rtc_clk>, <&clockgen 4 1>;
> -			status = "disabled";
> -		};
> -
> -		pwm5: pwm@2850000 {
> -			compatible = "fsl,vf610-ftm-pwm";
> -			#pwm-cells = <3>;
> -			reg = <0x0 0x2850000 0x0 0x10000>;
> -			clock-names = "ftm_sys", "ftm_ext",
> -				      "ftm_fix", "ftm_cnt_clk_en";
> -			clocks = <&clockgen 4 1>, <&clockgen 4 1>,
> -				 <&rtc_clk>, <&clockgen 4 1>;
> -			status = "disabled";
> -		};
> -
> -		pwm6: pwm@2860000 {
> -			compatible = "fsl,vf610-ftm-pwm";
> -			#pwm-cells = <3>;
> -			reg = <0x0 0x2860000 0x0 0x10000>;
> -			clock-names = "ftm_sys", "ftm_ext",
> -				      "ftm_fix", "ftm_cnt_clk_en";
> -			clocks = <&clockgen 4 1>, <&clockgen 4 1>,
> -				 <&rtc_clk>, <&clockgen 4 1>;
> -			status = "disabled";
> -		};
> -
> -		pwm7: pwm@2870000 {
> -			compatible = "fsl,vf610-ftm-pwm";
> -			#pwm-cells = <3>;
> -			reg = <0x0 0x2870000 0x0 0x10000>;
> -			clock-names = "ftm_sys", "ftm_ext",
> -				      "ftm_fix", "ftm_cnt_clk_en";
> -			clocks = <&clockgen 4 1>, <&clockgen 4 1>,
> -				 <&rtc_clk>, <&clockgen 4 1>;
> -			status = "disabled";
> -		};
> -
>  		rcpm: power-controller@1e34040 {
>  			compatible = "fsl,ls1028a-rcpm", "fsl,qoriq-rcpm-2.1+";
>  			reg = <0x0 0x1e34040 0x0 0x1c>;
> -- 
> 2.30.2
> 

^ permalink raw reply

* Re: [PATCH] arm64: dts: ls1028a: sl28: re-enable ftm_alarm0
From: Shawn Guo @ 2022-01-29  5:34 UTC (permalink / raw)
  To: Michael Walle
  Cc: devicetree, linux-kernel, linux-arm-kernel, Li Yang, Rob Herring,
	Biwen Li, Guillaume Tucker, kernelci.org bot
In-Reply-To: <20220115210432.449968-1-michael@walle.cc>

On Sat, Jan 15, 2022 at 10:04:32PM +0100, Michael Walle wrote:
> Commit dd3d936a1b17 ("arm64: dts: ls1028a: add ftm_alarm1 node to be
> used as wakeup source") disables ftm_alarm0 in the SoC dtsi but doesn't
> enable it on the board which is still using it. Re-enable it on the sl28
> board.
> 
> Fixes: dd3d936a1b17 ("arm64: dts: ls1028a: add ftm_alarm1 node to be used as wakeup source")
> Reported-by: Guillaume Tucker <guillaume.tucker@collabora.com>
> Reported-by: "kernelci.org bot" <bot@kernelci.org>
> Signed-off-by: Michael Walle <michael@walle.cc>

Applied, thanks!

^ permalink raw reply

* Re: [PATCH 1/1] arm64: dts: freescale: Fix sound card model for MBa8Mx
From: Shawn Guo @ 2022-01-29  5:29 UTC (permalink / raw)
  To: Alexander Stein; +Cc: Rob Herring, devicetree
In-Reply-To: <20220114085906.629218-1-alexander.stein@ew.tq-group.com>

On Fri, Jan 14, 2022 at 09:59:06AM +0100, Alexander Stein wrote:
> The audio codec connection on MBa8Mx is identical to MBa7 (imx7) and MBa6
> (imx6). Use the same sound card model as well.
> 
> Fixes commit dfcd1b6f7620 ("arm64: dts: freescale: add initial device tree
> for TQMa8MQML with i.MX8MM")
> 
> Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>

Applied, thanks!

^ permalink raw reply

* [PATCH v2 1/2] dt-bindings: interconnect: Convert snoc-mm to a sub-node of snoc
From: Bryan O'Donoghue @ 2022-01-29  3:27 UTC (permalink / raw)
  To: djakov, bjorn.andersson, agross, linux-arm-msm, linux-pm
  Cc: jun.nie, shawn.guo, benl, dmitry.baryshkov, bryan.odonoghue,
	Rob Herring, devicetree
In-Reply-To: <20220129032735.2410936-1-bryan.odonoghue@linaro.org>

snoc and snoc-mm in downstream use the same address space a mistake which
we have carried over into upstream. In silicon terms snoc-mm has been
tacked on to the original snoc which came from msm8916.

Convert to a better description where snoc-mm is a sub-node of snoc, thus
avoiding a mmio remap collision when using the RPM interconnect driver.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 .../bindings/interconnect/qcom,rpm.yaml       | 33 +++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml b/Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml
index e4c3c2818119e..89853b4825133 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml
@@ -26,7 +26,6 @@ properties:
       - qcom,msm8939-bimc
       - qcom,msm8939-pcnoc
       - qcom,msm8939-snoc
-      - qcom,msm8939-snoc-mm
       - qcom,msm8996-a0noc
       - qcom,msm8996-a1noc
       - qcom,msm8996-a2noc
@@ -80,7 +79,6 @@ allOf:
               - qcom,msm8939-bimc
               - qcom,msm8939-pcnoc
               - qcom,msm8939-snoc
-              - qcom,msm8939-snoc-mm
               - qcom,msm8996-a1noc
               - qcom,msm8996-a2noc
               - qcom,msm8996-bimc
@@ -107,6 +105,37 @@ allOf:
               - description: Bus Clock
               - description: Bus A Clock
 
+        # Child node's properties
+        patternProperties:
+          '^interconnect-[a-z0-9]+$':
+            type: object
+            description:
+              snoc-mm is a child of snoc, sharing snoc's register address space.
+
+            properties:
+              compatible:
+                enum:
+                  - qcom,msm8939-snoc-mm
+
+              '#interconnect-cells':
+                const: 1
+
+              clock-names:
+                items:
+                  - const: bus
+                  - const: bus_a
+
+              clocks:
+                items:
+                  - description: Bus Clock
+                  - description: Bus A Clock
+
+            required:
+              - compatible
+              - '#interconnect-cells'
+              - clock-names
+              - clocks
+
   - if:
       properties:
         compatible:
-- 
2.33.0


^ permalink raw reply related

* Re: [PATCH] ARM: dts: suniv: Add MMC and clock macros.
From: Andre Przywara @ 2022-01-29  2:31 UTC (permalink / raw)
  To: Jesse Taube
  Cc: devicetree, robh+dt, Mesih Kilinc, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, linux-arm-kernel, linux-sunxi, Chris Morgan
In-Reply-To: <d19e70d8-02e1-b986-c0cf-f081fd82b52a@gmail.com>

On Fri, 28 Jan 2022 21:05:28 -0500
Jesse Taube <mr.bossman075@gmail.com> wrote:

> On 1/26/22 19:53, Andre Przywara wrote:
> > On Wed, 26 Jan 2022 19:12:05 -0500
> > Jesse Taube <mr.bossman075@gmail.com> wrote:
> >   
> >> On 1/26/22 18:57, Andre Przywara wrote:  
> >>> On Mon, 24 Jan 2022 20:13:52 -0500
> >>> Jesse Taube <mr.bossman075@gmail.com> wrote:
> >>>
> >>> Hi Jesse,
> >>>
> >>> I understand that get_maintainers.pl suggested this CC: list,  but you
> >>> should add sunxi people and linux-arm kernel ML. Doing that now.  
> >> Uh yeah that makes sense in hind sight.  
> >>>> Include clock and reset macros and replace magic numbers.
> >>>> Add MMC node.  
> >>>
> >>> This patch itself does not do much, does it? You would at least need to
> >>> enable that in the board dts.  
> >> True it doesn't do much just so that its in both u-boot and linux.  
> >>> And this should be multiple patches:
> >>> 1) replace numbers with macros (part of this patch)
> >>> 2) Add the MMC compatible string combo to the the bindings doc  
> Uh there is no f1c100s driver yet its just a placeholder it should be 
> compatible with the a20 though.

That is expected, ideally we won't need any addition to the driver
file, as indeed chances are it's really compatible to the A20.
But in any case we need to document the compatible string, and how it
is used: paired with the actual defining A20 fallback string. This
needs to go to
Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml.
If you look around in that file and its git history, you should get the
idea what you need to do.

> >>> 3) Add the *two* MMC nodes and at least the pinctrl node for MMC0 to the
> >>> SoC .dtsi (partly in this patch)
> >>> 4) Enable the MMC and the card detect pin in the Nano board .dts  
> Uh after like an hour of trying to find the schematic I found it here 
> nano.lichee.pro but the card detect pin isn't connected ;-(.

That's fine, it wouldn't be the first one. We have the "broken-cd;"
property for this.

Cheers,
Andre


> >>>
> >>> I checked that the macros names match the numbers they replace, so
> >>> you can add my R-b: on that patch 1 (if you follow my suggestion).
> >>> The MMC node also seems to look sane.  
> >> That seems okay.  
> >>>>
> >>>> Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>  
> >>>
> >>> It is not evident why Mesih's S-o-b: is in here? The patch seems to be
> >>> authored and sent by you? Either you make him the author if that is his
> >>> patch originally, or you put him just as Cc: or in Suggested-by:, maybe.  
> >> I did write the patch after I wrote it I was looking at his github and
> >> he had almost the same patch.  
> > 
> > Yeah, not really surprising, there are only so many ways to write a DT.
> > I guess he never sent it, and since you wrote it, it's yours, so just
> > add him in Cc:, since he was involved in the F1C100s upstreaming.
> > 
> > Cheers,
> > Andre
> >   
> >>> Cheers,
> >>> Andre
> >>>      
> >>>> Signed-off-by: Jesse Taube <Mr.Bossman075@gmail.com>
> >>>> ---
> >>>>    arch/arm/boot/dts/suniv-f1c100s.dtsi | 41 +++++++++++++++++++++++-----
> >>>>    1 file changed, 34 insertions(+), 7 deletions(-)
> >>>>
> >>>> diff --git a/arch/arm/boot/dts/suniv-f1c100s.dtsi b/arch/arm/boot/dts/suniv-f1c100s.dtsi
> >>>> index 6100d3b75f61..32872bb29917 100644
> >>>> --- a/arch/arm/boot/dts/suniv-f1c100s.dtsi
> >>>> +++ b/arch/arm/boot/dts/suniv-f1c100s.dtsi
> >>>> @@ -4,6 +4,9 @@
> >>>>     * Copyright 2018 Mesih Kilinc <mesihkilinc@gmail.com>
> >>>>     */
> >>>>    
> >>>> +#include <dt-bindings/clock/suniv-ccu-f1c100s.h>
> >>>> +#include <dt-bindings/reset/suniv-ccu-f1c100s.h>
> >>>> +
> >>>>    / {
> >>>>    	#address-cells = <1>;
> >>>>    	#size-cells = <1>;
> >>>> @@ -82,7 +85,7 @@ pio: pinctrl@1c20800 {
> >>>>    			compatible = "allwinner,suniv-f1c100s-pinctrl";
> >>>>    			reg = <0x01c20800 0x400>;
> >>>>    			interrupts = <38>, <39>, <40>;
> >>>> -			clocks = <&ccu 37>, <&osc24M>, <&osc32k>;
> >>>> +			clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
> >>>>    			clock-names = "apb", "hosc", "losc";
> >>>>    			gpio-controller;
> >>>>    			interrupt-controller;
> >>>> @@ -93,6 +96,11 @@ uart0_pe_pins: uart0-pe-pins {
> >>>>    				pins = "PE0", "PE1";
> >>>>    				function = "uart0";
> >>>>    			};
> >>>> +
> >>>> +			mmc0_pins: mmc0-pins {
> >>>> +				pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
> >>>> +				function = "mmc0";
> >>>> +			};
> >>>>    		};
> >>>>    
> >>>>    		timer@1c20c00 {
> >>>> @@ -108,14 +116,33 @@ wdt: watchdog@1c20ca0 {
> >>>>    			reg = <0x01c20ca0 0x20>;
> >>>>    		};
> >>>>    
> >>>> +		mmc0: mmc@1c0f000 {
> >>>> +			compatible = "allwinner,suniv-f1c100s-mmc",
> >>>> +				     "allwinner,sun7i-a20-mmc";
> >>>> +			reg = <0x01c0f000 0x1000>;
> >>>> +			clocks = <&ccu CLK_BUS_MMC0>,
> >>>> +				 <&ccu CLK_MMC0>,
> >>>> +				 <&ccu CLK_MMC0_OUTPUT>,
> >>>> +				 <&ccu CLK_MMC0_SAMPLE>;
> >>>> +			clock-names = "ahb", "mmc", "output", "sample";
> >>>> +			resets = <&ccu RST_BUS_MMC0>;
> >>>> +			reset-names = "ahb";
> >>>> +			interrupts = <23>;
> >>>> +			pinctrl-names = "default";
> >>>> +			pinctrl-0 = <&mmc0_pins>;
> >>>> +			status = "disabled";
> >>>> +			#address-cells = <1>;
> >>>> +			#size-cells = <0>;
> >>>> +		};
> >>>> +
> >>>>    		uart0: serial@1c25000 {
> >>>>    			compatible = "snps,dw-apb-uart";
> >>>>    			reg = <0x01c25000 0x400>;
> >>>>    			interrupts = <1>;
> >>>>    			reg-shift = <2>;
> >>>>    			reg-io-width = <4>;
> >>>> -			clocks = <&ccu 38>;
> >>>> -			resets = <&ccu 24>;
> >>>> +			clocks = <&ccu CLK_BUS_UART0>;
> >>>> +			resets = <&ccu RST_BUS_UART0>;
> >>>>    			status = "disabled";
> >>>>    		};
> >>>>    
> >>>> @@ -125,8 +152,8 @@ uart1: serial@1c25400 {
> >>>>    			interrupts = <2>;
> >>>>    			reg-shift = <2>;
> >>>>    			reg-io-width = <4>;
> >>>> -			clocks = <&ccu 39>;
> >>>> -			resets = <&ccu 25>;
> >>>> +			clocks = <&ccu CLK_BUS_UART1>;
> >>>> +			resets = <&ccu RST_BUS_UART1>;
> >>>>    			status = "disabled";
> >>>>    		};
> >>>>    
> >>>> @@ -136,8 +163,8 @@ uart2: serial@1c25800 {
> >>>>    			interrupts = <3>;
> >>>>    			reg-shift = <2>;
> >>>>    			reg-io-width = <4>;
> >>>> -			clocks = <&ccu 40>;
> >>>> -			resets = <&ccu 26>;
> >>>> +			clocks = <&ccu CLK_BUS_UART2>;
> >>>> +			resets = <&ccu RST_BUS_UART2>;
> >>>>    			status = "disabled";
> >>>>    		};
> >>>>    	};  
> >>>      
> >   
> 


^ permalink raw reply

* Re: [PATCH] dt-bindings: gpio: convert faraday,ftgpio01 to yaml
From: Linus Walleij @ 2022-01-29  2:10 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: brgl, conleylee, robh+dt, devicetree, linux-gpio, linux-kernel
In-Reply-To: <20220127123028.3992288-1-clabbe@baylibre.com>

On Thu, Jan 27, 2022 at 1:30 PM Corentin Labbe <clabbe@baylibre.com> wrote:

> Converts gpio/faraday,ftgpio010.txt to yaml.
>
> Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
(...)
> This commit will cause arch/arm/boot/dts/moxart-uc7112lx.dts to fail DT validation,
> but the GPIO driver need an interrupt so the current moxart DT is incomplete and the error is appropriate.

The Linux GPIO driver may need it but that does not mean it is necessary
for all other operating systems. (Could be a Linux bug.)

But I think it should be there because the hardware does support it
and I'm pretty sure that IRQ is available on the Moxart as well,
so:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH] ARM: dts: suniv: Add MMC and clock macros.
From: Jesse Taube @ 2022-01-29  2:05 UTC (permalink / raw)
  To: Andre Przywara
  Cc: devicetree, robh+dt, Mesih Kilinc, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, linux-arm-kernel, linux-sunxi, Chris Morgan
In-Reply-To: <20220127005304.06215ae8@slackpad.fritz.box>



On 1/26/22 19:53, Andre Przywara wrote:
> On Wed, 26 Jan 2022 19:12:05 -0500
> Jesse Taube <mr.bossman075@gmail.com> wrote:
> 
>> On 1/26/22 18:57, Andre Przywara wrote:
>>> On Mon, 24 Jan 2022 20:13:52 -0500
>>> Jesse Taube <mr.bossman075@gmail.com> wrote:
>>>
>>> Hi Jesse,
>>>
>>> I understand that get_maintainers.pl suggested this CC: list,  but you
>>> should add sunxi people and linux-arm kernel ML. Doing that now.
>> Uh yeah that makes sense in hind sight.
>>>> Include clock and reset macros and replace magic numbers.
>>>> Add MMC node.
>>>
>>> This patch itself does not do much, does it? You would at least need to
>>> enable that in the board dts.
>> True it doesn't do much just so that its in both u-boot and linux.
>>> And this should be multiple patches:
>>> 1) replace numbers with macros (part of this patch)
>>> 2) Add the MMC compatible string combo to the the bindings doc
Uh there is no f1c100s driver yet its just a placeholder it should be 
compatible with the a20 though.
>>> 3) Add the *two* MMC nodes and at least the pinctrl node for MMC0 to the
>>> SoC .dtsi (partly in this patch)
>>> 4) Enable the MMC and the card detect pin in the Nano board .dts
Uh after like an hour of trying to find the schematic I found it here 
nano.lichee.pro but the card detect pin isn't connected ;-(.
>>>
>>> I checked that the macros names match the numbers they replace, so
>>> you can add my R-b: on that patch 1 (if you follow my suggestion).
>>> The MMC node also seems to look sane.
>> That seems okay.
>>>>
>>>> Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>
>>>
>>> It is not evident why Mesih's S-o-b: is in here? The patch seems to be
>>> authored and sent by you? Either you make him the author if that is his
>>> patch originally, or you put him just as Cc: or in Suggested-by:, maybe.
>> I did write the patch after I wrote it I was looking at his github and
>> he had almost the same patch.
> 
> Yeah, not really surprising, there are only so many ways to write a DT.
> I guess he never sent it, and since you wrote it, it's yours, so just
> add him in Cc:, since he was involved in the F1C100s upstreaming.
> 
> Cheers,
> Andre
> 
>>> Cheers,
>>> Andre
>>>    
>>>> Signed-off-by: Jesse Taube <Mr.Bossman075@gmail.com>
>>>> ---
>>>>    arch/arm/boot/dts/suniv-f1c100s.dtsi | 41 +++++++++++++++++++++++-----
>>>>    1 file changed, 34 insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/arch/arm/boot/dts/suniv-f1c100s.dtsi b/arch/arm/boot/dts/suniv-f1c100s.dtsi
>>>> index 6100d3b75f61..32872bb29917 100644
>>>> --- a/arch/arm/boot/dts/suniv-f1c100s.dtsi
>>>> +++ b/arch/arm/boot/dts/suniv-f1c100s.dtsi
>>>> @@ -4,6 +4,9 @@
>>>>     * Copyright 2018 Mesih Kilinc <mesihkilinc@gmail.com>
>>>>     */
>>>>    
>>>> +#include <dt-bindings/clock/suniv-ccu-f1c100s.h>
>>>> +#include <dt-bindings/reset/suniv-ccu-f1c100s.h>
>>>> +
>>>>    / {
>>>>    	#address-cells = <1>;
>>>>    	#size-cells = <1>;
>>>> @@ -82,7 +85,7 @@ pio: pinctrl@1c20800 {
>>>>    			compatible = "allwinner,suniv-f1c100s-pinctrl";
>>>>    			reg = <0x01c20800 0x400>;
>>>>    			interrupts = <38>, <39>, <40>;
>>>> -			clocks = <&ccu 37>, <&osc24M>, <&osc32k>;
>>>> +			clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
>>>>    			clock-names = "apb", "hosc", "losc";
>>>>    			gpio-controller;
>>>>    			interrupt-controller;
>>>> @@ -93,6 +96,11 @@ uart0_pe_pins: uart0-pe-pins {
>>>>    				pins = "PE0", "PE1";
>>>>    				function = "uart0";
>>>>    			};
>>>> +
>>>> +			mmc0_pins: mmc0-pins {
>>>> +				pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
>>>> +				function = "mmc0";
>>>> +			};
>>>>    		};
>>>>    
>>>>    		timer@1c20c00 {
>>>> @@ -108,14 +116,33 @@ wdt: watchdog@1c20ca0 {
>>>>    			reg = <0x01c20ca0 0x20>;
>>>>    		};
>>>>    
>>>> +		mmc0: mmc@1c0f000 {
>>>> +			compatible = "allwinner,suniv-f1c100s-mmc",
>>>> +				     "allwinner,sun7i-a20-mmc";
>>>> +			reg = <0x01c0f000 0x1000>;
>>>> +			clocks = <&ccu CLK_BUS_MMC0>,
>>>> +				 <&ccu CLK_MMC0>,
>>>> +				 <&ccu CLK_MMC0_OUTPUT>,
>>>> +				 <&ccu CLK_MMC0_SAMPLE>;
>>>> +			clock-names = "ahb", "mmc", "output", "sample";
>>>> +			resets = <&ccu RST_BUS_MMC0>;
>>>> +			reset-names = "ahb";
>>>> +			interrupts = <23>;
>>>> +			pinctrl-names = "default";
>>>> +			pinctrl-0 = <&mmc0_pins>;
>>>> +			status = "disabled";
>>>> +			#address-cells = <1>;
>>>> +			#size-cells = <0>;
>>>> +		};
>>>> +
>>>>    		uart0: serial@1c25000 {
>>>>    			compatible = "snps,dw-apb-uart";
>>>>    			reg = <0x01c25000 0x400>;
>>>>    			interrupts = <1>;
>>>>    			reg-shift = <2>;
>>>>    			reg-io-width = <4>;
>>>> -			clocks = <&ccu 38>;
>>>> -			resets = <&ccu 24>;
>>>> +			clocks = <&ccu CLK_BUS_UART0>;
>>>> +			resets = <&ccu RST_BUS_UART0>;
>>>>    			status = "disabled";
>>>>    		};
>>>>    
>>>> @@ -125,8 +152,8 @@ uart1: serial@1c25400 {
>>>>    			interrupts = <2>;
>>>>    			reg-shift = <2>;
>>>>    			reg-io-width = <4>;
>>>> -			clocks = <&ccu 39>;
>>>> -			resets = <&ccu 25>;
>>>> +			clocks = <&ccu CLK_BUS_UART1>;
>>>> +			resets = <&ccu RST_BUS_UART1>;
>>>>    			status = "disabled";
>>>>    		};
>>>>    
>>>> @@ -136,8 +163,8 @@ uart2: serial@1c25800 {
>>>>    			interrupts = <3>;
>>>>    			reg-shift = <2>;
>>>>    			reg-io-width = <4>;
>>>> -			clocks = <&ccu 40>;
>>>> -			resets = <&ccu 26>;
>>>> +			clocks = <&ccu CLK_BUS_UART2>;
>>>> +			resets = <&ccu RST_BUS_UART2>;
>>>>    			status = "disabled";
>>>>    		};
>>>>    	};
>>>    
> 

^ permalink raw reply

* Re: [PATCH 3/3] ARM: dts: qcom: basic HP TouchPad support
From: Linus Walleij @ 2022-01-29  1:53 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Ben Wolsieffer, Andy Gross, Rob Herring, Arnd Bergmann,
	Olof Johansson, soc, Stephen Boyd, linux-arm-msm, devicetree,
	linux-kernel, linux-arm-kernel
In-Reply-To: <YfDKTGQDh3tDMECz@builder.lan>

On Wed, Jan 26, 2022 at 5:13 AM Bjorn Andersson
<bjorn.andersson@linaro.org> wrote:

> @Linus, please take a look at the regulator question below.

OK!

> >  arch/arm/boot/dts/qcom-apq8060-tenderloin.dts | 549 ++----------------

Nice to see some use of all the work put into the APQ8060 support!

FYI: if you want graphics, this work may need to get finished:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=apq8060-dragonboard-graphics
(mainly the MMCC)

> >               pinctrl@800000 {
> > -                     /* eMMMC pins, all 8 data lines connected */
>
> It would be nice if you could throw a separate patch on the list that
> fixes this spelling mistake in the original as well.

Yes pls.

> >                               l21 {
> > -                                     // 1.1 V according to schematic
> >                                       regulator-min-microvolt = <1200000>;
> >                                       regulator-max-microvolt = <1200000>;
> >                                       bias-pull-down;
> > -                                     regulator-always-on;
> > +                                     /*
> > +                                      * RPM driver can't handle always-on regulators that are
> > +                                      * supplied by regulators initialized after them.
> > +                                      */
>
> That looks like an oversight that should be corrected, perhaps it needs
> similar attention that was given to the smd-rpm driver recently?

Indeed

> But this makes me wonder, how can this work on the other board? Linus?

I suppose these don't supply anything vital?

I know I have seen some regulators switch off and on but I
may have been confused.


> >                               s0 {
> > -                                     // regulator-min-microvolt = <500000>;
> > +                                     // regulator-min-microvolt = <800000>;
> >                                       // regulator-max-microvolt = <1325000>;
>
> This looks like the full range the regulator could do, do you see a
> reason for documenting that here? Unless there's a good reason I think
> you should leave the commented min/max out.

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH] dt-bindings: watchdog: convert faraday,ftwdt010 to yaml
From: Linus Walleij @ 2022-01-29  1:28 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: linux, robh+dt, wim, devicetree, linux-kernel, linux-watchdog
In-Reply-To: <20220128204856.494643-1-clabbe@baylibre.com>

On Fri, Jan 28, 2022 at 9:49 PM Corentin Labbe <clabbe@baylibre.com> wrote:

> Converts watchdog/faraday,ftwdt010.txt to yaml.
> This permits to detect missing properties like clocks and resets or
> compatible like moxa,moxart-watchdog.
>
> Signed-off-by: Corentin Labbe <clabbe@baylibre.com>

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>

It's fine if you also add yourself on these, the more maintainers
the better.

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH 1/2] ARM: dts: gemini: ns2502: permit to use gigabit
From: Linus Walleij @ 2022-01-29  1:21 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: robh+dt, ulli.kroll, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20220115100444.3014823-1-clabbe@baylibre.com>

On Sat, Jan 15, 2022 at 11:04 AM Corentin Labbe <clabbe@baylibre.com> wrote:

> I believed that gigabit was not working due to some unknown missing GPIO.
> In fact, gigabit worked when REALTEK_PHY was compiled out.
> So the problem was due to PHY delay and we need to use rgmii-id.
>
> Signed-off-by: Corentin Labbe <clabbe@baylibre.com>

Thanks Corentin!

Patches applied.

Do you think I need a similar fix "rgmii"->"rgmii-id" on other
Gemini devicetrees that claim gigabit performance?

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v11 2/2] leds: Add driver for Qualcomm LPG
From: Bjorn Andersson @ 2022-01-29  0:54 UTC (permalink / raw)
  To: Pavel Machek, Thierry Reding, Uwe Kleine-König, Lee Jones,
	Satya Priya Kakitapalli, Marijn Suijten, Luca Weiss
  Cc: Rob Herring, linux-leds, devicetree, linux-kernel, linux-pwm
In-Reply-To: <20220129005429.754727-1-bjorn.andersson@linaro.org>

The Light Pulse Generator (LPG) is a PWM-block found in a wide range of
PMICs from Qualcomm. These PMICs typically comes with 1-8 LPG instances,
with their output being routed to various other components, such as
current sinks or GPIOs.

Each LPG instance can operate on fixed parameters or based on a shared
lookup-table, altering the duty cycle over time. This provides the means
for hardware assisted transitions of LED brightness.

A typical use case for the fixed parameter mode is to drive a PWM
backlight control signal, the driver therefor allows each LPG instance
to be exposed to the kernel either through the LED framework or the PWM
framework.

A typical use case for the LED configuration is to drive RGB LEDs in
smartphones etc, for which the driver support multiple channels to be
ganged up to a MULTICOLOR LED. In this configuration the pattern
generators will be synchronized, to allow for multi-color patterns.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v10:
- Check for and reject pattern.delta_t greater than 9 bits
- Write all 9 bits of LPG_RAMP_DURATION_REG

 drivers/leds/Kconfig             |    3 +
 drivers/leds/Makefile            |    3 +
 drivers/leds/rgb/Kconfig         |   13 +
 drivers/leds/rgb/Makefile        |    3 +
 drivers/leds/rgb/leds-qcom-lpg.c | 1306 ++++++++++++++++++++++++++++++
 5 files changed, 1328 insertions(+)
 create mode 100644 drivers/leds/rgb/Kconfig
 create mode 100644 drivers/leds/rgb/Makefile
 create mode 100644 drivers/leds/rgb/leds-qcom-lpg.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 6090e647daee..a49979f41eee 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -869,6 +869,9 @@ source "drivers/leds/blink/Kconfig"
 comment "Flash and Torch LED drivers"
 source "drivers/leds/flash/Kconfig"
 
+comment "RGB LED drivers"
+source "drivers/leds/rgb/Kconfig"
+
 comment "LED Triggers"
 source "drivers/leds/trigger/Kconfig"
 
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e58ecb36360f..4fd2f92cd198 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -99,6 +99,9 @@ obj-$(CONFIG_LEDS_USER)			+= uleds.o
 # Flash and Torch LED Drivers
 obj-$(CONFIG_LEDS_CLASS_FLASH)		+= flash/
 
+# RGB LED Drivers
+obj-$(CONFIG_LEDS_CLASS_MULTICOLOR)	+= rgb/
+
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGERS)		+= trigger/
 
diff --git a/drivers/leds/rgb/Kconfig b/drivers/leds/rgb/Kconfig
new file mode 100644
index 000000000000..20be3e11fe4a
--- /dev/null
+++ b/drivers/leds/rgb/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if LEDS_CLASS_MULTICOLOR
+
+config LEDS_QCOM_LPG
+	tristate "LED support for Qualcomm LPG"
+	depends on OF
+	depends on SPMI
+	help
+	  This option enables support for the Light Pulse Generator found in a
+	  wide variety of Qualcomm PMICs.
+
+endif # LEDS_CLASS_MULTICOLOR
diff --git a/drivers/leds/rgb/Makefile b/drivers/leds/rgb/Makefile
new file mode 100644
index 000000000000..83114f44c4ea
--- /dev/null
+++ b/drivers/leds/rgb/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_LEDS_QCOM_LPG)	+= leds-qcom-lpg.o
diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c
new file mode 100644
index 000000000000..06d5fca1d4b5
--- /dev/null
+++ b/drivers/leds/rgb/leds-qcom-lpg.c
@@ -0,0 +1,1306 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2017-2022 Linaro Ltd
+ * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ */
+#include <linux/bits.h>
+#include <linux/led-class-multicolor.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define LPG_PATTERN_CONFIG_REG	0x40
+#define LPG_SIZE_CLK_REG	0x41
+#define LPG_PREDIV_CLK_REG	0x42
+#define PWM_TYPE_CONFIG_REG	0x43
+#define PWM_VALUE_REG		0x44
+#define PWM_ENABLE_CONTROL_REG	0x46
+#define PWM_SYNC_REG		0x47
+#define LPG_RAMP_DURATION_REG	0x50
+#define LPG_HI_PAUSE_REG	0x52
+#define LPG_LO_PAUSE_REG	0x54
+#define LPG_HI_IDX_REG		0x56
+#define LPG_LO_IDX_REG		0x57
+#define PWM_SEC_ACCESS_REG	0xd0
+#define PWM_DTEST_REG(x)	(0xe2 + (x) - 1)
+
+#define TRI_LED_SRC_SEL		0x45
+#define TRI_LED_EN_CTL		0x46
+#define TRI_LED_ATC_CTL		0x47
+
+#define LPG_LUT_REG(x)		(0x40 + (x) * 2)
+#define RAMP_CONTROL_REG	0xc8
+
+#define LPG_RESOLUTION		512
+#define LPG_MAX_M		7
+
+struct lpg_channel;
+struct lpg_data;
+
+/**
+ * struct lpg - LPG device context
+ * @dev:	struct device for LPG device
+ * @map:	regmap for register access
+ * @pwm:	PWM-chip object, if operating in PWM mode
+ * @data:	reference to version specific data
+ * @lut_base:	base address of the LUT block (optional)
+ * @lut_size:	number of entries in the LUT block
+ * @lut_bitmap:	allocation bitmap for LUT entries
+ * @triled_base: base address of the TRILED block (optional)
+ * @triled_src:	power-source for the TRILED
+ * @triled_has_atc_ctl:	true if there is TRI_LED_ATC_CTL register
+ * @triled_has_src_sel:	true if there is TRI_LED_SRC_SEL register
+ * @channels:	list of PWM channels
+ * @num_channels: number of @channels
+ */
+struct lpg {
+	struct device *dev;
+	struct regmap *map;
+
+	struct pwm_chip pwm;
+
+	const struct lpg_data *data;
+
+	u32 lut_base;
+	u32 lut_size;
+	unsigned long *lut_bitmap;
+
+	u32 triled_base;
+	u32 triled_src;
+	bool triled_has_atc_ctl;
+	bool triled_has_src_sel;
+
+	struct lpg_channel *channels;
+	unsigned int num_channels;
+};
+
+/**
+ * struct lpg_channel - per channel data
+ * @lpg:	reference to parent lpg
+ * @base:	base address of the PWM channel
+ * @triled_mask: mask in TRILED to enable this channel
+ * @lut_mask:	mask in LUT to start pattern generator for this channel
+ * @in_use:	channel is exposed to LED framework
+ * @color:	color of the LED attached to this channel
+ * @dtest_line:	DTEST line for output, or 0 if disabled
+ * @dtest_value: DTEST line configuration
+ * @pwm_value:	duty (in microseconds) of the generated pulses, overridden by LUT
+ * @enabled:	output enabled?
+ * @period:	period (in nanoseconds) of the generated pulses
+ * @clk:	base frequency of the clock generator
+ * @pre_div:	divider of @clk
+ * @pre_div_exp: exponential divider of @clk
+ * @ramp_enabled: duty cycle is driven by iterating over lookup table
+ * @ramp_ping_pong: reverse through pattern, rather than wrapping to start
+ * @ramp_oneshot: perform only a single pass over the pattern
+ * @ramp_reverse: iterate over pattern backwards
+ * @ramp_tick_ms: length (in milliseconds) of one step in the pattern
+ * @ramp_lo_pause_ms: pause (in milliseconds) before iterating over pattern
+ * @ramp_hi_pause_ms: pause (in milliseconds) after iterating over pattern
+ * @pattern_lo_idx: start index of associated pattern
+ * @pattern_hi_idx: last index of associated pattern
+ */
+struct lpg_channel {
+	struct lpg *lpg;
+
+	u32 base;
+	unsigned int triled_mask;
+	unsigned int lut_mask;
+
+	bool in_use;
+
+	int color;
+
+	u32 dtest_line;
+	u32 dtest_value;
+
+	u16 pwm_value;
+	bool enabled;
+
+	u64 period;
+	unsigned int clk;
+	unsigned int pre_div;
+	unsigned int pre_div_exp;
+
+	bool ramp_enabled;
+	bool ramp_ping_pong;
+	bool ramp_oneshot;
+	bool ramp_reverse;
+	unsigned short ramp_tick_ms;
+	unsigned long ramp_lo_pause_ms;
+	unsigned long ramp_hi_pause_ms;
+
+	unsigned int pattern_lo_idx;
+	unsigned int pattern_hi_idx;
+};
+
+/**
+ * struct lpg_led - logical LED object
+ * @lpg:		lpg context reference
+ * @cdev:		LED class device
+ * @mcdev:		Multicolor LED class device
+ * @num_channels:	number of @channels
+ * @channels:		list of channels associated with the LED
+ */
+struct lpg_led {
+	struct lpg *lpg;
+
+	struct led_classdev cdev;
+	struct led_classdev_mc mcdev;
+
+	unsigned int num_channels;
+	struct lpg_channel *channels[];
+};
+
+/**
+ * struct lpg_channel_data - per channel initialization data
+ * @base:		base address for PWM channel registers
+ * @triled_mask:	bitmask for controlling this channel in TRILED
+ */
+struct lpg_channel_data {
+	unsigned int base;
+	u8 triled_mask;
+};
+
+/**
+ * struct lpg_data - initialization data
+ * @lut_base:		base address of LUT block
+ * @lut_size:		number of entries in LUT
+ * @triled_base:	base address of TRILED
+ * @triled_has_atc_ctl:	true if there is TRI_LED_ATC_CTL register
+ * @triled_has_src_sel:	true if there is TRI_LED_SRC_SEL register
+ * @pwm_9bit_mask:	bitmask for switching from 6bit to 9bit pwm
+ * @num_channels:	number of channels in LPG
+ * @channels:		list of channel initialization data
+ */
+struct lpg_data {
+	unsigned int lut_base;
+	unsigned int lut_size;
+	unsigned int triled_base;
+	bool triled_has_atc_ctl;
+	bool triled_has_src_sel;
+	unsigned int pwm_9bit_mask;
+	int num_channels;
+	const struct lpg_channel_data *channels;
+};
+
+static int triled_set(struct lpg *lpg, unsigned int mask, unsigned int enable)
+{
+	/* Skip if we don't have a triled block */
+	if (!lpg->triled_base)
+		return 0;
+
+	return regmap_update_bits(lpg->map, lpg->triled_base + TRI_LED_EN_CTL,
+				  mask, enable);
+}
+
+static int lpg_lut_store(struct lpg *lpg, struct led_pattern *pattern,
+			 size_t len, unsigned int *lo_idx, unsigned int *hi_idx)
+{
+	unsigned int idx;
+	u16 val;
+	int i;
+
+	/* Hardware does not behave when LO_IDX == HI_IDX */
+	if (len == 1)
+		return -EINVAL;
+
+	idx = bitmap_find_next_zero_area(lpg->lut_bitmap, lpg->lut_size,
+					 0, len, 0);
+	if (idx >= lpg->lut_size)
+		return -ENOMEM;
+
+	for (i = 0; i < len; i++) {
+		val = pattern[i].brightness;
+
+		regmap_bulk_write(lpg->map, lpg->lut_base + LPG_LUT_REG(idx + i),
+				  &val, sizeof(val));
+	}
+
+	bitmap_set(lpg->lut_bitmap, idx, len);
+
+	*lo_idx = idx;
+	*hi_idx = idx + len - 1;
+
+	return 0;
+}
+
+static void lpg_lut_free(struct lpg *lpg, unsigned int lo_idx, unsigned int hi_idx)
+{
+	int len;
+
+	if (lo_idx == hi_idx)
+		return;
+
+	len = hi_idx - lo_idx + 1;
+	bitmap_clear(lpg->lut_bitmap, lo_idx, len);
+}
+
+static int lpg_lut_sync(struct lpg *lpg, unsigned int mask)
+{
+	return regmap_write(lpg->map, lpg->lut_base + RAMP_CONTROL_REG, mask);
+}
+
+static const unsigned int lpg_clk_rates[] = {1024, 32768, 19200000};
+static const unsigned int lpg_pre_divs[] = {1, 3, 5, 6};
+
+static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period)
+{
+	unsigned int clk, best_clk = 0;
+	unsigned int div, best_div = 0;
+	unsigned int m, best_m = 0;
+	unsigned int error;
+	unsigned int best_err = UINT_MAX;
+	u64 best_period = 0;
+
+	/*
+	 * The PWM period is determined by:
+	 *
+	 *          resolution * pre_div * 2^M
+	 * period = --------------------------
+	 *                   refclk
+	 *
+	 * With resolution fixed at 2^9 bits, pre_div = {1, 3, 5, 6} and
+	 * M = [0..7].
+	 *
+	 * This allows for periods between 27uS and 384s, as the PWM framework
+	 * wants a period of equal or lower length than requested, reject
+	 * anything below 27uS.
+	 */
+	if (period <= (u64)NSEC_PER_SEC * LPG_RESOLUTION / 19200000)
+		return -EINVAL;
+
+	/* Limit period to largest possible value, to avoid overflows */
+	if (period > (u64)NSEC_PER_SEC * LPG_RESOLUTION * 6 * (1 << LPG_MAX_M) / 1024)
+		period = (u64)NSEC_PER_SEC * LPG_RESOLUTION * 6 * (1 << LPG_MAX_M) / 2014;
+
+	/*
+	 * Search for the pre_div, clk and M by solving the rewritten formula
+	 * for each clk and pre_div value:
+	 *
+	 *                       period * clk
+	 * M = log2 -------------------------------------
+	 *           NSEC_PER_SEC * pre_div * resolution
+	 */
+	for (clk = 0; clk < ARRAY_SIZE(lpg_clk_rates); clk++) {
+		u64 nom = period * lpg_clk_rates[clk];
+
+		for (div = 0; div < ARRAY_SIZE(lpg_pre_divs); div++) {
+			u64 denom = (u64)NSEC_PER_SEC * lpg_pre_divs[div] * (1 << 9);
+			u64 actual;
+			u64 ratio;
+
+			if (nom < denom)
+				continue;
+
+			ratio = div64_u64(nom, denom);
+			m = ilog2(ratio);
+			if (m > LPG_MAX_M)
+				m = LPG_MAX_M;
+
+			actual = DIV_ROUND_UP_ULL(denom * (1 << m), lpg_clk_rates[clk]);
+
+			error = period - actual;
+			if (error < best_err) {
+				best_err = error;
+
+				best_div = div;
+				best_m = m;
+				best_clk = clk;
+				best_period = actual;
+			}
+		}
+	}
+
+	chan->clk = best_clk;
+	chan->pre_div = best_div;
+	chan->pre_div_exp = best_m;
+	chan->period = best_period;
+
+	return 0;
+}
+
+static void lpg_calc_duty(struct lpg_channel *chan, uint64_t duty)
+{
+	unsigned int max = LPG_RESOLUTION - 1;
+	unsigned int val;
+
+	val = div64_u64(duty * lpg_clk_rates[chan->clk],
+			(u64)NSEC_PER_SEC * lpg_pre_divs[chan->pre_div] * (1 << chan->pre_div_exp));
+
+	chan->pwm_value = min(val, max);
+}
+
+static void lpg_apply_freq(struct lpg_channel *chan)
+{
+	unsigned long val;
+	struct lpg *lpg = chan->lpg;
+
+	if (!chan->enabled)
+		return;
+
+	/* Clock register values are off-by-one from lpg_clk_table */
+	val = chan->clk + 1;
+
+	/* Enable 9bit resolution */
+	val |= lpg->data->pwm_9bit_mask;
+
+	regmap_write(lpg->map, chan->base + LPG_SIZE_CLK_REG, val);
+
+	val = chan->pre_div << 5 | chan->pre_div_exp;
+	regmap_write(lpg->map, chan->base + LPG_PREDIV_CLK_REG, val);
+}
+
+#define LPG_ENABLE_GLITCH_REMOVAL	BIT(5)
+
+static void lpg_enable_glitch(struct lpg_channel *chan)
+{
+	struct lpg *lpg = chan->lpg;
+
+	regmap_update_bits(lpg->map, chan->base + PWM_TYPE_CONFIG_REG,
+			   LPG_ENABLE_GLITCH_REMOVAL, 0);
+}
+
+static void lpg_disable_glitch(struct lpg_channel *chan)
+{
+	struct lpg *lpg = chan->lpg;
+
+	regmap_update_bits(lpg->map, chan->base + PWM_TYPE_CONFIG_REG,
+			   LPG_ENABLE_GLITCH_REMOVAL,
+			   LPG_ENABLE_GLITCH_REMOVAL);
+}
+
+static void lpg_apply_pwm_value(struct lpg_channel *chan)
+{
+	struct lpg *lpg = chan->lpg;
+	u16 val = chan->pwm_value;
+
+	if (!chan->enabled)
+		return;
+
+	regmap_bulk_write(lpg->map, chan->base + PWM_VALUE_REG, &val, sizeof(val));
+}
+
+#define LPG_PATTERN_CONFIG_LO_TO_HI	BIT(4)
+#define LPG_PATTERN_CONFIG_REPEAT	BIT(3)
+#define LPG_PATTERN_CONFIG_TOGGLE	BIT(2)
+#define LPG_PATTERN_CONFIG_PAUSE_HI	BIT(1)
+#define LPG_PATTERN_CONFIG_PAUSE_LO	BIT(0)
+
+static void lpg_apply_lut_control(struct lpg_channel *chan)
+{
+	struct lpg *lpg = chan->lpg;
+	unsigned int hi_pause;
+	unsigned int lo_pause;
+	unsigned int conf = 0;
+	unsigned int lo_idx = chan->pattern_lo_idx;
+	unsigned int hi_idx = chan->pattern_hi_idx;
+	u16 step = chan->ramp_tick_ms;
+
+	if (!chan->ramp_enabled || chan->pattern_lo_idx == chan->pattern_hi_idx)
+		return;
+
+	hi_pause = DIV_ROUND_UP(chan->ramp_hi_pause_ms, step);
+	lo_pause = DIV_ROUND_UP(chan->ramp_lo_pause_ms, step);
+
+	if (!chan->ramp_reverse)
+		conf |= LPG_PATTERN_CONFIG_LO_TO_HI;
+	if (!chan->ramp_oneshot)
+		conf |= LPG_PATTERN_CONFIG_REPEAT;
+	if (chan->ramp_ping_pong)
+		conf |= LPG_PATTERN_CONFIG_TOGGLE;
+	if (chan->ramp_hi_pause_ms)
+		conf |= LPG_PATTERN_CONFIG_PAUSE_HI;
+	if (chan->ramp_lo_pause_ms)
+		conf |= LPG_PATTERN_CONFIG_PAUSE_LO;
+
+	regmap_write(lpg->map, chan->base + LPG_PATTERN_CONFIG_REG, conf);
+	regmap_write(lpg->map, chan->base + LPG_HI_IDX_REG, hi_idx);
+	regmap_write(lpg->map, chan->base + LPG_LO_IDX_REG, lo_idx);
+
+	regmap_bulk_write(lpg->map, chan->base + LPG_RAMP_DURATION_REG, &step, sizeof(step));
+	regmap_write(lpg->map, chan->base + LPG_HI_PAUSE_REG, hi_pause);
+	regmap_write(lpg->map, chan->base + LPG_LO_PAUSE_REG, lo_pause);
+}
+
+#define LPG_ENABLE_CONTROL_OUTPUT		BIT(7)
+#define LPG_ENABLE_CONTROL_BUFFER_TRISTATE	BIT(5)
+#define LPG_ENABLE_CONTROL_SRC_PWM		BIT(2)
+#define LPG_ENABLE_CONTROL_RAMP_GEN		BIT(1)
+
+static void lpg_apply_control(struct lpg_channel *chan)
+{
+	unsigned int ctrl;
+	struct lpg *lpg = chan->lpg;
+
+	ctrl = LPG_ENABLE_CONTROL_BUFFER_TRISTATE;
+
+	if (chan->enabled)
+		ctrl |= LPG_ENABLE_CONTROL_OUTPUT;
+
+	if (chan->pattern_lo_idx != chan->pattern_hi_idx)
+		ctrl |= LPG_ENABLE_CONTROL_RAMP_GEN;
+	else
+		ctrl |= LPG_ENABLE_CONTROL_SRC_PWM;
+
+	regmap_write(lpg->map, chan->base + PWM_ENABLE_CONTROL_REG, ctrl);
+
+	/*
+	 * Due to LPG hardware bug, in the PWM mode, having enabled PWM,
+	 * We have to write PWM values one more time.
+	 */
+	if (chan->enabled)
+		lpg_apply_pwm_value(chan);
+}
+
+#define LPG_SYNC_PWM	BIT(0)
+
+static void lpg_apply_sync(struct lpg_channel *chan)
+{
+	struct lpg *lpg = chan->lpg;
+
+	regmap_write(lpg->map, chan->base + PWM_SYNC_REG, LPG_SYNC_PWM);
+}
+
+static int lpg_parse_dtest(struct lpg *lpg)
+{
+	struct lpg_channel *chan;
+	struct device_node *np = lpg->dev->of_node;
+	int count;
+	int ret;
+	int i;
+
+	count = of_property_count_u32_elems(np, "qcom,dtest");
+	if (count == -EINVAL) {
+		return 0;
+	} else if (count < 0) {
+		ret = count;
+		goto err_malformed;
+	} else if (count != lpg->data->num_channels * 2) {
+		dev_err(lpg->dev, "qcom,dtest needs to be %d items\n",
+			lpg->data->num_channels * 2);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < lpg->data->num_channels; i++) {
+		chan = &lpg->channels[i];
+
+		ret = of_property_read_u32_index(np, "qcom,dtest", i * 2,
+						 &chan->dtest_line);
+		if (ret)
+			goto err_malformed;
+
+		ret = of_property_read_u32_index(np, "qcom,dtest", i * 2 + 1,
+						 &chan->dtest_value);
+		if (ret)
+			goto err_malformed;
+	}
+
+	return 0;
+
+err_malformed:
+	dev_err(lpg->dev, "malformed qcom,dtest\n");
+	return ret;
+}
+
+static void lpg_apply_dtest(struct lpg_channel *chan)
+{
+	struct lpg *lpg = chan->lpg;
+
+	if (!chan->dtest_line)
+		return;
+
+	regmap_write(lpg->map, chan->base + PWM_SEC_ACCESS_REG, 0xa5);
+	regmap_write(lpg->map, chan->base + PWM_DTEST_REG(chan->dtest_line),
+		     chan->dtest_value);
+}
+
+static void lpg_apply(struct lpg_channel *chan)
+{
+	lpg_disable_glitch(chan);
+	lpg_apply_freq(chan);
+	lpg_apply_pwm_value(chan);
+	lpg_apply_control(chan);
+	lpg_apply_sync(chan);
+	lpg_apply_lut_control(chan);
+	lpg_enable_glitch(chan);
+}
+
+static void lpg_brightness_set(struct lpg_led *led, struct led_classdev *cdev,
+			       struct mc_subled *subleds)
+{
+	enum led_brightness brightness;
+	struct lpg_channel *chan;
+	unsigned int triled_enabled = 0;
+	unsigned int triled_mask = 0;
+	unsigned int lut_mask = 0;
+	unsigned int duty;
+	struct lpg *lpg = led->lpg;
+	int i;
+
+	for (i = 0; i < led->num_channels; i++) {
+		chan = led->channels[i];
+		brightness = subleds[i].brightness;
+
+		if (brightness == LED_OFF) {
+			chan->enabled = false;
+			chan->ramp_enabled = false;
+		} else if (chan->pattern_lo_idx != chan->pattern_hi_idx) {
+			lpg_calc_freq(chan, NSEC_PER_MSEC);
+
+			chan->enabled = true;
+			chan->ramp_enabled = true;
+
+			lut_mask |= chan->lut_mask;
+			triled_enabled |= chan->triled_mask;
+		} else {
+			lpg_calc_freq(chan, NSEC_PER_MSEC);
+
+			duty = div_u64(brightness * chan->period, cdev->max_brightness);
+			lpg_calc_duty(chan, duty);
+			chan->enabled = true;
+			chan->ramp_enabled = false;
+
+			triled_enabled |= chan->triled_mask;
+		}
+
+		triled_mask |= chan->triled_mask;
+
+		lpg_apply(chan);
+	}
+
+	/* Toggle triled lines */
+	if (triled_mask)
+		triled_set(lpg, triled_mask, triled_enabled);
+
+	/* Trigger start of ramp generator(s) */
+	if (lut_mask)
+		lpg_lut_sync(lpg, lut_mask);
+}
+
+static void lpg_brightness_single_set(struct led_classdev *cdev,
+				      enum led_brightness value)
+{
+	struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
+	struct mc_subled info;
+
+	info.brightness = value;
+	lpg_brightness_set(led, cdev, &info);
+}
+
+static void lpg_brightness_mc_set(struct led_classdev *cdev,
+				  enum led_brightness value)
+{
+	struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
+	struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
+
+	led_mc_calc_color_components(mc, value);
+	lpg_brightness_set(led, cdev, mc->subled_info);
+}
+
+static int lpg_blink_set(struct lpg_led *led,
+			 unsigned long *delay_on, unsigned long *delay_off)
+{
+	struct lpg_channel *chan;
+	unsigned int period;
+	unsigned int triled_mask = 0;
+	struct lpg *lpg = led->lpg;
+	u64 duty;
+	int i;
+
+	if (!*delay_on && !*delay_off) {
+		*delay_on = 500;
+		*delay_off = 500;
+	}
+
+	duty = *delay_on * NSEC_PER_MSEC;
+	period = (*delay_on + *delay_off) * NSEC_PER_MSEC;
+
+	for (i = 0; i < led->num_channels; i++) {
+		chan = led->channels[i];
+
+		lpg_calc_freq(chan, period);
+		lpg_calc_duty(chan, duty);
+
+		chan->enabled = true;
+		chan->ramp_enabled = false;
+
+		triled_mask |= chan->triled_mask;
+
+		lpg_apply(chan);
+	}
+
+	/* Enable triled lines */
+	triled_set(lpg, triled_mask, triled_mask);
+
+	chan = led->channels[0];
+	duty = div_u64(chan->pwm_value * chan->period, LPG_RESOLUTION);
+	*delay_on = div_u64(duty, NSEC_PER_MSEC);
+	*delay_off = div_u64(chan->period - duty, NSEC_PER_MSEC);
+
+	return 0;
+}
+
+static int lpg_blink_single_set(struct led_classdev *cdev,
+				unsigned long *delay_on, unsigned long *delay_off)
+{
+	struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
+
+	return lpg_blink_set(led, delay_on, delay_off);
+}
+
+static int lpg_blink_mc_set(struct led_classdev *cdev,
+			    unsigned long *delay_on, unsigned long *delay_off)
+{
+	struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
+	struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
+
+	return lpg_blink_set(led, delay_on, delay_off);
+}
+
+static int lpg_pattern_set(struct lpg_led *led, struct led_pattern *pattern,
+			   u32 len, int repeat)
+{
+	struct lpg_channel *chan;
+	struct lpg *lpg = led->lpg;
+	unsigned int hi_pause;
+	unsigned int lo_pause;
+	unsigned int lo_idx;
+	unsigned int hi_idx;
+	bool ping_pong = true;
+	int brightness_a;
+	int brightness_b;
+	int ret;
+	int i;
+
+	/* Only support oneshot or indefinite loops, due to limited pattern space */
+	if (repeat != -1 && repeat != 1)
+		return -EINVAL;
+
+	/* LPG_RAMP_DURATION_REG is 9 bit */
+	if (pattern[0].delta_t >= 512)
+		return -EINVAL;
+
+	/*
+	 * The LPG plays patterns with at a fixed pace, a "low pause" can be
+	 * performed before the pattern and a "high pause" after. In order to
+	 * save space the pattern can be played in "ping pong" mode, in which
+	 * the pattern is first played forward, then "high pause" is applied,
+	 * then the pattern is played backwards and finally the "low pause" is
+	 * applied.
+	 *
+	 * The delta_t of the first entry is used to determine the pace of the
+	 * pattern.
+	 *
+	 * If the specified pattern is a palindrome the ping pong mode is
+	 * enabled. In this scenario the delta_t of the last entry determines
+	 * the "low pause" time and the delta_t of the middle entry (i.e. the
+	 * last in the programmed pattern) determines the "high pause". If the
+	 * pattern consists of an odd number of values, no "high pause" is
+	 * used.
+	 *
+	 * When ping pong mode is not selected, the delta_t of the last entry
+	 * is used as "high pause". No "low pause" is used.
+	 *
+	 * delta_t of any other members of the pattern is ignored.
+	 */
+
+	/* Detect palindromes and use "ping pong" to reduce LUT usage */
+	for (i = 0; i < len / 2; i++) {
+		brightness_a = pattern[i].brightness;
+		brightness_b = pattern[len - i - 1].brightness;
+
+		if (brightness_a != brightness_b) {
+			ping_pong = false;
+			break;
+		}
+	}
+
+	if (ping_pong) {
+		if (len % 2)
+			hi_pause = 0;
+		else
+			hi_pause = pattern[(len + 1) / 2].delta_t;
+		lo_pause = pattern[len - 1].delta_t;
+
+		len = (len + 1) / 2;
+	} else {
+		hi_pause = pattern[len - 1].delta_t;
+		lo_pause = 0;
+	}
+
+	ret = lpg_lut_store(lpg, pattern, len, &lo_idx, &hi_idx);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < led->num_channels; i++) {
+		chan = led->channels[i];
+
+		chan->ramp_tick_ms = pattern[0].delta_t;
+		chan->ramp_ping_pong = ping_pong;
+		chan->ramp_oneshot = repeat != -1;
+
+		chan->ramp_lo_pause_ms = lo_pause;
+		chan->ramp_hi_pause_ms = hi_pause;
+
+		chan->pattern_lo_idx = lo_idx;
+		chan->pattern_hi_idx = hi_idx;
+	}
+
+	return 0;
+}
+
+static int lpg_pattern_single_set(struct led_classdev *cdev,
+				  struct led_pattern *pattern, u32 len,
+				  int repeat)
+{
+	struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
+	int ret;
+
+	ret = lpg_pattern_set(led, pattern, len, repeat);
+	if (ret < 0)
+		return ret;
+
+	lpg_brightness_single_set(cdev, LED_FULL);
+
+	return 0;
+}
+
+static int lpg_pattern_mc_set(struct led_classdev *cdev,
+			      struct led_pattern *pattern, u32 len,
+			      int repeat)
+{
+	struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
+	struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
+	int ret;
+
+	ret = lpg_pattern_set(led, pattern, len, repeat);
+	if (ret < 0)
+		return ret;
+
+	led_mc_calc_color_components(mc, LED_FULL);
+	lpg_brightness_set(led, cdev, mc->subled_info);
+
+	return 0;
+}
+
+static int lpg_pattern_clear(struct lpg_led *led)
+{
+	struct lpg_channel *chan;
+	struct lpg *lpg = led->lpg;
+	int i;
+
+	chan = led->channels[0];
+	lpg_lut_free(lpg, chan->pattern_lo_idx, chan->pattern_hi_idx);
+
+	for (i = 0; i < led->num_channels; i++) {
+		chan = led->channels[i];
+		chan->pattern_lo_idx = 0;
+		chan->pattern_hi_idx = 0;
+	}
+
+	return 0;
+}
+
+static int lpg_pattern_single_clear(struct led_classdev *cdev)
+{
+	struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
+
+	return lpg_pattern_clear(led);
+}
+
+static int lpg_pattern_mc_clear(struct led_classdev *cdev)
+{
+	struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
+	struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
+
+	return lpg_pattern_clear(led);
+}
+
+static int lpg_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct lpg *lpg = container_of(chip, struct lpg, pwm);
+	struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
+
+	return chan->in_use ? -EBUSY : 0;
+}
+
+/*
+ * Limitations:
+ * - Updating both duty and period is not done atomically, so the output signal
+ *   will momentarily be a mix of the settings.
+ */
+static int lpg_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			 const struct pwm_state *state)
+{
+	struct lpg *lpg = container_of(chip, struct lpg, pwm);
+	struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
+	int ret;
+
+	if (state->polarity != PWM_POLARITY_NORMAL)
+		return -EINVAL;
+
+	ret = lpg_calc_freq(chan, state->period);
+	if (ret < 0)
+		return ret;
+
+	lpg_calc_duty(chan, state->duty_cycle);
+	chan->enabled = state->enabled;
+
+	lpg_apply(chan);
+
+	triled_set(lpg, chan->triled_mask, chan->enabled ? chan->triled_mask : 0);
+
+	return 0;
+}
+
+static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+			      struct pwm_state *state)
+{
+	struct lpg *lpg = container_of(chip, struct lpg, pwm);
+	struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
+	u64 duty = DIV_ROUND_UP_ULL(chan->pwm_value * chan->period, LPG_RESOLUTION - 1);
+
+	state->period = chan->period;
+	state->duty_cycle = duty;
+	state->polarity = PWM_POLARITY_NORMAL;
+	state->enabled = chan->enabled;
+}
+
+static const struct pwm_ops lpg_pwm_ops = {
+	.request = lpg_pwm_request,
+	.apply = lpg_pwm_apply,
+	.get_state = lpg_pwm_get_state,
+	.owner = THIS_MODULE,
+};
+
+static int lpg_add_pwm(struct lpg *lpg)
+{
+	int ret;
+
+	lpg->pwm.base = -1;
+	lpg->pwm.dev = lpg->dev;
+	lpg->pwm.npwm = lpg->num_channels;
+	lpg->pwm.ops = &lpg_pwm_ops;
+
+	ret = pwmchip_add(&lpg->pwm);
+	if (ret)
+		dev_err(lpg->dev, "failed to add PWM chip: ret %d\n", ret);
+
+	return ret;
+}
+
+static int lpg_parse_channel(struct lpg *lpg, struct device_node *np,
+			     struct lpg_channel **channel)
+{
+	struct lpg_channel *chan;
+	u32 color = LED_COLOR_ID_GREEN;
+	u32 reg;
+	int ret;
+
+	ret = of_property_read_u32(np, "reg", &reg);
+	if (ret || !reg || reg > lpg->num_channels) {
+		dev_err(lpg->dev, "invalid \"reg\" of %pOFn\n", np);
+		return -EINVAL;
+	}
+
+	chan = &lpg->channels[reg - 1];
+	chan->in_use = true;
+
+	ret = of_property_read_u32(np, "color", &color);
+	if (ret < 0 && ret != -EINVAL) {
+		dev_err(lpg->dev, "failed to parse \"color\" of %pOF\n", np);
+		return ret;
+	}
+
+	chan->color = color;
+
+	*channel = chan;
+
+	return 0;
+}
+
+static int lpg_add_led(struct lpg *lpg, struct device_node *np)
+{
+	struct led_init_data init_data = {};
+	struct led_classdev *cdev;
+	struct device_node *child;
+	struct mc_subled *info;
+	struct lpg_led *led;
+	const char *state;
+	int num_channels;
+	u32 color = 0;
+	int ret;
+	int i;
+
+	ret = of_property_read_u32(np, "color", &color);
+	if (ret < 0 && ret != -EINVAL) {
+		dev_err(lpg->dev, "failed to parse \"color\" of %pOF\n", np);
+		return ret;
+	}
+
+	if (color == LED_COLOR_ID_RGB)
+		num_channels = of_get_available_child_count(np);
+	else
+		num_channels = 1;
+
+	led = devm_kzalloc(lpg->dev, struct_size(led, channels, num_channels), GFP_KERNEL);
+	if (!led)
+		return -ENOMEM;
+
+	led->lpg = lpg;
+	led->num_channels = num_channels;
+
+	if (color == LED_COLOR_ID_RGB) {
+		info = devm_kcalloc(lpg->dev, num_channels, sizeof(*info), GFP_KERNEL);
+		if (!info)
+			return -ENOMEM;
+		i = 0;
+		for_each_available_child_of_node(np, child) {
+			ret = lpg_parse_channel(lpg, child, &led->channels[i]);
+			if (ret < 0)
+				return ret;
+
+			info[i].color_index = led->channels[i]->color;
+			info[i].intensity = LED_FULL;
+			i++;
+		}
+
+		led->mcdev.subled_info = info;
+		led->mcdev.num_colors = num_channels;
+
+		cdev = &led->mcdev.led_cdev;
+		cdev->brightness_set = lpg_brightness_mc_set;
+		cdev->blink_set = lpg_blink_mc_set;
+
+		/* Register pattern accessors only if we have a LUT block */
+		if (lpg->lut_base) {
+			cdev->pattern_set = lpg_pattern_mc_set;
+			cdev->pattern_clear = lpg_pattern_mc_clear;
+		}
+	} else {
+		ret = lpg_parse_channel(lpg, np, &led->channels[0]);
+		if (ret < 0)
+			return ret;
+
+		cdev = &led->cdev;
+		cdev->brightness_set = lpg_brightness_single_set;
+		cdev->blink_set = lpg_blink_single_set;
+
+		/* Register pattern accessors only if we have a LUT block */
+		if (lpg->lut_base) {
+			cdev->pattern_set = lpg_pattern_single_set;
+			cdev->pattern_clear = lpg_pattern_single_clear;
+		}
+	}
+
+	cdev->default_trigger = of_get_property(np, "linux,default-trigger", NULL);
+	cdev->max_brightness = 255;
+
+	if (!of_property_read_string(np, "default-state", &state) &&
+	    !strcmp(state, "on"))
+		cdev->brightness = LED_FULL;
+	else
+		cdev->brightness = LED_OFF;
+
+	cdev->brightness_set(cdev, cdev->brightness);
+
+	init_data.fwnode = of_fwnode_handle(np);
+
+	if (color == LED_COLOR_ID_RGB)
+		ret = devm_led_classdev_multicolor_register_ext(lpg->dev, &led->mcdev, &init_data);
+	else
+		ret = devm_led_classdev_register_ext(lpg->dev, &led->cdev, &init_data);
+	if (ret)
+		dev_err(lpg->dev, "unable to register %s\n", cdev->name);
+
+	return ret;
+}
+
+static int lpg_init_channels(struct lpg *lpg)
+{
+	const struct lpg_data *data = lpg->data;
+	int i;
+
+	lpg->num_channels = data->num_channels;
+	lpg->channels = devm_kcalloc(lpg->dev, data->num_channels,
+				     sizeof(struct lpg_channel), GFP_KERNEL);
+	if (!lpg->channels)
+		return -ENOMEM;
+
+	for (i = 0; i < data->num_channels; i++) {
+		lpg->channels[i].lpg = lpg;
+		lpg->channels[i].base = data->channels[i].base;
+		lpg->channels[i].triled_mask = data->channels[i].triled_mask;
+		lpg->channels[i].lut_mask = BIT(i);
+	}
+
+	return 0;
+}
+
+static int lpg_init_triled(struct lpg *lpg)
+{
+	struct device_node *np = lpg->dev->of_node;
+	int ret;
+
+	/* Skip initialization if we don't have a triled block */
+	if (!lpg->data->triled_base)
+		return 0;
+
+	lpg->triled_base = lpg->data->triled_base;
+	lpg->triled_has_atc_ctl = lpg->data->triled_has_atc_ctl;
+	lpg->triled_has_src_sel = lpg->data->triled_has_src_sel;
+
+	if (lpg->triled_has_src_sel) {
+		ret = of_property_read_u32(np, "qcom,power-source", &lpg->triled_src);
+		if (ret || lpg->triled_src == 2 || lpg->triled_src > 3) {
+			dev_err(lpg->dev, "invalid power source\n");
+			return -EINVAL;
+		}
+	}
+
+	/* Disable automatic trickle charge LED */
+	if (lpg->triled_has_atc_ctl)
+		regmap_write(lpg->map, lpg->triled_base + TRI_LED_ATC_CTL, 0);
+
+	/* Configure power source */
+	if (lpg->triled_has_src_sel)
+		regmap_write(lpg->map, lpg->triled_base + TRI_LED_SRC_SEL, lpg->triled_src);
+
+	/* Default all outputs to off */
+	regmap_write(lpg->map, lpg->triled_base + TRI_LED_EN_CTL, 0);
+
+	return 0;
+}
+
+static int lpg_init_lut(struct lpg *lpg)
+{
+	const struct lpg_data *data = lpg->data;
+	size_t bitmap_size;
+
+	if (!data->lut_base)
+		return 0;
+
+	lpg->lut_base = data->lut_base;
+	lpg->lut_size = data->lut_size;
+
+	bitmap_size = BITS_TO_BYTES(lpg->lut_size);
+	lpg->lut_bitmap = devm_kzalloc(lpg->dev, bitmap_size, GFP_KERNEL);
+	if (!lpg->lut_bitmap)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int lpg_probe(struct platform_device *pdev)
+{
+	struct device_node *np;
+	struct lpg *lpg;
+	int ret;
+	int i;
+
+	lpg = devm_kzalloc(&pdev->dev, sizeof(*lpg), GFP_KERNEL);
+	if (!lpg)
+		return -ENOMEM;
+
+	lpg->data = of_device_get_match_data(&pdev->dev);
+	if (!lpg->data)
+		return -EINVAL;
+
+	platform_set_drvdata(pdev, lpg);
+
+	lpg->dev = &pdev->dev;
+
+	lpg->map = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!lpg->map) {
+		dev_err(&pdev->dev, "parent regmap unavailable\n");
+		return -ENXIO;
+	}
+
+	ret = lpg_init_channels(lpg);
+	if (ret < 0)
+		return ret;
+
+	ret = lpg_parse_dtest(lpg);
+	if (ret < 0)
+		return ret;
+
+	ret = lpg_init_triled(lpg);
+	if (ret < 0)
+		return ret;
+
+	ret = lpg_init_lut(lpg);
+	if (ret < 0)
+		return ret;
+
+	for_each_available_child_of_node(pdev->dev.of_node, np) {
+		ret = lpg_add_led(lpg, np);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < lpg->num_channels; i++)
+		lpg_apply_dtest(&lpg->channels[i]);
+
+	return lpg_add_pwm(lpg);
+}
+
+static int lpg_remove(struct platform_device *pdev)
+{
+	struct lpg *lpg = platform_get_drvdata(pdev);
+
+	pwmchip_remove(&lpg->pwm);
+
+	return 0;
+}
+
+static const struct lpg_data pm8916_pwm_data = {
+	.pwm_9bit_mask = BIT(2),
+
+	.num_channels = 1,
+	.channels = (const struct lpg_channel_data[]) {
+		{ .base = 0xbc00 },
+	},
+};
+
+static const struct lpg_data pm8941_lpg_data = {
+	.lut_base = 0xb000,
+	.lut_size = 64,
+
+	.triled_base = 0xd000,
+	.triled_has_atc_ctl = true,
+	.triled_has_src_sel = true,
+
+	.pwm_9bit_mask = 3 << 4,
+
+	.num_channels = 8,
+	.channels = (const struct lpg_channel_data[]) {
+		{ .base = 0xb100 },
+		{ .base = 0xb200 },
+		{ .base = 0xb300 },
+		{ .base = 0xb400 },
+		{ .base = 0xb500, .triled_mask = BIT(5) },
+		{ .base = 0xb600, .triled_mask = BIT(6) },
+		{ .base = 0xb700, .triled_mask = BIT(7) },
+		{ .base = 0xb800 },
+	},
+};
+
+static const struct lpg_data pm8994_lpg_data = {
+	.lut_base = 0xb000,
+	.lut_size = 64,
+
+	.pwm_9bit_mask = 3 << 4,
+
+	.num_channels = 6,
+	.channels = (const struct lpg_channel_data[]) {
+		{ .base = 0xb100 },
+		{ .base = 0xb200 },
+		{ .base = 0xb300 },
+		{ .base = 0xb400 },
+		{ .base = 0xb500 },
+		{ .base = 0xb600 },
+	},
+};
+
+static const struct lpg_data pmi8994_lpg_data = {
+	.lut_base = 0xb000,
+	.lut_size = 24,
+
+	.triled_base = 0xd000,
+	.triled_has_atc_ctl = true,
+	.triled_has_src_sel = true,
+
+	.pwm_9bit_mask = BIT(4),
+
+	.num_channels = 4,
+	.channels = (const struct lpg_channel_data[]) {
+		{ .base = 0xb100, .triled_mask = BIT(5) },
+		{ .base = 0xb200, .triled_mask = BIT(6) },
+		{ .base = 0xb300, .triled_mask = BIT(7) },
+		{ .base = 0xb400 },
+	},
+};
+
+static const struct lpg_data pmi8998_lpg_data = {
+	.lut_base = 0xb000,
+	.lut_size = 49,
+
+	.triled_base = 0xd000,
+
+	.pwm_9bit_mask = BIT(4),
+
+	.num_channels = 6,
+	.channels = (const struct lpg_channel_data[]) {
+		{ .base = 0xb100 },
+		{ .base = 0xb200 },
+		{ .base = 0xb300, .triled_mask = BIT(5) },
+		{ .base = 0xb400, .triled_mask = BIT(6) },
+		{ .base = 0xb500, .triled_mask = BIT(7) },
+		{ .base = 0xb600 },
+	},
+};
+
+static const struct lpg_data pm8150b_lpg_data = {
+	.lut_base = 0xb000,
+	.lut_size = 24,
+
+	.triled_base = 0xd000,
+
+	.pwm_9bit_mask = BIT(4),
+
+	.num_channels = 2,
+	.channels = (const struct lpg_channel_data[]) {
+		{ .base = 0xb100, .triled_mask = BIT(7) },
+		{ .base = 0xb200, .triled_mask = BIT(6) },
+	},
+};
+
+static const struct lpg_data pm8150l_lpg_data = {
+	.lut_base = 0xb000,
+	.lut_size = 48,
+
+	.triled_base = 0xd000,
+
+	.pwm_9bit_mask = BIT(4),
+
+	.num_channels = 5,
+	.channels = (const struct lpg_channel_data[]) {
+		{ .base = 0xb100, .triled_mask = BIT(7) },
+		{ .base = 0xb200, .triled_mask = BIT(6) },
+		{ .base = 0xb300, .triled_mask = BIT(5) },
+		{ .base = 0xbc00 },
+		{ .base = 0xbd00 },
+
+	},
+};
+
+static const struct of_device_id lpg_of_table[] = {
+	{ .compatible = "qcom,pm8150b-lpg", .data = &pm8150b_lpg_data },
+	{ .compatible = "qcom,pm8150l-lpg", .data = &pm8150l_lpg_data },
+	{ .compatible = "qcom,pm8916-pwm", .data = &pm8916_pwm_data },
+	{ .compatible = "qcom,pm8941-lpg", .data = &pm8941_lpg_data },
+	{ .compatible = "qcom,pm8994-lpg", .data = &pm8994_lpg_data },
+	{ .compatible = "qcom,pmi8994-lpg", .data = &pmi8994_lpg_data },
+	{ .compatible = "qcom,pmi8998-lpg", .data = &pmi8998_lpg_data },
+	{ .compatible = "qcom,pmc8180c-lpg", .data = &pm8150l_lpg_data },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lpg_of_table);
+
+static struct platform_driver lpg_driver = {
+	.probe = lpg_probe,
+	.remove = lpg_remove,
+	.driver = {
+		.name = "qcom-spmi-lpg",
+		.of_match_table = lpg_of_table,
+	},
+};
+module_platform_driver(lpg_driver);
+
+MODULE_DESCRIPTION("Qualcomm LPG LED driver");
+MODULE_LICENSE("GPL v2");
-- 
2.33.1


^ permalink raw reply related

* [PATCH v11 1/2] dt-bindings: leds: Add Qualcomm Light Pulse Generator binding
From: Bjorn Andersson @ 2022-01-29  0:54 UTC (permalink / raw)
  To: Pavel Machek, Thierry Reding, Uwe Kleine-König, Lee Jones,
	Satya Priya Kakitapalli, Marijn Suijten, Luca Weiss
  Cc: Rob Herring, linux-leds, devicetree, linux-kernel, linux-pwm,
	Stephen Boyd, Rob Herring

This adds the binding document describing the three hardware blocks
related to the Light Pulse Generator found in a wide range of Qualcomm
PMICs.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---

Changes since v10:
- Picked up Rob and Stephen's R-b

 .../bindings/leds/leds-qcom-lpg.yaml          | 173 ++++++++++++++++++
 1 file changed, 173 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml

diff --git a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
new file mode 100644
index 000000000000..336bd8e10efd
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/leds-qcom-lpg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Light Pulse Generator
+
+maintainers:
+  - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description: >
+  The Qualcomm Light Pulse Generator consists of three different hardware blocks;
+  a ramp generator with lookup table, the light pulse generator and a three
+  channel current sink. These blocks are found in a wide range of Qualcomm PMICs.
+
+properties:
+  compatible:
+    enum:
+      - qcom,pm8150b-lpg
+      - qcom,pm8150l-lpg
+      - qcom,pm8916-pwm
+      - qcom,pm8941-lpg
+      - qcom,pm8994-lpg
+      - qcom,pmc8180c-lpg
+      - qcom,pmi8994-lpg
+      - qcom,pmi8998-lpg
+
+  "#pwm-cells":
+    const: 2
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 0
+
+  qcom,power-source:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      power-source used to drive the output, as defined in the datasheet.
+      Should be specified if the TRILED block is present
+    enum: [0, 1, 3]
+
+  qcom,dtest:
+    $ref: /schemas/types.yaml#/definitions/uint32-matrix
+    description: >
+      A list of integer pairs, where each pair represent the dtest line the
+      particular channel should be connected to and the flags denoting how the
+      value should be outputed, as defined in the datasheet. The number of
+      pairs should be the same as the number of channels.
+    items:
+      items:
+        - description: dtest line to attach
+        - description: flags for the attachment
+
+  multi-led:
+    type: object
+    $ref: leds-class-multicolor.yaml#
+    properties:
+      "#address-cells":
+        const: 1
+
+      "#size-cells":
+        const: 0
+
+    patternProperties:
+      "^led@[0-9a-f]$":
+        type: object
+        $ref: common.yaml#
+
+patternProperties:
+  "^led@[0-9a-f]$":
+    type: object
+    $ref: common.yaml#
+
+    properties:
+      reg: true
+
+    required:
+      - reg
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/leds/common.h>
+
+    led-controller {
+      compatible = "qcom,pmi8994-lpg";
+
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      qcom,power-source = <1>;
+
+      qcom,dtest = <0 0>,
+                   <0 0>,
+                   <0 0>,
+                   <4 1>;
+
+      led@1 {
+        reg = <1>;
+        color = <LED_COLOR_ID_GREEN>;
+        function = LED_FUNCTION_INDICATOR;
+        function-enumerator = <1>;
+      };
+
+      led@2 {
+        reg = <2>;
+        color = <LED_COLOR_ID_GREEN>;
+        function = LED_FUNCTION_INDICATOR;
+        function-enumerator = <0>;
+        default-state = "on";
+      };
+
+      led@3 {
+        reg = <3>;
+        color = <LED_COLOR_ID_GREEN>;
+        function = LED_FUNCTION_INDICATOR;
+        function-enumerator = <2>;
+      };
+
+      led@4 {
+        reg = <4>;
+        color = <LED_COLOR_ID_GREEN>;
+        function = LED_FUNCTION_INDICATOR;
+        function-enumerator = <3>;
+      };
+    };
+  - |
+    #include <dt-bindings/leds/common.h>
+
+    led-controller {
+      compatible = "qcom,pmi8994-lpg";
+
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      qcom,power-source = <1>;
+
+      multi-led {
+        color = <LED_COLOR_ID_RGB>;
+        function = LED_FUNCTION_STATUS;
+
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        led@1 {
+          reg = <1>;
+          color = <LED_COLOR_ID_RED>;
+        };
+
+        led@2 {
+          reg = <2>;
+          color = <LED_COLOR_ID_GREEN>;
+        };
+
+        led@3 {
+          reg = <3>;
+          color = <LED_COLOR_ID_BLUE>;
+        };
+      };
+    };
+  - |
+    pwm-controller {
+      compatible = "qcom,pm8916-pwm";
+      #pwm-cells = <2>;
+    };
+...
-- 
2.33.1


^ permalink raw reply related

* Re: [PATCH v10 2/2] leds: Add driver for Qualcomm LPG
From: Bjorn Andersson @ 2022-01-29  0:53 UTC (permalink / raw)
  To: Marijn Suijten
  Cc: Pavel Machek, Rob Herring, Andy Gross, Thierry Reding,
	Uwe Kleine-K?nig, Lee Jones, linux-leds, devicetree, linux-kernel,
	linux-arm-msm, linux-pwm, Yassine Oudjana, Luca Weiss,
	Subbaraman Narayanamurthy
In-Reply-To: <20211027212709.4ma5uzy5titmgzqv@SoMainline.org>

On Wed 27 Oct 16:27 CDT 2021, Marijn Suijten wrote:

> On 2021-10-27 23:19:30, Marijn Suijten wrote:
> > Hi Bjorn,
> > 
> > On 2021-10-22 10:25:35, Bjorn Andersson wrote:
> > > On Sat 09 Oct 21:39 PDT 2021, Bjorn Andersson wrote:
> > > 
> > > > The Light Pulse Generator (LPG) is a PWM-block found in a wide range of
> > > > PMICs from Qualcomm. These PMICs typically comes with 1-8 LPG instances,
> > > > with their output being routed to various other components, such as
> > > > current sinks or GPIOs.
> > > > 
> > > > Each LPG instance can operate on fixed parameters or based on a shared
> > > > lookup-table, altering the duty cycle over time. This provides the means
> > > > for hardware assisted transitions of LED brightness.
> > > > 
> > > > A typical use case for the fixed parameter mode is to drive a PWM
> > > > backlight control signal, the driver therefor allows each LPG instance
> > > > to be exposed to the kernel either through the LED framework or the PWM
> > > > framework.
> > > > 
> > > > A typical use case for the LED configuration is to drive RGB LEDs in
> > > > smartphones etc, for which the driver support multiple channels to be
> > > > ganged up to a MULTICOLOR LED. In this configuration the pattern
> > > > generators will be synchronized, to allow for multi-color patterns.
> > > > 
> > > > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > > > ---
> > > 
> > > Any feedback on this?
> > 
> > I asked in #linux-msm whether anything is wrong with the patterns,
> > since my Sony Discovery (sdm630 with a pm660l) blinks way quicker on a
> > pattern that's supposed to stay on for 1s and off for 1s:
> > 
> >     echo "0 1000 255 1000" > /sys/class/leds/rgb\:status/hw_pattern
> > 
> > It however seems to be broken in the same way on an older version now
> > (this might be v9 or v8) which I don't remember to be the case.  Can you
> > double-check if this is all working fine on your side?  If so, I'll have
> > to find some time to debug it on my end.
> > 
> > Thanks!
> > - Marijn
> 
> Another thing I just ran into: on both patch revisions the colors are
> flipped.  multi_index reports "red green glue", but the values written
> to multi_intensity correspond to "blue green red" instead.  Is it the
> same on your side?
> 

I booted one of my 8974 devices with RGB LED and the colors matches my
expectations. Can you confirm that your mapping in the DT node is
correct?

E.g. with pm8941 the mapping should be "backwards":

lpg {
    ...;
    rgb-led {
        color = <LED_COLOR_ID_RGB>;
        function = LED_FUNCTION_STATUS;

        #address-cells = <1>;
        #size-cells = <0>;

        led@1 {
            reg = <7>;
            color = <LED_COLOR_ID_RED>;
        };

        led@2 {
            reg = <6>;
            color = <LED_COLOR_ID_GREEN>;
        };

        led@3 {
            reg = <5>;
            color = <LED_COLOR_ID_BLUE>;
        };
};

Regards,
Bjorn

^ permalink raw reply

* Re: [PATCH v10 2/2] leds: Add driver for Qualcomm LPG
From: Bjorn Andersson @ 2022-01-29  0:50 UTC (permalink / raw)
  To: Marijn Suijten
  Cc: Pavel Machek, Rob Herring, Andy Gross, Thierry Reding,
	Uwe Kleine-K?nig, Lee Jones, linux-leds, devicetree, linux-kernel,
	linux-arm-msm, linux-pwm, Yassine Oudjana, Luca Weiss,
	Subbaraman Narayanamurthy
In-Reply-To: <20211027211928.tjybwy2lokj6eoun@SoMainline.org>

On Wed 27 Oct 16:19 CDT 2021, Marijn Suijten wrote:

> Hi Bjorn,
> 
> On 2021-10-22 10:25:35, Bjorn Andersson wrote:
> > On Sat 09 Oct 21:39 PDT 2021, Bjorn Andersson wrote:
> > 
> > > The Light Pulse Generator (LPG) is a PWM-block found in a wide range of
> > > PMICs from Qualcomm. These PMICs typically comes with 1-8 LPG instances,
> > > with their output being routed to various other components, such as
> > > current sinks or GPIOs.
> > > 
> > > Each LPG instance can operate on fixed parameters or based on a shared
> > > lookup-table, altering the duty cycle over time. This provides the means
> > > for hardware assisted transitions of LED brightness.
> > > 
> > > A typical use case for the fixed parameter mode is to drive a PWM
> > > backlight control signal, the driver therefor allows each LPG instance
> > > to be exposed to the kernel either through the LED framework or the PWM
> > > framework.
> > > 
> > > A typical use case for the LED configuration is to drive RGB LEDs in
> > > smartphones etc, for which the driver support multiple channels to be
> > > ganged up to a MULTICOLOR LED. In this configuration the pattern
> > > generators will be synchronized, to allow for multi-color patterns.
> > > 
> > > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > > ---
> > 
> > Any feedback on this?
> 
> I asked in #linux-msm whether anything is wrong with the patterns,
> since my Sony Discovery (sdm630 with a pm660l) blinks way quicker on a
> pattern that's supposed to stay on for 1s and off for 1s:
> 
>     echo "0 1000 255 1000" > /sys/class/leds/rgb\:status/hw_pattern
> 
> It however seems to be broken in the same way on an older version now
> (this might be v9 or v8) which I don't remember to be the case.  Can you
> double-check if this is all working fine on your side?  If so, I'll have
> to find some time to debug it on my end.
> 

I had missed the fact that LPG_RAMP_DURATION_REG is two registers for
msg and lsb, for a total of 9 bits of duration. So what you saw was
probably ticking at 232ms.

Note though that the pattern uses the last time as "high pause", so I
expect that you should have seen 232 ms of off, followed by 464ms of
light.

I've fixed this for v11, both rejecting invalid input and writing out
all 9 bits.

Thanks for spotting this!
Bjorn

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox