* [PATCH v4 1/6] dt-bindings: PCI: rcar-gen4-pci-host: Add R-Car X5H PCIe4 compatible
2026-09-05 21:26 [PATCH v4 0/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
@ 2026-09-05 21:26 ` Marek Vasut
2026-09-05 21:26 ` [PATCH v4 2/6] PCI: dwc: rcar-gen4: Rework rcar_gen4_pcie_drvdata .additional_common_init into .init Marek Vasut
` (4 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2026-09-05 21:26 UTC (permalink / raw)
To: linux-pci
Cc: Marek Vasut, Krzysztof Kozlowski, Krzysztof Wilczyński,
Bjorn Helgaas, Conor Dooley, Geert Uytterhoeven,
Krzysztof Kozlowski, Lorenzo Pieralisi, Manivannan Sadhasivam,
Rob Herring, Yoshihiro Shimoda, devicetree, linux-kernel,
linux-renesas-soc
Document bindings for R-Car X5H (R8A78000) PCIe4 host module.
The binding document is deliberately using "renesas,rcar-gen5-pcie4"
DT compatible string to discern R-Car X5H PCIe4 controller supported
by this binding, from R-Car X5H PCIe6 controller which will use a
separate binding.
The R-Car X5H PCIe4 controller does no longer include PHY register
range, the PHY is now a separate IP and referenced via the 'phy' DT
property. The 'reg' and 'reg-names' DT properties therefore differ
between R-Car Gen4 PCIe and R-Car X5H PCIe4, and the difference is
handled in the allOf section.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
V2: Add RB from Krzysztof
V3: No change
V4: Rebase on next-20260904
---
.../bindings/pci/rcar-gen4-pci-host.yaml | 74 +++++++++++++------
1 file changed, 52 insertions(+), 22 deletions(-)
diff --git a/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml
index 64f456c6a75a1..9767a52f3904e 100644
--- a/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml
+++ b/Documentation/devicetree/bindings/pci/rcar-gen4-pci-host.yaml
@@ -10,30 +10,20 @@ title: Renesas R-Car Gen4 PCIe Host
maintainers:
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-allOf:
- - $ref: snps,dw-pcie.yaml#
-
properties:
compatible:
- items:
- - enum:
- - renesas,r8a779f0-pcie # R-Car S4-8
- - renesas,r8a779g0-pcie # R-Car V4H
- - renesas,r8a779h0-pcie # R-Car V4M
- - const: renesas,rcar-gen4-pcie # R-Car Gen4
-
- reg:
- maxItems: 7
-
- reg-names:
- items:
- - const: dbi
- - const: dbi2
- - const: atu
- - const: dma
- - const: app
- - const: phy
- - const: config
+ oneOf:
+ - items:
+ - enum:
+ - renesas,r8a779f0-pcie # R-Car S4-8
+ - renesas,r8a779g0-pcie # R-Car V4H
+ - renesas,r8a779h0-pcie # R-Car V4M
+ - const: renesas,rcar-gen4-pcie # R-Car Gen4
+
+ - items:
+ - enum:
+ - renesas,r8a78000-pcie4 # R-Car X5H PCIe4
+ - const: renesas,rcar-gen5-pcie4 # R-Car Gen5 PCIe4
interrupts:
maxItems: 4
@@ -84,6 +74,46 @@ required:
- resets
- reset-names
+allOf:
+ - $ref: snps,dw-pcie.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,rcar-gen4-pcie
+ then:
+ properties:
+ reg:
+ maxItems: 7
+
+ reg-names:
+ items:
+ - const: dbi
+ - const: dbi2
+ - const: atu
+ - const: dma
+ - const: app
+ - const: phy
+ - const: config
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,rcar-gen5-pcie4
+ then:
+ properties:
+ reg:
+ maxItems: 6
+
+ reg-names:
+ items:
+ - const: dbi
+ - const: dbi2
+ - const: atu
+ - const: dma
+ - const: app
+ - const: config
+
unevaluatedProperties: false
examples:
--
2.53.0
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v4 2/6] PCI: dwc: rcar-gen4: Rework rcar_gen4_pcie_drvdata .additional_common_init into .init
2026-09-05 21:26 [PATCH v4 0/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
2026-09-05 21:26 ` [PATCH v4 1/6] dt-bindings: PCI: rcar-gen4-pci-host: Add R-Car X5H PCIe4 compatible Marek Vasut
@ 2026-09-05 21:26 ` Marek Vasut
2026-09-05 21:26 ` [PATCH v4 3/6] PCI: dwc: rcar-gen4: Add .deinit callback Marek Vasut
` (3 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2026-09-05 21:26 UTC (permalink / raw)
To: linux-pci
Cc: Marek Vasut, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Manivannan Sadhasivam, Rob Herring,
Yoshihiro Shimoda, devicetree, linux-kernel, linux-renesas-soc
Rework the current complicated initialization callchain that invokes
host_init->common_init->additional_common_init() for host and
ep_init->common_init->additional_common_init() for endpoint into
simpler host_init->init() and ep_init->init() .
The init callback is now always implmented for all R-Car Gen4 SoCs,
therefore there is no need to check whether the callback is not NULL.
For R-Car S4 the .init callback is rcar_gen4_pcie_common_init(),
for R-Car V4H and V4M the .init callback is implemented using a
new function rcar_gen4_v4h_v4m_pcie_init() which calls the common
rcar_gen4_pcie_common_init() followed by R-Car V4H and V4M specific
hardware initialization. The hardware initialization sequence remains
unchanged.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
V2: Rename additional_common_init to init, reworked from previous patch
PCI: dwc: rcar-gen4: Return error code from .additional_common_init
V3: No change
V4: Rebase on next-20260904
---
drivers/pci/controller/dwc/pcie-rcar-gen4.c | 56 ++++++++++++---------
1 file changed, 32 insertions(+), 24 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index 5a076aa3f4904..a19ebbab2f8c3 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -87,7 +87,7 @@ MODULE_FIRMWARE(RCAR_GEN4_PCIE_FIRMWARE_NAME);
struct rcar_gen4_pcie;
struct rcar_gen4_pcie_drvdata {
- void (*additional_common_init)(struct rcar_gen4_pcie *rcar);
+ int (*init)(struct rcar_gen4_pcie *rcar);
int (*ltssm_control)(struct rcar_gen4_pcie *rcar, bool enable);
enum dw_pcie_device_mode mode;
};
@@ -241,9 +241,6 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
reset_control_status(dw->core_rsts[DW_PCIE_PWR_RST].rstc);
fsleep(1000);
- if (rcar->drvdata->additional_common_init)
- rcar->drvdata->additional_common_init(rcar);
-
return 0;
err_unprepare:
@@ -252,6 +249,31 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar)
return ret;
}
+static int rcar_gen4_v4h_v4m_pcie_init(struct rcar_gen4_pcie *rcar)
+{
+ struct dw_pcie *dw = &rcar->dw;
+ u32 val;
+ int ret;
+
+ /* R-Car Gen4 common initialization. */
+ ret = rcar_gen4_pcie_common_init(rcar);
+ if (ret)
+ return ret;
+
+ /* R-Car V4H and V4M specific additional initialization. */
+ 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);
+
+ return 0;
+}
+
static void rcar_gen4_pcie_common_deinit(struct rcar_gen4_pcie *rcar)
{
struct dw_pcie *dw = &rcar->dw;
@@ -474,7 +496,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
gpiod_set_value_cansleep(dw->pe_rst, 1);
- ret = rcar_gen4_pcie_common_init(rcar);
+ ret = rcar->drvdata->init(rcar);
if (ret)
return ret;
@@ -543,7 +565,7 @@ static int rcar_gen4_pcie_ep_pre_init(struct dw_pcie_ep *ep)
writel(0, rcar->base + PCIEDMAINTSTSEN);
- ret = rcar_gen4_pcie_common_init(rcar);
+ ret = rcar->drvdata->init(rcar);
if (ret)
return ret;
@@ -739,22 +761,6 @@ static int r8a779f0_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
return 0;
}
-static void rcar_gen4_pcie_additional_common_init(struct rcar_gen4_pcie *rcar)
-{
- struct dw_pcie *dw = &rcar->dw;
- u32 val;
-
- 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 void rcar_gen4_pcie_phy_reg_update_bits(struct rcar_gen4_pcie *rcar,
u32 offset, u32 mask, u32 val)
{
@@ -906,23 +912,25 @@ static int rcar_gen4_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable
}
static struct rcar_gen4_pcie_drvdata drvdata_r8a779f0_pcie = {
+ .init = rcar_gen4_pcie_common_init,
.ltssm_control = r8a779f0_pcie_ltssm_control,
.mode = DW_PCIE_RC_TYPE,
};
static struct rcar_gen4_pcie_drvdata drvdata_r8a779f0_pcie_ep = {
+ .init = rcar_gen4_pcie_common_init,
.ltssm_control = r8a779f0_pcie_ltssm_control,
.mode = DW_PCIE_EP_TYPE,
};
static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie = {
- .additional_common_init = rcar_gen4_pcie_additional_common_init,
+ .init = rcar_gen4_v4h_v4m_pcie_init,
.ltssm_control = rcar_gen4_pcie_ltssm_control,
.mode = DW_PCIE_RC_TYPE,
};
static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie_ep = {
- .additional_common_init = rcar_gen4_pcie_additional_common_init,
+ .init = rcar_gen4_v4h_v4m_pcie_init,
.ltssm_control = rcar_gen4_pcie_ltssm_control,
.mode = DW_PCIE_EP_TYPE,
};
--
2.53.0
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v4 3/6] PCI: dwc: rcar-gen4: Add .deinit callback
2026-09-05 21:26 [PATCH v4 0/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
2026-09-05 21:26 ` [PATCH v4 1/6] dt-bindings: PCI: rcar-gen4-pci-host: Add R-Car X5H PCIe4 compatible Marek Vasut
2026-09-05 21:26 ` [PATCH v4 2/6] PCI: dwc: rcar-gen4: Rework rcar_gen4_pcie_drvdata .additional_common_init into .init Marek Vasut
@ 2026-09-05 21:26 ` Marek Vasut
2026-09-05 21:26 ` [PATCH v4 4/6] PCI: dwc: rcar-gen4: Split .start_link into ltssm_control and speed_control Marek Vasut
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2026-09-05 21:26 UTC (permalink / raw)
To: linux-pci
Cc: Marek Vasut, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Manivannan Sadhasivam, Rob Herring,
Yoshihiro Shimoda, devicetree, linux-kernel, linux-renesas-soc
Add .deinit callback in preparation for R-Car Gen5 support. The
.deinit callback will be used to tear down the PHY on R-Car Gen5.
Thus far, it does what rcar_gen4_pcie_common_deinit() used to do
directly.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
V3: New patch
V4: Rebase on next-20260904
---
drivers/pci/controller/dwc/pcie-rcar-gen4.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index a19ebbab2f8c3..04871ac11c348 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -88,6 +88,7 @@ MODULE_FIRMWARE(RCAR_GEN4_PCIE_FIRMWARE_NAME);
struct rcar_gen4_pcie;
struct rcar_gen4_pcie_drvdata {
int (*init)(struct rcar_gen4_pcie *rcar);
+ void (*deinit)(struct rcar_gen4_pcie *rcar);
int (*ltssm_control)(struct rcar_gen4_pcie *rcar, bool enable);
enum dw_pcie_device_mode mode;
};
@@ -520,7 +521,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
return 0;
err:
- rcar_gen4_pcie_common_deinit(rcar);
+ rcar->drvdata->deinit(rcar);
return ret;
}
@@ -530,7 +531,7 @@ static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp)
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
gpiod_set_value_cansleep(dw->pe_rst, 1);
- rcar_gen4_pcie_common_deinit(rcar);
+ rcar->drvdata->deinit(rcar);
}
static const struct dw_pcie_host_ops rcar_gen4_pcie_host_ops = {
@@ -580,7 +581,7 @@ static void rcar_gen4_pcie_ep_post_deinit(struct dw_pcie_ep *ep)
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
writel(0, rcar->base + PCIEDMAINTSTSEN);
- rcar_gen4_pcie_common_deinit(rcar);
+ rcar->drvdata->deinit(rcar);
}
static int rcar_gen4_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
@@ -913,24 +914,28 @@ static int rcar_gen4_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable
static struct rcar_gen4_pcie_drvdata drvdata_r8a779f0_pcie = {
.init = rcar_gen4_pcie_common_init,
+ .deinit = rcar_gen4_pcie_common_deinit,
.ltssm_control = r8a779f0_pcie_ltssm_control,
.mode = DW_PCIE_RC_TYPE,
};
static struct rcar_gen4_pcie_drvdata drvdata_r8a779f0_pcie_ep = {
.init = rcar_gen4_pcie_common_init,
+ .deinit = rcar_gen4_pcie_common_deinit,
.ltssm_control = r8a779f0_pcie_ltssm_control,
.mode = DW_PCIE_EP_TYPE,
};
static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie = {
.init = rcar_gen4_v4h_v4m_pcie_init,
+ .deinit = rcar_gen4_pcie_common_deinit,
.ltssm_control = rcar_gen4_pcie_ltssm_control,
.mode = DW_PCIE_RC_TYPE,
};
static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie_ep = {
.init = rcar_gen4_v4h_v4m_pcie_init,
+ .deinit = rcar_gen4_pcie_common_deinit,
.ltssm_control = rcar_gen4_pcie_ltssm_control,
.mode = DW_PCIE_EP_TYPE,
};
--
2.53.0
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v4 4/6] PCI: dwc: rcar-gen4: Split .start_link into ltssm_control and speed_control
2026-09-05 21:26 [PATCH v4 0/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
` (2 preceding siblings ...)
2026-09-05 21:26 ` [PATCH v4 3/6] PCI: dwc: rcar-gen4: Add .deinit callback Marek Vasut
@ 2026-09-05 21:26 ` Marek Vasut
2026-09-05 21:26 ` [PATCH v4 5/6] PCI: dwc: rcar-gen4: Handle PERST via reset subsystem Marek Vasut
2026-09-05 21:26 ` [PATCH v4 6/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
5 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2026-09-05 21:26 UTC (permalink / raw)
To: linux-pci
Cc: Marek Vasut, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Manivannan Sadhasivam, Rob Herring,
Yoshihiro Shimoda, devicetree, linux-kernel, linux-renesas-soc
Introduce new .speed_control callback and implement it on R-Car Gen4.
The callback implements the second half of what is currently present
in rcar_gen4_pcie_start_link(), and rcar_gen4_pcie_start_link() does
call the .speed_control callback. This is a preparatory patch for
R-Car Gen5 support, where the .speed_control implementation is
different.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
V2: No change
V3: No change
V4: Rebase on next-20260904
---
drivers/pci/controller/dwc/pcie-rcar-gen4.c | 39 ++++++++++++++-------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index 04871ac11c348..c768a9c7b3b76 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -90,6 +90,7 @@ struct rcar_gen4_pcie_drvdata {
int (*init)(struct rcar_gen4_pcie *rcar);
void (*deinit)(struct rcar_gen4_pcie *rcar);
int (*ltssm_control)(struct rcar_gen4_pcie *rcar, bool enable);
+ int (*speed_control)(struct rcar_gen4_pcie *rcar);
enum dw_pcie_device_mode mode;
};
@@ -141,20 +142,10 @@ static int rcar_gen4_pcie_speed_change(struct dw_pcie *dw)
return -ETIMEDOUT;
}
-/*
- * Enable LTSSM of this controller and manually initiate the speed change.
- * Always return 0.
- */
-static int rcar_gen4_pcie_start_link(struct dw_pcie *dw)
+static int rcar_gen4_pcie_speed_control(struct rcar_gen4_pcie *rcar)
{
- struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
- int i, changes, ret;
-
- if (rcar->drvdata->ltssm_control) {
- ret = rcar->drvdata->ltssm_control(rcar, true);
- if (ret)
- return ret;
- }
+ struct dw_pcie *dw = &rcar->dw;
+ int i, changes;
/*
* Require direct speed change with retrying here if the max_link_speed
@@ -178,6 +169,24 @@ static int rcar_gen4_pcie_start_link(struct dw_pcie *dw)
return 0;
}
+/*
+ * Enable LTSSM of this controller and manually initiate the speed change.
+ * Always return 0.
+ */
+static int rcar_gen4_pcie_start_link(struct dw_pcie *dw)
+{
+ struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
+ int ret;
+
+ if (rcar->drvdata->ltssm_control) {
+ ret = rcar->drvdata->ltssm_control(rcar, true);
+ if (ret)
+ return ret;
+ }
+
+ return rcar->drvdata->speed_control(rcar);
+}
+
static void rcar_gen4_pcie_stop_link(struct dw_pcie *dw)
{
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
@@ -916,6 +925,7 @@ static struct rcar_gen4_pcie_drvdata drvdata_r8a779f0_pcie = {
.init = rcar_gen4_pcie_common_init,
.deinit = rcar_gen4_pcie_common_deinit,
.ltssm_control = r8a779f0_pcie_ltssm_control,
+ .speed_control = rcar_gen4_pcie_speed_control,
.mode = DW_PCIE_RC_TYPE,
};
@@ -923,6 +933,7 @@ static struct rcar_gen4_pcie_drvdata drvdata_r8a779f0_pcie_ep = {
.init = rcar_gen4_pcie_common_init,
.deinit = rcar_gen4_pcie_common_deinit,
.ltssm_control = r8a779f0_pcie_ltssm_control,
+ .speed_control = rcar_gen4_pcie_speed_control,
.mode = DW_PCIE_EP_TYPE,
};
@@ -930,6 +941,7 @@ static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie = {
.init = rcar_gen4_v4h_v4m_pcie_init,
.deinit = rcar_gen4_pcie_common_deinit,
.ltssm_control = rcar_gen4_pcie_ltssm_control,
+ .speed_control = rcar_gen4_pcie_speed_control,
.mode = DW_PCIE_RC_TYPE,
};
@@ -937,6 +949,7 @@ static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie_ep = {
.init = rcar_gen4_v4h_v4m_pcie_init,
.deinit = rcar_gen4_pcie_common_deinit,
.ltssm_control = rcar_gen4_pcie_ltssm_control,
+ .speed_control = rcar_gen4_pcie_speed_control,
.mode = DW_PCIE_EP_TYPE,
};
--
2.53.0
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v4 5/6] PCI: dwc: rcar-gen4: Handle PERST via reset subsystem
2026-09-05 21:26 [PATCH v4 0/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
` (3 preceding siblings ...)
2026-09-05 21:26 ` [PATCH v4 4/6] PCI: dwc: rcar-gen4: Split .start_link into ltssm_control and speed_control Marek Vasut
@ 2026-09-05 21:26 ` Marek Vasut
2026-09-21 15:46 ` Manivannan Sadhasivam
2026-09-05 21:26 ` [PATCH v4 6/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
5 siblings, 1 reply; 11+ messages in thread
From: Marek Vasut @ 2026-09-05 21:26 UTC (permalink / raw)
To: linux-pci
Cc: Marek Vasut, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Manivannan Sadhasivam, Rob Herring,
Yoshihiro Shimoda, devicetree, linux-kernel, linux-renesas-soc
Handle PERST via both GPIO and reset subsystem. On R-Car Gen4, the
PERST signal is operated as a GPIO, on R-Car Gen5 it might only be
accessible via SCMI reset via reset subsystem. Support both options.
This is a preparatory patch for R-Car Gen5 support.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
V2: - Use dev_err_probe() for perst in rcar_gen4_pcie_get_resources()
- Use of_get_next_available_child() to obtain root port OF node
- Switch to of_reset_control_get_optional_exclusive() to deal with
R-Car Gen4, where the PERST is handled as GPIO instead of reset
- Rename rcar_gen4_pcie_host_perst() to rcar_gen4_pcie_host_perst_assert()
and use bool type for assert and deassert selection
- Add missing reset_control_put() into rcar_gen4_pcie_probe() fail path
V3: - Handle controllers without root port DT node
- Swap fail path order
V4: Rebase on next-20260904
---
drivers/pci/controller/dwc/pcie-rcar-gen4.c | 44 +++++++++++++++++++--
1 file changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index c768a9c7b3b76..89472a4becc46 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -99,6 +99,7 @@ struct rcar_gen4_pcie {
void __iomem *base;
void __iomem *phy_base;
struct platform_device *pdev;
+ struct reset_control *perst;
const struct rcar_gen4_pcie_drvdata *drvdata;
};
#define to_rcar_gen4_pcie(_dw) container_of(_dw, struct rcar_gen4_pcie, dw)
@@ -317,12 +318,27 @@ static void rcar_gen4_pcie_unprepare(struct rcar_gen4_pcie *rcar)
static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
{
+ struct device *dev = rcar->dw.dev;
+ struct device_node *root_port;
+
rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
if (IS_ERR(rcar->phy_base))
return PTR_ERR(rcar->phy_base);
+ root_port = of_get_next_available_child(dev->of_node, NULL);
+ if (root_port) {
+ rcar->perst = of_reset_control_get_optional_exclusive(root_port, "perst");
+ of_node_put(root_port);
+ if (IS_ERR(rcar->perst))
+ return dev_err_probe(dev, PTR_ERR(rcar->perst), "Failed to get PERST#\n");
+ } else {
+ rcar->perst = NULL;
+ }
+
/* Renesas-specific registers */
rcar->base = devm_platform_ioremap_resource_byname(rcar->pdev, "app");
+ if (IS_ERR(rcar->base))
+ reset_control_put(rcar->perst);
return PTR_ERR_OR_ZERO(rcar->base);
}
@@ -494,6 +510,22 @@ static int rcar_gen4_pcie_enable_device(struct pci_host_bridge *bridge,
return 0;
}
+static void rcar_gen4_pcie_host_perst_assert(struct dw_pcie_rp *pp, bool assert)
+{
+ struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
+ struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
+
+ gpiod_set_value_cansleep(dw->pe_rst, assert);
+
+ if (!rcar->perst)
+ return;
+
+ if (assert)
+ reset_control_assert(rcar->perst);
+ else
+ reset_control_deassert(rcar->perst);
+}
+
/* Host mode */
static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
{
@@ -504,7 +536,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
if (pp->bridge)
pp->bridge->enable_device = rcar_gen4_pcie_enable_device;
- gpiod_set_value_cansleep(dw->pe_rst, 1);
+ rcar_gen4_pcie_host_perst_assert(pp, true);
ret = rcar->drvdata->init(rcar);
if (ret)
@@ -525,7 +557,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
msleep(PCIE_T_PVPERL_MS); /* pe_rst requires 100msec delay */
- gpiod_set_value_cansleep(dw->pe_rst, 0);
+ rcar_gen4_pcie_host_perst_assert(pp, false);
return 0;
@@ -539,7 +571,7 @@ static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp)
struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
- gpiod_set_value_cansleep(dw->pe_rst, 1);
+ rcar_gen4_pcie_host_perst_assert(pp, true);
rcar->drvdata->deinit(rcar);
}
@@ -713,7 +745,7 @@ static int rcar_gen4_pcie_probe(struct platform_device *pdev)
err = rcar_gen4_pcie_prepare(rcar);
if (err)
- return err;
+ goto err_prepare;
err = rcar_gen4_add_dw_pcie(rcar);
if (err)
@@ -724,6 +756,9 @@ static int rcar_gen4_pcie_probe(struct platform_device *pdev)
err_unprepare:
rcar_gen4_pcie_unprepare(rcar);
+err_prepare:
+ reset_control_put(rcar->perst);
+
return err;
}
@@ -747,6 +782,7 @@ static void rcar_gen4_pcie_remove(struct platform_device *pdev)
rcar_gen4_remove_dw_pcie(rcar);
rcar_gen4_pcie_unprepare(rcar);
+ reset_control_put(rcar->perst);
}
static int r8a779f0_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
--
2.53.0
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH v4 5/6] PCI: dwc: rcar-gen4: Handle PERST via reset subsystem
2026-09-05 21:26 ` [PATCH v4 5/6] PCI: dwc: rcar-gen4: Handle PERST via reset subsystem Marek Vasut
@ 2026-09-21 15:46 ` Manivannan Sadhasivam
2026-09-21 16:31 ` Marek Vasut
0 siblings, 1 reply; 11+ messages in thread
From: Manivannan Sadhasivam @ 2026-09-21 15:46 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-pci, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Rob Herring, Yoshihiro Shimoda, devicetree,
linux-kernel, linux-renesas-soc
On Sat, Sep 05, 2026 at 11:26:26PM +0200, Marek Vasut wrote:
> Handle PERST via both GPIO and reset subsystem. On R-Car Gen4, the
> PERST signal is operated as a GPIO, on R-Car Gen5 it might only be
> accessible via SCMI reset via reset subsystem. Support both options.
> This is a preparatory patch for R-Car Gen5 support.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Manivannan Sadhasivam <mani@kernel.org>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Cc: devicetree@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-pci@vger.kernel.org
> Cc: linux-renesas-soc@vger.kernel.org
> ---
> V2: - Use dev_err_probe() for perst in rcar_gen4_pcie_get_resources()
> - Use of_get_next_available_child() to obtain root port OF node
> - Switch to of_reset_control_get_optional_exclusive() to deal with
> R-Car Gen4, where the PERST is handled as GPIO instead of reset
> - Rename rcar_gen4_pcie_host_perst() to rcar_gen4_pcie_host_perst_assert()
> and use bool type for assert and deassert selection
> - Add missing reset_control_put() into rcar_gen4_pcie_probe() fail path
> V3: - Handle controllers without root port DT node
> - Swap fail path order
> V4: Rebase on next-20260904
> ---
> drivers/pci/controller/dwc/pcie-rcar-gen4.c | 44 +++++++++++++++++++--
> 1 file changed, 40 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> index c768a9c7b3b76..89472a4becc46 100644
> --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> @@ -99,6 +99,7 @@ struct rcar_gen4_pcie {
> void __iomem *base;
> void __iomem *phy_base;
> struct platform_device *pdev;
> + struct reset_control *perst;
> const struct rcar_gen4_pcie_drvdata *drvdata;
> };
> #define to_rcar_gen4_pcie(_dw) container_of(_dw, struct rcar_gen4_pcie, dw)
> @@ -317,12 +318,27 @@ static void rcar_gen4_pcie_unprepare(struct rcar_gen4_pcie *rcar)
>
> static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
> {
> + struct device *dev = rcar->dw.dev;
> + struct device_node *root_port;
> +
> rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
> if (IS_ERR(rcar->phy_base))
> return PTR_ERR(rcar->phy_base);
>
> + root_port = of_get_next_available_child(dev->of_node, NULL);
> + if (root_port) {
> + rcar->perst = of_reset_control_get_optional_exclusive(root_port, "perst");
> + of_node_put(root_port);
> + if (IS_ERR(rcar->perst))
> + return dev_err_probe(dev, PTR_ERR(rcar->perst), "Failed to get PERST#\n");
> + } else {
> + rcar->perst = NULL;
'rcar->perst' is NULL by default.
> + }
> +
> /* Renesas-specific registers */
> rcar->base = devm_platform_ioremap_resource_byname(rcar->pdev, "app");
> + if (IS_ERR(rcar->base))
> + reset_control_put(rcar->perst);
>
> return PTR_ERR_OR_ZERO(rcar->base);
> }
> @@ -494,6 +510,22 @@ static int rcar_gen4_pcie_enable_device(struct pci_host_bridge *bridge,
> return 0;
> }
>
> +static void rcar_gen4_pcie_host_perst_assert(struct dw_pcie_rp *pp, bool assert)
> +{
> + struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
> + struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
> +
> + gpiod_set_value_cansleep(dw->pe_rst, assert);
> +
> + if (!rcar->perst)
> + return;
> +
> + if (assert)
> + reset_control_assert(rcar->perst);
> + else
> + reset_control_deassert(rcar->perst);
So the controller will only have one form of PERST# implemented at a time. Even
though this code is technically correct, it also gives an impression that both
form could co-exist.
So I'd recommend using:
if (dw->pe_rst) {
gpiod_set_value_cansleep(dw->pe_rst, assert);
} else {
if (assert)
reset_control_assert(rcar->perst);
else
reset_control_deassert(rcar->perst);
}
to makes it clear that only one form of PERST# is supported.
I'll implement both of these changes while applying.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH v4 5/6] PCI: dwc: rcar-gen4: Handle PERST via reset subsystem
2026-09-21 15:46 ` Manivannan Sadhasivam
@ 2026-09-21 16:31 ` Marek Vasut
0 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2026-09-21 16:31 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: linux-pci, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Rob Herring, Yoshihiro Shimoda, devicetree,
linux-kernel, linux-renesas-soc
On 9/21/26 5:46 PM, Manivannan Sadhasivam wrote:
Hello Manivannan,
>> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
>> @@ -99,6 +99,7 @@ struct rcar_gen4_pcie {
>> void __iomem *base;
>> void __iomem *phy_base;
>> struct platform_device *pdev;
>> + struct reset_control *perst;
>> const struct rcar_gen4_pcie_drvdata *drvdata;
>> };
>> #define to_rcar_gen4_pcie(_dw) container_of(_dw, struct rcar_gen4_pcie, dw)
>> @@ -317,12 +318,27 @@ static void rcar_gen4_pcie_unprepare(struct rcar_gen4_pcie *rcar)
>>
>> static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
>> {
>> + struct device *dev = rcar->dw.dev;
>> + struct device_node *root_port;
>> +
>> rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
>> if (IS_ERR(rcar->phy_base))
>> return PTR_ERR(rcar->phy_base);
>>
>> + root_port = of_get_next_available_child(dev->of_node, NULL);
>> + if (root_port) {
>> + rcar->perst = of_reset_control_get_optional_exclusive(root_port, "perst");
>> + of_node_put(root_port);
>> + if (IS_ERR(rcar->perst))
>> + return dev_err_probe(dev, PTR_ERR(rcar->perst), "Failed to get PERST#\n");
>> + } else {
>> + rcar->perst = NULL;
>
> 'rcar->perst' is NULL by default.
Indeed.
>> + }
>> +
>> /* Renesas-specific registers */
>> rcar->base = devm_platform_ioremap_resource_byname(rcar->pdev, "app");
>> + if (IS_ERR(rcar->base))
>> + reset_control_put(rcar->perst);
>>
>> return PTR_ERR_OR_ZERO(rcar->base);
>> }
>> @@ -494,6 +510,22 @@ static int rcar_gen4_pcie_enable_device(struct pci_host_bridge *bridge,
>> return 0;
>> }
>>
>> +static void rcar_gen4_pcie_host_perst_assert(struct dw_pcie_rp *pp, bool assert)
>> +{
>> + struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
>> + struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
>> +
>> + gpiod_set_value_cansleep(dw->pe_rst, assert);
>> +
>> + if (!rcar->perst)
>> + return;
>> +
>> + if (assert)
>> + reset_control_assert(rcar->perst);
>> + else
>> + reset_control_deassert(rcar->perst);
>
> So the controller will only have one form of PERST# implemented at a time. Even
> though this code is technically correct, it also gives an impression that both
> form could co-exist.
>
> So I'd recommend using:
>
> if (dw->pe_rst) {
> gpiod_set_value_cansleep(dw->pe_rst, assert);
> } else {
> if (assert)
> reset_control_assert(rcar->perst);
> else
> reset_control_deassert(rcar->perst);
> }
>
> to makes it clear that only one form of PERST# is supported.
>
> I'll implement both of these changes while applying.
Please do. Thank you !
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 6/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4
2026-09-05 21:26 [PATCH v4 0/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
` (4 preceding siblings ...)
2026-09-05 21:26 ` [PATCH v4 5/6] PCI: dwc: rcar-gen4: Handle PERST via reset subsystem Marek Vasut
@ 2026-09-05 21:26 ` Marek Vasut
2026-09-21 16:03 ` Manivannan Sadhasivam
5 siblings, 1 reply; 11+ messages in thread
From: Marek Vasut @ 2026-09-05 21:26 UTC (permalink / raw)
To: linux-pci
Cc: Marek Vasut, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Manivannan Sadhasivam, Rob Herring,
Yoshihiro Shimoda, devicetree, linux-kernel, linux-renesas-soc
Add support for R8A78000 (R-Car X5H) PCIe4.
This driver previously supported R-Car Gen4 S4/V4H/V4M. PCIe features
of R-Car X5H PCIe4 are almost all the same.
The controller initialization sequence is slightly different and is
factored out into controller specific callbacks, in a manner similar
to previous R-Car Gen4 handling.
The controller does have a PHY attached to it, but the PHY is operated
by a separate PHY driver, the PHY driver instance binding is handled
in rcar_gen4_pcie_get_resources() and controlled in the aforementioned
controller specific callbacks.
The controller driver is deliberately using "renesas,rcar-gen5-pcie4"
DT compatible string to discern R-Car X5H PCIe4 controller supported
by this driver, from R-Car X5H PCIe6 controller which will most likely
use a separate driver.
The R-Car X5H PCIe4 controller embeds HDMA instead of EDMA embedded
in the R-Car Gen4 PCIe controller, "dw-edma" driver supports both
DMA variants.
Endpoint mode is currently not implemented for R-Car Gen5 PCIe4.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
V2: No change
V3: - Disable clock in case of PHY init failure in rcar_gen5_pcie_init()
- Add .deinit callback and tear down Gen5 PHY in it
- Use 16bit accessors on LNKCTL register
V4: Rebase on next-20260904
---
drivers/pci/controller/dwc/pcie-rcar-gen4.c | 128 +++++++++++++++++++-
1 file changed, 126 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index 89472a4becc46..5c0d5fd686cb5 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -19,6 +19,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/pci.h>
+#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
@@ -36,6 +37,7 @@
/* MSI Capability */
#define MSICAP0 0x0050
+#define MSICAP0_MMESCAP_MASK GENMASK(19, 17)
#define MSICAP0_MSIE BIT(16)
/* PCIe Interrupt Status 0 */
@@ -74,6 +76,11 @@
#define PCIEPWRMNGCTRL 0x0070
#define APP_CLK_REQ_N BIT(11)
#define APP_CLK_PM_EN BIT(10)
+#define APP_READY_ENTR_L23 BIT(6)
+#define APP_REQ_ENTR_L1 BIT(5)
+
+/* PCI Express capability */
+#define EXPCAP(x) (0x0070 + (x))
#define RCAR_NUM_SPEED_CHANGE_RETRIES 10
#define RCAR_MAX_LINK_SPEED 4
@@ -98,6 +105,7 @@ struct rcar_gen4_pcie {
struct dw_pcie dw;
void __iomem *base;
void __iomem *phy_base;
+ struct phy *phy;
struct platform_device *pdev;
struct reset_control *perst;
const struct rcar_gen4_pcie_drvdata *drvdata;
@@ -170,6 +178,35 @@ static int rcar_gen4_pcie_speed_control(struct rcar_gen4_pcie *rcar)
return 0;
}
+static int rcar_gen5_pcie_speed_control(struct rcar_gen4_pcie *rcar)
+{
+ struct dw_pcie *dw = &rcar->dw;
+ u32 lnkcap = dw_pcie_readl_dbi(dw, EXPCAP(PCI_EXP_LNKCAP));
+ u32 lnksta = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKSTA));
+ u32 val, retries;
+
+ if ((lnksta & PCI_EXP_LNKSTA_CLS) == (lnkcap & PCI_EXP_LNKCAP_SLS))
+ return 0;
+
+ /* Retrain link */
+ val = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKCTL));
+ val |= PCI_EXP_LNKCTL_RL;
+ dw_pcie_writew_dbi(dw, EXPCAP(PCI_EXP_LNKCTL), val);
+
+ /* Wait for link retrain */
+ for (retries = 0; retries <= 10; retries++) {
+ lnksta = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKSTA));
+
+ /* Check retrain flag */
+ if (!(lnksta & PCI_EXP_LNKSTA_LT))
+ break;
+
+ usleep_range(1000, 1100);
+ }
+
+ return 0;
+}
+
/*
* Enable LTSSM of this controller and manually initiate the speed change.
* Always return 0.
@@ -285,6 +322,49 @@ static int rcar_gen4_v4h_v4m_pcie_init(struct rcar_gen4_pcie *rcar)
return 0;
}
+static int rcar_gen5_pcie_init(struct rcar_gen4_pcie *rcar)
+{
+ struct dw_pcie *dw = &rcar->dw;
+ int ret;
+ u32 val;
+
+ /* R-Car Gen4 and Gen5 common initialization. */
+ ret = rcar_gen4_pcie_common_init(rcar);
+ if (ret)
+ return ret;
+
+ /* R-Car Gen5 specific additional initialization. */
+ ret = phy_init(rcar->phy);
+ if (ret)
+ goto err_unprepare;
+
+ dw_pcie_dbi_ro_wr_en(dw);
+
+ val = dw_pcie_readl_dbi(dw, PCIE_PORT_LANE_SKEW);
+ val &= ~PORT_LANE_SKEW_INSERT_MASK;
+ if (dw->num_lanes < 8)
+ val |= BIT(6);
+ dw_pcie_writel_dbi(dw, PCIE_PORT_LANE_SKEW, val);
+
+ val = dw_pcie_readl_dbi(dw, MSICAP0);
+ FIELD_MODIFY(MSICAP0_MMESCAP_MASK, &val, 4);
+ dw_pcie_writel_dbi(dw, MSICAP0, val);
+
+ dw_pcie_dbi_ro_wr_dis(dw);
+
+ val = readl(rcar->base + PCIEPWRMNGCTRL);
+ val |= APP_CLK_REQ_N | APP_CLK_PM_EN |
+ APP_READY_ENTR_L23 | APP_REQ_ENTR_L1;
+ writel(val, rcar->base + PCIEPWRMNGCTRL);
+
+ return 0;
+
+err_unprepare:
+ clk_bulk_disable_unprepare(DW_PCIE_NUM_CORE_CLKS, dw->core_clks);
+
+ return ret;
+}
+
static void rcar_gen4_pcie_common_deinit(struct rcar_gen4_pcie *rcar)
{
struct dw_pcie *dw = &rcar->dw;
@@ -293,6 +373,12 @@ static void rcar_gen4_pcie_common_deinit(struct rcar_gen4_pcie *rcar)
clk_bulk_disable_unprepare(DW_PCIE_NUM_CORE_CLKS, dw->core_clks);
}
+static void rcar_gen5_pcie_deinit(struct rcar_gen4_pcie *rcar)
+{
+ phy_exit(rcar->phy);
+ rcar_gen4_pcie_common_deinit(rcar);
+}
+
static int rcar_gen4_pcie_prepare(struct rcar_gen4_pcie *rcar)
{
struct device *dev = rcar->dw.dev;
@@ -322,8 +408,12 @@ static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
struct device_node *root_port;
rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
- if (IS_ERR(rcar->phy_base))
- return PTR_ERR(rcar->phy_base);
+ if (IS_ERR(rcar->phy_base)) {
+ rcar->phy_base = NULL;
+ rcar->phy = devm_phy_get(dev, NULL);
+ if (IS_ERR(rcar->phy))
+ return PTR_ERR(rcar->phy);
+ }
root_port = of_get_next_available_child(dev->of_node, NULL);
if (root_port) {
@@ -807,6 +897,28 @@ static int r8a779f0_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
return 0;
}
+static int rcar_gen5_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
+{
+ u32 val;
+
+ val = readl(rcar->base + PCIERSTCTRL1);
+ if (enable) {
+ val |= APP_LTSSM_ENABLE;
+ val &= ~APP_HOLD_PHY_RST;
+ } else {
+ val &= ~APP_LTSSM_ENABLE;
+ val |= APP_HOLD_PHY_RST;
+ }
+ writel(val, rcar->base + PCIERSTCTRL1);
+
+ if (enable)
+ phy_power_on(rcar->phy);
+ else
+ phy_power_off(rcar->phy);
+
+ return 0;
+}
+
static void rcar_gen4_pcie_phy_reg_update_bits(struct rcar_gen4_pcie *rcar,
u32 offset, u32 mask, u32 val)
{
@@ -989,6 +1101,14 @@ static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie_ep = {
.mode = DW_PCIE_EP_TYPE,
};
+static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen5_pcie = {
+ .init = rcar_gen5_pcie_init,
+ .deinit = rcar_gen5_pcie_deinit,
+ .ltssm_control = rcar_gen5_pcie_ltssm_control,
+ .speed_control = rcar_gen5_pcie_speed_control,
+ .mode = DW_PCIE_RC_TYPE,
+};
+
static const struct of_device_id rcar_gen4_pcie_of_match[] = {
{
.compatible = "renesas,r8a779f0-pcie",
@@ -1006,6 +1126,10 @@ static const struct of_device_id rcar_gen4_pcie_of_match[] = {
.compatible = "renesas,rcar-gen4-pcie-ep",
.data = &drvdata_rcar_gen4_pcie_ep,
},
+ {
+ .compatible = "renesas,rcar-gen5-pcie4",
+ .data = &drvdata_rcar_gen5_pcie,
+ },
{},
};
MODULE_DEVICE_TABLE(of, rcar_gen4_pcie_of_match);
--
2.53.0
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH v4 6/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4
2026-09-05 21:26 ` [PATCH v4 6/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4 Marek Vasut
@ 2026-09-21 16:03 ` Manivannan Sadhasivam
2026-09-21 20:24 ` Marek Vasut
0 siblings, 1 reply; 11+ messages in thread
From: Manivannan Sadhasivam @ 2026-09-21 16:03 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-pci, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Rob Herring, Yoshihiro Shimoda, devicetree,
linux-kernel, linux-renesas-soc
On Sat, Sep 05, 2026 at 11:26:27PM +0200, Marek Vasut wrote:
> Add support for R8A78000 (R-Car X5H) PCIe4.
>
> This driver previously supported R-Car Gen4 S4/V4H/V4M. PCIe features
> of R-Car X5H PCIe4 are almost all the same.
>
> The controller initialization sequence is slightly different and is
> factored out into controller specific callbacks, in a manner similar
> to previous R-Car Gen4 handling.
>
> The controller does have a PHY attached to it, but the PHY is operated
> by a separate PHY driver, the PHY driver instance binding is handled
> in rcar_gen4_pcie_get_resources() and controlled in the aforementioned
> controller specific callbacks.
>
> The controller driver is deliberately using "renesas,rcar-gen5-pcie4"
> DT compatible string to discern R-Car X5H PCIe4 controller supported
> by this driver, from R-Car X5H PCIe6 controller which will most likely
> use a separate driver.
>
> The R-Car X5H PCIe4 controller embeds HDMA instead of EDMA embedded
> in the R-Car Gen4 PCIe controller, "dw-edma" driver supports both
> DMA variants.
>
> Endpoint mode is currently not implemented for R-Car Gen5 PCIe4.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Manivannan Sadhasivam <mani@kernel.org>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Cc: devicetree@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-pci@vger.kernel.org
> Cc: linux-renesas-soc@vger.kernel.org
> ---
> V2: No change
> V3: - Disable clock in case of PHY init failure in rcar_gen5_pcie_init()
> - Add .deinit callback and tear down Gen5 PHY in it
> - Use 16bit accessors on LNKCTL register
> V4: Rebase on next-20260904
> ---
> drivers/pci/controller/dwc/pcie-rcar-gen4.c | 128 +++++++++++++++++++-
> 1 file changed, 126 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> index 89472a4becc46..5c0d5fd686cb5 100644
> --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> @@ -19,6 +19,7 @@
> #include <linux/of_address.h>
> #include <linux/of_irq.h>
> #include <linux/pci.h>
> +#include <linux/phy/phy.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> #include <linux/reset.h>
> @@ -36,6 +37,7 @@
>
> /* MSI Capability */
> #define MSICAP0 0x0050
> +#define MSICAP0_MMESCAP_MASK GENMASK(19, 17)
> #define MSICAP0_MSIE BIT(16)
>
> /* PCIe Interrupt Status 0 */
> @@ -74,6 +76,11 @@
> #define PCIEPWRMNGCTRL 0x0070
> #define APP_CLK_REQ_N BIT(11)
> #define APP_CLK_PM_EN BIT(10)
> +#define APP_READY_ENTR_L23 BIT(6)
> +#define APP_REQ_ENTR_L1 BIT(5)
> +
> +/* PCI Express capability */
> +#define EXPCAP(x) (0x0070 + (x))
>
> #define RCAR_NUM_SPEED_CHANGE_RETRIES 10
> #define RCAR_MAX_LINK_SPEED 4
> @@ -98,6 +105,7 @@ struct rcar_gen4_pcie {
> struct dw_pcie dw;
> void __iomem *base;
> void __iomem *phy_base;
> + struct phy *phy;
> struct platform_device *pdev;
> struct reset_control *perst;
> const struct rcar_gen4_pcie_drvdata *drvdata;
> @@ -170,6 +178,35 @@ static int rcar_gen4_pcie_speed_control(struct rcar_gen4_pcie *rcar)
> return 0;
> }
>
> +static int rcar_gen5_pcie_speed_control(struct rcar_gen4_pcie *rcar)
> +{
> + struct dw_pcie *dw = &rcar->dw;
> + u32 lnkcap = dw_pcie_readl_dbi(dw, EXPCAP(PCI_EXP_LNKCAP));
> + u32 lnksta = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKSTA));
> + u32 val, retries;
> +
> + if ((lnksta & PCI_EXP_LNKSTA_CLS) == (lnkcap & PCI_EXP_LNKCAP_SLS))
> + return 0;
> +
> + /* Retrain link */
> + val = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKCTL));
> + val |= PCI_EXP_LNKCTL_RL;
> + dw_pcie_writew_dbi(dw, EXPCAP(PCI_EXP_LNKCTL), val);
> +
> + /* Wait for link retrain */
> + for (retries = 0; retries <= 10; retries++) {
So this loop executes 11 times. Is that intented?
> + lnksta = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKSTA));
> +
> + /* Check retrain flag */
> + if (!(lnksta & PCI_EXP_LNKSTA_LT))
> + break;
> +
> + usleep_range(1000, 1100);
What is the expected behavior if the Link retrain is not successfull? If it is
safe to continue, shouldn't the users be warned atleast?
> + }
> +
> + return 0;
> +}
> +
> /*
> * Enable LTSSM of this controller and manually initiate the speed change.
> * Always return 0.
> @@ -285,6 +322,49 @@ static int rcar_gen4_v4h_v4m_pcie_init(struct rcar_gen4_pcie *rcar)
> return 0;
> }
>
> +static int rcar_gen5_pcie_init(struct rcar_gen4_pcie *rcar)
> +{
> + struct dw_pcie *dw = &rcar->dw;
> + int ret;
> + u32 val;
> +
> + /* R-Car Gen4 and Gen5 common initialization. */
> + ret = rcar_gen4_pcie_common_init(rcar);
> + if (ret)
> + return ret;
> +
> + /* R-Car Gen5 specific additional initialization. */
> + ret = phy_init(rcar->phy);
> + if (ret)
> + goto err_unprepare;
> +
> + dw_pcie_dbi_ro_wr_en(dw);
> +
> + val = dw_pcie_readl_dbi(dw, PCIE_PORT_LANE_SKEW);
> + val &= ~PORT_LANE_SKEW_INSERT_MASK;
> + if (dw->num_lanes < 8)
> + val |= BIT(6);
> + dw_pcie_writel_dbi(dw, PCIE_PORT_LANE_SKEW, val);
> +
> + val = dw_pcie_readl_dbi(dw, MSICAP0);
> + FIELD_MODIFY(MSICAP0_MMESCAP_MASK, &val, 4);
> + dw_pcie_writel_dbi(dw, MSICAP0, val);
> +
> + dw_pcie_dbi_ro_wr_dis(dw);
> +
> + val = readl(rcar->base + PCIEPWRMNGCTRL);
> + val |= APP_CLK_REQ_N | APP_CLK_PM_EN |
> + APP_READY_ENTR_L23 | APP_REQ_ENTR_L1;
> + writel(val, rcar->base + PCIEPWRMNGCTRL);
> +
> + return 0;
> +
> +err_unprepare:
> + clk_bulk_disable_unprepare(DW_PCIE_NUM_CORE_CLKS, dw->core_clks);
> +
> + return ret;
> +}
> +
> static void rcar_gen4_pcie_common_deinit(struct rcar_gen4_pcie *rcar)
> {
> struct dw_pcie *dw = &rcar->dw;
> @@ -293,6 +373,12 @@ static void rcar_gen4_pcie_common_deinit(struct rcar_gen4_pcie *rcar)
> clk_bulk_disable_unprepare(DW_PCIE_NUM_CORE_CLKS, dw->core_clks);
> }
>
> +static void rcar_gen5_pcie_deinit(struct rcar_gen4_pcie *rcar)
> +{
> + phy_exit(rcar->phy);
> + rcar_gen4_pcie_common_deinit(rcar);
> +}
> +
> static int rcar_gen4_pcie_prepare(struct rcar_gen4_pcie *rcar)
> {
> struct device *dev = rcar->dw.dev;
> @@ -322,8 +408,12 @@ static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
> struct device_node *root_port;
>
> rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
> - if (IS_ERR(rcar->phy_base))
> - return PTR_ERR(rcar->phy_base);
> + if (IS_ERR(rcar->phy_base)) {
> + rcar->phy_base = NULL;
> + rcar->phy = devm_phy_get(dev, NULL);
> + if (IS_ERR(rcar->phy))
> + return PTR_ERR(rcar->phy);
> + }
>
> root_port = of_get_next_available_child(dev->of_node, NULL);
> if (root_port) {
> @@ -807,6 +897,28 @@ static int r8a779f0_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
> return 0;
> }
>
> +static int rcar_gen5_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
> +{
> + u32 val;
> +
> + val = readl(rcar->base + PCIERSTCTRL1);
> + if (enable) {
> + val |= APP_LTSSM_ENABLE;
> + val &= ~APP_HOLD_PHY_RST;
> + } else {
> + val &= ~APP_LTSSM_ENABLE;
> + val |= APP_HOLD_PHY_RST;
> + }
> + writel(val, rcar->base + PCIERSTCTRL1);
> +
> + if (enable)
> + phy_power_on(rcar->phy);
> + else
> + phy_power_off(rcar->phy);
It is quite unusual to handle PHY power on/off in the start_link() callback.
Should this be moved to init/deinit callbacks?
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH v4 6/6] PCI: dwc: rcar-gen4: Add support for R-Car X5H PCIe4
2026-09-21 16:03 ` Manivannan Sadhasivam
@ 2026-09-21 20:24 ` Marek Vasut
0 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2026-09-21 20:24 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: linux-pci, Krzysztof Wilczyński, Bjorn Helgaas,
Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski,
Lorenzo Pieralisi, Rob Herring, Yoshihiro Shimoda, devicetree,
linux-kernel, linux-renesas-soc
On 9/21/26 6:03 PM, Manivannan Sadhasivam wrote:
Hello Manivannan,
>> +static int rcar_gen5_pcie_speed_control(struct rcar_gen4_pcie *rcar)
>> +{
>> + struct dw_pcie *dw = &rcar->dw;
>> + u32 lnkcap = dw_pcie_readl_dbi(dw, EXPCAP(PCI_EXP_LNKCAP));
>> + u32 lnksta = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKSTA));
>> + u32 val, retries;
>> +
>> + if ((lnksta & PCI_EXP_LNKSTA_CLS) == (lnkcap & PCI_EXP_LNKCAP_SLS))
>> + return 0;
>> +
>> + /* Retrain link */
>> + val = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKCTL));
>> + val |= PCI_EXP_LNKCTL_RL;
>> + dw_pcie_writew_dbi(dw, EXPCAP(PCI_EXP_LNKCTL), val);
>> +
>> + /* Wait for link retrain */
>> + for (retries = 0; retries <= 10; retries++) {
>
> So this loop executes 11 times. Is that intented?
No, I don't think this is correct, or in fact sufficient. The training
should poll for at least 100ms.
>> + lnksta = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKSTA));
>> +
>> + /* Check retrain flag */
>> + if (!(lnksta & PCI_EXP_LNKSTA_LT))
>> + break;
>> +
>> + usleep_range(1000, 1100);
>
> What is the expected behavior if the Link retrain is not successfull? If it is
> safe to continue, shouldn't the users be warned atleast?
They should, I will be replacing this with this simpler option, which
returns -ETIMEDOUT in case the training failed:
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index a5feb73864c7f..7f4bda6a492ab 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -183,7 +183,7 @@ static int rcar_gen5_pcie_speed_control(struct
rcar_gen4_pcie *rcar)
struct dw_pcie *dw = &rcar->dw;
u32 lnkcap = dw_pcie_readl_dbi(dw, EXPCAP(PCI_EXP_LNKCAP));
u32 lnksta = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKSTA));
- u32 val, retries;
+ u32 val;
if ((lnksta & PCI_EXP_LNKSTA_CLS) == (lnkcap & PCI_EXP_LNKCAP_SLS))
return 0;
@@ -193,18 +193,10 @@ static int rcar_gen5_pcie_speed_control(struct
rcar_gen4_pcie *rcar)
val |= PCI_EXP_LNKCTL_RL;
dw_pcie_writew_dbi(dw, EXPCAP(PCI_EXP_LNKCTL), val);
- /* Wait for link retrain */
- for (retries = 0; retries <= 10; retries++) {
- lnksta = dw_pcie_readw_dbi(dw, EXPCAP(PCI_EXP_LNKSTA));
-
- /* Check retrain flag */
- if (!(lnksta & PCI_EXP_LNKSTA_LT))
- break;
-
- usleep_range(1000, 1100);
- }
-
- return 0;
+ /* Wait for link retrain, 500ms must be enough for all link
rates. */
+ return read_poll_timeout(dw_pcie_readw_dbi, lnksta, !(lnksta &
PCI_EXP_LNKSTA_LT),
+ 1000, 5 * PCIE_RESET_CONFIG_WAIT_MS *
USEC_PER_MSEC,
+ false, dw, EXPCAP(PCI_EXP_LNKSTA));
}
/*
>> + }
>> +
>> + return 0;
>> +}
>> +
>> /*
>> * Enable LTSSM of this controller and manually initiate the speed change.
>> * Always return 0.
>> @@ -285,6 +322,49 @@ static int rcar_gen4_v4h_v4m_pcie_init(struct rcar_gen4_pcie *rcar)
>> return 0;
>> }
>>
[...]
>> +static int rcar_gen5_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
>> +{
>> + u32 val;
>> +
>> + val = readl(rcar->base + PCIERSTCTRL1);
>> + if (enable) {
>> + val |= APP_LTSSM_ENABLE;
>> + val &= ~APP_HOLD_PHY_RST;
>> + } else {
>> + val &= ~APP_LTSSM_ENABLE;
>> + val |= APP_HOLD_PHY_RST;
>> + }
>> + writel(val, rcar->base + PCIERSTCTRL1);
>> +
>> + if (enable)
>> + phy_power_on(rcar->phy);
>> + else
>> + phy_power_off(rcar->phy);
>
> It is quite unusual to handle PHY power on/off in the start_link() callback.
> Should this be moved to init/deinit callbacks?
This really has to be here, else the controller programming order does
not follow the sequence in the SoC datasheet.
^ permalink raw reply [flat|nested] 11+ messages in thread