Devicetree
 help / color / mirror / Atom feed
* RE: [PATCH v1 2/3] dt-bindings: phy: phy-imx8-pcie: Add binding for i.MX8Q HSIO SerDes PHY
From: Hongxing Zhu @ 2024-04-01  2:12 UTC (permalink / raw)
  To: Frank Li
  Cc: vkoul@kernel.org, kishon@kernel.org, robh+dt@kernel.org,
	krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org,
	linux-phy@lists.infradead.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, kernel@pengutronix.de, dl-linux-imx
In-Reply-To: <ZgbOTgtdEBJyg/By@lizhi-Precision-Tower-5810>

> -----Original Message-----
> From: Frank Li <frank.li@nxp.com>
> Sent: 2024年3月29日 22:21
> To: Hongxing Zhu <hongxing.zhu@nxp.com>
> Cc: vkoul@kernel.org; kishon@kernel.org; robh+dt@kernel.org;
> krzysztof.kozlowski+dt@linaro.org; conor+dt@kernel.org;
> linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v1 2/3] dt-bindings: phy: phy-imx8-pcie: Add binding for
> i.MX8Q HSIO SerDes PHY
> 
> On Fri, Mar 29, 2024 at 04:09:49PM +0800, Richard Zhu wrote:
> > Add binding for controller ID and HSIO configuration setting of the
> > i.MX8Q HSIO SerDes PHY.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > ---
> >  include/dt-bindings/phy/phy-imx8-pcie.h | 26
> > +++++++++++++++++++++++++
> >  1 file changed, 26 insertions(+)
> 
> This one should be first patch. (1/3).
> 
> After fix small improve
> 
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> 
Thanks for your review.
> >
> > diff --git a/include/dt-bindings/phy/phy-imx8-pcie.h
> > b/include/dt-bindings/phy/phy-imx8-pcie.h
> > index 8bbe2d6538d8..5cd5580879fa 100644
> > --- a/include/dt-bindings/phy/phy-imx8-pcie.h
> > +++ b/include/dt-bindings/phy/phy-imx8-pcie.h
> > @@ -11,4 +11,30 @@
> >  #define IMX8_PCIE_REFCLK_PAD_INPUT	1
> >  #define IMX8_PCIE_REFCLK_PAD_OUTPUT	2
> >
> > +/*
> > + * i.MX8QM HSIO subsystem has three lane PHYs and three controllers:
> > + * PCIEA(2 lanes capapble PCIe controller), PCIEB (only support one
> > + * lane) and SATA.
> 
> Suggest add empty line between segment.
> 
Okay, would be added later. Thanks.
Best Regards
Richard Zhu
> > + * In the different use cases. PCIEA can be binded to PHY lane0,
> > +lane1
> > + * or Lane0 and lane1. PCIEB can be binded to lane1 or lane2 PHY.
> > +SATA
> > + * can only be binded to last lane2 PHY.
> > + * Define i.MX8Q HSIO controller ID here to specify the controller
> > + * binded to the PHY.
> > + * Meanwhile, i.MX8QXP HSIO subsystem has one lane PHY and PCIEB(only
> > + * support one lane) controller.
> > + */
> > +#define IMX8Q_HSIO_PCIEA_ID	0
> > +#define IMX8Q_HSIO_PCIEB_ID	1
> > +#define IMX8Q_HSIO_SATA_ID	2
> > +
> > +/*
> > + * On i.MX8QM, PCIEA is mandatory required if the HSIO is enabled.
> > + * Define configurations beside PCIEA is enabled.
> > + * On i.MX8QXP, HSIO module only has PCIEB and one lane PHY.
> > + * The "IMX8Q_HSIO_CFG_PCIEB" can be used on i.MX8QXP platforms.
> > + */
> > +#define IMX8Q_HSIO_CFG_SATA		1
> > +#define IMX8Q_HSIO_CFG_PCIEB		2
> > +#define IMX8Q_HSIO_CFG_PCIEBSATA	3
> > +
> >  #endif /* _DT_BINDINGS_IMX8_PCIE_H */
> > --
> > 2.37.1
> >

^ permalink raw reply

* RE: [v1 0/3] Add i.MX8Q HSIO PHY driver support
From: Hongxing Zhu @ 2024-04-01  2:13 UTC (permalink / raw)
  To: Krzysztof Kozlowski, vkoul@kernel.org, kishon@kernel.org,
	robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org,
	conor+dt@kernel.org, Frank Li
  Cc: linux-phy@lists.infradead.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, kernel@pengutronix.de, dl-linux-imx
In-Reply-To: <0b5997e9-97b3-4863-87d0-b70e9d051d42@linaro.org>

> -----Original Message-----
> From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Sent: 2024年3月30日 19:55
> To: Hongxing Zhu <hongxing.zhu@nxp.com>; vkoul@kernel.org;
> kishon@kernel.org; robh+dt@kernel.org; krzysztof.kozlowski+dt@linaro.org;
> conor+dt@kernel.org; Frank Li <frank.li@nxp.com>
> Cc: linux-phy@lists.infradead.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>
> Subject: Re: [v1 0/3] Add i.MX8Q HSIO PHY driver support
> 
> On 29/03/2024 09:09, Richard Zhu wrote:
> > v1 changes:
> > - Rebase to the 6.9-rc1, and constify of_phandle_args in xlate.
> > No other changes.
> >
> 
> I found some RFC of this... confusing so:
> 1. v1 is the first version. If you send RFC, that RFC is v1, so anything newer is v2 or
> whatever.
> 
> 2. One patchset per 24h. Give people chance to actually review your code.
Okay, got that.
Thanks for your comments and suggests.

Best Regards
Richard Zhu
> 
> Best regards,
> Krzysztof


^ permalink raw reply

* Re: [PATCH v4 2/2] arm64: dts: qcom: sm8650-qrd: enable GPU
From: Jun Nie @ 2024-04-01  2:23 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20240318-topic-sm8650-gpu-v4-2-206eb0d31694@linaro.org>

Neil Armstrong <neil.armstrong@linaro.org> 于2024年3月18日周一 18:12写道:
>
> Add path of the GPU firmware for the SM8650-QRD board
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  arch/arm64/boot/dts/qcom/sm8650-qrd.dts | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
Reviewed-by: Jun Nie <jun.nie@linaro.org>

^ permalink raw reply

* Re: [PATCH v4 1/2] arm64: dts: qcom: sm8650: add GPU nodes
From: Jun Nie @ 2024-04-01  2:25 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Neil Armstrong, Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <3e15fd38-13d1-4b99-aaf0-f422b2dbab59@linaro.org>

Konrad Dybcio <konrad.dybcio@linaro.org> 于2024年3月27日周三 08:24写道:
>
> On 18.03.2024 11:09 AM, Neil Armstrong wrote:
> > Add GPU nodes for the SM8650 platform.
> >
> > Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> > ---
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
>
Acked-by: Jun Nie <jun.nie@linaro.org>

^ permalink raw reply

* [PATCH v3 1/7] dt-bindings: PCI: rcar-gen4-pci-host: Add R-Car V4H compatible
From: Yoshihiro Shimoda @ 2024-04-01  2:39 UTC (permalink / raw)
  To: lpieralisi, kw, robh, bhelgaas, krzysztof.kozlowski+dt, conor+dt,
	jingoohan1, mani
  Cc: marek.vasut+renesas, linux-pci, devicetree, linux-renesas-soc,
	Yoshihiro Shimoda, Conor Dooley, Geert Uytterhoeven
In-Reply-To: <20240401023942.134704-1-yoshihiro.shimoda.uh@renesas.com>

Document bindings for R-Car V4H (R8A779G0) PCIe host module.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml
index ffb34339b637..955c664f1fbb 100644
--- a/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml
+++ b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml
@@ -16,7 +16,9 @@ allOf:
 properties:
   compatible:
     items:
-      - const: renesas,r8a779f0-pcie   # R-Car S4-8
+      - enum:
+          - renesas,r8a779f0-pcie      # R-Car S4-8
+          - renesas,r8a779g0-pcie      # R-Car V4H
       - const: renesas,rcar-gen4-pcie  # R-Car Gen4
 
   reg:
-- 
2.25.1


^ permalink raw reply related

* [PATCH v3 0/7] PCI: dwc: rcar-gen4: Add R-Car V4H support
From: Yoshihiro Shimoda @ 2024-04-01  2:39 UTC (permalink / raw)
  To: lpieralisi, kw, robh, bhelgaas, krzysztof.kozlowski+dt, conor+dt,
	jingoohan1, mani
  Cc: marek.vasut+renesas, linux-pci, devicetree, linux-renesas-soc,
	Yoshihiro Shimoda

The pcie-rcar-gen4 driver can reuse other R-Car Gen4 support like
r8a779g0 (R-Car V4H) and r8a779h0 (R-Car V4M). However, some
initializing settings differ between R-Car S4-8 (r8a779f0) and
others. The R-Car S4-8 will be minority about the setting way. So,
R-Car V4H will be majority and this is generic initialization way
as "renesas,rcar-gen4-pcie{-ep}" compatible. For now, I tested
both R-Car S4-8 and R-Car V4H on this driver. I'll support one more
other SoC (R-Car V4M) in the future.

Changes from v2:
https://lore.kernel.org/linux-pci/20240326024540.2336155-1-yoshihiro.shimoda.uh@renesas.com/
- Add a new patch which just add a platdata in patch 4/7.
- Modify the subjects in patch [56]/7.
- Modify the description and code about Bjorn's comment in patch [56]/7.
- Add missing MODULE_FIRMWARE(9 in patch 6/7.
- Document a policy aboud adding pci_device_id instead of adding r8a779g0's id
  in patch 7/7.

Changes from v1:
https://lore.kernel.org/linux-pci/20240229120719.2553638-1-yoshihiro.shimoda.uh@renesas.com/
- Based on v6.9-rc1.
- Add Acked-by and/or Reviewed-by in patch [126/6].

Yoshihiro Shimoda (7):
  dt-bindings: PCI: rcar-gen4-pci-host: Add R-Car V4H compatible
  dt-bindings: PCI: rcar-gen4-pci-ep: Add R-Car V4H compatible
  PCI: dwc: Add PCIE_PORT_{FORCE,LANE_SKEW} macros
  PCI: dwc: rcar-gen4: Add rcar_gen4_pcie_platdata
  PCI: dwc: rcar-gen4: Add .ltssm_enable() for other SoC support
  PCI: dwc: rcar-gen4: Add support for r8a779g0
  misc: pci_endpoint_test: Document a policy about adding pci_device_id

 .../bindings/pci/rcar-gen4-pci-ep.yaml        |   4 +-
 .../bindings/pci/rcar-gen4-pci-host.yaml      |   4 +-
 drivers/misc/pci_endpoint_test.c              |   1 +
 drivers/pci/controller/dwc/pcie-designware.h  |   6 +
 drivers/pci/controller/dwc/pcie-rcar-gen4.c   | 272 +++++++++++++++++-
 5 files changed, 270 insertions(+), 17 deletions(-)

-- 
2.25.1


^ permalink raw reply

* [PATCH v3 3/7] PCI: dwc: Add PCIE_PORT_{FORCE,LANE_SKEW} macros
From: Yoshihiro Shimoda @ 2024-04-01  2:39 UTC (permalink / raw)
  To: lpieralisi, kw, robh, bhelgaas, krzysztof.kozlowski+dt, conor+dt,
	jingoohan1, mani
  Cc: marek.vasut+renesas, linux-pci, devicetree, linux-renesas-soc,
	Yoshihiro Shimoda
In-Reply-To: <20240401023942.134704-1-yoshihiro.shimoda.uh@renesas.com>

R-Car Gen4 PCIe controller needs to use the Synopsys-specific PCIe
configuration registers. So, add the macros.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 drivers/pci/controller/dwc/pcie-designware.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 26dae4837462..aa4db6eaf02a 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -71,6 +71,9 @@
 #define LINK_WAIT_IATU			9
 
 /* Synopsys-specific PCIe configuration registers */
+#define PCIE_PORT_FORCE			0x708
+#define PORT_FORCE_DO_DESKEW_FOR_SRIS	BIT(23)
+
 #define PCIE_PORT_AFR			0x70C
 #define PORT_AFR_N_FTS_MASK		GENMASK(15, 8)
 #define PORT_AFR_N_FTS(n)		FIELD_PREP(PORT_AFR_N_FTS_MASK, n)
@@ -92,6 +95,9 @@
 #define PORT_LINK_MODE_4_LANES		PORT_LINK_MODE(0x7)
 #define PORT_LINK_MODE_8_LANES		PORT_LINK_MODE(0xf)
 
+#define PCIE_PORT_LANE_SKEW		0x714
+#define PORT_LANE_SKEW_INSERT_MASK	GENMASK(23, 0)
+
 #define PCIE_PORT_DEBUG0		0x728
 #define PORT_LOGIC_LTSSM_STATE_MASK	0x1f
 #define PORT_LOGIC_LTSSM_STATE_L0	0x11
-- 
2.25.1


^ permalink raw reply related

* [PATCH v3 2/7] dt-bindings: PCI: rcar-gen4-pci-ep: Add R-Car V4H compatible
From: Yoshihiro Shimoda @ 2024-04-01  2:39 UTC (permalink / raw)
  To: lpieralisi, kw, robh, bhelgaas, krzysztof.kozlowski+dt, conor+dt,
	jingoohan1, mani
  Cc: marek.vasut+renesas, linux-pci, devicetree, linux-renesas-soc,
	Yoshihiro Shimoda, Conor Dooley, Geert Uytterhoeven
In-Reply-To: <20240401023942.134704-1-yoshihiro.shimoda.uh@renesas.com>

Document bindings for R-Car V4H (R8A779G0) PCIe endpoint module.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml
index fe38f62da066..91b81ac75592 100644
--- a/Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-ep.yaml
@@ -16,7 +16,9 @@ allOf:
 properties:
   compatible:
     items:
-      - const: renesas,r8a779f0-pcie-ep   # R-Car S4-8
+      - enum:
+          - renesas,r8a779f0-pcie-ep      # R-Car S4-8
+          - renesas,r8a779g0-pcie-ep      # R-Car V4H
       - const: renesas,rcar-gen4-pcie-ep  # R-Car Gen4
 
   reg:
-- 
2.25.1


^ permalink raw reply related

* [PATCH v3 5/7] PCI: dwc: rcar-gen4: Add .ltssm_enable() for other SoC support
From: Yoshihiro Shimoda @ 2024-04-01  2:39 UTC (permalink / raw)
  To: lpieralisi, kw, robh, bhelgaas, krzysztof.kozlowski+dt, conor+dt,
	jingoohan1, mani
  Cc: marek.vasut+renesas, linux-pci, devicetree, linux-renesas-soc,
	Yoshihiro Shimoda
In-Reply-To: <20240401023942.134704-1-yoshihiro.shimoda.uh@renesas.com>

This driver can reuse other R-Car Gen4 SoCs support like r8a779g0 and
r8a779h0. However, r8a779g0 and r8a779h0 require other initializing
settings that differ than r8a779f0. So, add a new function pointer
.ltssm_enable() for it. No behavior changes.

After applied this patch, probing SoCs by rcar_gen4_pcie_of_match[]
will be changed like below:

- r8a779f0 as "renesas,r8a779f0-pcie" and "renesas,r8a779f0-pcie-ep"

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 drivers/pci/controller/dwc/pcie-rcar-gen4.c | 41 ++++++++++++++++++---
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index da2821d6efce..e760bcd30c4e 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -48,7 +48,9 @@
 #define RCAR_GEN4_PCIE_EP_FUNC_DBI_OFFSET	0x1000
 #define RCAR_GEN4_PCIE_EP_FUNC_DBI2_OFFSET	0x800
 
+struct rcar_gen4_pcie;
 struct rcar_gen4_pcie_platdata {
+	int (*ltssm_enable)(struct rcar_gen4_pcie *rcar);
 	enum dw_pcie_device_mode mode;
 };
 
@@ -61,8 +63,8 @@ struct rcar_gen4_pcie {
 #define to_rcar_gen4_pcie(_dw)	container_of(_dw, struct rcar_gen4_pcie, dw)
 
 /* Common */
-static void rcar_gen4_pcie_ltssm_enable(struct rcar_gen4_pcie *rcar,
-					bool enable)
+static void rcar_gen4_pcie_ltssm_control(struct rcar_gen4_pcie *rcar,
+					 bool enable)
 {
 	u32 val;
 
@@ -127,9 +129,13 @@ static int rcar_gen4_pcie_speed_change(struct dw_pcie *dw)
 static int rcar_gen4_pcie_start_link(struct dw_pcie *dw)
 {
 	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
-	int i, changes;
+	int i, changes, ret;
 
-	rcar_gen4_pcie_ltssm_enable(rcar, true);
+	if (rcar->platdata->ltssm_enable) {
+		ret = rcar->platdata->ltssm_enable(rcar);
+		if (ret)
+			return ret;
+	}
 
 	/*
 	 * Require direct speed change with retrying here if the link_gen is
@@ -157,7 +163,7 @@ static void rcar_gen4_pcie_stop_link(struct dw_pcie *dw)
 {
 	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
 
-	rcar_gen4_pcie_ltssm_enable(rcar, false);
+	rcar_gen4_pcie_ltssm_control(rcar, false);
 }
 
 static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
@@ -504,6 +510,23 @@ static void rcar_gen4_pcie_remove(struct platform_device *pdev)
 	rcar_gen4_pcie_unprepare(rcar);
 }
 
+static int r8a779f0_pcie_ltssm_enable(struct rcar_gen4_pcie *rcar)
+{
+	rcar_gen4_pcie_ltssm_control(rcar, true);
+
+	return 0;
+}
+
+static struct rcar_gen4_pcie_platdata platdata_r8a779f0_pcie = {
+	.ltssm_enable = r8a779f0_pcie_ltssm_enable,
+	.mode = DW_PCIE_RC_TYPE,
+};
+
+static struct rcar_gen4_pcie_platdata platdata_r8a779f0_pcie_ep = {
+	.ltssm_enable = r8a779f0_pcie_ltssm_enable,
+	.mode = DW_PCIE_EP_TYPE,
+};
+
 static struct rcar_gen4_pcie_platdata platdata_rcar_gen4_pcie = {
 	.mode = DW_PCIE_RC_TYPE,
 };
@@ -513,6 +536,14 @@ static struct rcar_gen4_pcie_platdata platdata_rcar_gen4_pcie_ep = {
 };
 
 static const struct of_device_id rcar_gen4_pcie_of_match[] = {
+	{
+		.compatible = "renesas,r8a779f0-pcie",
+		.data = &platdata_r8a779f0_pcie,
+	},
+	{
+		.compatible = "renesas,r8a779f04-pcie-ep",
+		.data = &platdata_r8a779f0_pcie_ep,
+	},
 	{
 		.compatible = "renesas,rcar-gen4-pcie",
 		.data = &platdata_rcar_gen4_pcie,
-- 
2.25.1


^ permalink raw reply related

* [PATCH v3 4/7] PCI: dwc: rcar-gen4: Add rcar_gen4_pcie_platdata
From: Yoshihiro Shimoda @ 2024-04-01  2:39 UTC (permalink / raw)
  To: lpieralisi, kw, robh, bhelgaas, krzysztof.kozlowski+dt, conor+dt,
	jingoohan1, mani
  Cc: marek.vasut+renesas, linux-pci, devicetree, linux-renesas-soc,
	Yoshihiro Shimoda
In-Reply-To: <20240401023942.134704-1-yoshihiro.shimoda.uh@renesas.com>

This driver supports r8a779f0 now. In the future, add support for
r8a779g0 and r8a779h0. To support these new SoCs, need other
initializing settings. So, at first, add rcar_gen4_pcie_platdata
and have a member with mode. No behavior changes.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 drivers/pci/controller/dwc/pcie-rcar-gen4.c | 30 ++++++++++++++-------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index 0be760ed420b..da2821d6efce 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -48,11 +48,15 @@
 #define RCAR_GEN4_PCIE_EP_FUNC_DBI_OFFSET	0x1000
 #define RCAR_GEN4_PCIE_EP_FUNC_DBI2_OFFSET	0x800
 
+struct rcar_gen4_pcie_platdata {
+	enum dw_pcie_device_mode mode;
+};
+
 struct rcar_gen4_pcie {
 	struct dw_pcie dw;
 	void __iomem *base;
 	struct platform_device *pdev;
-	enum dw_pcie_device_mode mode;
+	const struct rcar_gen4_pcie_platdata *platdata;
 };
 #define to_rcar_gen4_pcie(_dw)	container_of(_dw, struct rcar_gen4_pcie, dw)
 
@@ -137,7 +141,7 @@ static int rcar_gen4_pcie_start_link(struct dw_pcie *dw)
 	 * Since dw_pcie_setup_rc() sets it once, PCIe Gen2 will be trained.
 	 * So, this needs remaining times for up to PCIe Gen4 if RC mode.
 	 */
-	if (changes && rcar->mode == DW_PCIE_RC_TYPE)
+	if (changes && rcar->platdata->mode == DW_PCIE_RC_TYPE)
 		changes--;
 
 	for (i = 0; i < changes; i++) {
@@ -172,9 +176,9 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
 		reset_control_assert(dw->core_rsts[DW_PCIE_PWR_RST].rstc);
 
 	val = readl(rcar->base + PCIEMSR0);
-	if (rcar->mode == DW_PCIE_RC_TYPE) {
+	if (rcar->platdata->mode == DW_PCIE_RC_TYPE) {
 		val |= DEVICE_TYPE_RC;
-	} else if (rcar->mode == DW_PCIE_EP_TYPE) {
+	} else if (rcar->platdata->mode == DW_PCIE_EP_TYPE) {
 		val |= DEVICE_TYPE_EP;
 	} else {
 		ret = -EINVAL;
@@ -437,9 +441,9 @@ static void rcar_gen4_remove_dw_pcie_ep(struct rcar_gen4_pcie *rcar)
 /* Common */
 static int rcar_gen4_add_dw_pcie(struct rcar_gen4_pcie *rcar)
 {
-	rcar->mode = (uintptr_t)of_device_get_match_data(&rcar->pdev->dev);
+	rcar->platdata = of_device_get_match_data(&rcar->pdev->dev);
 
-	switch (rcar->mode) {
+	switch (rcar->platdata->mode) {
 	case DW_PCIE_RC_TYPE:
 		return rcar_gen4_add_dw_pcie_rp(rcar);
 	case DW_PCIE_EP_TYPE:
@@ -480,7 +484,7 @@ static int rcar_gen4_pcie_probe(struct platform_device *pdev)
 
 static void rcar_gen4_remove_dw_pcie(struct rcar_gen4_pcie *rcar)
 {
-	switch (rcar->mode) {
+	switch (rcar->platdata->mode) {
 	case DW_PCIE_RC_TYPE:
 		rcar_gen4_remove_dw_pcie_rp(rcar);
 		break;
@@ -500,14 +504,22 @@ static void rcar_gen4_pcie_remove(struct platform_device *pdev)
 	rcar_gen4_pcie_unprepare(rcar);
 }
 
+static struct rcar_gen4_pcie_platdata platdata_rcar_gen4_pcie = {
+	.mode = DW_PCIE_RC_TYPE,
+};
+
+static struct rcar_gen4_pcie_platdata platdata_rcar_gen4_pcie_ep = {
+	.mode = DW_PCIE_EP_TYPE,
+};
+
 static const struct of_device_id rcar_gen4_pcie_of_match[] = {
 	{
 		.compatible = "renesas,rcar-gen4-pcie",
-		.data = (void *)DW_PCIE_RC_TYPE,
+		.data = &platdata_rcar_gen4_pcie,
 	},
 	{
 		.compatible = "renesas,rcar-gen4-pcie-ep",
-		.data = (void *)DW_PCIE_EP_TYPE,
+		.data = &platdata_rcar_gen4_pcie_ep,
 	},
 	{},
 };
-- 
2.25.1


^ permalink raw reply related

* [PATCH v3 7/7] misc: pci_endpoint_test: Document a policy about adding pci_device_id
From: Yoshihiro Shimoda @ 2024-04-01  2:39 UTC (permalink / raw)
  To: lpieralisi, kw, robh, bhelgaas, krzysztof.kozlowski+dt, conor+dt,
	jingoohan1, mani
  Cc: marek.vasut+renesas, linux-pci, devicetree, linux-renesas-soc,
	Yoshihiro Shimoda, Frank Li
In-Reply-To: <20240401023942.134704-1-yoshihiro.shimoda.uh@renesas.com>

To avoid becoming struct pci_device_id pci_endpoint_test_tbl longer
and longer, document a policy. For example, if PCIe endpoint controller
can configure vendor id and/or product id, you can reuse one of
existing entries to test.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
Cc: Frank Li <Frank.li@nxp.com>
---
 drivers/misc/pci_endpoint_test.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index c38a6083f0a7..3c8a0afad91d 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -980,6 +980,7 @@ static const struct pci_endpoint_test_data j721e_data = {
 	.irq_type = IRQ_TYPE_MSI,
 };
 
+/* Don't need to add a new entry if you can use existing entry to test */
 static const struct pci_device_id pci_endpoint_test_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x),
 	  .driver_data = (kernel_ulong_t)&default_data,
-- 
2.25.1


^ permalink raw reply related

* [PATCH v3 6/7] PCI: dwc: rcar-gen4: Add support for r8a779g0
From: Yoshihiro Shimoda @ 2024-04-01  2:39 UTC (permalink / raw)
  To: lpieralisi, kw, robh, bhelgaas, krzysztof.kozlowski+dt, conor+dt,
	jingoohan1, mani
  Cc: marek.vasut+renesas, linux-pci, devicetree, linux-renesas-soc,
	Yoshihiro Shimoda
In-Reply-To: <20240401023942.134704-1-yoshihiro.shimoda.uh@renesas.com>

This driver previously supported r8a779f0 (R-Car S4-8). Add support
for r8a779g0 (R-Car V4H).

To support r8a779g0, it requires specific firmware.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 drivers/pci/controller/dwc/pcie-rcar-gen4.c | 201 +++++++++++++++++++-
 1 file changed, 200 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index e760bcd30c4e..fdd7a41fae33 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -5,8 +5,10 @@
  */
 
 #include <linux/delay.h>
+#include <linux/firmware.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/pci.h>
@@ -20,9 +22,10 @@
 /* Renesas-specific */
 /* PCIe Mode Setting Register 0 */
 #define PCIEMSR0		0x0000
-#define BIFUR_MOD_SET_ON	BIT(0)
+#define APP_SRIS_MODE		BIT(6)
 #define DEVICE_TYPE_EP		0
 #define DEVICE_TYPE_RC		BIT(4)
+#define BIFUR_MOD_SET_ON	BIT(0)
 
 /* PCIe Interrupt Status 0 */
 #define PCIEINTSTS0		0x0084
@@ -37,19 +40,47 @@
 #define PCIEDMAINTSTSEN		0x0314
 #define PCIEDMAINTSTSEN_INIT	GENMASK(15, 0)
 
+/* Port Logic Registers 89 */
+#define PRTLGC89		0x0b70
+
+/* Port Logic Registers 90 */
+#define PRTLGC90		0x0b74
+
 /* PCIe Reset Control Register 1 */
 #define PCIERSTCTRL1		0x0014
 #define APP_HOLD_PHY_RST	BIT(16)
 #define APP_LTSSM_ENABLE	BIT(0)
 
+/* PCIe Power Management Control */
+#define PCIEPWRMNGCTRL		0x0070
+#define APP_CLK_REQ_N		BIT(11)
+#define APP_CLK_PM_EN		BIT(10)
+
+/*
+ * The R-Car Gen4 documents don't describe the PHY registers' name.
+ * But, the initialization procedure describes these offsets. So,
+ * this driver makes up own #defines for the offsets.
+ */
+#define RCAR_GEN4_PCIE_PHY_0f8	0x0f8
+#define RCAR_GEN4_PCIE_PHY_148	0x148
+#define RCAR_GEN4_PCIE_PHY_1d4	0x1d4
+#define RCAR_GEN4_PCIE_PHY_514	0x514
+#define RCAR_GEN4_PCIE_PHY_700	0x700
+
 #define RCAR_NUM_SPEED_CHANGE_RETRIES	10
 #define RCAR_MAX_LINK_SPEED		4
 
 #define RCAR_GEN4_PCIE_EP_FUNC_DBI_OFFSET	0x1000
 #define RCAR_GEN4_PCIE_EP_FUNC_DBI2_OFFSET	0x800
 
+#define RCAR_GEN4_PCIE_FIRMWARE_NAME		"rcar_gen4_pcie.bin"
+#define RCAR_GEN4_PCIE_FIRMWARE_BASE_ADDR	0xc000
+
+MODULE_FIRMWARE(RCAR_GEN4_PCIE_FIRMWARE_NAME);
+
 struct rcar_gen4_pcie;
 struct rcar_gen4_pcie_platdata {
+	void (*additional_common_init)(struct rcar_gen4_pcie *rcar);
 	int (*ltssm_enable)(struct rcar_gen4_pcie *rcar);
 	enum dw_pcie_device_mode mode;
 };
@@ -57,12 +88,144 @@ struct rcar_gen4_pcie_platdata {
 struct rcar_gen4_pcie {
 	struct dw_pcie dw;
 	void __iomem *base;
+	void __iomem *phy_base;
 	struct platform_device *pdev;
 	const struct rcar_gen4_pcie_platdata *platdata;
 };
 #define to_rcar_gen4_pcie(_dw)	container_of(_dw, struct rcar_gen4_pcie, dw)
 
 /* Common */
+static void rcar_gen4_pcie_phy_reg_update_bits(struct rcar_gen4_pcie *rcar,
+					       u32 offset, u32 mask, u32 val)
+{
+	u32 tmp;
+
+	tmp = readl(rcar->phy_base + offset);
+	tmp &= ~mask;
+	tmp |= val;
+	writel(tmp, rcar->phy_base + offset);
+}
+
+static int rcar_gen4_pcie_reg_check_bit(struct rcar_gen4_pcie *rcar,
+					u32 offset, u32 mask)
+{
+	struct dw_pcie *dw = &rcar->dw;
+
+	if (dw_pcie_readl_dbi(dw, offset) & mask)
+		return -EAGAIN;
+
+	return 0;
+}
+
+static int rcar_gen4_pcie_update_phy_firmware(struct rcar_gen4_pcie *rcar)
+{
+	const u32 check_addr[] = { 0x00101018, 0x00101118, 0x00101021, 0x00101121};
+	struct dw_pcie *dw = &rcar->dw;
+	const struct firmware *fw;
+	unsigned int i, timeout;
+	u32 data;
+	int ret;
+
+	ret = request_firmware(&fw, RCAR_GEN4_PCIE_FIRMWARE_NAME, dw->dev);
+	if (ret) {
+		dev_err(dw->dev, "%s: Requesting firmware failed\n", __func__);
+		return ret;
+	}
+
+	for (i = 0; i < (fw->size / 2); i++) {
+		data = fw->data[i * 2] | fw->data[(i * 2) + 1] << 8;
+		timeout = 100;
+retry_data:
+		dw_pcie_writel_dbi(dw, PRTLGC89, RCAR_GEN4_PCIE_FIRMWARE_BASE_ADDR + i);
+		dw_pcie_writel_dbi(dw, PRTLGC90, data);
+		if (rcar_gen4_pcie_reg_check_bit(rcar, PRTLGC89, BIT(30)) < 0) {
+			if (!(--timeout)) {
+				ret = -ETIMEDOUT;
+				goto exit;
+			}
+			usleep_range(100, 200);
+			goto retry_data;
+		}
+	}
+
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_0f8, BIT(17), BIT(17));
+
+	for (i = 0; i < ARRAY_SIZE(check_addr); i++) {
+		timeout = 100;
+retry_check:
+		dw_pcie_writel_dbi(dw, PRTLGC89, check_addr[i]);
+		ret = rcar_gen4_pcie_reg_check_bit(rcar, PRTLGC89, BIT(30));
+		ret |= rcar_gen4_pcie_reg_check_bit(rcar, PRTLGC90, BIT(0));
+		if (ret < 0) {
+			if (!(--timeout)) {
+				ret = -ETIMEDOUT;
+				goto exit;
+			}
+			usleep_range(100, 200);
+			goto retry_check;
+		}
+	}
+
+	ret = 0;
+exit:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static int rcar_gen4_pcie_enable_phy(struct rcar_gen4_pcie *rcar)
+{
+	struct dw_pcie *dw = &rcar->dw;
+	u32 val;
+	int ret;
+
+	val = dw_pcie_readl_dbi(dw, PCIE_PORT_FORCE);
+	val |= PORT_FORCE_DO_DESKEW_FOR_SRIS;
+	dw_pcie_writel_dbi(dw, PCIE_PORT_FORCE, val);
+
+	val = readl(rcar->base + PCIEMSR0);
+	val |= APP_SRIS_MODE;
+	writel(val, rcar->base + PCIEMSR0);
+
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_700, BIT(28), 0);
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_700, BIT(20), 0);
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_700, BIT(12), 0);
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_700, BIT(4), 0);
+
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_148,
+					   GENMASK(23, 22), BIT(22));
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_148,
+					   GENMASK(18, 16), GENMASK(17, 16));
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_148,
+					   GENMASK(7, 6), BIT(6));
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_148,
+					   GENMASK(2, 0), GENMASK(11, 0));
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_1d4,
+					   GENMASK(16, 15), GENMASK(16, 15));
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_514, BIT(26), BIT(26));
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_0f8, BIT(16), 0);
+	rcar_gen4_pcie_phy_reg_update_bits(rcar, RCAR_GEN4_PCIE_PHY_0f8, BIT(19), BIT(19));
+
+	val = readl(rcar->base + PCIERSTCTRL1);
+	val &= ~APP_HOLD_PHY_RST;
+	writel(val, rcar->base + PCIERSTCTRL1);
+
+	ret = readl_poll_timeout(rcar->phy_base + RCAR_GEN4_PCIE_PHY_0f8, val,
+				 !(val & BIT(18)), 100, 10000);
+	if (ret < 0)
+		return ret;
+
+	ret = rcar_gen4_pcie_update_phy_firmware(rcar);
+	if (ret)
+		return ret;
+
+	val = readl(rcar->base + PCIERSTCTRL1);
+	val |= APP_LTSSM_ENABLE;
+	writel(val, rcar->base + PCIERSTCTRL1);
+
+	return 0;
+}
+
 static void rcar_gen4_pcie_ltssm_control(struct rcar_gen4_pcie *rcar,
 					 bool enable)
 {
@@ -200,6 +363,9 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
 	if (ret)
 		goto err_unprepare;
 
+	if (rcar->platdata->additional_common_init)
+		rcar->platdata->additional_common_init(rcar);
+
 	return 0;
 
 err_unprepare:
@@ -241,6 +407,10 @@ static void rcar_gen4_pcie_unprepare(struct rcar_gen4_pcie *rcar)
 
 static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
 {
+	rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
+	if (IS_ERR(rcar->phy_base))
+		return PTR_ERR(rcar->base);
+
 	/* Renesas-specific registers */
 	rcar->base = devm_platform_ioremap_resource_byname(rcar->pdev, "app");
 
@@ -517,6 +687,31 @@ static int r8a779f0_pcie_ltssm_enable(struct rcar_gen4_pcie *rcar)
 	return 0;
 }
 
+static void rcar_gen4_pcie_additional_common_init(struct rcar_gen4_pcie *rcar)
+{
+	struct dw_pcie *dw = &rcar->dw;
+	u32 val;
+
+	/*
+	 * The SoC manual said the register setting is required. Otherwise,
+	 * linkup failed.
+	 */
+	val = dw_pcie_readl_dbi(dw, PCIE_PORT_LANE_SKEW);
+	val &= ~PORT_LANE_SKEW_INSERT_MASK;
+	if (dw->num_lanes < 4)
+		val |= BIT(6);
+	dw_pcie_writel_dbi(dw, PCIE_PORT_LANE_SKEW, val);
+
+	val = readl(rcar->base + PCIEPWRMNGCTRL);
+	val |= APP_CLK_REQ_N | APP_CLK_PM_EN;
+	writel(val, rcar->base + PCIEPWRMNGCTRL);
+}
+
+static int rcar_gen4_pcie_ltssm_enable(struct rcar_gen4_pcie *rcar)
+{
+	return rcar_gen4_pcie_enable_phy(rcar);
+}
+
 static struct rcar_gen4_pcie_platdata platdata_r8a779f0_pcie = {
 	.ltssm_enable = r8a779f0_pcie_ltssm_enable,
 	.mode = DW_PCIE_RC_TYPE,
@@ -528,10 +723,14 @@ static struct rcar_gen4_pcie_platdata platdata_r8a779f0_pcie_ep = {
 };
 
 static struct rcar_gen4_pcie_platdata platdata_rcar_gen4_pcie = {
+	.additional_common_init = rcar_gen4_pcie_additional_common_init,
+	.ltssm_enable = rcar_gen4_pcie_ltssm_enable,
 	.mode = DW_PCIE_RC_TYPE,
 };
 
 static struct rcar_gen4_pcie_platdata platdata_rcar_gen4_pcie_ep = {
+	.additional_common_init = rcar_gen4_pcie_additional_common_init,
+	.ltssm_enable = rcar_gen4_pcie_ltssm_enable,
 	.mode = DW_PCIE_EP_TYPE,
 };
 
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH v7 2/2] dmaengine: Loongson1: Add Loongson-1 APB DMA driver
From: Keguang Zhang @ 2024-04-01  2:44 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Vinod Koul, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-mips, dmaengine, devicetree, linux-kernel
In-Reply-To: <CAAhV-H6gG5KGxku+aZPwfmqAVF9zfL-9-nNqCd2Z_swxgCe_HA@mail.gmail.com>

Hi Huacai,

On Sat, Mar 30, 2024 at 9:59 PM Huacai Chen <chenhuacai@kernel.org> wrote:
>
> Hi, Keguang,
>
> On Fri, Mar 29, 2024 at 7:28 PM Keguang Zhang via B4 Relay
> <devnull+keguang.zhang.gmail.com@kernel.org> wrote:
> >
> > From: Keguang Zhang <keguang.zhang@gmail.com>
> >
> > This patch adds APB DMA driver for Loongson-1 SoCs.
> >
> > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > ---
> > Changes in v7:
> > - Change the comptible to 'loongson,ls1*-apbdma'
> > - Update Kconfig and Makefile accordingly
> > - Rename the file to loongson1-apb-dma.c to keep the consistency
> >
> > Changes in v6:
> > - Implement .device_prep_dma_cyclic for Loongson1 audio driver,
> > - as well as .device_pause and .device_resume.
> > - Set the limitation LS1X_DMA_MAX_DESC and put all descriptors
> > - into one page to save memory
> > - Move dma_pool_zalloc() into ls1x_dma_alloc_desc()
> > - Drop dma_slave_config structure
> > - Use .remove_new instead of .remove
> > - Use KBUILD_MODNAME for the driver name
> > - Improve the debug information
> >
> > Changes in v5:
> > - Add DT support
> > - Use DT data instead of platform data
> > - Use chan_id of struct dma_chan instead of own id
> > - Use of_dma_xlate_by_chan_id() instead of ls1x_dma_filter()
> > - Update the author information to my official name
> >
> > Changes in v4:
> > - Use dma_slave_map to find the proper channel.
> > - Explicitly call devm_request_irq() and tasklet_kill().
> > - Fix namespace issue.
> > - Some minor fixes and cleanups.
> >
> > Changes in v3:
> > - Rename ls1x_dma_filter_fn to ls1x_dma_filter.
> >
> > Changes in v2:
> > - Change the config from 'DMA_LOONGSON1' to 'LOONGSON1_DMA',
> > - and rearrange it in alphabetical order in Kconfig and Makefile.
> > - Fix comment style.
> > ---
> >  drivers/dma/Kconfig             |   9 +
> >  drivers/dma/Makefile            |   1 +
> >  drivers/dma/loongson1-apb-dma.c | 665 ++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 675 insertions(+)
> >
> > diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> > index 002a5ec80620..f7b06c4cdf3f 100644
> > --- a/drivers/dma/Kconfig
> > +++ b/drivers/dma/Kconfig
> > @@ -369,6 +369,15 @@ config K3_DMA
> >           Support the DMA engine for Hisilicon K3 platform
> >           devices.
> >
> > +config LOONGSON1_APB_DMA
> > +       tristate "Loongson1 APB DMA support"
> > +       depends on MACH_LOONGSON32 || COMPILE_TEST
> > +       select DMA_ENGINE
> > +       select DMA_VIRTUAL_CHANNELS
> > +       help
> > +         This selects support for the APB DMA controller in Loongson1 SoCs,
> > +         which is required by Loongson1 NAND and audio support.
> Why not rename to LS1X_APB_DMA and put it just before LS2X_APB_DMA
> (and also the driver file name)?
>
So far all Kconfig entries of Loongson-1 drivers are named with the
keyword "LOONGSON1".
The same is true for these file names.
Therefore, I need to keep the consistency.


> Huacai
>
> > +
> >  config LPC18XX_DMAMUX
> >         bool "NXP LPC18xx/43xx DMA MUX for PL080"
> >         depends on ARCH_LPC18XX || COMPILE_TEST
> > diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> > index dfd40d14e408..b26f6677978a 100644
> > --- a/drivers/dma/Makefile
> > +++ b/drivers/dma/Makefile
> > @@ -47,6 +47,7 @@ obj-$(CONFIG_INTEL_IDMA64) += idma64.o
> >  obj-$(CONFIG_INTEL_IOATDMA) += ioat/
> >  obj-y += idxd/
> >  obj-$(CONFIG_K3_DMA) += k3dma.o
> > +obj-$(CONFIG_LOONGSON1_APB_DMA) += loongson1-apb-dma.o
> >  obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
> >  obj-$(CONFIG_LS2X_APB_DMA) += ls2x-apb-dma.o
> >  obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
> > diff --git a/drivers/dma/loongson1-apb-dma.c b/drivers/dma/loongson1-apb-dma.c
> > new file mode 100644
> > index 000000000000..d474a2601e6e
> > --- /dev/null
> > +++ b/drivers/dma/loongson1-apb-dma.c
> > @@ -0,0 +1,665 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Driver for Loongson-1 APB DMA Controller
> > + *
> > + * Copyright (C) 2015-2024 Keguang Zhang <keguang.zhang@gmail.com>
> > + */
> > +
> > +#include <linux/dmapool.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/init.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_dma.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +
> > +#include "dmaengine.h"
> > +#include "virt-dma.h"
> > +
> > +/* Loongson-1 DMA Control Register */
> > +#define DMA_CTRL                       0x0
> > +
> > +/* DMA Control Register Bits */
> > +#define DMA_STOP                       BIT(4)
> > +#define DMA_START                      BIT(3)
> > +#define DMA_ASK_VALID                  BIT(2)
> > +
> > +#define DMA_ADDR_MASK                  GENMASK(31, 6)
> > +
> > +/* DMA Next Field Bits */
> > +#define DMA_NEXT_VALID                 BIT(0)
> > +
> > +/* DMA Command Field Bits */
> > +#define DMA_RAM2DEV                    BIT(12)
> > +#define DMA_INT                                BIT(1)
> > +#define DMA_INT_MASK                   BIT(0)
> > +
> > +#define LS1X_DMA_MAX_CHANNELS          3
> > +
> > +/* Size of allocations for hardware descriptors */
> > +#define LS1X_DMA_DESCS_SIZE            PAGE_SIZE
> > +#define LS1X_DMA_MAX_DESC              \
> > +       (LS1X_DMA_DESCS_SIZE / sizeof(struct ls1x_dma_hwdesc))
> > +
> > +struct ls1x_dma_hwdesc {
> > +       u32 next;               /* next descriptor address */
> > +       u32 saddr;              /* memory DMA address */
> > +       u32 daddr;              /* device DMA address */
> > +       u32 length;
> > +       u32 stride;
> > +       u32 cycles;
> > +       u32 cmd;
> > +       u32 stats;
> > +};
> > +
> > +struct ls1x_dma_desc {
> > +       struct virt_dma_desc vdesc;
> > +       enum dma_transfer_direction dir;
> > +       enum dma_transaction_type type;
> > +       unsigned int bus_width;
> > +
> > +       unsigned int nr_descs;  /* number of descriptors */
> > +
> > +       struct ls1x_dma_hwdesc *hwdesc;
> > +       dma_addr_t hwdesc_phys;
> > +};
> > +
> > +struct ls1x_dma_chan {
> > +       struct virt_dma_chan vchan;
> > +       struct dma_pool *desc_pool;
> > +       phys_addr_t src_addr;
> > +       phys_addr_t dst_addr;
> > +       enum dma_slave_buswidth src_addr_width;
> > +       enum dma_slave_buswidth dst_addr_width;
> > +
> > +       void __iomem *reg_base;
> > +       int irq;
> > +
> > +       struct ls1x_dma_desc *desc;
> > +
> > +       struct ls1x_dma_hwdesc *curr_hwdesc;
> > +       dma_addr_t curr_hwdesc_phys;
> > +};
> > +
> > +struct ls1x_dma {
> > +       struct dma_device ddev;
> > +       void __iomem *reg_base;
> > +
> > +       unsigned int nr_chans;
> > +       struct ls1x_dma_chan chan[];
> > +};
> > +
> > +#define to_ls1x_dma_chan(dchan)                \
> > +       container_of(dchan, struct ls1x_dma_chan, vchan.chan)
> > +
> > +#define to_ls1x_dma_desc(vd)           \
> > +       container_of(vd, struct ls1x_dma_desc, vdesc)
> > +
> > +/* macros for registers read/write */
> > +#define chan_readl(chan, off)          \
> > +       readl((chan)->reg_base + (off))
> > +
> > +#define chan_writel(chan, off, val)    \
> > +       writel((val), (chan)->reg_base + (off))
> > +
> > +static inline struct device *chan2dev(struct dma_chan *chan)
> > +{
> > +       return &chan->dev->device;
> > +}
> > +
> > +static inline int ls1x_dma_query(struct ls1x_dma_chan *chan,
> > +                                dma_addr_t *hwdesc_phys)
> > +{
> > +       struct dma_chan *dchan = &chan->vchan.chan;
> > +       int val, ret;
> > +
> > +       val = *hwdesc_phys & DMA_ADDR_MASK;
> > +       val |= DMA_ASK_VALID;
> > +       val |= dchan->chan_id;
> > +       chan_writel(chan, DMA_CTRL, val);
> > +       ret = readl_poll_timeout_atomic(chan->reg_base + DMA_CTRL, val,
> > +                                       !(val & DMA_ASK_VALID), 0, 3000);
> > +       if (ret)
> > +               dev_err(chan2dev(dchan), "failed to query DMA\n");
> > +
> > +       return ret;
> > +}
> > +
> > +static inline int ls1x_dma_start(struct ls1x_dma_chan *chan,
> > +                                dma_addr_t *hwdesc_phys)
> > +{
> > +       struct dma_chan *dchan = &chan->vchan.chan;
> > +       int val, ret;
> > +
> > +       dev_dbg(chan2dev(dchan), "cookie=%d, starting hwdesc=%x\n",
> > +               dchan->cookie, *hwdesc_phys);
> > +
> > +       val = *hwdesc_phys & DMA_ADDR_MASK;
> > +       val |= DMA_START;
> > +       val |= dchan->chan_id;
> > +       chan_writel(chan, DMA_CTRL, val);
> > +       ret = readl_poll_timeout(chan->reg_base + DMA_CTRL, val,
> > +                                !(val & DMA_START), 0, 3000);
> > +       if (ret)
> > +               dev_err(chan2dev(dchan), "failed to start DMA\n");
> > +
> > +       return ret;
> > +}
> > +
> > +static inline void ls1x_dma_stop(struct ls1x_dma_chan *chan)
> > +{
> > +       chan_writel(chan, DMA_CTRL, chan_readl(chan, DMA_CTRL) | DMA_STOP);
> > +}
> > +
> > +static void ls1x_dma_free_chan_resources(struct dma_chan *dchan)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +
> > +       dma_free_coherent(chan2dev(dchan), sizeof(struct ls1x_dma_hwdesc),
> > +                         chan->curr_hwdesc, chan->curr_hwdesc_phys);
> > +       vchan_free_chan_resources(&chan->vchan);
> > +       dma_pool_destroy(chan->desc_pool);
> > +       chan->desc_pool = NULL;
> > +}
> > +
> > +static int ls1x_dma_alloc_chan_resources(struct dma_chan *dchan)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +
> > +       chan->desc_pool = dma_pool_create(dma_chan_name(dchan),
> > +                                         chan2dev(dchan),
> > +                                         sizeof(struct ls1x_dma_hwdesc),
> > +                                         __alignof__(struct ls1x_dma_hwdesc),
> > +                                         0);
> > +       if (!chan->desc_pool)
> > +               return -ENOMEM;
> > +
> > +       /* allocate memory for querying current HW descriptor */
> > +       dma_set_coherent_mask(chan2dev(dchan), DMA_BIT_MASK(32));
> > +       chan->curr_hwdesc = dma_alloc_coherent(chan2dev(dchan),
> > +                                              sizeof(struct ls1x_dma_hwdesc),
> > +                                              &chan->curr_hwdesc_phys,
> > +                                              GFP_KERNEL);
> > +       if (!chan->curr_hwdesc)
> > +               return -ENOMEM;
> > +
> > +       return 0;
> > +}
> > +
> > +static void ls1x_dma_free_desc(struct virt_dma_desc *vdesc)
> > +{
> > +       struct ls1x_dma_desc *desc = to_ls1x_dma_desc(vdesc);
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(vdesc->tx.chan);
> > +
> > +       dma_pool_free(chan->desc_pool, desc->hwdesc, desc->hwdesc_phys);
> > +       chan->desc = NULL;
> > +       kfree(desc);
> > +}
> > +
> > +static struct ls1x_dma_desc *
> > +ls1x_dma_alloc_desc(struct dma_chan *dchan, int sg_len,
> > +                   enum dma_transfer_direction direction,
> > +                   enum dma_transaction_type type)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       struct ls1x_dma_desc *desc;
> > +
> > +       if (sg_len > LS1X_DMA_MAX_DESC) {
> > +               dev_err(chan2dev(dchan), "sg_len %u exceeds limit %lu",
> > +                       sg_len, LS1X_DMA_MAX_DESC);
> > +               return NULL;
> > +       }
> > +
> > +       desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
> > +       if (!desc)
> > +               return NULL;
> > +
> > +       /* allocate HW descriptors */
> > +       desc->hwdesc = dma_pool_zalloc(chan->desc_pool, GFP_NOWAIT,
> > +                                      &desc->hwdesc_phys);
> > +       if (!desc->hwdesc) {
> > +               dev_err(chan2dev(dchan), "failed to alloc HW descriptors\n");
> > +               ls1x_dma_free_desc(&desc->vdesc);
> > +               return NULL;
> > +       }
> > +
> > +       desc->dir = direction;
> > +       desc->type = type;
> > +       desc->nr_descs = sg_len;
> > +
> > +       return desc;
> > +}
> > +
> > +static int ls1x_dma_setup_hwdescs(struct dma_chan *dchan,
> > +                                 struct ls1x_dma_desc *desc,
> > +                                 struct scatterlist *sgl, unsigned int sg_len)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       dma_addr_t next_hwdesc_phys = desc->hwdesc_phys;
> > +
> > +       struct scatterlist *sg;
> > +       unsigned int dev_addr, cmd, i;
> > +
> > +       switch (desc->dir) {
> > +       case DMA_MEM_TO_DEV:
> > +               dev_addr = chan->dst_addr;
> > +               desc->bus_width = chan->dst_addr_width;
> > +               cmd = DMA_RAM2DEV | DMA_INT;
> > +               break;
> > +       case DMA_DEV_TO_MEM:
> > +               dev_addr = chan->src_addr;
> > +               desc->bus_width = chan->src_addr_width;
> > +               cmd = DMA_INT;
> > +               break;
> > +       default:
> > +               dev_err(chan2dev(dchan), "unsupported DMA direction: %s\n",
> > +                       dmaengine_get_direction_text(desc->dir));
> > +               return -EINVAL;
> > +       }
> > +
> > +       /* setup HW descriptors */
> > +       for_each_sg(sgl, sg, sg_len, i) {
> > +               dma_addr_t buf_addr = sg_dma_address(sg);
> > +               size_t buf_len = sg_dma_len(sg);
> > +               struct ls1x_dma_hwdesc *hwdesc = &desc->hwdesc[i];
> > +
> > +               if (!is_dma_copy_aligned(dchan->device, buf_addr, 0, buf_len)) {
> > +                       dev_err(chan2dev(dchan), "buffer is not aligned!\n");
> > +                       return -EINVAL;
> > +               }
> > +
> > +               hwdesc->saddr = buf_addr;
> > +               hwdesc->daddr = dev_addr;
> > +               hwdesc->length = buf_len / desc->bus_width;
> > +               hwdesc->stride = 0;
> > +               hwdesc->cycles = 1;
> > +               hwdesc->cmd = cmd;
> > +
> > +               if (i) {
> > +                       next_hwdesc_phys += sizeof(*hwdesc);
> > +                       desc->hwdesc[i - 1].next = next_hwdesc_phys
> > +                           | DMA_NEXT_VALID;
> > +               }
> > +       }
> > +
> > +       if (desc->type == DMA_CYCLIC)
> > +               desc->hwdesc[i - 1].next = desc->hwdesc_phys | DMA_NEXT_VALID;
> > +
> > +       for_each_sg(sgl, sg, sg_len, i) {
> > +               struct ls1x_dma_hwdesc *hwdesc = &desc->hwdesc[i];
> > +
> > +               print_hex_dump_debug("HW DESC: ", DUMP_PREFIX_OFFSET, 16, 4,
> > +                                    hwdesc, sizeof(*hwdesc), false);
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static struct dma_async_tx_descriptor *
> > +ls1x_dma_prep_slave_sg(struct dma_chan *dchan,
> > +                      struct scatterlist *sgl, unsigned int sg_len,
> > +                      enum dma_transfer_direction direction,
> > +                      unsigned long flags, void *context)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       struct ls1x_dma_desc *desc;
> > +
> > +       dev_dbg(chan2dev(dchan), "sg_len=%u flags=0x%lx dir=%s\n",
> > +               sg_len, flags, dmaengine_get_direction_text(direction));
> > +
> > +       desc = ls1x_dma_alloc_desc(dchan, sg_len, direction, DMA_SLAVE);
> > +       if (!desc)
> > +               return NULL;
> > +
> > +       if (ls1x_dma_setup_hwdescs(dchan, desc, sgl, sg_len)) {
> > +               ls1x_dma_free_desc(&desc->vdesc);
> > +               return NULL;
> > +       }
> > +
> > +       return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
> > +}
> > +
> > +static struct dma_async_tx_descriptor *
> > +ls1x_dma_prep_dma_cyclic(struct dma_chan *dchan,
> > +                        dma_addr_t buf_addr, size_t buf_len, size_t period_len,
> > +                        enum dma_transfer_direction direction,
> > +                        unsigned long flags)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       struct ls1x_dma_desc *desc;
> > +       struct scatterlist *sgl;
> > +       unsigned int sg_len;
> > +       unsigned int i;
> > +
> > +       dev_dbg(chan2dev(dchan),
> > +               "buf_len=%d period_len=%zu flags=0x%lx dir=%s\n", buf_len,
> > +               period_len, flags, dmaengine_get_direction_text(direction));
> > +
> > +       sg_len = buf_len / period_len;
> > +       desc = ls1x_dma_alloc_desc(dchan, sg_len, direction, DMA_CYCLIC);
> > +       if (!desc)
> > +               return NULL;
> > +
> > +       /* allocate the scatterlist */
> > +       sgl = kmalloc_array(sg_len, sizeof(*sgl), GFP_NOWAIT);
> > +       if (!sgl)
> > +               return NULL;
> > +
> > +       sg_init_table(sgl, sg_len);
> > +       for (i = 0; i < sg_len; ++i) {
> > +               sg_set_page(&sgl[i], pfn_to_page(PFN_DOWN(buf_addr)),
> > +                           period_len, offset_in_page(buf_addr));
> > +               sg_dma_address(&sgl[i]) = buf_addr;
> > +               sg_dma_len(&sgl[i]) = period_len;
> > +               buf_addr += period_len;
> > +       }
> > +
> > +       if (ls1x_dma_setup_hwdescs(dchan, desc, sgl, sg_len)) {
> > +               ls1x_dma_free_desc(&desc->vdesc);
> > +               return NULL;
> > +       }
> > +
> > +       kfree(sgl);
> > +
> > +       return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
> > +}
> > +
> > +static int ls1x_dma_slave_config(struct dma_chan *dchan,
> > +                                struct dma_slave_config *config)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +
> > +       chan->src_addr = config->src_addr;
> > +       chan->src_addr_width = config->src_addr_width;
> > +       chan->dst_addr = config->dst_addr;
> > +       chan->dst_addr_width = config->dst_addr_width;
> > +
> > +       return 0;
> > +}
> > +
> > +static int ls1x_dma_pause(struct dma_chan *dchan)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       unsigned long flags;
> > +       int ret;
> > +
> > +       spin_lock_irqsave(&chan->vchan.lock, flags);
> > +       ret = ls1x_dma_query(chan, &chan->curr_hwdesc_phys);
> > +       if (!ret)
> > +               ls1x_dma_stop(chan);
> > +       spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > +
> > +       return ret;
> > +}
> > +
> > +static int ls1x_dma_resume(struct dma_chan *dchan)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       unsigned long flags;
> > +       int ret;
> > +
> > +       spin_lock_irqsave(&chan->vchan.lock, flags);
> > +       ret = ls1x_dma_start(chan, &chan->curr_hwdesc_phys);
> > +       spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > +
> > +       return ret;
> > +}
> > +
> > +static int ls1x_dma_terminate_all(struct dma_chan *dchan)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       unsigned long flags;
> > +       LIST_HEAD(head);
> > +
> > +       spin_lock_irqsave(&chan->vchan.lock, flags);
> > +       ls1x_dma_stop(chan);
> > +       vchan_get_all_descriptors(&chan->vchan, &head);
> > +       spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > +
> > +       vchan_dma_desc_free_list(&chan->vchan, &head);
> > +
> > +       return 0;
> > +}
> > +
> > +static enum dma_status ls1x_dma_tx_status(struct dma_chan *dchan,
> > +                                         dma_cookie_t cookie,
> > +                                         struct dma_tx_state *state)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       struct virt_dma_desc *vdesc;
> > +       enum dma_status status;
> > +       size_t bytes = 0;
> > +       unsigned long flags;
> > +
> > +       status = dma_cookie_status(dchan, cookie, state);
> > +       if (status == DMA_COMPLETE)
> > +               return status;
> > +
> > +       spin_lock_irqsave(&chan->vchan.lock, flags);
> > +       vdesc = vchan_find_desc(&chan->vchan, cookie);
> > +       if (chan->desc && cookie == chan->desc->vdesc.tx.cookie) {
> > +               struct ls1x_dma_desc *desc = chan->desc;
> > +               int i;
> > +
> > +               if (ls1x_dma_query(chan, &chan->curr_hwdesc_phys))
> > +                       return status;
> > +
> > +               /* locate the current HW descriptor */
> > +               for (i = 0; i < desc->nr_descs; i++)
> > +                       if (desc->hwdesc[i].next == chan->curr_hwdesc->next)
> > +                               break;
> > +
> > +               /* count the residues */
> > +               for (; i < desc->nr_descs; i++)
> > +                       bytes += desc->hwdesc[i].length * desc->bus_width;
> > +
> > +               dma_set_residue(state, bytes);
> > +       }
> > +       spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > +
> > +       return status;
> > +}
> > +
> > +static void ls1x_dma_issue_pending(struct dma_chan *dchan)
> > +{
> > +       struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
> > +       struct virt_dma_desc *vdesc;
> > +       unsigned long flags;
> > +
> > +       spin_lock_irqsave(&chan->vchan.lock, flags);
> > +       if (vchan_issue_pending(&chan->vchan) && !chan->desc) {
> > +               vdesc = vchan_next_desc(&chan->vchan);
> > +               if (!vdesc) {
> > +                       chan->desc = NULL;
> > +                       return;
> > +               }
> > +               chan->desc = to_ls1x_dma_desc(vdesc);
> > +               ls1x_dma_start(chan, &chan->desc->hwdesc_phys);
> > +       }
> > +       spin_unlock_irqrestore(&chan->vchan.lock, flags);
> > +}
> > +
> > +static irqreturn_t ls1x_dma_irq_handler(int irq, void *data)
> > +{
> > +       struct ls1x_dma_chan *chan = data;
> > +       struct ls1x_dma_desc *desc = chan->desc;
> > +       struct dma_chan *dchan = &chan->vchan.chan;
> > +
> > +       if (!desc) {
> > +               dev_warn(chan2dev(dchan),
> > +                        "IRQ %d with no active descriptor on channel %d\n",
> > +                        irq, dchan->chan_id);
> > +               return IRQ_NONE;
> > +       }
> > +
> > +       dev_dbg(chan2dev(dchan), "DMA IRQ %d on channel %d\n", irq,
> > +               dchan->chan_id);
> > +
> > +       spin_lock(&chan->vchan.lock);
> > +
> > +       if (desc->type == DMA_CYCLIC) {
> > +               vchan_cyclic_callback(&desc->vdesc);
> > +       } else {
> > +               list_del(&desc->vdesc.node);
> > +               vchan_cookie_complete(&desc->vdesc);
> > +               chan->desc = NULL;
> > +       }
> > +
> > +       spin_unlock(&chan->vchan.lock);
> > +       return IRQ_HANDLED;
> > +}
> > +
> > +static int ls1x_dma_chan_probe(struct platform_device *pdev,
> > +                              struct ls1x_dma *dma, int chan_id)
> > +{
> > +       struct device *dev = &pdev->dev;
> > +       struct ls1x_dma_chan *chan = &dma->chan[chan_id];
> > +       char pdev_irqname[4];
> > +       char *irqname;
> > +       int ret;
> > +
> > +       sprintf(pdev_irqname, "ch%u", chan_id);
> > +       chan->irq = platform_get_irq_byname(pdev, pdev_irqname);
> > +       if (chan->irq < 0)
> > +               return -ENODEV;
> > +
> > +       irqname = devm_kasprintf(dev, GFP_KERNEL, "%s:%s",
> > +                                dev_name(dev), pdev_irqname);
> > +       if (!irqname)
> > +               return -ENOMEM;
> > +
> > +       ret = devm_request_irq(dev, chan->irq, ls1x_dma_irq_handler,
> > +                              IRQF_SHARED, irqname, chan);
> > +       if (ret)
> > +               return dev_err_probe(dev, ret,
> > +                                    "failed to request IRQ %u!\n", chan->irq);
> > +
> > +       chan->reg_base = dma->reg_base;
> > +       chan->vchan.desc_free = ls1x_dma_free_desc;
> > +       vchan_init(&chan->vchan, &dma->ddev);
> > +       dev_info(dev, "%s (irq %d) initialized\n", pdev_irqname, chan->irq);
> > +
> > +       return 0;
> > +}
> > +
> > +static void ls1x_dma_chan_remove(struct ls1x_dma *dma, int chan_id)
> > +{
> > +       struct device *dev = dma->ddev.dev;
> > +       struct ls1x_dma_chan *chan = &dma->chan[chan_id];
> > +
> > +       devm_free_irq(dev, chan->irq, chan);
> > +       list_del(&chan->vchan.chan.device_node);
> > +       tasklet_kill(&chan->vchan.task);
> > +}
> > +
> > +static int ls1x_dma_probe(struct platform_device *pdev)
> > +{
> > +       struct device *dev = &pdev->dev;
> > +       struct dma_device *ddev;
> > +       struct ls1x_dma *dma;
> > +       int nr_chans, ret, i;
> > +
> > +       nr_chans = platform_irq_count(pdev);
> > +       if (nr_chans <= 0)
> > +               return nr_chans;
> > +       if (nr_chans > LS1X_DMA_MAX_CHANNELS)
> > +               return dev_err_probe(dev, -EINVAL,
> > +                                    "nr_chans=%d exceeds the maximum\n",
> > +                                    nr_chans);
> > +
> > +       dma = devm_kzalloc(dev, struct_size(dma, chan, nr_chans), GFP_KERNEL);
> > +       if (!dma)
> > +               return -ENOMEM;
> > +
> > +       /* initialize DMA device */
> > +       dma->reg_base = devm_platform_ioremap_resource(pdev, 0);
> > +       if (IS_ERR(dma->reg_base))
> > +               return PTR_ERR(dma->reg_base);
> > +
> > +       ddev = &dma->ddev;
> > +       ddev->dev = dev;
> > +       ddev->copy_align = DMAENGINE_ALIGN_4_BYTES;
> > +       ddev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > +           BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
> > +       ddev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > +           BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
> > +       ddev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
> > +       ddev->max_sg_burst = LS1X_DMA_MAX_DESC;
> > +       ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
> > +       ddev->device_alloc_chan_resources = ls1x_dma_alloc_chan_resources;
> > +       ddev->device_free_chan_resources = ls1x_dma_free_chan_resources;
> > +       ddev->device_prep_slave_sg = ls1x_dma_prep_slave_sg;
> > +       ddev->device_prep_dma_cyclic = ls1x_dma_prep_dma_cyclic;
> > +       ddev->device_config = ls1x_dma_slave_config;
> > +       ddev->device_pause = ls1x_dma_pause;
> > +       ddev->device_resume = ls1x_dma_resume;
> > +       ddev->device_terminate_all = ls1x_dma_terminate_all;
> > +       ddev->device_tx_status = ls1x_dma_tx_status;
> > +       ddev->device_issue_pending = ls1x_dma_issue_pending;
> > +
> > +       dma_cap_set(DMA_SLAVE, ddev->cap_mask);
> > +       INIT_LIST_HEAD(&ddev->channels);
> > +
> > +       /* initialize DMA channels */
> > +       for (i = 0; i < nr_chans; i++) {
> > +               ret = ls1x_dma_chan_probe(pdev, dma, i);
> > +               if (ret)
> > +                       return ret;
> > +       }
> > +       dma->nr_chans = nr_chans;
> > +
> > +       ret = dmaenginem_async_device_register(ddev);
> > +       if (ret) {
> > +               dev_err(dev, "failed to register DMA device! %d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       ret =
> > +           of_dma_controller_register(dev->of_node, of_dma_xlate_by_chan_id,
> > +                                      ddev);
> > +       if (ret) {
> > +               dev_err(dev, "failed to register DMA controller! %d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       platform_set_drvdata(pdev, dma);
> > +       dev_info(dev, "Loongson1 DMA driver registered\n");
> > +
> > +       return 0;
> > +}
> > +
> > +static void ls1x_dma_remove(struct platform_device *pdev)
> > +{
> > +       struct ls1x_dma *dma = platform_get_drvdata(pdev);
> > +       int i;
> > +
> > +       of_dma_controller_free(pdev->dev.of_node);
> > +
> > +       for (i = 0; i < dma->nr_chans; i++)
> > +               ls1x_dma_chan_remove(dma, i);
> > +}
> > +
> > +static const struct of_device_id ls1x_dma_match[] = {
> > +       { .compatible = "loongson,ls1b-apbdma" },
> > +       { .compatible = "loongson,ls1c-apbdma" },
> > +       { /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, ls1x_dma_match);
> > +
> > +static struct platform_driver ls1x_dma_driver = {
> > +       .probe = ls1x_dma_probe,
> > +       .remove_new = ls1x_dma_remove,
> > +       .driver = {
> > +               .name = KBUILD_MODNAME,
> > +               .of_match_table = ls1x_dma_match,
> > +       },
> > +};
> > +
> > +module_platform_driver(ls1x_dma_driver);
> > +
> > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > +MODULE_DESCRIPTION("Loongson-1 APB DMA Controller driver");
> > +MODULE_LICENSE("GPL");
> >
> > --
> > 2.40.1
> >
> >



--
Best regards,

Keguang Zhang

^ permalink raw reply

* Re: [RFC PATCH 1/2] spi: dt-bindings: add Siflower Quad SPI controller
From: Qingfang Deng @ 2024-04-01  3:36 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Qingfang Deng, linux-spi, devicetree, linux-kernel
In-Reply-To: <261f2995-b279-48bc-b9d4-023a8a705857@linaro.org>

Hi Krzysztof,

On Sun, Mar 31, 2024 at 1:42 AM Krzysztof Kozlowski
<krzysztof.kozlowski@linaro.org> wrote:
> On 29/03/2024 02:51, Qingfang Deng wrote:
> > Add YAML devicetree bindings for Siflower Quad SPI controller.
>
> Describe the hardware. What is this Siflower?

It's a new RISC-V SoC which hasn't been upstreamed yet.

> > +properties:
> > +  compatible:
> > +    const: siflower,qspi
>
> Except that this was not tested, aren't you adding it for some SoC? If
> so, then you miss here SoC part.

I should add the "siflower" prefix to
Documentation/devicetree/bindings/vendor-prefixes.yaml, right?

Regards,
Qingfang

^ permalink raw reply

* Re: [PATCH v6 0/2] ASoC: nau8325: Modify driver code and dtschema.
From: WTLI @ 2024-04-01  3:59 UTC (permalink / raw)
  To: Mark Brown
  Cc: lgirdwood, alsa-devel, devicetree, linux-sound,
	krzysztof.kozlowski+dt, linux-kernel, robh+dt, conor+dt, perex,
	tiwai, YHCHuang, KCHSU0, CTLIN0, SJLIN0, scott6986,
	supercraig0719, dardar923
In-Reply-To: <ZgbFv+c3fjME+x+Y@finisterre.sirena.org.uk>


Mark Brown 於 3/29/2024 9:44 PM 寫道:
> On Fri, Mar 29, 2024 at 04:54:00PM +0800, Seven Lee wrote:
>> Revise properties description and use standard units in dtschema.
>> The unit conversion driver based on the attribute must also be
>> changed accordingly.
> My applying the prior version raced with you sending this new one, could
> you please send incremental patches with the changes from your v6?

Sorry, I misunderstood. I will send incremental patches with my v6.

________________________________
________________________________
 The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.

^ permalink raw reply

* [PATCH] ASoC: dt-bindings: mt2701-wm8960: Convert to dtschema
From: Kartik Agarwala @ 2024-04-01  4:35 UTC (permalink / raw)
  To: lgirdwood, broonie, robh, krzysztof.kozlowski+dt, conor+dt,
	matthias.bgg, angelogioacchino.delregno
  Cc: Kartik Agarwala, linux-sound, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek

Convert mt2701-wm890 bindings from text to dtschema. This is used by MediaTek mt77623a/n SoC.

Signed-off-by: Kartik Agarwala <agarwala.kartik@gmail.com>
---
 .../sound/mediatek,mt2701-wm8960.yaml         | 59 +++++++++++++++++++
 .../bindings/sound/mt2701-wm8960.txt          | 24 --------
 2 files changed, 59 insertions(+), 24 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt2701-wm8960.yaml
 delete mode 100644 Documentation/devicetree/bindings/sound/mt2701-wm8960.txt

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt2701-wm8960.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt2701-wm8960.yaml
new file mode 100644
index 000000000..771f14a59
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt2701-wm8960.yaml
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt2701-wm8960.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT2701 with WM8960 CODEC
+
+maintainers:
+  - Kartik Agarwala <agarwala.kartik@gmail.com>
+
+properties:
+  compatible:
+    const: mediatek,mt2701-wm8960-machine
+
+  mediatek,platform:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: The phandle of MT2701 ASoC platform.
+
+  audio-routing:
+    $ref: /schemas/types.yaml#/definitions/non-unique-string-array
+    description: |
+      A list of the connections between audio components. Each entry is a
+      pair of strings, the first being the connection's sink, the second
+      being the connection's source.
+
+  mediatek,audio-codec:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: The phandle of the WM8960 audio codec.
+  
+  pinctrl-names:
+    const: default
+
+  pinctrl-0: true
+
+unevaluatedProperties: false
+
+required:
+  - compatible
+  - mediatek,platform
+  - audio-routing
+  - mediatek,audio-codec
+  - pinctrl-names
+  - pinctrl-0
+
+examples:
+  - |
+    sound {
+        compatible = "mediatek,mt2701-wm8960-machine";
+        mediatek,platform = <&afe>;
+        audio-routing =
+            "Headphone", "HP_L",
+            "Headphone", "HP_R",
+            "LINPUT1", "AMIC",
+            "RINPUT1", "AMIC";
+        mediatek,audio-codec = <&wm8960>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&aud_pins_default>;
+    };
diff --git a/Documentation/devicetree/bindings/sound/mt2701-wm8960.txt b/Documentation/devicetree/bindings/sound/mt2701-wm8960.txt
deleted file mode 100644
index 809b609ea..000000000
--- a/Documentation/devicetree/bindings/sound/mt2701-wm8960.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-MT2701 with WM8960 CODEC
-
-Required properties:
-- compatible: "mediatek,mt2701-wm8960-machine"
-- mediatek,platform: the phandle of MT2701 ASoC platform
-- audio-routing: a list of the connections between audio
-- mediatek,audio-codec: the phandles of wm8960 codec
-- pinctrl-names: Should contain only one value - "default"
-- pinctrl-0: Should specify pin control groups used for this controller.
-
-Example:
-
-	sound:sound {
-		compatible = "mediatek,mt2701-wm8960-machine";
-		mediatek,platform = <&afe>;
-		audio-routing =
-			"Headphone", "HP_L",
-			"Headphone", "HP_R",
-			"LINPUT1", "AMIC",
-			"RINPUT1", "AMIC";
-		mediatek,audio-codec = <&wm8960>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&aud_pins_default>;
-	};
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH] ASoC: dt-bindings: mt2701-wm8960: Convert to dtschema
From: Kartik Agarwala @ 2024-04-01  4:49 UTC (permalink / raw)
  To: lgirdwood, broonie, robh, krzysztof.kozlowski+dt, conor+dt,
	matthias.bgg, angelogioacchino.delregno
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20240401043505.40972-1-agarwala.kartik@gmail.com>

On 4/1/24 10:05 AM, Kartik Agarwala wrote:
> Convert mt2701-wm890 bindings from text to dtschema. This is used by MediaTek mt77623a/n SoC.

Apologies for the typo, it should be mt7623a/n instead of mt77623a/n.

Regards,
Kartik Agarwala

^ permalink raw reply

* Re: [PATCH v5 1/2] dt-bindings: hwmon: Add NCT7363Y documentation
From: Ban Feng @ 2024-04-01  6:20 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Guenter Roeck, Rob Herring, linux-hwmon, krzysztof.kozlowski+dt,
	robh+dt, conor+dt, corbet, jdelvare, kwliu, kcfeng0, Paul Menzel,
	linux-kernel, devicetree, Bonnie_Lo, linux-doc, DELPHINE_CHIU,
	openbmc
In-Reply-To: <e1102a00-0c94-4d35-8de2-1173ee417bdc@linaro.org>

Hi Krzysztof,

Thanks for your support.

Best regards,
Ban

On Tue, Mar 26, 2024 at 2:29 AM Krzysztof Kozlowski
<krzysztof.kozlowski@linaro.org> wrote:
>
> On 25/03/2024 18:09, Guenter Roeck wrote:
> > On 3/22/24 02:26, Rob Herring wrote:
> >>
> >> On Fri, 22 Mar 2024 16:11:57 +0800, baneric926@gmail.com wrote:
> >>> From: Ban Feng <kcfeng0@nuvoton.com>
> >>>
> >>> Add bindings for the Nuvoton NCT7363Y Fan Controller
> >>>
> >>> Reviewed-by: Rob Herring <robh@kernel.org>
> >>> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
> >>> Signed-off-by: Ban Feng <kcfeng0@nuvoton.com>
> >>> ---
> >>>   .../bindings/hwmon/nuvoton,nct7363.yaml       | 66 +++++++++++++++++++
> >>>   MAINTAINERS                                   |  6 ++
> >>>   2 files changed, 72 insertions(+)
> >>>   create mode 100644 Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.yaml
> >>>
> >>
> >> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> >> on your patch (DT_CHECKER_FLAGS is new in v5.13):
> >>
> >> yamllint warnings/errors:
> >>
> >> dtschema/dtc warnings/errors:
> >> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.yaml:
> >> Error in referenced schema matching $id: http://devicetree.org/schemas/hwmon/fan-common.yaml
> >> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.example.dtb: hwmon@22: fan-0: False schema does not allow {'pwms': [[1, 0, 50000]], 'tach-ch': ['']}
> >>      from schema $id: http://devicetree.org/schemas/hwmon/nuvoton,nct7363.yaml#
> >> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.example.dtb: hwmon@22: fan-0: Unevaluated properties are not allowed ('pwms', 'tach-ch' were unexpected)
> >>      from schema $id: http://devicetree.org/schemas/hwmon/nuvoton,nct7363.yaml#
> >> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.example.dtb: hwmon@22: fan-1: False schema does not allow {'pwms': [[1, 1, 50000]], 'tach-ch': b'\x01'}
> >>      from schema $id: http://devicetree.org/schemas/hwmon/nuvoton,nct7363.yaml#
> >> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.example.dtb: hwmon@22: fan-1: Unevaluated properties are not allowed ('pwms', 'tach-ch' were unexpected)
> >>      from schema $id: http://devicetree.org/schemas/hwmon/nuvoton,nct7363.yaml#
> >> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.example.dtb: fan-1: tach-ch: b'\x01' is not of type 'object', 'array', 'boolean', 'null'
> >>      from schema $id: http://devicetree.org/schemas/dt-core.yaml#
> >>
> >> doc reference errors (make refcheckdocs):
> >>
> >> See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240322081158.4106326-2-kcfeng0@nuvoton.com
> >>
> >> The base for the series is generally the latest rc1. A different dependency
> >> should be noted in *this* patch.
> >>
> >> If you already ran 'make dt_binding_check' and didn't see the above
> >> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> >> date:
> >>
> >> pip3 install dtschema --upgrade
> >>
> >> Please check and re-submit after running the above command yourself. Note
> >> that DT_SCHEMA_FILES can be set to your schema file to speed up checking
> >> your schema. However, it must be unset to test all examples with your schema.
> >>
> >
> > I am a bit puzzled by this one. The patch has a Reviewed-by: tag from Rob,
> > but then Rob's bot complains about errors. hat am I missing ?
>
> The warning is a result of missing fan-common.yaml in the tree used as a
> base.
>
> I checked now and I don't see warnings on next or v6.9-rc1, so it is
> safe for you to apply it.
>
> For the record:
>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>
> Best regards,
> Krzysztof
>

^ permalink raw reply

* RE: 回复: [PATCH v2 1/2] ASoC: dt-bindings: Add bindings for Cadence I2S-MC controller
From: Xingyu Wu @ 2024-04-01  6:32 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Mark Brown
  Cc: Liam Girdwood, Claudiu Beznea, Jaroslav Kysela, Takashi Iwai,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	alsa-devel@alsa-project.org, linux-sound@vger.kernel.org
In-Reply-To: <7297bd78-4f74-4d23-afb3-9b7aecbe451d@linaro.org>

On 30/03/2024 0:02, Krzysztof Kozlowski wrote:
> 
> On 29/03/2024 14:36, Mark Brown wrote:
> > On Fri, Mar 29, 2024 at 12:42:22PM +0100, Krzysztof Kozlowski wrote:
> >
> >> I stated and I keep my statement that such block is usually not
> >> usable on its own and always needs some sort of quirks or
> >> SoC-specific implementation. At least this is what I saw in other
> >> similar cases, but not exactly I2S.
> >
> > I wouldn't be so pessimistic, especially not for I2S - a good portion
> > of quirks there are extra features rather than things needed for basic
> > operation, a lot of things that might in the past have been quirks for
> > basic operation are these days hidden behind the DT bindings.
> 
> OK, I trust your judgement, so cdns as fallback seems okay, but I don't think it
> warrants cdns as used alone. Not particularly because cdns is different, but
> because we expect specific SoC compatible always.
> 
> Thus if cdns,i2s-mc stays, then:
> 
> items:
>   - enum:
>       - starfive,jh8100-i2s
>   - cdns,i2s-mc
> 

OK, thanks Krzysztof and Mark. I will modify it in next patch.

Best regards,
Xingyu Wu

^ permalink raw reply

* RE: [PATCH v5 3/4] dt-bindings: clock: add i.MX95 clock header
From: Peng Fan @ 2024-04-01  7:26 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Peng Fan (OSS), Michael Turquette,
	Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Abel Vesa
  Cc: linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
	imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <31b493d1-ad74-48c7-8585-9df323418ae3@linaro.org>

> Subject: Re: [PATCH v5 3/4] dt-bindings: clock: add i.MX95 clock header
> 
> On 24/03/2024 08:52, Peng Fan (OSS) wrote:
> > From: Peng Fan <peng.fan@nxp.com>
> >
> > Add clock header for i.MX95 BLK CTL modules
> >
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > ---
> >  include/dt-bindings/clock/nxp,imx95-clock.h | 32
> +++++++++++++++++++++++++++++
> >  1 file changed, 32 insertions(+)
> >
> > diff --git a/include/dt-bindings/clock/nxp,imx95-clock.h b/include/dt-
> bindings/clock/nxp,imx95-clock.h
> > new file mode 100644
> > index 000000000000..83fa3ffe78a8
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/nxp,imx95-clock.h
> > @@ -0,0 +1,32 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
> > +/*
> > + * Copyright 2024 NXP
> > + */
> > +
> > +#ifndef __DT_BINDINGS_CLOCK_IMX95_H
> > +#define __DT_BINDINGS_CLOCK_IMX95_H
> > +
> > +#define IMX95_CLK_VPUBLK_WAVE			0
> > +#define IMX95_CLK_VPUBLK_JPEG_ENC		1
> > +#define IMX95_CLK_VPUBLK_JPEG_DEC		2
> > +#define IMX95_CLK_VPUBLK_END			3
> 
> No improvements, so again: drop counting.

Could you please give more details on what you think needs
to be addressed here? I may overlook your comments before,
but I search v1-v4, not find comments on the headers,
except the one file name align with binding if 1:1 match.

Thanks,
Peng.

> 
> Same in other places.
> 
> Best regards,
> Krzysztof


^ permalink raw reply

* [PATCH V3] schemas: pci: Extend the meaning of 'linux,pci-probe-only'
From: Vidya Sagar @ 2024-04-01  7:49 UTC (permalink / raw)
  To: robh, bhelgaas
  Cc: devicetree, linux-kernel, treding, jonathanh, kthota, mmaddireddy,
	vidyas, sagar.tv

Extend the meaning of 'linux,pci-probe-only' to cover the cases where
it is applicable only to a specific PCI host bridge if defined in a
PCI node instead of chosen node. Add the documentation for the same
in schemas/pci/pci-host-bridge.yaml

Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
---
V3:
* Addressed Rob's review comments

V2:
* Addressed Bjorn's review comments
 dtschema/schemas/chosen.yaml              |  7 +++++--
 dtschema/schemas/pci/pci-host-bridge.yaml | 11 +++++++++++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/dtschema/schemas/chosen.yaml b/dtschema/schemas/chosen.yaml
index 6d5c3f1..f806646 100644
--- a/dtschema/schemas/chosen.yaml
+++ b/dtschema/schemas/chosen.yaml
@@ -142,8 +142,11 @@ properties:
     enum: [ 0, 1 ]
     description:
       Optional property which takes a single-cell argument. If '0', then Linux
-      will assign devices in its usual manner, otherwise it will not try to
-      assign devices and instead use them as they are configured already.
+      will reassign BARs and bridge windows in its usual manner, otherwise it will
+      not try to reassign BARs and bridge windows, instead use them as they are
+      configured already by the platform firmware.
+      NOTE:- To restrict the applicability of this property to a specific PCI
+             host bridge, please refer to /schemas/pci/pci-host-bridge.yaml
 
   stdout-path:
     $ref: types.yaml#/definitions/string
diff --git a/dtschema/schemas/pci/pci-host-bridge.yaml b/dtschema/schemas/pci/pci-host-bridge.yaml
index fbbb829..e6665e7 100644
--- a/dtschema/schemas/pci/pci-host-bridge.yaml
+++ b/dtschema/schemas/pci/pci-host-bridge.yaml
@@ -31,6 +31,17 @@ properties:
       number for each host bridge in the system must be unique.
     $ref: /schemas/types.yaml#/definitions/uint32
 
+  linux,pci-probe-only:
+    $ref: types.yaml#/definitions/uint32
+    enum: [ 0, 1 ]
+    description:
+      Optional property which takes a single-cell argument. If '0', then Linux
+      will reassign BARs and bridge windows in its usual manner, otherwise it will
+      not try to reassign BARs and bridge windows, instead use them as they are
+      configured already by the platform firmware.
+      NOTE:- If defined in chosen node, this property has system wide applicability.
+             Please refer to /schemas/chosen.yaml for more info.
+
   msi-map:
     $ref: /schemas/types.yaml#/definitions/uint32-matrix
     items:
-- 
2.25.1


^ permalink raw reply related

* [PATCH V5] PCI: Add support for preserving boot configuration
From: Vidya Sagar @ 2024-04-01  7:50 UTC (permalink / raw)
  To: bhelgaas, rafael, lenb, will, lpieralisi, kw, robh, frowand.list
  Cc: linux-pci, linux-acpi, linux-kernel, linux-arm-kernel, devicetree,
	treding, jonathanh, kthota, mmaddireddy, vidyas, sagar.tv
In-Reply-To: <20240223080021.1692996-1-vidyas@nvidia.com>

Add support for preserving the boot configuration done by the
platform firmware per host bridge basis, based on the presence of
'linux,pci-probe-only' property in the respective PCI host bridge
device-tree node. It also unifies the ACPI and DT based boot flows
in this regard.

Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
---
V5:
* Addressed Rob's review comments

V4:
* Addressed Bjorn's review comments

V3:
* Unified ACPI and DT flows as part of addressing Bjorn's review comments

V2:
* Addressed issues reported by kernel test robot <lkp@intel.com>

 drivers/acpi/pci_root.c                  | 12 -----
 drivers/pci/controller/pci-host-common.c |  4 --
 drivers/pci/of.c                         | 57 +++++++++++++++++++-----
 drivers/pci/probe.c                      | 46 ++++++++++++++-----
 include/linux/of_pci.h                   |  6 +++
 5 files changed, 88 insertions(+), 37 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 84030804a763..ddc2b3e89111 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -1008,7 +1008,6 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
 	int node = acpi_get_node(device->handle);
 	struct pci_bus *bus;
 	struct pci_host_bridge *host_bridge;
-	union acpi_object *obj;
 
 	info->root = root;
 	info->bridge = device;
@@ -1050,17 +1049,6 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
 	if (!(root->osc_ext_control_set & OSC_CXL_ERROR_REPORTING_CONTROL))
 		host_bridge->native_cxl_error = 0;
 
-	/*
-	 * Evaluate the "PCI Boot Configuration" _DSM Function.  If it
-	 * exists and returns 0, we must preserve any PCI resource
-	 * assignments made by firmware for this host bridge.
-	 */
-	obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1,
-				DSM_PCI_PRESERVE_BOOT_CONFIG, NULL);
-	if (obj && obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 0)
-		host_bridge->preserve_config = 1;
-	ACPI_FREE(obj);
-
 	acpi_dev_power_up_children_with_adr(device);
 
 	pci_scan_child_bus(bus);
diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/controller/pci-host-common.c
index 6be3266cd7b5..e2602e38ae45 100644
--- a/drivers/pci/controller/pci-host-common.c
+++ b/drivers/pci/controller/pci-host-common.c
@@ -73,10 +73,6 @@ int pci_host_common_probe(struct platform_device *pdev)
 	if (IS_ERR(cfg))
 		return PTR_ERR(cfg);
 
-	/* Do not reassign resources if probe only */
-	if (!pci_has_flag(PCI_PROBE_ONLY))
-		pci_add_flags(PCI_REASSIGN_ALL_BUS);
-
 	bridge->sysdata = cfg;
 	bridge->ops = (struct pci_ops *)&ops->pci_ops;
 	bridge->msi_domain = true;
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 51e3dd0ea5ab..e6da3654f9ac 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -239,24 +239,61 @@ EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
  */
 void of_pci_check_probe_only(void)
 {
-	u32 val;
+	bool is_preserve_config = of_pci_bridge_preserve_resources(of_chosen);
+
+	if (is_preserve_config)
+		pci_add_flags(PCI_PROBE_ONLY);
+	else
+		pci_clear_flags(PCI_PROBE_ONLY);
+
+	pr_info("PROBE_ONLY %s\n", is_preserve_config ? "enabled" : "disabled");
+}
+EXPORT_SYMBOL_GPL(of_pci_check_probe_only);
+
+/**
+ * of_pci_bridge_preserve_resources - Return true if the boot configuration
+ *                                    needs to be preserved
+ * @node: Device tree node.
+ *
+ * This function looks for "linux,pci-probe-only" property for a given
+ * PCI controller's node and returns true if found. It will also look in the
+ * chosen node if the property is not found in the given controller's node.
+ * Having this property ensures that the kernel doesn't reconfigure the
+ * BARs and bridge windows that are already done by the platform firmware.
+ *
+ * Return: true if the property exists false otherwise.
+ */
+bool of_pci_bridge_preserve_resources(struct device_node *node)
+{
+	u32 val = 0;
 	int ret;
 
-	ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val);
+	if (!node) {
+		pr_warn("device node is NULL, trying with of_chosen\n");
+		node = of_chosen;
+	}
+
+retry:
+	ret = of_property_read_u32(node, "linux,pci-probe-only", &val);
 	if (ret) {
-		if (ret == -ENODATA || ret == -EOVERFLOW)
-			pr_warn("linux,pci-probe-only without valid value, ignoring\n");
-		return;
+		if (ret == -ENODATA || ret == -EOVERFLOW) {
+			pr_warn("Incorrect value for linux,pci-probe-only in %pOF, ignoring\n", node);
+			return false;
+		}
+		if (ret == -EINVAL) {
+			if (node == of_chosen)
+				return false;
+
+			node = of_chosen;
+			goto retry;
+		}
 	}
 
 	if (val)
-		pci_add_flags(PCI_PROBE_ONLY);
+		return true;
 	else
-		pci_clear_flags(PCI_PROBE_ONLY);
-
-	pr_info("PROBE_ONLY %s\n", val ? "enabled" : "disabled");
+		return false;
 }
-EXPORT_SYMBOL_GPL(of_pci_check_probe_only);
 
 /**
  * devm_of_pci_get_host_bridge_resources() - Resource-managed parsing of PCI
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 795534589b98..b0e0226a8da8 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -15,6 +15,7 @@
 #include <linux/cpumask.h>
 #include <linux/aer.h>
 #include <linux/acpi.h>
+#include <linux/pci-acpi.h>
 #include <linux/hypervisor.h>
 #include <linux/irqdomain.h>
 #include <linux/pm_runtime.h>
@@ -877,6 +878,28 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus)
 	dev_set_msi_domain(&bus->dev, d);
 }
 
+static void pci_check_config_preserve(struct pci_host_bridge *host_bridge)
+{
+	if (ACPI_HANDLE(&host_bridge->dev)) {
+		union acpi_object *obj;
+
+		/*
+		 * Evaluate the "PCI Boot Configuration" _DSM Function.  If it
+		 * exists and returns 0, we must preserve any PCI resource
+		 * assignments made by firmware for this host bridge.
+		 */
+		obj = acpi_evaluate_dsm(ACPI_HANDLE(&host_bridge->dev), &pci_acpi_dsm_guid, 1,
+					DSM_PCI_PRESERVE_BOOT_CONFIG, NULL);
+		if (obj && obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 0)
+			host_bridge->preserve_config = 1;
+		ACPI_FREE(obj);
+	}
+
+	if (host_bridge->dev.parent && host_bridge->dev.parent->of_node)
+		host_bridge->preserve_config =
+			of_pci_bridge_preserve_resources(host_bridge->dev.parent->of_node);
+}
+
 static int pci_register_host_bridge(struct pci_host_bridge *bridge)
 {
 	struct device *parent = bridge->dev.parent;
@@ -971,6 +994,9 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
 	if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE)
 		dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n");
 
