1*63a562b3SChristian Bruel // SPDX-License-Identifier: GPL-2.0-only 2*63a562b3SChristian Bruel /* 3*63a562b3SChristian Bruel * STMicroelectronics STM32MP25 PCIe root complex driver. 4*63a562b3SChristian Bruel * 5*63a562b3SChristian Bruel * Copyright (C) 2025 STMicroelectronics 6*63a562b3SChristian Bruel * Author: Christian Bruel <christian.bruel@foss.st.com> 7*63a562b3SChristian Bruel */ 8*63a562b3SChristian Bruel 9*63a562b3SChristian Bruel #include <linux/clk.h> 10*63a562b3SChristian Bruel #include <linux/mfd/syscon.h> 11*63a562b3SChristian Bruel #include <linux/of_platform.h> 12*63a562b3SChristian Bruel #include <linux/phy/phy.h> 13*63a562b3SChristian Bruel #include <linux/pinctrl/consumer.h> 14*63a562b3SChristian Bruel #include <linux/platform_device.h> 15*63a562b3SChristian Bruel #include <linux/pm_runtime.h> 16*63a562b3SChristian Bruel #include <linux/pm_wakeirq.h> 17*63a562b3SChristian Bruel #include <linux/regmap.h> 18*63a562b3SChristian Bruel #include <linux/reset.h> 19*63a562b3SChristian Bruel #include "pcie-designware.h" 20*63a562b3SChristian Bruel #include "pcie-stm32.h" 21*63a562b3SChristian Bruel #include "../../pci.h" 22*63a562b3SChristian Bruel 23*63a562b3SChristian Bruel struct stm32_pcie { 24*63a562b3SChristian Bruel struct dw_pcie pci; 25*63a562b3SChristian Bruel struct regmap *regmap; 26*63a562b3SChristian Bruel struct reset_control *rst; 27*63a562b3SChristian Bruel struct phy *phy; 28*63a562b3SChristian Bruel struct clk *clk; 29*63a562b3SChristian Bruel struct gpio_desc *perst_gpio; 30*63a562b3SChristian Bruel struct gpio_desc *wake_gpio; 31*63a562b3SChristian Bruel }; 32*63a562b3SChristian Bruel 33*63a562b3SChristian Bruel static void stm32_pcie_deassert_perst(struct stm32_pcie *stm32_pcie) 34*63a562b3SChristian Bruel { 35*63a562b3SChristian Bruel if (stm32_pcie->perst_gpio) { 36*63a562b3SChristian Bruel msleep(PCIE_T_PVPERL_MS); 37*63a562b3SChristian Bruel gpiod_set_value(stm32_pcie->perst_gpio, 0); 38*63a562b3SChristian Bruel } 39*63a562b3SChristian Bruel 40*63a562b3SChristian Bruel msleep(PCIE_RESET_CONFIG_WAIT_MS); 41*63a562b3SChristian Bruel } 42*63a562b3SChristian Bruel 43*63a562b3SChristian Bruel static void stm32_pcie_assert_perst(struct stm32_pcie *stm32_pcie) 44*63a562b3SChristian Bruel { 45*63a562b3SChristian Bruel gpiod_set_value(stm32_pcie->perst_gpio, 1); 46*63a562b3SChristian Bruel } 47*63a562b3SChristian Bruel 48*63a562b3SChristian Bruel static int stm32_pcie_start_link(struct dw_pcie *pci) 49*63a562b3SChristian Bruel { 50*63a562b3SChristian Bruel struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 51*63a562b3SChristian Bruel 52*63a562b3SChristian Bruel return regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 53*63a562b3SChristian Bruel STM32MP25_PCIECR_LTSSM_EN, 54*63a562b3SChristian Bruel STM32MP25_PCIECR_LTSSM_EN); 55*63a562b3SChristian Bruel } 56*63a562b3SChristian Bruel 57*63a562b3SChristian Bruel static void stm32_pcie_stop_link(struct dw_pcie *pci) 58*63a562b3SChristian Bruel { 59*63a562b3SChristian Bruel struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 60*63a562b3SChristian Bruel 61*63a562b3SChristian Bruel regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 62*63a562b3SChristian Bruel STM32MP25_PCIECR_LTSSM_EN, 0); 63*63a562b3SChristian Bruel } 64*63a562b3SChristian Bruel 65*63a562b3SChristian Bruel static int stm32_pcie_suspend_noirq(struct device *dev) 66*63a562b3SChristian Bruel { 67*63a562b3SChristian Bruel struct stm32_pcie *stm32_pcie = dev_get_drvdata(dev); 68*63a562b3SChristian Bruel int ret; 69*63a562b3SChristian Bruel 70*63a562b3SChristian Bruel ret = dw_pcie_suspend_noirq(&stm32_pcie->pci); 71*63a562b3SChristian Bruel if (ret) 72*63a562b3SChristian Bruel return ret; 73*63a562b3SChristian Bruel 74*63a562b3SChristian Bruel stm32_pcie_assert_perst(stm32_pcie); 75*63a562b3SChristian Bruel 76*63a562b3SChristian Bruel clk_disable_unprepare(stm32_pcie->clk); 77*63a562b3SChristian Bruel 78*63a562b3SChristian Bruel if (!device_wakeup_path(dev)) 79*63a562b3SChristian Bruel phy_exit(stm32_pcie->phy); 80*63a562b3SChristian Bruel 81*63a562b3SChristian Bruel return pinctrl_pm_select_sleep_state(dev); 82*63a562b3SChristian Bruel } 83*63a562b3SChristian Bruel 84*63a562b3SChristian Bruel static int stm32_pcie_resume_noirq(struct device *dev) 85*63a562b3SChristian Bruel { 86*63a562b3SChristian Bruel struct stm32_pcie *stm32_pcie = dev_get_drvdata(dev); 87*63a562b3SChristian Bruel int ret; 88*63a562b3SChristian Bruel 89*63a562b3SChristian Bruel /* 90*63a562b3SChristian Bruel * The core clock is gated with CLKREQ# from the COMBOPHY REFCLK, 91*63a562b3SChristian Bruel * thus if no device is present, must deassert it with a GPIO from 92*63a562b3SChristian Bruel * pinctrl pinmux before accessing the DBI registers. 93*63a562b3SChristian Bruel */ 94*63a562b3SChristian Bruel ret = pinctrl_pm_select_init_state(dev); 95*63a562b3SChristian Bruel if (ret) { 96*63a562b3SChristian Bruel dev_err(dev, "Failed to activate pinctrl pm state: %d\n", ret); 97*63a562b3SChristian Bruel return ret; 98*63a562b3SChristian Bruel } 99*63a562b3SChristian Bruel 100*63a562b3SChristian Bruel if (!device_wakeup_path(dev)) { 101*63a562b3SChristian Bruel ret = phy_init(stm32_pcie->phy); 102*63a562b3SChristian Bruel if (ret) { 103*63a562b3SChristian Bruel pinctrl_pm_select_default_state(dev); 104*63a562b3SChristian Bruel return ret; 105*63a562b3SChristian Bruel } 106*63a562b3SChristian Bruel } 107*63a562b3SChristian Bruel 108*63a562b3SChristian Bruel ret = clk_prepare_enable(stm32_pcie->clk); 109*63a562b3SChristian Bruel if (ret) 110*63a562b3SChristian Bruel goto err_phy_exit; 111*63a562b3SChristian Bruel 112*63a562b3SChristian Bruel stm32_pcie_deassert_perst(stm32_pcie); 113*63a562b3SChristian Bruel 114*63a562b3SChristian Bruel ret = dw_pcie_resume_noirq(&stm32_pcie->pci); 115*63a562b3SChristian Bruel if (ret) 116*63a562b3SChristian Bruel goto err_disable_clk; 117*63a562b3SChristian Bruel 118*63a562b3SChristian Bruel pinctrl_pm_select_default_state(dev); 119*63a562b3SChristian Bruel 120*63a562b3SChristian Bruel return 0; 121*63a562b3SChristian Bruel 122*63a562b3SChristian Bruel err_disable_clk: 123*63a562b3SChristian Bruel stm32_pcie_assert_perst(stm32_pcie); 124*63a562b3SChristian Bruel clk_disable_unprepare(stm32_pcie->clk); 125*63a562b3SChristian Bruel 126*63a562b3SChristian Bruel err_phy_exit: 127*63a562b3SChristian Bruel phy_exit(stm32_pcie->phy); 128*63a562b3SChristian Bruel pinctrl_pm_select_default_state(dev); 129*63a562b3SChristian Bruel 130*63a562b3SChristian Bruel return ret; 131*63a562b3SChristian Bruel } 132*63a562b3SChristian Bruel 133*63a562b3SChristian Bruel static const struct dev_pm_ops stm32_pcie_pm_ops = { 134*63a562b3SChristian Bruel NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_pcie_suspend_noirq, 135*63a562b3SChristian Bruel stm32_pcie_resume_noirq) 136*63a562b3SChristian Bruel }; 137*63a562b3SChristian Bruel 138*63a562b3SChristian Bruel static const struct dw_pcie_host_ops stm32_pcie_host_ops = { 139*63a562b3SChristian Bruel }; 140*63a562b3SChristian Bruel 141*63a562b3SChristian Bruel static const struct dw_pcie_ops dw_pcie_ops = { 142*63a562b3SChristian Bruel .start_link = stm32_pcie_start_link, 143*63a562b3SChristian Bruel .stop_link = stm32_pcie_stop_link 144*63a562b3SChristian Bruel }; 145*63a562b3SChristian Bruel 146*63a562b3SChristian Bruel static int stm32_add_pcie_port(struct stm32_pcie *stm32_pcie) 147*63a562b3SChristian Bruel { 148*63a562b3SChristian Bruel struct device *dev = stm32_pcie->pci.dev; 149*63a562b3SChristian Bruel unsigned int wake_irq; 150*63a562b3SChristian Bruel int ret; 151*63a562b3SChristian Bruel 152*63a562b3SChristian Bruel ret = phy_set_mode(stm32_pcie->phy, PHY_MODE_PCIE); 153*63a562b3SChristian Bruel if (ret) 154*63a562b3SChristian Bruel return ret; 155*63a562b3SChristian Bruel 156*63a562b3SChristian Bruel ret = phy_init(stm32_pcie->phy); 157*63a562b3SChristian Bruel if (ret) 158*63a562b3SChristian Bruel return ret; 159*63a562b3SChristian Bruel 160*63a562b3SChristian Bruel ret = regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 161*63a562b3SChristian Bruel STM32MP25_PCIECR_TYPE_MASK, 162*63a562b3SChristian Bruel STM32MP25_PCIECR_RC); 163*63a562b3SChristian Bruel if (ret) 164*63a562b3SChristian Bruel goto err_phy_exit; 165*63a562b3SChristian Bruel 166*63a562b3SChristian Bruel stm32_pcie_deassert_perst(stm32_pcie); 167*63a562b3SChristian Bruel 168*63a562b3SChristian Bruel if (stm32_pcie->wake_gpio) { 169*63a562b3SChristian Bruel wake_irq = gpiod_to_irq(stm32_pcie->wake_gpio); 170*63a562b3SChristian Bruel ret = dev_pm_set_dedicated_wake_irq(dev, wake_irq); 171*63a562b3SChristian Bruel if (ret) { 172*63a562b3SChristian Bruel dev_err(dev, "Failed to enable wakeup irq %d\n", ret); 173*63a562b3SChristian Bruel goto err_assert_perst; 174*63a562b3SChristian Bruel } 175*63a562b3SChristian Bruel irq_set_irq_type(wake_irq, IRQ_TYPE_EDGE_FALLING); 176*63a562b3SChristian Bruel } 177*63a562b3SChristian Bruel 178*63a562b3SChristian Bruel return 0; 179*63a562b3SChristian Bruel 180*63a562b3SChristian Bruel err_assert_perst: 181*63a562b3SChristian Bruel stm32_pcie_assert_perst(stm32_pcie); 182*63a562b3SChristian Bruel 183*63a562b3SChristian Bruel err_phy_exit: 184*63a562b3SChristian Bruel phy_exit(stm32_pcie->phy); 185*63a562b3SChristian Bruel 186*63a562b3SChristian Bruel return ret; 187*63a562b3SChristian Bruel } 188*63a562b3SChristian Bruel 189*63a562b3SChristian Bruel static void stm32_remove_pcie_port(struct stm32_pcie *stm32_pcie) 190*63a562b3SChristian Bruel { 191*63a562b3SChristian Bruel dev_pm_clear_wake_irq(stm32_pcie->pci.dev); 192*63a562b3SChristian Bruel 193*63a562b3SChristian Bruel stm32_pcie_assert_perst(stm32_pcie); 194*63a562b3SChristian Bruel 195*63a562b3SChristian Bruel phy_exit(stm32_pcie->phy); 196*63a562b3SChristian Bruel } 197*63a562b3SChristian Bruel 198*63a562b3SChristian Bruel static int stm32_pcie_parse_port(struct stm32_pcie *stm32_pcie) 199*63a562b3SChristian Bruel { 200*63a562b3SChristian Bruel struct device *dev = stm32_pcie->pci.dev; 201*63a562b3SChristian Bruel struct device_node *root_port; 202*63a562b3SChristian Bruel 203*63a562b3SChristian Bruel root_port = of_get_next_available_child(dev->of_node, NULL); 204*63a562b3SChristian Bruel 205*63a562b3SChristian Bruel stm32_pcie->phy = devm_of_phy_get(dev, root_port, NULL); 206*63a562b3SChristian Bruel if (IS_ERR(stm32_pcie->phy)) { 207*63a562b3SChristian Bruel of_node_put(root_port); 208*63a562b3SChristian Bruel return dev_err_probe(dev, PTR_ERR(stm32_pcie->phy), 209*63a562b3SChristian Bruel "Failed to get pcie-phy\n"); 210*63a562b3SChristian Bruel } 211*63a562b3SChristian Bruel 212*63a562b3SChristian Bruel stm32_pcie->perst_gpio = devm_fwnode_gpiod_get(dev, of_fwnode_handle(root_port), 213*63a562b3SChristian Bruel "reset", GPIOD_OUT_HIGH, NULL); 214*63a562b3SChristian Bruel if (IS_ERR(stm32_pcie->perst_gpio)) { 215*63a562b3SChristian Bruel if (PTR_ERR(stm32_pcie->perst_gpio) != -ENOENT) { 216*63a562b3SChristian Bruel of_node_put(root_port); 217*63a562b3SChristian Bruel return dev_err_probe(dev, PTR_ERR(stm32_pcie->perst_gpio), 218*63a562b3SChristian Bruel "Failed to get reset GPIO\n"); 219*63a562b3SChristian Bruel } 220*63a562b3SChristian Bruel stm32_pcie->perst_gpio = NULL; 221*63a562b3SChristian Bruel } 222*63a562b3SChristian Bruel 223*63a562b3SChristian Bruel stm32_pcie->wake_gpio = devm_fwnode_gpiod_get(dev, of_fwnode_handle(root_port), 224*63a562b3SChristian Bruel "wake", GPIOD_IN, NULL); 225*63a562b3SChristian Bruel 226*63a562b3SChristian Bruel if (IS_ERR(stm32_pcie->wake_gpio)) { 227*63a562b3SChristian Bruel if (PTR_ERR(stm32_pcie->wake_gpio) != -ENOENT) { 228*63a562b3SChristian Bruel of_node_put(root_port); 229*63a562b3SChristian Bruel return dev_err_probe(dev, PTR_ERR(stm32_pcie->wake_gpio), 230*63a562b3SChristian Bruel "Failed to get wake GPIO\n"); 231*63a562b3SChristian Bruel } 232*63a562b3SChristian Bruel stm32_pcie->wake_gpio = NULL; 233*63a562b3SChristian Bruel } 234*63a562b3SChristian Bruel 235*63a562b3SChristian Bruel of_node_put(root_port); 236*63a562b3SChristian Bruel 237*63a562b3SChristian Bruel return 0; 238*63a562b3SChristian Bruel } 239*63a562b3SChristian Bruel 240*63a562b3SChristian Bruel static int stm32_pcie_probe(struct platform_device *pdev) 241*63a562b3SChristian Bruel { 242*63a562b3SChristian Bruel struct stm32_pcie *stm32_pcie; 243*63a562b3SChristian Bruel struct device *dev = &pdev->dev; 244*63a562b3SChristian Bruel int ret; 245*63a562b3SChristian Bruel 246*63a562b3SChristian Bruel stm32_pcie = devm_kzalloc(dev, sizeof(*stm32_pcie), GFP_KERNEL); 247*63a562b3SChristian Bruel if (!stm32_pcie) 248*63a562b3SChristian Bruel return -ENOMEM; 249*63a562b3SChristian Bruel 250*63a562b3SChristian Bruel stm32_pcie->pci.dev = dev; 251*63a562b3SChristian Bruel stm32_pcie->pci.ops = &dw_pcie_ops; 252*63a562b3SChristian Bruel stm32_pcie->pci.pp.ops = &stm32_pcie_host_ops; 253*63a562b3SChristian Bruel 254*63a562b3SChristian Bruel stm32_pcie->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg"); 255*63a562b3SChristian Bruel if (IS_ERR(stm32_pcie->regmap)) 256*63a562b3SChristian Bruel return dev_err_probe(dev, PTR_ERR(stm32_pcie->regmap), 257*63a562b3SChristian Bruel "No syscfg specified\n"); 258*63a562b3SChristian Bruel 259*63a562b3SChristian Bruel stm32_pcie->clk = devm_clk_get(dev, NULL); 260*63a562b3SChristian Bruel if (IS_ERR(stm32_pcie->clk)) 261*63a562b3SChristian Bruel return dev_err_probe(dev, PTR_ERR(stm32_pcie->clk), 262*63a562b3SChristian Bruel "Failed to get PCIe clock source\n"); 263*63a562b3SChristian Bruel 264*63a562b3SChristian Bruel stm32_pcie->rst = devm_reset_control_get_exclusive(dev, NULL); 265*63a562b3SChristian Bruel if (IS_ERR(stm32_pcie->rst)) 266*63a562b3SChristian Bruel return dev_err_probe(dev, PTR_ERR(stm32_pcie->rst), 267*63a562b3SChristian Bruel "Failed to get PCIe reset\n"); 268*63a562b3SChristian Bruel 269*63a562b3SChristian Bruel ret = stm32_pcie_parse_port(stm32_pcie); 270*63a562b3SChristian Bruel if (ret) 271*63a562b3SChristian Bruel return ret; 272*63a562b3SChristian Bruel 273*63a562b3SChristian Bruel platform_set_drvdata(pdev, stm32_pcie); 274*63a562b3SChristian Bruel 275*63a562b3SChristian Bruel ret = stm32_add_pcie_port(stm32_pcie); 276*63a562b3SChristian Bruel if (ret) 277*63a562b3SChristian Bruel return ret; 278*63a562b3SChristian Bruel 279*63a562b3SChristian Bruel reset_control_assert(stm32_pcie->rst); 280*63a562b3SChristian Bruel reset_control_deassert(stm32_pcie->rst); 281*63a562b3SChristian Bruel 282*63a562b3SChristian Bruel ret = clk_prepare_enable(stm32_pcie->clk); 283*63a562b3SChristian Bruel if (ret) { 284*63a562b3SChristian Bruel dev_err(dev, "Core clock enable failed %d\n", ret); 285*63a562b3SChristian Bruel goto err_remove_port; 286*63a562b3SChristian Bruel } 287*63a562b3SChristian Bruel 288*63a562b3SChristian Bruel ret = pm_runtime_set_active(dev); 289*63a562b3SChristian Bruel if (ret < 0) { 290*63a562b3SChristian Bruel dev_err_probe(dev, ret, "Failed to activate runtime PM\n"); 291*63a562b3SChristian Bruel goto err_disable_clk; 292*63a562b3SChristian Bruel } 293*63a562b3SChristian Bruel 294*63a562b3SChristian Bruel pm_runtime_no_callbacks(dev); 295*63a562b3SChristian Bruel 296*63a562b3SChristian Bruel ret = devm_pm_runtime_enable(dev); 297*63a562b3SChristian Bruel if (ret < 0) { 298*63a562b3SChristian Bruel dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); 299*63a562b3SChristian Bruel goto err_disable_clk; 300*63a562b3SChristian Bruel } 301*63a562b3SChristian Bruel 302*63a562b3SChristian Bruel ret = dw_pcie_host_init(&stm32_pcie->pci.pp); 303*63a562b3SChristian Bruel if (ret) 304*63a562b3SChristian Bruel goto err_disable_clk; 305*63a562b3SChristian Bruel 306*63a562b3SChristian Bruel if (stm32_pcie->wake_gpio) 307*63a562b3SChristian Bruel device_init_wakeup(dev, true); 308*63a562b3SChristian Bruel 309*63a562b3SChristian Bruel return 0; 310*63a562b3SChristian Bruel 311*63a562b3SChristian Bruel err_disable_clk: 312*63a562b3SChristian Bruel clk_disable_unprepare(stm32_pcie->clk); 313*63a562b3SChristian Bruel 314*63a562b3SChristian Bruel err_remove_port: 315*63a562b3SChristian Bruel stm32_remove_pcie_port(stm32_pcie); 316*63a562b3SChristian Bruel 317*63a562b3SChristian Bruel return ret; 318*63a562b3SChristian Bruel } 319*63a562b3SChristian Bruel 320*63a562b3SChristian Bruel static void stm32_pcie_remove(struct platform_device *pdev) 321*63a562b3SChristian Bruel { 322*63a562b3SChristian Bruel struct stm32_pcie *stm32_pcie = platform_get_drvdata(pdev); 323*63a562b3SChristian Bruel struct dw_pcie_rp *pp = &stm32_pcie->pci.pp; 324*63a562b3SChristian Bruel 325*63a562b3SChristian Bruel if (stm32_pcie->wake_gpio) 326*63a562b3SChristian Bruel device_init_wakeup(&pdev->dev, false); 327*63a562b3SChristian Bruel 328*63a562b3SChristian Bruel dw_pcie_host_deinit(pp); 329*63a562b3SChristian Bruel 330*63a562b3SChristian Bruel clk_disable_unprepare(stm32_pcie->clk); 331*63a562b3SChristian Bruel 332*63a562b3SChristian Bruel stm32_remove_pcie_port(stm32_pcie); 333*63a562b3SChristian Bruel 334*63a562b3SChristian Bruel pm_runtime_put_noidle(&pdev->dev); 335*63a562b3SChristian Bruel } 336*63a562b3SChristian Bruel 337*63a562b3SChristian Bruel static const struct of_device_id stm32_pcie_of_match[] = { 338*63a562b3SChristian Bruel { .compatible = "st,stm32mp25-pcie-rc" }, 339*63a562b3SChristian Bruel {}, 340*63a562b3SChristian Bruel }; 341*63a562b3SChristian Bruel 342*63a562b3SChristian Bruel static struct platform_driver stm32_pcie_driver = { 343*63a562b3SChristian Bruel .probe = stm32_pcie_probe, 344*63a562b3SChristian Bruel .remove = stm32_pcie_remove, 345*63a562b3SChristian Bruel .driver = { 346*63a562b3SChristian Bruel .name = "stm32-pcie", 347*63a562b3SChristian Bruel .of_match_table = stm32_pcie_of_match, 348*63a562b3SChristian Bruel .pm = &stm32_pcie_pm_ops, 349*63a562b3SChristian Bruel .probe_type = PROBE_PREFER_ASYNCHRONOUS, 350*63a562b3SChristian Bruel }, 351*63a562b3SChristian Bruel }; 352*63a562b3SChristian Bruel 353*63a562b3SChristian Bruel module_platform_driver(stm32_pcie_driver); 354*63a562b3SChristian Bruel 355*63a562b3SChristian Bruel MODULE_AUTHOR("Christian Bruel <christian.bruel@foss.st.com>"); 356*63a562b3SChristian Bruel MODULE_DESCRIPTION("STM32MP25 PCIe Controller driver"); 357*63a562b3SChristian Bruel MODULE_LICENSE("GPL"); 358*63a562b3SChristian Bruel MODULE_DEVICE_TABLE(of, stm32_pcie_of_match); 359