Re: [PATCH v8 4/9] PCI: stm32: Add PCIe Endpoint support for STM32MP25

From: Christian Bruel
Date: Fri May 16 2025 - 08:11:02 EST


(Sorry I missed the last point before my reply with a new v9/v10 series)

On 5/15/25 13:26, Manivannan Sadhasivam wrote:
On Mon, May 12, 2025 at 06:06:16PM +0200, Christian Bruel wrote:
Hello Manivannan,

On 4/30/25 09:50, Manivannan Sadhasivam wrote:
On Wed, Apr 23, 2025 at 11:01:14AM +0200, Christian Bruel wrote:
Add driver to configure the STM32MP25 SoC PCIe Gen1 2.5GT/s or Gen2 5GT/s
controller based on the DesignWare PCIe core in endpoint mode.

Uses the common reference clock provided by the host.

The PCIe core_clk receives the pipe0_clk from the ComboPHY as input,
and the ComboPHY PLL must be locked for pipe0_clk to be ready.
Consequently, PCIe core registers cannot be accessed until the ComboPHY is
fully initialised and refclk is enabled and ready.

Signed-off-by: Christian Bruel <christian.bruel@xxxxxxxxxxx>
---
drivers/pci/controller/dwc/Kconfig | 12 +
drivers/pci/controller/dwc/Makefile | 1 +
drivers/pci/controller/dwc/pcie-stm32-ep.c | 414 +++++++++++++++++++++
drivers/pci/controller/dwc/pcie-stm32.h | 1 +
4 files changed, 428 insertions(+)
create mode 100644 drivers/pci/controller/dwc/pcie-stm32-ep.c

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 2aec5d2f9a46..aceff7d1ef33 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -422,6 +422,18 @@ config PCIE_STM32_HOST
This driver can also be built as a module. If so, the module
will be called pcie-stm32.
+config PCIE_STM32_EP
+ tristate "STMicroelectronics STM32MP25 PCIe Controller (endpoint mode)"
+ depends on ARCH_STM32 || COMPILE_TEST
+ depends on PCI_ENDPOINT
+ select PCIE_DW_EP
+ help
+ Enables endpoint support for DesignWare core based PCIe controller
+ found in STM32MP25 SoC.

Can you please use similar description for the RC driver also?

"Enables Root Complex (RC) support for the DesignWare core based PCIe host
controller found in STM32MP25 SoC."

Yes, will align the messages

+
+ This driver can also be built as a module. If so, the module
+ will be called pcie-stm32-ep.
+
config PCI_DRA7XX
tristate

[...]

+static int stm32_add_pcie_ep(struct stm32_pcie *stm32_pcie,
+ struct platform_device *pdev)
+{
+ struct dw_pcie_ep *ep = &stm32_pcie->pci.ep;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(dev);

This needs to be called before devm_pm_runtime_enable().

OK. Also and we must use pm_runtime_get_noresume() here.


Yes!


+ if (ret < 0) {
+ dev_err(dev, "pm runtime resume failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR,
+ STM32MP25_PCIECR_TYPE_MASK,
+ STM32MP25_PCIECR_EP);
+ if (ret) {
+ goto err_pm_put_sync;
+ return ret;
+ }
+
+ reset_control_assert(stm32_pcie->rst);
+ reset_control_deassert(stm32_pcie->rst);
+
+ ep->ops = &stm32_pcie_ep_ops;
+
+ ret = dw_pcie_ep_init(ep);
+ if (ret) {
+ dev_err(dev, "failed to initialize ep: %d\n", ret);
+ goto err_pm_put_sync;
+ }
+
+ ret = stm32_pcie_enable_resources(stm32_pcie);
+ if (ret) {
+ dev_err(dev, "failed to enable resources: %d\n", ret);
+ goto err_ep_deinit;
+ }
+
+ ret = dw_pcie_ep_init_registers(ep);
+ if (ret) {
+ dev_err(dev, "Failed to initialize DWC endpoint registers\n");
+ goto err_disable_resources;
+ }
+
+ pci_epc_init_notify(ep->epc);
+

Hmm, looks like you need to duplicate dw_pcie_ep_init_registers() and
pci_epc_init_notify() in stm32_pcie_perst_deassert() for hw specific reasons.
So can you drop these from there?

We cannot remove dw_pcie_ep_init_registers() and dw_pcie_ep_init_registers()
here because the PCIe registers need to be ready at the end of
pcie_stm32_probe, as the host might already be running. In that case the
host enumerates with /sys/bus/pci/rescan rather than asserting/deasserting
PERST#.
Therefore, we do not need to reboot the host after initializing the EP."


Since PERST# is level triggered, the endpoint should still receive the PERST#
deassert interrupt if the host was already booted. In that case, these will be
called by the stm32_pcie_perst_deassert() function.

GPIO level interrupts are simulated on STM32 (*), so I didn't consider using them here
However, using the same sequence as in pcie-qcom-ep.c works fine with the gpio hack, avoiding the call the dw_pcie_ep_init_registers() here.

I will switch to this scheme. Thank you

Christian

(*) 47beed513a85b3561e74cbb4dd7af848716fa4e0 ("pinctrl: stm32: Add level interrupt support to gpio irq chip")



- Mani