+	/* Check if the boot configuration by FW needs to be preserved */
+	pci_check_config_preserve(bridge);
+
 	/* Coalesce contiguous windows */
 	resource_list_for_each_entry_safe(window, n, &resources) {
 		if (list_is_last(&window->node, &resources))
@@ -3080,20 +3106,18 @@ int pci_host_probe(struct pci_host_bridge *bridge)
 
 	bus = bridge->bus;
 
+	/* If we must preserve the resource configuration, claim now */
+	if (bridge->preserve_config)
+		pci_bus_claim_resources(bus);
+
 	/*
-	 * We insert PCI resources into the iomem_resource and
-	 * ioport_resource trees in either pci_bus_claim_resources()
-	 * or pci_bus_assign_resources().
+	 * Assign whatever was left unassigned. If we didn't claim above,
+	 * this will reassign everything.
 	 */
-	if (pci_has_flag(PCI_PROBE_ONLY)) {
-		pci_bus_claim_resources(bus);
-	} else {
-		pci_bus_size_bridges(bus);
-		pci_bus_assign_resources(bus);
+	pci_assign_unassigned_root_bus_resources(bus);
 
-		list_for_each_entry(child, &bus->children, node)
-			pcie_bus_configure_settings(child);
-	}
+	list_for_each_entry(child, &bus->children, node)
+		pcie_bus_configure_settings(child);
 
 	pci_bus_add_devices(bus);
 	return 0;
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 29658c0ee71f..3f3909a5d55d 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -13,6 +13,7 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 					     unsigned int devfn);
 int of_pci_get_devfn(struct device_node *np);
 void of_pci_check_probe_only(void);
+bool of_pci_bridge_preserve_resources(struct device_node *node);
 #else
 static inline struct device_node *of_pci_find_child_device(struct device_node *parent,
 					     unsigned int devfn)
@@ -26,6 +27,11 @@ static inline int of_pci_get_devfn(struct device_node *np)
 }
 
 static inline void of_pci_check_probe_only(void) { }
+
+static inline bool of_pci_bridge_preserve_resources(struct device_node *node)
+{
+	return false;
+}
 #endif
 
 #if IS_ENABLED(CONFIG_OF_IRQ)
-- 
2.25.1


^ permalink raw reply related

* [PATCH] arm64: dts: rockchip: remove startup-delay-us from vcc3v3_pcie2x1l0 on rock-5b
From: Jianfeng Liu @ 2024-04-01  8:13 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
  Cc: robh, krzysztof.kozlowski+dt, conor+dt, heiko, sfr,
	liujianfeng1994

Property startup-delay-us is copied from vendor dts and it will
make kernel not detect pcie wifi device. If I run command:
"echo 1 > /sys/bus/pci/rescan", pcie wifi device is detected, but
my wifi device RTL8822CE failed to load driver. Another device
RTL8723BE can load driver but no wifi signal is detected.

Removing this property will fix issues above.

Signed-off-by: Jianfeng Liu <liujianfeng1994@gmail.com>
---
 arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index d6bf2ee07..a9af654a0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -76,7 +76,6 @@ vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator {
 		regulator-boot-on;
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
-		startup-delay-us = <50000>;
 		vin-supply = <&vcc5v0_sys>;
 	};

