On Tue, Nov 26, 2024 at 04:51:18PM +0100, Christian Bruel wrote: [...] > +static int stm32_pcie_start_link(struct dw_pcie *pci) > +{ > + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); > + int ret; > + > + if (stm32_pcie->link_status == STM32_PCIE_EP_LINK_ENABLED) { > + dev_dbg(pci->dev, "Link is already enabled\n"); > + return 0; > + } > + > + ret = stm32_pcie_enable_link(pci); > + if (ret) { > + dev_err(pci->dev, "PCIe cannot establish link: %d\n", ret); > + return ret; > + } How the REFCLK is supplied to the endpoint? From host or generated locally? > + > + stm32_pcie->link_status = STM32_PCIE_EP_LINK_ENABLED; > + > + enable_irq(stm32_pcie->perst_irq); > + > + return 0; > +} > + > +static void stm32_pcie_stop_link(struct dw_pcie *pci) > +{ > + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); > + > + if (stm32_pcie->link_status == STM32_PCIE_EP_LINK_DISABLED) { > + dev_dbg(pci->dev, "Link is already disabled\n"); > + return; > + } > + > + disable_irq(stm32_pcie->perst_irq); > + > + stm32_pcie_disable_link(pci); > + > + stm32_pcie->link_status = STM32_PCIE_EP_LINK_DISABLED; > +} > + > +static int stm32_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, > + unsigned int type, u16 interrupt_num) > +{ > + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); > + > + switch (type) { > + case PCI_IRQ_INTX: > + return dw_pcie_ep_raise_intx_irq(ep, func_no); > + case PCI_IRQ_MSI: > + return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); > + default: > + dev_err(pci->dev, "UNKNOWN IRQ type\n"); > + return -EINVAL; > + } > +} > + > +static const struct pci_epc_features stm32_pcie_epc_features = { > + .msi_capable = true, > + .align = 1 << 16, Use SZ_64K > +}; > + [...] > +static int stm32_add_pcie_ep(struct stm32_pcie *stm32_pcie, > + struct platform_device *pdev) > +{ > + struct dw_pcie *pci = stm32_pcie->pci; > + struct dw_pcie_ep *ep = &pci->ep; > + struct device *dev = &pdev->dev; > + int ret; > + > + ret = regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, > + STM32MP25_PCIECR_TYPE_MASK, > + STM32MP25_PCIECR_EP); > + if (ret) > + return ret; > + > + ret = pm_runtime_resume_and_get(dev); > + if (ret < 0) { > + dev_err(dev, "pm runtime resume failed: %d\n", ret); > + return ret; > + } You might want to do runtime resume before accessing regmap. > + > + 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_init; > + } > + > + ret = stm32_pcie_enable_resources(stm32_pcie); > + if (ret) { > + dev_err(dev, "failed to enable resources: %d\n", ret); > + goto err_clk; > + } > + > + ret = dw_pcie_ep_init_registers(ep); > + if (ret) { > + dev_err(dev, "Failed to initialize DWC endpoint registers\n"); > + goto err_init_regs; > + } > + > + pci_epc_init_notify(ep->epc); > + > + return 0; > + > +err_init_regs: > + stm32_pcie_disable_resources(stm32_pcie); > + > +err_clk: > + dw_pcie_ep_deinit(ep); > + > +err_init: > + pm_runtime_put_sync(dev); > + return ret; > +} > + > +static int stm32_pcie_probe(struct platform_device *pdev) > +{ > + struct stm32_pcie *stm32_pcie; > + struct dw_pcie *dw; > + struct device *dev = &pdev->dev; > + int ret; > + > + stm32_pcie = devm_kzalloc(dev, sizeof(*stm32_pcie), GFP_KERNEL); > + if (!stm32_pcie) > + return -ENOMEM; > + > + dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL); > + if (!dw) > + return -ENOMEM; Why can't you allocate it statically inside 'struct stm32_pcie'? > + > + stm32_pcie->pci = dw; > + > + dw->dev = dev; > + dw->ops = &dw_pcie_ops; > + > + stm32_pcie->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg"); > + if (IS_ERR(stm32_pcie->regmap)) > + return dev_err_probe(dev, PTR_ERR(stm32_pcie->regmap), > + "No syscfg specified\n"); > + > + stm32_pcie->phy = devm_phy_get(dev, "pcie-phy"); > + if (IS_ERR(stm32_pcie->phy)) > + return dev_err_probe(dev, PTR_ERR(stm32_pcie->phy), > + "failed to get pcie-phy\n"); > + > + stm32_pcie->clk = devm_clk_get(dev, NULL); > + if (IS_ERR(stm32_pcie->clk)) > + return dev_err_probe(dev, PTR_ERR(stm32_pcie->clk), > + "Failed to get PCIe clock source\n"); > + > + stm32_pcie->rst = devm_reset_control_get_exclusive(dev, NULL); > + if (IS_ERR(stm32_pcie->rst)) > + return dev_err_probe(dev, PTR_ERR(stm32_pcie->rst), > + "Failed to get PCIe reset\n"); > + > + stm32_pcie->perst_gpio = devm_gpiod_get(dev, "reset", GPIOD_IN); > + if (IS_ERR(stm32_pcie->perst_gpio)) > + return dev_err_probe(dev, PTR_ERR(stm32_pcie->perst_gpio), > + "Failed to get reset GPIO\n"); > + > + ret = phy_set_mode(stm32_pcie->phy, PHY_MODE_PCIE); Hmm, so PHY mode is common for both endpoint and host? - Mani -- மணிவண்ணன் சதாசிவம்