xref: /linux/drivers/pci/controller/dwc/pcie-stm32-ep.c (revision d30c1683aaecb93d2ab95685dc4300a33d3cea7a)
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