--
2.34.1


^ permalink raw reply related

* Re: [PATCH] iio: industrialio-core: look for aliases to request device index
From: Dominique Martinet @ 2024-04-01  8:18 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Jonathan Cameron, David Lechner, Krzysztof Kozlowski,
	Syunya Ohshio, Guido Günther, Lars-Peter Clausen,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-iio,
	devicetree, linux-kernel
In-Reply-To: <20240331152042.394b4289@jic23-huawei>

Jonathan Cameron wrote on Sun, Mar 31, 2024 at 03:20:42PM +0100:
> Hi, got back to this finally...

Thank you for taking the time to express your thoughts!

> So the problems compared to other 'alias' users is that IIO is a bit more
> complex than for example LEDs.  A single DT node/compatible (or equivalent) can
> result in a 1+ IIO devices and 1+ triggers.

Right. I'm no longer really arguing for it at this point, but for
comparison in the patch I sent, the alias sets the start of the idr for
the device index, so if you have a driver that creates two IIO devices
you could just "reserve" two for this DT node and assuming the order
within this node is constant you'd still get constant numbering, so I
think it still somewhat holds up here.

For triggers though the numbers are separate and it wouldn't make sense
to use the same alias, if we wanted a coherent design with this we'd
need to add a second alias (such as iio_trigger = ..), but that makes
much less sense to me given they're also likely to be dynamically
instancied via configfs from what I've seen; I wouldn't want to do this
kind of mapping, so I agree with you.

> So I've messed around a bit and can think of various possible options to make
> this simpler.
> 1) Use a tmpfs mount and link from that.
>    Now we 'could' put an alias directory somewhere under /sys/bus/iio/ that
>    is a mount point created via sysfs_create_mount_point() - I abused the
>    /sys/kernel/debug directory to test this (unmounted debugfs and mounted
>    a tmpfs).  That would provide somewhere in sysfs that allows suitable
>    links. However, this is unusual so likely to be controversial.

Agreed that's probably not something we want to put our hands into.

> 2) Alternatively the relevant platform could create one of these somewhere
>    outside of sysfs and use udev rules to create the links.

I'm not sure I understood this one, something akin to the udev rules
I've showed that made links to the /sys iio device in /dev?
"relevant platform" here would be vendors?

> 3) Stick to the oddity of doing it under /dev/
> 4) Access the things in the first place via more stable paths?
>   /sys/bus/i2c/devices/i2c-0/0-0008/iio\:device?/ etc 
>    Relying on the alias support for i2c bus numbering to make that stable should work
>    and if you are sure there will only be one entry (most devices) that matches
>    the wild card, should be easy enough to use in scripts.
> 
> My personal preference is this last option.  Basically if you want stable paths
> don't use /sys/bus/iio/devices/ to get them.

