* [PATCH v2 1/4] dt-bindings: PCI: renesas,r9a08g045-pcie: Add RZ/V2H(P) support
2026-05-18 15:53 [PATCH v2 0/4] Add PCIe support for RZ/V2H(P) SoC Prabhakar
@ 2026-05-18 15:53 ` Prabhakar
2026-05-18 16:12 ` sashiko-bot
2026-05-19 6:57 ` Geert Uytterhoeven
2026-05-18 15:53 ` [PATCH v2 2/4] PCI: rzg3s-host: Use shared reset controls for power domain resets Prabhakar
` (2 subsequent siblings)
3 siblings, 2 replies; 8+ messages in thread
From: Prabhakar @ 2026-05-18 15:53 UTC (permalink / raw)
To: Lorenzo Pieralisi, Manivannan Sadhasivam,
Krzysztof Wilczyński, Bjorn Helgaas, Rob Herring,
Claudiu Beznea, Krzysztof Kozlowski, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven, Magnus Damm
Cc: linux-pci, linux-renesas-soc, devicetree, linux-kernel, Prabhakar,
Biju Das, Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Add support for the PCIe controller found on the Renesas RZ/V2H(P) SoC.
The RZ/V2H(P) controller is similar to the RZ/G3E variant but includes
additional registers and configuration bits for PCIe lane control. It
supports multilink operation configured as either a single x4 link
or two independent x2 link controllers.
Unlike earlier SoCs supported by this driver which only feature a single
PCIe controller, the RZ/V2H(P) SoC implements two controllers. Both
controllers rely on the system controller (`sysc`) for configuration,
but the required registers reside at different offsets for each instance.
To correctly identify the controller instance and map the corresponding
system controller registers, make the "linux,pci-domain" and "num-lanes"
properties mandatory for this SoC and restrict their values according to
the hardware capabilities.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
v1->v2:
- Updated commit message.
- Dropped un-necessary new line in schema.
---
.../bindings/pci/renesas,r9a08g045-pcie.yaml | 21 +++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml b/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml
index 90086909e921..149a2973b16e 100644
--- a/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml
@@ -14,7 +14,7 @@ description: |
with PCIe Base Specification 4.0 and supports different link speeds
depending on the SoC variant:
- Gen2 (5 GT/s): RZ/G3S
- - Gen3 (8 GT/s): RZ/G3E, RZ/V2N
+ - Gen3 (8 GT/s): RZ/G3E, RZ/V2H(P), RZ/V2N
properties:
compatible:
@@ -22,6 +22,7 @@ properties:
- enum:
- renesas,r9a08g045-pcie # RZ/G3S
- renesas,r9a09g047-pcie # RZ/G3E
+ - renesas,r9a09g057-pcie # RZ/V2H(P)
- items:
- const: renesas,r9a09g056-pcie # RZ/V2N
- const: renesas,r9a09g047-pcie
@@ -220,7 +221,9 @@ allOf:
properties:
compatible:
contains:
- const: renesas,r9a09g047-pcie
+ enum:
+ - renesas,r9a09g047-pcie
+ - renesas,r9a09g057-pcie
then:
properties:
interrupts:
@@ -235,6 +238,20 @@ allOf:
maxItems: 1
reset-names:
maxItems: 1
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,r9a09g057-pcie
+ then:
+ properties:
+ linux,pci-domain:
+ enum: [0, 1]
+ num-lanes:
+ enum: [2, 4]
+ required:
+ - linux,pci-domain
+ - num-lanes
unevaluatedProperties: false
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/4] dt-bindings: PCI: renesas,r9a08g045-pcie: Add RZ/V2H(P) support
2026-05-18 15:53 ` [PATCH v2 1/4] dt-bindings: PCI: renesas,r9a08g045-pcie: Add RZ/V2H(P) support Prabhakar
@ 2026-05-18 16:12 ` sashiko-bot
2026-05-19 6:57 ` Geert Uytterhoeven
1 sibling, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-05-18 16:12 UTC (permalink / raw)
To: Prabhakar; +Cc: linux-pci, devicetree, wsa+renesas, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The patch mandates `linux,pci-domain` to identify the hardware controller instance and determine system controller register offsets, which is a Device Tree architectural violation.
--
commit ed13e82a06909d08d89ba9cf97e57413bb3dc6c8
Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
dt-bindings: PCI: renesas,r9a08g045-pcie: Add RZ/V2H(P) support
This commit adds support for the PCIe controller found on the Renesas
RZ/V2H(P) SoC. It makes the linux,pci-domain and num-lanes properties
mandatory for identifying the controller instance and mapping system
controller registers.
> Unlike earlier SoCs supported by this driver which only feature a single
> PCIe controller, the RZ/V2H(P) SoC implements two controllers. Both
> controllers rely on the system controller (`sysc`) for configuration,
> but the required registers reside at different offsets for each instance.
> To correctly identify the controller instance and map the corresponding
> system controller registers, make the "linux,pci-domain" and "num-lanes"
> properties mandatory for this SoC and restrict their values according to
> the hardware capabilities.
Is it appropriate to use linux,pci-domain to identify the hardware
controller instance?
Device Tree is designed to describe hardware rather than software policy
or configuration. The linux,pci-domain property is an OS-specific hint
used to assign logical PCI domain numbers.
Using it to identify hardware instances strictly couples the hardware
register mapping to an OS numbering scheme.
> diff --git a/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml b/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml
> index 90086909e9210..149a2973b16eb 100644
> --- a/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml
> +++ b/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml
[ ... ]
> @@ -235,6 +238,20 @@ allOf:
> maxItems: 1
> reset-names:
> maxItems: 1
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: renesas,r9a09g057-pcie
> + then:
> + properties:
> + linux,pci-domain:
> + enum: [0, 1]
Does limiting this to [0, 1] cause a regression for valid software
configurations?
For example, if a board with multiple PCIe controllers assigns domains 2
and 3 to these instances to avoid conflicts, the binding will fail
validation and the driver will fail to probe.
Could the hardware instances instead be identified via standard hardware
descriptive mechanisms, such as their physical base address (reg),
standard aliases, or by adding a phandle specifier argument to
renesas,sysc?
> + num-lanes:
> + enum: [2, 4]
> + required:
> + - linux,pci-domain
> + - num-lanes
>
> unevaluatedProperties: false
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260518155324.168948-1-prabhakar.mahadev-lad.rj@bp.renesas.com?part=1
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/4] dt-bindings: PCI: renesas,r9a08g045-pcie: Add RZ/V2H(P) support
2026-05-18 15:53 ` [PATCH v2 1/4] dt-bindings: PCI: renesas,r9a08g045-pcie: Add RZ/V2H(P) support Prabhakar
2026-05-18 16:12 ` sashiko-bot
@ 2026-05-19 6:57 ` Geert Uytterhoeven
1 sibling, 0 replies; 8+ messages in thread
From: Geert Uytterhoeven @ 2026-05-19 6:57 UTC (permalink / raw)
To: Prabhakar
Cc: Lorenzo Pieralisi, Manivannan Sadhasivam,
Krzysztof Wilczyński, Bjorn Helgaas, Rob Herring,
Claudiu Beznea, Krzysztof Kozlowski, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven, Magnus Damm, linux-pci, linux-renesas-soc,
devicetree, linux-kernel, Biju Das, Fabrizio Castro,
Lad Prabhakar, sashiko-bot
Hi Prabhakar,
On Mon, 18 May 2026 at 17:53, Prabhakar <prabhakar.csengg@gmail.com> wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Add support for the PCIe controller found on the Renesas RZ/V2H(P) SoC.
>
> The RZ/V2H(P) controller is similar to the RZ/G3E variant but includes
> additional registers and configuration bits for PCIe lane control. It
> supports multilink operation configured as either a single x4 link
> or two independent x2 link controllers.
>
> Unlike earlier SoCs supported by this driver which only feature a single
> PCIe controller, the RZ/V2H(P) SoC implements two controllers. Both
> controllers rely on the system controller (`sysc`) for configuration,
> but the required registers reside at different offsets for each instance.
> To correctly identify the controller instance and map the corresponding
> system controller registers, make the "linux,pci-domain" and "num-lanes"
> properties mandatory for this SoC and restrict their values according to
> the hardware capabilities.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Thanks for your patch!
> --- a/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml
> +++ b/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml
> @@ -235,6 +238,20 @@ allOf:
> maxItems: 1
> reset-names:
> maxItems: 1
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: renesas,r9a09g057-pcie
> + then:
> + properties:
> + linux,pci-domain:
> + enum: [0, 1]
Sashiko has the following comments about this property[1]:
| Is it appropriate to use linux,pci-domain to identify the hardware
| controller instance?
| Device Tree is designed to describe hardware rather than software policy
| or configuration. The linux,pci-domain property is an OS-specific hint
| used to assign logical PCI domain numbers.
| Using it to identify hardware instances strictly couples the hardware
| register mapping to an OS numbering scheme.
and
| Does limiting this to [0, 1] cause a regression for valid software
| configurations?
| For example, if a board with multiple PCIe controllers assigns domains 2
| and 3 to these instances to avoid conflicts, the binding will fail
| validation and the driver will fail to probe.
| Could the hardware instances instead be identified via standard hardware
| descriptive mechanisms, such as their physical base address (reg),
| standard aliases, or by adding a phandle specifier argument to
| renesas,sysc?
dtschema/schemas/pci/pci-host-bridge.yaml states:
| linux,pci-domain:
| description:
| If present this property assigns a fixed PCI domain number to a
host bridge,
| otherwise an unstable (across boots) unique number will be assigned.
| It is required to either not set this property at all or set it for all
| host bridges in the system, otherwise potentially conflicting
domain numbers
| may be assigned to root buses behind different host bridges. The domain
| number for each host bridge in the system must be unique.
In the RZ/V2H case, the number is local to the SYSC instance referenced
by the renesas,sysc property, while linux,pci-domain is global to the
full system by definition. Fixing the numbers to zero and one works,
until some other controller in the system has conflicting requirements.
I do see a future case where this may break: if Renesas would release a
new SoC containing two RZ/V2H dies, there would be four PCIe controllers
and two SYSC controllers. This would require two PCIe controllers to
have linux,pci-domain = <0>, and two having linux,pci-domain = <1>,
which is not permitted.
Hence adding a second cell to the renesas,sysc property, to specify
the base offset of the PCIe-related registers inside SYSC seems like
the best way to go?
[1] https://sashiko.dev/#/patchset/20260518155324.168948-1-prabhakar.mahadev-lad.rj@bp.renesas.com?part=1
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/4] PCI: rzg3s-host: Use shared reset controls for power domain resets
2026-05-18 15:53 [PATCH v2 0/4] Add PCIe support for RZ/V2H(P) SoC Prabhakar
2026-05-18 15:53 ` [PATCH v2 1/4] dt-bindings: PCI: renesas,r9a08g045-pcie: Add RZ/V2H(P) support Prabhakar
@ 2026-05-18 15:53 ` Prabhakar
2026-05-18 16:42 ` sashiko-bot
2026-05-18 15:53 ` [PATCH v2 3/4] PCI: rzg3s-host: Prepare System Controller handling for multiple controllers Prabhakar
2026-05-18 15:53 ` [PATCH v2 4/4] PCI: rzg3s-host: Add support for RZ/V2H(P) SoC Prabhakar
3 siblings, 1 reply; 8+ messages in thread
From: Prabhakar @ 2026-05-18 15:53 UTC (permalink / raw)
To: Lorenzo Pieralisi, Manivannan Sadhasivam,
Krzysztof Wilczyński, Bjorn Helgaas, Rob Herring,
Claudiu Beznea, Krzysztof Kozlowski, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven, Magnus Damm
Cc: linux-pci, linux-renesas-soc, devicetree, linux-kernel, Prabhakar,
Biju Das, Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Switch to shared reset controls for PCIe power resets to prepare for
RZ/V2H(P) support. On this platform, multiple PCIe controllers share
the same reset line, requiring shared ownership of the reset control.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
v1->v2:
- Updated commit message.
---
drivers/pci/controller/pcie-rzg3s-host.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c
index d86e7516dcc2..a5192e4b58df 100644
--- a/drivers/pci/controller/pcie-rzg3s-host.c
+++ b/drivers/pci/controller/pcie-rzg3s-host.c
@@ -1276,9 +1276,9 @@ static int rzg3s_pcie_resets_prepare_and_get(struct rzg3s_pcie_host *host)
for (i = 0; i < data->num_cfg_resets; i++)
host->cfg_resets[i].id = data->cfg_resets[i];
- ret = devm_reset_control_bulk_get_exclusive(host->dev,
- data->num_power_resets,
- host->power_resets);
+ ret = devm_reset_control_bulk_get_shared(host->dev,
+ data->num_power_resets,
+ host->power_resets);
if (ret)
return ret;
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/4] PCI: rzg3s-host: Use shared reset controls for power domain resets
2026-05-18 15:53 ` [PATCH v2 2/4] PCI: rzg3s-host: Use shared reset controls for power domain resets Prabhakar
@ 2026-05-18 16:42 ` sashiko-bot
0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-05-18 16:42 UTC (permalink / raw)
To: Prabhakar; +Cc: linux-pci, conor+dt, robh, devicetree, wsa+renesas
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] Missing chained IRQ handler cleanup in error paths leads to Use-After-Free of the host structure.
- [High] The `rzg3s_pcie_resume_noirq` callback unconditionally executes `fsleep(5000)` while local interrupts are disabled, leading to a system hang or scheduling BUG.
--
commit 41ddeeaac37e089f4b9cce52ea971db3b995ab04
Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
PCI: rzg3s-host: Use shared reset controls for power domain resets
Switch to shared reset controls for PCIe power resets to prepare for
RZ/V2H(P) support. On this platform, multiple PCIe controllers share
the same reset line, requiring shared ownership of the reset control.
> diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c
> index d86e7516dcc29..a5192e4b58dfb 100644
> --- a/drivers/pci/controller/pcie-rzg3s-host.c
> +++ b/drivers/pci/controller/pcie-rzg3s-host.c
[ ... ]
While reviewing this code, I noticed a potential regression that was not
introduced by this patch.
In rzg3s_pcie_init_irqdomain(), the driver loops over PCI_NUM_INTX and
installs chained handlers for INTx interrupts:
drivers/pci/controller/pcie-rzg3s-host.c:rzg3s_pcie_init_irqdomain() {
...
for (int i = 0; i < PCI_NUM_INTX; i++) {
...
irq_set_chained_handler_and_data(irq, rzg3s_pcie_intx_irq_handler,
host);
...
}
However, if an error occurs later in the initialization sequence, the error
handling paths do not tear down these chained handlers by calling
irq_set_chained_handler_and_data(irq, NULL, NULL).
Since the host structure is allocated via devm_pci_alloc_host_bridge(), it is
automatically freed when the probe function fails.
If any of the mapped INTx interrupts trigger after probe failure, the kernel
will execute the stale rzg3s_pcie_intx_irq_handler which dereferences the
freed host pointer.
Can this lead to a use-after-free regression on the host structure?
I also noticed another issue in the resume path:
drivers/pci/controller/pcie-rzg3s-host.c:rzg3s_pcie_resume_noirq() {
...
ret = rzg3s_pcie_power_resets_deassert(host);
...
}
drivers/pci/controller/pcie-rzg3s-host.c:rzg3s_pcie_power_resets_deassert() {
...
fsleep(5000);
...
}
rzg3s_pcie_resume_noirq() is registered as a .resume_noirq PM callback via
NOIRQ_SYSTEM_SLEEP_PM_OPS.
The PM core executes noirq phase callbacks with local CPU interrupts explicitly
disabled.
Within rzg3s_pcie_resume_noirq(), the driver calls
rzg3s_pcie_power_resets_deassert(), which unconditionally executes
fsleep(5000).
For a 5000us delay, fsleep() delegates to usleep_range(), which uses
schedule_hrtimeout() and sleeps the task.
Because timer interrupts are disabled on the local CPU in the noirq phase,
the hrtimer may never fire to wake the task.
Could sleeping with interrupts disabled here trigger a scheduling bug or lead
to a silent system hang regression during resume?
If a delay is strictly required in the noirq phase, should a busy-wait
function like mdelay(5) be used instead?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260518155324.168948-1-prabhakar.mahadev-lad.rj@bp.renesas.com?part=2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 3/4] PCI: rzg3s-host: Prepare System Controller handling for multiple controllers
2026-05-18 15:53 [PATCH v2 0/4] Add PCIe support for RZ/V2H(P) SoC Prabhakar
2026-05-18 15:53 ` [PATCH v2 1/4] dt-bindings: PCI: renesas,r9a08g045-pcie: Add RZ/V2H(P) support Prabhakar
2026-05-18 15:53 ` [PATCH v2 2/4] PCI: rzg3s-host: Use shared reset controls for power domain resets Prabhakar
@ 2026-05-18 15:53 ` Prabhakar
2026-05-18 15:53 ` [PATCH v2 4/4] PCI: rzg3s-host: Add support for RZ/V2H(P) SoC Prabhakar
3 siblings, 0 replies; 8+ messages in thread
From: Prabhakar @ 2026-05-18 15:53 UTC (permalink / raw)
To: Lorenzo Pieralisi, Manivannan Sadhasivam,
Krzysztof Wilczyński, Bjorn Helgaas, Rob Herring,
Claudiu Beznea, Krzysztof Kozlowski, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven, Magnus Damm
Cc: linux-pci, linux-renesas-soc, devicetree, linux-kernel, Prabhakar,
Biju Das, Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Prepare the driver to handle multiple PCIe controllers with distinct
System Controller (SYSC) register sets, as required by RZ/V2H(P). The
current design stores a single sysc_info structure per SoC, which is
insufficient for multi-controller configurations.
Introduce controller identifiers and extend struct rzg3s_pcie_soc_data
to hold a sysc_info array indexed per PCIe controller. Add a
controller_id field to struct rzg3s_pcie_host and select the appropriate
System Controller information during probe based on the hardware
instance.
Keep existing single-controller SoCs functionally unchanged while
preparing the driver for RZ/V2H(P) multi-controller support.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
v1->v2:
- Renamed RZG3S_PCIE_CHANNEL_ID* to RZG3S_PCIE_CONTROLLER_ID* for clarity.
- Updated commit message.
---
drivers/pci/controller/pcie-rzg3s-host.c | 48 ++++++++++++++++--------
1 file changed, 33 insertions(+), 15 deletions(-)
diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c
index a5192e4b58df..edb49af7429a 100644
--- a/drivers/pci/controller/pcie-rzg3s-host.c
+++ b/drivers/pci/controller/pcie-rzg3s-host.c
@@ -241,6 +241,18 @@ struct rzg3s_pcie_msi {
int irq;
};
+/**
+ * enum rzg3s_pcie_controller_id - RZ/G3S PCIe controller IDs
+ * @RZG3S_PCIE_CONTROLLER_ID_0: PCIe controller 0
+ * @RZG3S_PCIE_CONTROLLER_ID_1: PCIe controller 1
+ * @RZG3S_PCIE_CONTROLLER_ID_MAX: Max PCIe controllers
+ */
+enum rzg3s_pcie_controller_id {
+ RZG3S_PCIE_CONTROLLER_ID_0,
+ RZG3S_PCIE_CONTROLLER_ID_1,
+ RZG3S_PCIE_CONTROLLER_ID_MAX,
+};
+
struct rzg3s_pcie_host;
/**
@@ -253,7 +265,7 @@ struct rzg3s_pcie_host;
* power-on
* @cfg_resets: array with the resets that need to be de-asserted after
* configuration
- * @sysc_info: SYSC info
+ * @sysc_info: System Controller info for each controller
* @num_power_resets: number of power resets
* @num_cfg_resets: number of configuration resets
*/
@@ -264,7 +276,7 @@ struct rzg3s_pcie_soc_data {
int (*config_deinit)(struct rzg3s_pcie_host *host);
const char * const *power_resets;
const char * const *cfg_resets;
- struct rzg3s_sysc_info sysc_info;
+ struct rzg3s_sysc_info sysc_info[RZG3S_PCIE_CONTROLLER_ID_MAX];
u8 num_power_resets;
u8 num_cfg_resets;
};
@@ -296,6 +308,7 @@ struct rzg3s_pcie_port {
* @hw_lock: lock for access to the HW resources
* @intx_irqs: INTx interrupts
* @max_link_speed: maximum supported link speed
+ * @controller_id: PCIe controller identifier, used for System Controller access
*/
struct rzg3s_pcie_host {
void __iomem *axi;
@@ -311,6 +324,7 @@ struct rzg3s_pcie_host {
raw_spinlock_t hw_lock;
int intx_irqs[PCI_NUM_INTX];
int max_link_speed;
+ enum rzg3s_pcie_controller_id controller_id;
};
#define rzg3s_msi_to_host(_msi) container_of(_msi, struct rzg3s_pcie_host, msi)
@@ -1698,7 +1712,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
return -ENOMEM;
sysc = host->sysc;
- sysc->info = &host->data->sysc_info;
+ sysc->info = &host->data->sysc_info[host->controller_id];
host->axi = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(host->axi))
@@ -1891,10 +1905,12 @@ static const struct rzg3s_pcie_soc_data rzg3s_soc_data = {
.config_deinit = rzg3s_pcie_config_deinit,
.init_phy = rzg3s_soc_pcie_init_phy,
.sysc_info = {
- .functions = {
- [RZG3S_SYSC_FUNC_ID_RST_RSM_B] = {
- .offset = 0xd74,
- .mask = BIT(0),
+ [RZG3S_PCIE_CONTROLLER_ID_0] = {
+ .functions = {
+ [RZG3S_SYSC_FUNC_ID_RST_RSM_B] = {
+ .offset = 0xd74,
+ .mask = BIT(0),
+ },
},
},
},
@@ -1909,14 +1925,16 @@ static const struct rzg3s_pcie_soc_data rzg3e_soc_data = {
.config_post_init = rzg3e_pcie_config_post_init,
.config_deinit = rzg3e_pcie_config_deinit,
.sysc_info = {
- .functions = {
- [RZG3S_SYSC_FUNC_ID_L1_ALLOW] = {
- .offset = 0x1020,
- .mask = BIT(0),
- },
- [RZG3S_SYSC_FUNC_ID_MODE] = {
- .offset = 0x1024,
- .mask = BIT(0),
+ [RZG3S_PCIE_CONTROLLER_ID_0] = {
+ .functions = {
+ [RZG3S_SYSC_FUNC_ID_L1_ALLOW] = {
+ .offset = 0x1020,
+ .mask = BIT(0),
+ },
+ [RZG3S_SYSC_FUNC_ID_MODE] = {
+ .offset = 0x1024,
+ .mask = BIT(0),
+ },
},
},
},
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 4/4] PCI: rzg3s-host: Add support for RZ/V2H(P) SoC
2026-05-18 15:53 [PATCH v2 0/4] Add PCIe support for RZ/V2H(P) SoC Prabhakar
` (2 preceding siblings ...)
2026-05-18 15:53 ` [PATCH v2 3/4] PCI: rzg3s-host: Prepare System Controller handling for multiple controllers Prabhakar
@ 2026-05-18 15:53 ` Prabhakar
3 siblings, 0 replies; 8+ messages in thread
From: Prabhakar @ 2026-05-18 15:53 UTC (permalink / raw)
To: Lorenzo Pieralisi, Manivannan Sadhasivam,
Krzysztof Wilczyński, Bjorn Helgaas, Rob Herring,
Claudiu Beznea, Krzysztof Kozlowski, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven, Magnus Damm
Cc: linux-pci, linux-renesas-soc, devicetree, linux-kernel, Prabhakar,
Biju Das, Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Add support for the RZ/V2H(P) SoC PCIe controllers to the rzg3s-host
driver.
The RZ/V2H(P) SoC features two independent PCIe controllers that share
four physical lanes. The hardware supports two configuration modes:
single x4 mode where the first controller uses all four lanes, or dual
x2 mode where both controllers use two lanes each.
Introduce a setup_lanes() function pointer to configure the PCIe lanes
based on the hardware instance. Implement rzv2h_pcie_setup_lanes() to
detect the configuration at boot time and program the lane mode via the
system controller.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
v1->v2:
- Updated commit message.
- Added locks to protect shared lane configuration state and
prevent concurrent access issues during probe.
- Added cleanup action to release lanes on driver removal.
- Reconfigured RZG3S_SYSC_FUNC_ID_LINK_MASTER in resume path.
- Renamed num_channels to num_pcie_controllers for clarity.
---
drivers/pci/controller/pcie-rzg3s-host.c | 177 +++++++++++++++++++++++
1 file changed, 177 insertions(+)
diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c
index edb49af7429a..1cd9f7c10357 100644
--- a/drivers/pci/controller/pcie-rzg3s-host.c
+++ b/drivers/pci/controller/pcie-rzg3s-host.c
@@ -179,6 +179,16 @@
/* Timeouts experimentally determined */
#define RZG3S_REQ_ISSUE_TIMEOUT_US 2500
+/**
+ * enum rzg3s_sysc_link_mode - PCIe link configuration modes
+ * @RZG3S_SYSC_LINK_MODE_SINGLE_X4: Single port with x4 lanes
+ * @RZG3S_SYSC_LINK_MODE_DUAL_X2: Dual ports with x2 lanes each
+ */
+enum rzg3s_sysc_link_mode {
+ RZG3S_SYSC_LINK_MODE_SINGLE_X4 = 1,
+ RZG3S_SYSC_LINK_MODE_DUAL_X2 = 3,
+};
+
/**
* struct rzg3s_sysc_function - System Controller function descriptor
* @offset: Register offset from the System Controller base address
@@ -194,12 +204,14 @@ struct rzg3s_sysc_function {
* @RZG3S_SYSC_FUNC_ID_RST_RSM_B: RST_RSM_B SYSC function ID
* @RZG3S_SYSC_FUNC_ID_L1_ALLOW: L1 allow SYSC function ID
* @RZG3S_SYSC_FUNC_ID_MODE: Mode SYSC function ID
+ * @RZG3S_SYSC_FUNC_ID_LINK_MASTER: Link master SYSC function ID
* @RZG3S_SYSC_FUNC_ID_MAX: Max SYSC function ID
*/
enum rzg3s_sysc_func_id {
RZG3S_SYSC_FUNC_ID_RST_RSM_B,
RZG3S_SYSC_FUNC_ID_L1_ALLOW,
RZG3S_SYSC_FUNC_ID_MODE,
+ RZG3S_SYSC_FUNC_ID_LINK_MASTER,
RZG3S_SYSC_FUNC_ID_MAX,
};
@@ -261,6 +273,7 @@ struct rzg3s_pcie_host;
* @config_pre_init: Optional callback for SoC-specific pre-configuration
* @config_post_init: Callback for SoC-specific post-configuration
* @config_deinit: Callback for SoC-specific de-initialization
+ * @setup_lanes: Callback for setting up the number of lanes
* @power_resets: array with the resets that need to be de-asserted after
* power-on
* @cfg_resets: array with the resets that need to be de-asserted after
@@ -268,17 +281,20 @@ struct rzg3s_pcie_host;
* @sysc_info: System Controller info for each controller
* @num_power_resets: number of power resets
* @num_cfg_resets: number of configuration resets
+ * @num_pcie_controllers: number of PCIe controllers
*/
struct rzg3s_pcie_soc_data {
int (*init_phy)(struct rzg3s_pcie_host *host);
void (*config_pre_init)(struct rzg3s_pcie_host *host);
int (*config_post_init)(struct rzg3s_pcie_host *host);
int (*config_deinit)(struct rzg3s_pcie_host *host);
+ int (*setup_lanes)(struct rzg3s_pcie_host *host);
const char * const *power_resets;
const char * const *cfg_resets;
struct rzg3s_sysc_info sysc_info[RZG3S_PCIE_CONTROLLER_ID_MAX];
u8 num_power_resets;
u8 num_cfg_resets;
+ u8 num_pcie_controllers;
};
/**
@@ -309,6 +325,7 @@ struct rzg3s_pcie_port {
* @intx_irqs: INTx interrupts
* @max_link_speed: maximum supported link speed
* @controller_id: PCIe controller identifier, used for System Controller access
+ * @num_lanes: The number of lanes
*/
struct rzg3s_pcie_host {
void __iomem *axi;
@@ -325,10 +342,23 @@ struct rzg3s_pcie_host {
int intx_irqs[PCI_NUM_INTX];
int max_link_speed;
enum rzg3s_pcie_controller_id controller_id;
+ u8 num_lanes;
};
#define rzg3s_msi_to_host(_msi) container_of(_msi, struct rzg3s_pcie_host, msi)
+/*
+ * RZ/V2H(P) supports a total of 4 lanes shared across two controllers.
+ * rzv2h_lane_lock serialises both the counter update and the SYSC
+ * register write so that concurrent async probes cannot race on the
+ * shared LINK_MASTER register (offset 0x1060).
+ * rzv2h_num_total_lanes tracks global lane usage to prevent
+ * over-allocation or invalid bifurcation modes.
+ */
+#define RZV2H_PCIE_MAX_LANES 4
+static DEFINE_SPINLOCK(rzv2h_lane_lock);
+static u8 rzv2h_num_total_lanes;
+
static int rzg3s_sysc_config_func(struct rzg3s_sysc *sysc,
enum rzg3s_sysc_func_id fid, u32 val)
{
@@ -1155,6 +1185,13 @@ static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host)
rzg3s_pcie_update_bits(host->pcie, PCI_CLASS_REVISION, mask,
field_prep(mask, PCI_CLASS_BRIDGE_PCI_NORMAL));
+ if (host->num_lanes) {
+ rzg3s_pcie_update_bits(host->pcie + RZG3S_PCI_CFG_PCIEC,
+ PCI_EXP_LNKCAP, PCI_EXP_LNKCAP_MLW,
+ FIELD_PREP(PCI_EXP_LNKCAP_MLW,
+ host->num_lanes));
+ }
+
/* Disable access control to the CFGU */
writel_relaxed(0, host->axi + RZG3S_PCI_PERM);
@@ -1687,6 +1724,72 @@ rzg3s_pcie_host_setup(struct rzg3s_pcie_host *host,
return ret;
}
+static int rzg3s_pcie_get_controller_id(struct rzg3s_pcie_host *host)
+{
+ struct device_node *np = host->dev->of_node;
+ u32 domain;
+ int ret;
+
+ if (host->data->num_pcie_controllers == 1)
+ return 0;
+
+ ret = of_property_read_u32(np, "linux,pci-domain", &domain);
+ if (ret)
+ return ret;
+
+ if (domain >= host->data->num_pcie_controllers || domain >= RZG3S_PCIE_CONTROLLER_ID_MAX)
+ return -EINVAL;
+
+ host->controller_id = domain;
+
+ return 0;
+}
+
+static int rzv2h_pcie_setup_lanes(struct rzg3s_pcie_host *host)
+{
+ struct device_node *np = host->dev->of_node;
+ u32 num_lanes;
+ int ret;
+
+ ret = of_property_read_u32(np, "num-lanes", &num_lanes);
+ if (ret)
+ return ret;
+
+ /*
+ * RZ/V2H(P) supports up to 4 lanes, but only in single x4 mode
+ * for the first controller. Dual x2 mode is supported with 2
+ * lanes for both controllers.
+ */
+ if (num_lanes != 4 && num_lanes != 2)
+ return -EINVAL;
+
+ if (host->controller_id == RZG3S_PCIE_CONTROLLER_ID_1 && num_lanes > 2)
+ return -EINVAL;
+
+ guard(spinlock)(&rzv2h_lane_lock);
+ if (rzv2h_num_total_lanes + num_lanes > RZV2H_PCIE_MAX_LANES)
+ return -EINVAL;
+
+ ret = rzg3s_sysc_config_func(host->sysc, RZG3S_SYSC_FUNC_ID_LINK_MASTER,
+ num_lanes == 2 ?
+ RZG3S_SYSC_LINK_MODE_DUAL_X2 :
+ RZG3S_SYSC_LINK_MODE_SINGLE_X4);
+ if (!ret) {
+ rzv2h_num_total_lanes += num_lanes;
+ host->num_lanes = num_lanes;
+ }
+
+ return ret;
+}
+
+static void rzv2h_pcie_release_lanes(void *data)
+{
+ struct rzg3s_pcie_host *host = data;
+
+ guard(spinlock)(&rzv2h_lane_lock);
+ rzv2h_num_total_lanes -= host->num_lanes;
+}
+
static int rzg3s_pcie_probe(struct platform_device *pdev)
{
struct pci_host_bridge *bridge;
@@ -1711,6 +1814,10 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
if (!host->sysc)
return -ENOMEM;
+ ret = rzg3s_pcie_get_controller_id(host);
+ if (ret)
+ return ret;
+
sysc = host->sysc;
sysc->info = &host->data->sysc_info[host->controller_id];
@@ -1740,6 +1847,16 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
if (ret)
goto port_refclk_put;
+ if (host->data->setup_lanes) {
+ ret = host->data->setup_lanes(host);
+ if (ret)
+ goto sysc_signal_restore;
+
+ ret = devm_add_action_or_reset(dev, rzv2h_pcie_release_lanes, host);
+ if (ret)
+ goto sysc_signal_restore;
+ }
+
ret = rzg3s_pcie_resets_prepare_and_get(host);
if (ret)
goto sysc_signal_restore;
@@ -1854,6 +1971,16 @@ static int rzg3s_pcie_resume_noirq(struct device *dev)
if (ret)
return ret;
+ if (host->num_lanes) {
+ ret = rzg3s_sysc_config_func(host->sysc,
+ RZG3S_SYSC_FUNC_ID_LINK_MASTER,
+ host->num_lanes == 2 ?
+ RZG3S_SYSC_LINK_MODE_DUAL_X2 :
+ RZG3S_SYSC_LINK_MODE_SINGLE_X4);
+ if (ret)
+ goto assert_rst_rsm_b;
+ }
+
ret = rzg3s_pcie_power_resets_deassert(host);
if (ret)
goto assert_rst_rsm_b;
@@ -1901,6 +2028,7 @@ static const struct rzg3s_pcie_soc_data rzg3s_soc_data = {
.num_power_resets = ARRAY_SIZE(rzg3s_soc_power_resets),
.cfg_resets = rzg3s_soc_cfg_resets,
.num_cfg_resets = ARRAY_SIZE(rzg3s_soc_cfg_resets),
+ .num_pcie_controllers = 1,
.config_post_init = rzg3s_pcie_config_post_init,
.config_deinit = rzg3s_pcie_config_deinit,
.init_phy = rzg3s_soc_pcie_init_phy,
@@ -1921,6 +2049,7 @@ static const char * const rzg3e_soc_power_resets[] = { "aresetn" };
static const struct rzg3s_pcie_soc_data rzg3e_soc_data = {
.power_resets = rzg3e_soc_power_resets,
.num_power_resets = ARRAY_SIZE(rzg3e_soc_power_resets),
+ .num_pcie_controllers = 1,
.config_pre_init = rzg3e_pcie_config_pre_init,
.config_post_init = rzg3e_pcie_config_post_init,
.config_deinit = rzg3e_pcie_config_deinit,
@@ -1940,6 +2069,50 @@ static const struct rzg3s_pcie_soc_data rzg3e_soc_data = {
},
};
+static const struct rzg3s_pcie_soc_data rzv2h_soc_data = {
+ .power_resets = rzg3e_soc_power_resets,
+ .num_power_resets = ARRAY_SIZE(rzg3e_soc_power_resets),
+ .num_pcie_controllers = 2,
+ .config_pre_init = rzg3e_pcie_config_pre_init,
+ .config_post_init = rzg3e_pcie_config_post_init,
+ .config_deinit = rzg3e_pcie_config_deinit,
+ .setup_lanes = rzv2h_pcie_setup_lanes,
+ .sysc_info = {
+ [RZG3S_PCIE_CONTROLLER_ID_0] = {
+ .functions = {
+ [RZG3S_SYSC_FUNC_ID_L1_ALLOW] = {
+ .offset = 0x1020,
+ .mask = BIT(0),
+ },
+ [RZG3S_SYSC_FUNC_ID_MODE] = {
+ .offset = 0x1024,
+ .mask = BIT(0),
+ },
+ [RZG3S_SYSC_FUNC_ID_LINK_MASTER] = {
+ .offset = 0x1060,
+ .mask = GENMASK(9, 8),
+ },
+ },
+ },
+ [RZG3S_PCIE_CONTROLLER_ID_1] = {
+ .functions = {
+ [RZG3S_SYSC_FUNC_ID_L1_ALLOW] = {
+ .offset = 0x1050,
+ .mask = BIT(0),
+ },
+ [RZG3S_SYSC_FUNC_ID_MODE] = {
+ .offset = 0x1054,
+ .mask = BIT(0),
+ },
+ [RZG3S_SYSC_FUNC_ID_LINK_MASTER] = {
+ .offset = 0x1060,
+ .mask = GENMASK(9, 8),
+ },
+ },
+ },
+ },
+};
+
static const struct of_device_id rzg3s_pcie_of_match[] = {
{
.compatible = "renesas,r9a08g045-pcie",
@@ -1949,6 +2122,10 @@ static const struct of_device_id rzg3s_pcie_of_match[] = {
.compatible = "renesas,r9a09g047-pcie",
.data = &rzg3e_soc_data,
},
+ {
+ .compatible = "renesas,r9a09g057-pcie",
+ .data = &rzv2h_soc_data,
+ },
{}
};
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread