1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * STMicroelectronics STM32MP25 PCIe endpoint driver. 4 * 5 * Copyright (C) 2025 STMicroelectronics 6 * Author: Christian Bruel <christian.bruel@foss.st.com> 7 */ 8 9 #include <linux/clk.h> 10 #include <linux/gpio/consumer.h> 11 #include <linux/mfd/syscon.h> 12 #include <linux/of_platform.h> 13 #include <linux/phy/phy.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/regmap.h> 17 #include <linux/reset.h> 18 #include "pcie-designware.h" 19 #include "pcie-stm32.h" 20 21 struct stm32_pcie { 22 struct dw_pcie pci; 23 struct regmap *regmap; 24 struct reset_control *rst; 25 struct phy *phy; 26 struct clk *clk; 27 struct gpio_desc *perst_gpio; 28 unsigned int perst_irq; 29 }; 30 31 static void stm32_pcie_ep_init(struct dw_pcie_ep *ep) 32 { 33 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 34 enum pci_barno bar; 35 36 for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) 37 dw_pcie_ep_reset_bar(pci, bar); 38 } 39 40 static int stm32_pcie_start_link(struct dw_pcie *pci) 41 { 42 struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 43 44 enable_irq(stm32_pcie->perst_irq); 45 46 return 0; 47 } 48 49 static void stm32_pcie_stop_link(struct dw_pcie *pci) 50 { 51 struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 52 53 disable_irq(stm32_pcie->perst_irq); 54 } 55 56 static int stm32_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 57 unsigned int type, u16 interrupt_num) 58 { 59 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 60 61 switch (type) { 62 case PCI_IRQ_INTX: 63 return dw_pcie_ep_raise_intx_irq(ep, func_no); 64 case PCI_IRQ_MSI: 65 return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); 66 default: 67 dev_err(pci->dev, "UNKNOWN IRQ type\n"); 68 return -EINVAL; 69 } 70 } 71 72 static const struct pci_epc_features stm32_pcie_epc_features = { 73 .msi_capable = true, 74 .align = SZ_64K, 75 }; 76 77 static const struct pci_epc_features* 78 stm32_pcie_get_features(struct dw_pcie_ep *ep) 79 { 80 return &stm32_pcie_epc_features; 81 } 82 83 static const struct dw_pcie_ep_ops stm32_pcie_ep_ops = { 84 .init = stm32_pcie_ep_init, 85 .raise_irq = stm32_pcie_raise_irq, 86 .get_features = stm32_pcie_get_features, 87 }; 88 89 static const struct dw_pcie_ops dw_pcie_ops = { 90 .start_link = stm32_pcie_start_link, 91 .stop_link = stm32_pcie_stop_link, 92 }; 93 94 static int stm32_pcie_enable_resources(struct stm32_pcie *stm32_pcie) 95 { 96 int ret; 97 98 ret = phy_init(stm32_pcie->phy); 99 if (ret) 100 return ret; 101 102 ret = clk_prepare_enable(stm32_pcie->clk); 103 if (ret) 104 phy_exit(stm32_pcie->phy); 105 106 return ret; 107 } 108 109 static void stm32_pcie_disable_resources(struct stm32_pcie *stm32_pcie) 110 { 111 clk_disable_unprepare(stm32_pcie->clk); 112 113 phy_exit(stm32_pcie->phy); 114 } 115 116 static void stm32_pcie_perst_assert(struct dw_pcie *pci) 117 { 118 struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 119 struct dw_pcie_ep *ep = &stm32_pcie->pci.ep; 120 struct device *dev = pci->dev; 121 122 dev_dbg(dev, "PERST asserted by host\n"); 123 124 regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 125 STM32MP25_PCIECR_LTSSM_EN, 0); 126 127 pci_epc_deinit_notify(ep->epc); 128 129 stm32_pcie_disable_resources(stm32_pcie); 130 131 pm_runtime_put_sync(dev); 132 } 133 134 static void stm32_pcie_perst_deassert(struct dw_pcie *pci) 135 { 136 struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 137 struct device *dev = pci->dev; 138 struct dw_pcie_ep *ep = &pci->ep; 139 int ret; 140 141 dev_dbg(dev, "PERST de-asserted by host\n"); 142 143 ret = pm_runtime_resume_and_get(dev); 144 if (ret < 0) { 145 dev_err(dev, "Failed to resume runtime PM: %d\n", ret); 146 return; 147 } 148 149 ret = stm32_pcie_enable_resources(stm32_pcie); 150 if (ret) { 151 dev_err(dev, "Failed to enable resources: %d\n", ret); 152 goto err_pm_put_sync; 153 } 154 155 /* 156 * Reprogram the configuration space registers here because the DBI 157 * registers were reset by the PHY RCC during phy_init(). 158 */ 159 ret = dw_pcie_ep_init_registers(ep); 160 if (ret) { 161 dev_err(dev, "Failed to complete initialization: %d\n", ret); 162 goto err_disable_resources; 163 } 164 165 pci_epc_init_notify(ep->epc); 166 167 /* Enable link training */ 168 regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 169 STM32MP25_PCIECR_LTSSM_EN, 170 STM32MP25_PCIECR_LTSSM_EN); 171 172 return; 173 174 err_disable_resources: 175 stm32_pcie_disable_resources(stm32_pcie); 176 177 err_pm_put_sync: 178 pm_runtime_put_sync(dev); 179 } 180 181 static irqreturn_t stm32_pcie_ep_perst_irq_thread(int irq, void *data) 182 { 183 struct stm32_pcie *stm32_pcie = data; 184 struct dw_pcie *pci = &stm32_pcie->pci; 185 u32 perst; 186 187 perst = gpiod_get_value(stm32_pcie->perst_gpio); 188 if (perst) 189 stm32_pcie_perst_assert(pci); 190 else 191 stm32_pcie_perst_deassert(pci); 192 193 irq_set_irq_type(gpiod_to_irq(stm32_pcie->perst_gpio), 194 (perst ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW)); 195 196 return IRQ_HANDLED; 197 } 198 199 static int stm32_add_pcie_ep(struct stm32_pcie *stm32_pcie, 200 struct platform_device *pdev) 201 { 202 struct dw_pcie_ep *ep = &stm32_pcie->pci.ep; 203 struct device *dev = &pdev->dev; 204 int ret; 205 206 ret = regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 207 STM32MP25_PCIECR_TYPE_MASK, 208 STM32MP25_PCIECR_EP); 209 if (ret) 210 return ret; 211 212 reset_control_assert(stm32_pcie->rst); 213 reset_control_deassert(stm32_pcie->rst); 214 215 ep->ops = &stm32_pcie_ep_ops; 216 217 ep->page_size = stm32_pcie_epc_features.align; 218 219 ret = dw_pcie_ep_init(ep); 220 if (ret) { 221 dev_err(dev, "Failed to initialize ep: %d\n", ret); 222 return ret; 223 } 224 225 ret = stm32_pcie_enable_resources(stm32_pcie); 226 if (ret) { 227 dev_err(dev, "Failed to enable resources: %d\n", ret); 228 dw_pcie_ep_deinit(ep); 229 return ret; 230 } 231 232 return 0; 233 } 234 235 static int stm32_pcie_probe(struct platform_device *pdev) 236 { 237 struct stm32_pcie *stm32_pcie; 238 struct device *dev = &pdev->dev; 239 int ret; 240 241 stm32_pcie = devm_kzalloc(dev, sizeof(*stm32_pcie), GFP_KERNEL); 242 if (!stm32_pcie) 243 return -ENOMEM; 244 245 stm32_pcie->pci.dev = dev; 246 stm32_pcie->pci.ops = &dw_pcie_ops; 247 248 stm32_pcie->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg"); 249 if (IS_ERR(stm32_pcie->regmap)) 250 return dev_err_probe(dev, PTR_ERR(stm32_pcie->regmap), 251 "No syscfg specified\n"); 252 253 stm32_pcie->phy = devm_phy_get(dev, NULL); 254 if (IS_ERR(stm32_pcie->phy)) 255 return dev_err_probe(dev, PTR_ERR(stm32_pcie->phy), 256 "failed to get pcie-phy\n"); 257 258 stm32_pcie->clk = devm_clk_get(dev, NULL); 259 if (IS_ERR(stm32_pcie->clk)) 260 return dev_err_probe(dev, PTR_ERR(stm32_pcie->clk), 261 "Failed to get PCIe clock source\n"); 262 263 stm32_pcie->rst = devm_reset_control_get_exclusive(dev, NULL); 264 if (IS_ERR(stm32_pcie->rst)) 265 return dev_err_probe(dev, PTR_ERR(stm32_pcie->rst), 266 "Failed to get PCIe reset\n"); 267 268 stm32_pcie->perst_gpio = devm_gpiod_get(dev, "reset", GPIOD_IN); 269 if (IS_ERR(stm32_pcie->perst_gpio)) 270 return dev_err_probe(dev, PTR_ERR(stm32_pcie->perst_gpio), 271 "Failed to get reset GPIO\n"); 272 273 ret = phy_set_mode(stm32_pcie->phy, PHY_MODE_PCIE); 274 if (ret) 275 return ret; 276 277 platform_set_drvdata(pdev, stm32_pcie); 278 279 pm_runtime_get_noresume(dev); 280 281 ret = devm_pm_runtime_enable(dev); 282 if (ret < 0) { 283 pm_runtime_put_noidle(&pdev->dev); 284 return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); 285 } 286 287 stm32_pcie->perst_irq = gpiod_to_irq(stm32_pcie->perst_gpio); 288 289 /* Will be enabled in start_link when device is initialized. */ 290 irq_set_status_flags(stm32_pcie->perst_irq, IRQ_NOAUTOEN); 291 292 ret = devm_request_threaded_irq(dev, stm32_pcie->perst_irq, NULL, 293 stm32_pcie_ep_perst_irq_thread, 294 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 295 "perst_irq", stm32_pcie); 296 if (ret) { 297 pm_runtime_put_noidle(&pdev->dev); 298 return dev_err_probe(dev, ret, "Failed to request PERST IRQ\n"); 299 } 300 301 ret = stm32_add_pcie_ep(stm32_pcie, pdev); 302 if (ret) 303 pm_runtime_put_noidle(&pdev->dev); 304 305 return ret; 306 } 307 308 static void stm32_pcie_remove(struct platform_device *pdev) 309 { 310 struct stm32_pcie *stm32_pcie = platform_get_drvdata(pdev); 311 struct dw_pcie *pci = &stm32_pcie->pci; 312 struct dw_pcie_ep *ep = &pci->ep; 313 314 dw_pcie_stop_link(pci); 315 316 pci_epc_deinit_notify(ep->epc); 317 dw_pcie_ep_deinit(ep); 318 319 stm32_pcie_disable_resources(stm32_pcie); 320 321 pm_runtime_put_sync(&pdev->dev); 322 } 323 324 static const struct of_device_id stm32_pcie_ep_of_match[] = { 325 { .compatible = "st,stm32mp25-pcie-ep" }, 326 {}, 327 }; 328 329 static struct platform_driver stm32_pcie_ep_driver = { 330 .probe = stm32_pcie_probe, 331 .remove = stm32_pcie_remove, 332 .driver = { 333 .name = "stm32-ep-pcie", 334 .of_match_table = stm32_pcie_ep_of_match, 335 }, 336 }; 337 338 module_platform_driver(stm32_pcie_ep_driver); 339 340 MODULE_AUTHOR("Christian Bruel <christian.bruel@foss.st.com>"); 341 MODULE_DESCRIPTION("STM32MP25 PCIe Endpoint Controller driver"); 342 MODULE_LICENSE("GPL"); 343 MODULE_DEVICE_TABLE(of, stm32_pcie_ep_of_match); 344