Hmm, I wouldn't call that path stable given the '?' portion can change,
but at least that certainly is a single glob away so it's definitely
simpler than checking every labels all the time.

My second nitpick with this is that while these paths are stable for a
given kernel version, but we've had some paths changes over many years
(not sure if it was 3.14 or 4.9 but one of these perhaps didn't have
/sys/devices/platform yet? and things got moved there at some point with
some subtle name changes, breaking a couple of scripts).
OTOH /sys/bus/iio/devices feels less likely to change, but I guess this
is something that'd come up on tests when preparing a new kernel anyway,
so this is probably acceptable; I'm just thinking out loud.


With that said I can't think of anything that'd work everywhere either,
so I guess we can stick to the status-quo and I'll rediscuss what we
want to do with coworkers.


Thanks,
-- 
Dominique



^ permalink raw reply

* [PATCH v3] dt-bindings: mfd: twl: Convert trivial subdevices to json-schema
From: Andreas Kemnade @ 2024-04-01  8:18 UTC (permalink / raw)
  To: dmitry.torokhov, robh, krzysztof.kozlowski+dt, conor+dt, lee,
	alexandre.belloni, wim, linux, andreas, linux-input, devicetree,
	linux-kernel, linux-rtc, linux-watchdog, sre

Convert subdevices with just an interrupt and compatbile to
json-schema and wire up already converted subdevices.
RTC is available in all variants, so allow it unconditionally.
GPADC binding for TWL603X uses two different compatibles, so
specify just the compatible and do not include it.

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
Acked-by: Guenter Roeck <linux@roeck-us.net>
---
Changes in v3:
- added Ack
  (apparantly many recipients did not receive the V2 patch,
   so there is a need for a resend)

