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