[PATCH v6 09/10] PCI: dw-rockchip: Add system PM support
Manivannan Sadhasivam
mani at kernel.org
Tue Oct 13 11:48:57 PDT 2026
On 2026-09-08 16:51 +0200, Sebastian Reichel wrote:
> Add system PM support for Rockchip PCIe Designware Controllers.
>
> I've tested this on the Rockchip RK3576 EVB1, the Radxa ROCK 4D
> and the ArmSom Sige5 boards.
>
> While I haven't experienced any issues, most of my tests have been done
> without any devices attached (i.e. default board without any extras), so
> there _might_ still be some problems. As system suspend does not work at
> all right now, I think it makes sense to get at least the basic
> configurations working as soon as possible as it will allow us to catch
> regressions by enabling system suspend in CI systems like KernelCI.
>
> Co-developed-by: Shawn Lin <shawn.lin at rock-chips.com>
> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
> Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
> ---
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 100 ++++++++++++++++++++++++++
> 1 file changed, 100 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> index 47d9cab909bc..e675918ba184 100644
> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> @@ -120,6 +120,7 @@ struct rockchip_pcie {
> struct gpio_desc *rst_gpio;
> struct regulator *vpcie3v3;
> struct irq_domain *irq_domain;
> + u32 intx;
> const struct rockchip_pcie_of_data *data;
> bool supports_clkreq;
> struct delayed_work trace_work;
> @@ -1042,6 +1043,99 @@ static int rockchip_pcie_rc_reset_root_port(struct pci_host_bridge *bridge,
> return ret;
> }
>
> +static int rockchip_pcie_suspend(struct device *dev)
> +{
> + struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
> + struct dw_pcie *pci = &rockchip->pci;
> + int ret;
> +
> + if (rockchip->data->mode == DW_PCIE_EP_TYPE) {
> + dev_err(dev, "suspend is not supported in EP mode\n");
> + return -EOPNOTSUPP;
> + }
> +
> + rockchip->intx = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_MASK_LEGACY);
> +
> + ret = dw_pcie_suspend_noirq(pci);
> + if (ret)
> + return ret;
> +
> + gpiod_set_value_cansleep(rockchip->rst_gpio, 0);
> + rockchip_pcie_phy_deinit(rockchip);
> + clk_bulk_disable_unprepare(rockchip->clk_cnt, rockchip->clks);
> + reset_control_assert(rockchip->rst);
> + if (rockchip->vpcie3v3)
> + regulator_disable(rockchip->vpcie3v3);
> +
> + return 0;
> +}
> +
> +static int rockchip_pcie_resume(struct device *dev)
> +{
> + struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
> + struct dw_pcie *pci = &rockchip->pci;
> + int ret;
> +
> + if (rockchip->data->mode == DW_PCIE_EP_TYPE) {
> + dev_err(dev, "resume is not supported in EP mode\n");
> + return -EOPNOTSUPP;
> + }
This is going to regress the EP system suspend. If the EP suspend used to work
before this patch, then you can safely return 0 here.
> +
> + ret = clk_bulk_prepare_enable(rockchip->clk_cnt, rockchip->clks);
> + if (ret) {
> + dev_err(dev, "clock init failed: %d\n", ret);
> + return ret;
> + }
> +
> + if (rockchip->vpcie3v3) {
> + ret = regulator_enable(rockchip->vpcie3v3);
> + if (ret)
> + goto err_disable_clk;
> + }
> +
> + ret = rockchip_pcie_phy_init(rockchip);
> + if (ret) {
> + dev_err(dev, "phy init failed: %d\n", ret);
> + goto err_disable_regulator;
> + }
> +
> + reset_control_deassert(rockchip->rst);
> +
> + rockchip_pcie_writel_apb(rockchip, FIELD_PREP_WM16(0xffff, rockchip->intx),
> + PCIE_CLIENT_INTR_MASK_LEGACY);
> +
> + rockchip_pcie_enable_enhanced_ltssm_control_mode(rockchip, 0);
> + rockchip_pcie_set_controller_mode(rockchip, PCIE_CLIENT_MODE_RC);
> + rockchip_pcie_unmask_dll_indicator(rockchip);
> +
> + gpiod_set_value_cansleep(rockchip->rst_gpio, 1);
> +
> + ret = dw_pcie_resume_noirq(pci);
> + if (ret) {
> + dev_err(dev, "failed to resume: %d\n", ret);
> + /*
> + * During resume, dw_pcie_wait_for_link() is called and when
> + * there is no device connected at all it returns -EIO with
> + * the message "Device found, but not active". Ignore it for
> + * now.
> + */
This is not correct. When there is no device connected, -ENODEV will be
returned.
- Mani
More information about the linux-arm-kernel
mailing list