Changes in v2:
- style cleanup
- absolute paths
- unevalutedProperties instead of additionalProperties
  due to not accepting things in if: clauses without it

 .../bindings/input/twl4030-pwrbutton.txt      | 21 ------
 .../devicetree/bindings/mfd/ti,twl.yaml       | 72 ++++++++++++++++++-
 .../devicetree/bindings/rtc/twl-rtc.txt       | 11 ---
 .../bindings/watchdog/twl4030-wdt.txt         | 10 ---
 4 files changed, 71 insertions(+), 43 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
 delete mode 100644 Documentation/devicetree/bindings/rtc/twl-rtc.txt
 delete mode 100644 Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt

diff --git a/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt b/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
deleted file mode 100644
index 6c201a2ba8acf..0000000000000
--- a/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Texas Instruments TWL family (twl4030) pwrbutton module
-
-This module is part of the TWL4030. For more details about the whole
-chip see Documentation/devicetree/bindings/mfd/ti,twl.yaml.
-
-This module provides a simple power button event via an Interrupt.
-
-Required properties:
-- compatible: should be one of the following
-   - "ti,twl4030-pwrbutton": For controllers compatible with twl4030
-- interrupts: should be one of the following
-   - <8>: For controllers compatible with twl4030
-
-Example:
-
-&twl {
-	twl_pwrbutton: pwrbutton {
-		compatible = "ti,twl4030-pwrbutton";
-		interrupts = <8>;
-	};
-};
diff --git a/Documentation/devicetree/bindings/mfd/ti,twl.yaml b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
index 52ed228fb1e7e..c2357fecb56cc 100644
--- a/Documentation/devicetree/bindings/mfd/ti,twl.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
@@ -15,6 +15,67 @@ description: |
   USB transceiver or Audio amplifier.
   These chips are connected to an i2c bus.
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,twl4030
+    then:
+      properties:
+        madc:
+          type: object
+          $ref: /schemas/iio/adc/ti,twl4030-madc.yaml
+          unevaluatedProperties: false
+
+        bci:
+          type: object
+          $ref: /schemas/power/supply/twl4030-charger.yaml
+          unevaluatedProperties: false
+
+        pwrbutton:
+          type: object
+          additionalProperties: false
+          properties:
+            compatible:
+              const: ti,twl4030-pwrbutton
+            interrupts:
+              items:
+                - items:
+                    const: 8
+
+        watchdog:
+          type: object
+          additionalProperties: false
+          properties:
+            compatible:
+              const: ti,twl4030-wdt
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,twl6030
+    then:
+      properties:
+        gpadc:
+          type: object
+          properties:
+            compatible:
+              const: ti,twl6030-gpadc
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,twl6032
+    then:
+      properties:
+        gpadc:
+          type: object
+          properties:
+            compatible:
+              const: ti,twl6032-gpadc
+
 properties:
   compatible:
     description:
@@ -42,7 +103,16 @@ properties:
   "#clock-cells":
     const: 1
 
-additionalProperties: false
+  rtc:
+    type: object
+    additionalProperties: false
+    properties:
+      compatible:
+        const: ti,twl4030-rtc
+      interrupts:
+        maxItems: 1
+
+unevaluatedProperties: false
 
 required:
   - compatible
diff --git a/Documentation/devicetree/bindings/rtc/twl-rtc.txt b/Documentation/devicetree/bindings/rtc/twl-rtc.txt
deleted file mode 100644
index 8f9a94f2f8969..0000000000000
--- a/Documentation/devicetree/bindings/rtc/twl-rtc.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-* Texas Instruments TWL4030/6030 RTC
-
-Required properties:
-- compatible : Should be "ti,twl4030-rtc"
-- interrupts : Should be the interrupt number.
-
-Example:
-	rtc {
-		compatible = "ti,twl4030-rtc";
-		interrupts = <11>;
-	};
diff --git a/Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt b/Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt
deleted file mode 100644
index 80a37193c0b86..0000000000000
--- a/Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Device tree bindings for twl4030-wdt driver (TWL4030 watchdog)
-
-Required properties:
-	compatible = "ti,twl4030-wdt";
-
-Example:
-
-watchdog {
-	compatible = "ti,twl4030-wdt";
-};
-- 
2.39.2


^ permalink raw reply related


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