1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * PCIe host controller driver for NXP S32G SoCs
4 *
5 * Copyright 2019-2025 NXP
6 */
7
8 #include <linux/interrupt.h>
9 #include <linux/io.h>
10 #include <linux/module.h>
11 #include <linux/of_device.h>
12 #include <linux/of_address.h>
13 #include <linux/pci.h>
14 #include <linux/phy/phy.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/sizes.h>
18 #include <linux/types.h>
19
20 #include "pcie-designware.h"
21
22 /* PCIe controller Sub-System */
23
24 /* PCIe controller 0 General Control 1 */
25 #define PCIE_S32G_PE0_GEN_CTRL_1 0x50
26 #define DEVICE_TYPE_MASK GENMASK(3, 0)
27 #define SRIS_MODE BIT(8)
28
29 /* PCIe controller 0 General Control 3 */
30 #define PCIE_S32G_PE0_GEN_CTRL_3 0x58
31 #define LTSSM_EN BIT(0)
32
33 /* PCIe Controller 0 Interrupt Status */
34 #define PCIE_S32G_PE0_INT_STS 0xE8
35 #define HP_INT_STS BIT(6)
36
37 /* Boundary between peripheral space and physical memory space */
38 #define S32G_MEMORY_BOUNDARY_ADDR 0x80000000
39
40 struct s32g_pcie_port {
41 struct list_head list;
42 struct phy *phy;
43 };
44
45 struct s32g_pcie {
46 struct dw_pcie pci;
47 void __iomem *ctrl_base;
48 struct list_head ports;
49 };
50
51 #define to_s32g_from_dw_pcie(x) \
52 container_of(x, struct s32g_pcie, pci)
53
s32g_pcie_writel_ctrl(struct s32g_pcie * s32g_pp,u32 reg,u32 val)54 static void s32g_pcie_writel_ctrl(struct s32g_pcie *s32g_pp, u32 reg, u32 val)
55 {
56 writel(val, s32g_pp->ctrl_base + reg);
57 }
58
s32g_pcie_readl_ctrl(struct s32g_pcie * s32g_pp,u32 reg)59 static u32 s32g_pcie_readl_ctrl(struct s32g_pcie *s32g_pp, u32 reg)
60 {
61 return readl(s32g_pp->ctrl_base + reg);
62 }
63
s32g_pcie_enable_ltssm(struct s32g_pcie * s32g_pp)64 static void s32g_pcie_enable_ltssm(struct s32g_pcie *s32g_pp)
65 {
66 u32 reg;
67
68 reg = s32g_pcie_readl_ctrl(s32g_pp, PCIE_S32G_PE0_GEN_CTRL_3);
69 reg |= LTSSM_EN;
70 s32g_pcie_writel_ctrl(s32g_pp, PCIE_S32G_PE0_GEN_CTRL_3, reg);
71 }
72
s32g_pcie_disable_ltssm(struct s32g_pcie * s32g_pp)73 static void s32g_pcie_disable_ltssm(struct s32g_pcie *s32g_pp)
74 {
75 u32 reg;
76
77 reg = s32g_pcie_readl_ctrl(s32g_pp, PCIE_S32G_PE0_GEN_CTRL_3);
78 reg &= ~LTSSM_EN;
79 s32g_pcie_writel_ctrl(s32g_pp, PCIE_S32G_PE0_GEN_CTRL_3, reg);
80 }
81
s32g_pcie_start_link(struct dw_pcie * pci)82 static int s32g_pcie_start_link(struct dw_pcie *pci)
83 {
84 struct s32g_pcie *s32g_pp = to_s32g_from_dw_pcie(pci);
85
86 s32g_pcie_enable_ltssm(s32g_pp);
87
88 return 0;
89 }
90
s32g_pcie_stop_link(struct dw_pcie * pci)91 static void s32g_pcie_stop_link(struct dw_pcie *pci)
92 {
93 struct s32g_pcie *s32g_pp = to_s32g_from_dw_pcie(pci);
94
95 s32g_pcie_disable_ltssm(s32g_pp);
96 }
97
98 static struct dw_pcie_ops s32g_pcie_ops = {
99 .start_link = s32g_pcie_start_link,
100 .stop_link = s32g_pcie_stop_link,
101 };
102
103 /* Configure the AMBA AXI Coherency Extensions (ACE) interface */
s32g_pcie_reset_mstr_ace(struct dw_pcie * pci)104 static void s32g_pcie_reset_mstr_ace(struct dw_pcie *pci)
105 {
106 u32 ddr_base_low = lower_32_bits(S32G_MEMORY_BOUNDARY_ADDR);
107 u32 ddr_base_high = upper_32_bits(S32G_MEMORY_BOUNDARY_ADDR);
108
109 dw_pcie_dbi_ro_wr_en(pci);
110 dw_pcie_writel_dbi(pci, COHERENCY_CONTROL_3_OFF, 0x0);
111
112 /*
113 * Ncore is a cache-coherent interconnect module that enables the
114 * integration of heterogeneous coherent and non-coherent agents in
115 * the chip. Ncore transactions to peripheral should be non-coherent
116 * or it might drop them.
117 *
118 * One example where this is needed are PCIe MSIs, which use NoSnoop=0
119 * and might end up routed to Ncore. PCIe coherent traffic (e.g. MSIs)
120 * that targets peripheral space will be dropped by Ncore because
121 * peripherals on S32G are not coherent as slaves. We add a hard
122 * boundary in the PCIe controller coherency control registers to
123 * separate physical memory space from peripheral space.
124 *
125 * Define the start of DDR as seen by Linux as this boundary between
126 * "memory" and "peripherals", with peripherals being below.
127 */
128 dw_pcie_writel_dbi(pci, COHERENCY_CONTROL_1_OFF,
129 (ddr_base_low & CFG_MEMTYPE_BOUNDARY_LOW_ADDR_MASK));
130 dw_pcie_writel_dbi(pci, COHERENCY_CONTROL_2_OFF, ddr_base_high);
131 dw_pcie_dbi_ro_wr_dis(pci);
132 }
133
s32g_init_pcie_controller(struct dw_pcie_rp * pp)134 static int s32g_init_pcie_controller(struct dw_pcie_rp *pp)
135 {
136 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
137 struct s32g_pcie *s32g_pp = to_s32g_from_dw_pcie(pci);
138 u32 val;
139
140 /* Set RP mode */
141 val = s32g_pcie_readl_ctrl(s32g_pp, PCIE_S32G_PE0_GEN_CTRL_1);
142 val &= ~DEVICE_TYPE_MASK;
143 val |= FIELD_PREP(DEVICE_TYPE_MASK, PCI_EXP_TYPE_ROOT_PORT);
144
145 /* Use default CRNS */
146 val &= ~SRIS_MODE;
147
148 s32g_pcie_writel_ctrl(s32g_pp, PCIE_S32G_PE0_GEN_CTRL_1, val);
149
150 /*
151 * Make sure we use the coherency defaults (just in case the settings
152 * have been changed from their reset values)
153 */
154 s32g_pcie_reset_mstr_ace(pci);
155
156 dw_pcie_dbi_ro_wr_en(pci);
157
158 val = dw_pcie_readl_dbi(pci, PCIE_PORT_FORCE);
159 val |= PORT_FORCE_DO_DESKEW_FOR_SRIS;
160 dw_pcie_writel_dbi(pci, PCIE_PORT_FORCE, val);
161
162 val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
163 val |= GEN3_RELATED_OFF_EQ_PHASE_2_3;
164 dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
165
166 dw_pcie_dbi_ro_wr_dis(pci);
167
168 return 0;
169 }
170
171 static const struct dw_pcie_host_ops s32g_pcie_host_ops = {
172 .init = s32g_init_pcie_controller,
173 };
174
s32g_init_pcie_phy(struct s32g_pcie * s32g_pp)175 static int s32g_init_pcie_phy(struct s32g_pcie *s32g_pp)
176 {
177 struct dw_pcie *pci = &s32g_pp->pci;
178 struct device *dev = pci->dev;
179 struct s32g_pcie_port *port, *tmp;
180 int ret;
181
182 list_for_each_entry(port, &s32g_pp->ports, list) {
183 ret = phy_init(port->phy);
184 if (ret) {
185 dev_err(dev, "Failed to init serdes PHY\n");
186 goto err_phy_revert;
187 }
188
189 ret = phy_set_mode_ext(port->phy, PHY_MODE_PCIE, 0);
190 if (ret) {
191 dev_err(dev, "Failed to set mode on serdes PHY\n");
192 goto err_phy_exit;
193 }
194
195 ret = phy_power_on(port->phy);
196 if (ret) {
197 dev_err(dev, "Failed to power on serdes PHY\n");
198 goto err_phy_exit;
199 }
200 }
201
202 return 0;
203
204 err_phy_exit:
205 phy_exit(port->phy);
206
207 err_phy_revert:
208 list_for_each_entry_continue_reverse(port, &s32g_pp->ports, list) {
209 phy_power_off(port->phy);
210 phy_exit(port->phy);
211 }
212
213 list_for_each_entry_safe(port, tmp, &s32g_pp->ports, list)
214 list_del(&port->list);
215
216 return ret;
217 }
218
s32g_deinit_pcie_phy(struct s32g_pcie * s32g_pp)219 static void s32g_deinit_pcie_phy(struct s32g_pcie *s32g_pp)
220 {
221 struct s32g_pcie_port *port, *tmp;
222
223 list_for_each_entry_safe(port, tmp, &s32g_pp->ports, list) {
224 phy_power_off(port->phy);
225 phy_exit(port->phy);
226 list_del(&port->list);
227 }
228 }
229
s32g_pcie_init(struct device * dev,struct s32g_pcie * s32g_pp)230 static int s32g_pcie_init(struct device *dev, struct s32g_pcie *s32g_pp)
231 {
232 s32g_pcie_disable_ltssm(s32g_pp);
233
234 return s32g_init_pcie_phy(s32g_pp);
235 }
236
s32g_pcie_deinit(struct s32g_pcie * s32g_pp)237 static void s32g_pcie_deinit(struct s32g_pcie *s32g_pp)
238 {
239 s32g_pcie_disable_ltssm(s32g_pp);
240
241 s32g_deinit_pcie_phy(s32g_pp);
242 }
243
s32g_pcie_parse_port(struct s32g_pcie * s32g_pp,struct device_node * node)244 static int s32g_pcie_parse_port(struct s32g_pcie *s32g_pp, struct device_node *node)
245 {
246 struct device *dev = s32g_pp->pci.dev;
247 struct s32g_pcie_port *port;
248 int num_lanes;
249
250 port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
251 if (!port)
252 return -ENOMEM;
253
254 port->phy = devm_of_phy_get(dev, node, NULL);
255 if (IS_ERR(port->phy))
256 return dev_err_probe(dev, PTR_ERR(port->phy),
257 "Failed to get serdes PHY\n");
258
259 INIT_LIST_HEAD(&port->list);
260 list_add_tail(&port->list, &s32g_pp->ports);
261
262 /*
263 * The DWC core initialization code cannot yet parse the num-lanes
264 * attribute in the Root Port node. The S32G only supports one Root
265 * Port for now so its driver can parse the node and set the num_lanes
266 * field of struct dwc_pcie before calling dw_pcie_host_init().
267 */
268 if (!of_property_read_u32(node, "num-lanes", &num_lanes))
269 s32g_pp->pci.num_lanes = num_lanes;
270
271 return 0;
272 }
273
s32g_pcie_parse_ports(struct device * dev,struct s32g_pcie * s32g_pp)274 static int s32g_pcie_parse_ports(struct device *dev, struct s32g_pcie *s32g_pp)
275 {
276 struct s32g_pcie_port *port, *tmp;
277 int ret = -ENOENT;
278
279 for_each_available_child_of_node_scoped(dev->of_node, of_port) {
280 if (!of_node_is_type(of_port, "pci"))
281 continue;
282
283 ret = s32g_pcie_parse_port(s32g_pp, of_port);
284 if (ret)
285 break;
286 }
287
288 if (ret)
289 list_for_each_entry_safe(port, tmp, &s32g_pp->ports, list)
290 list_del(&port->list);
291
292 return ret;
293 }
294
s32g_pcie_get_resources(struct platform_device * pdev,struct s32g_pcie * s32g_pp)295 static int s32g_pcie_get_resources(struct platform_device *pdev,
296 struct s32g_pcie *s32g_pp)
297 {
298 struct dw_pcie *pci = &s32g_pp->pci;
299 struct device *dev = &pdev->dev;
300 int ret;
301
302 pci->dev = dev;
303 pci->ops = &s32g_pcie_ops;
304
305 s32g_pp->ctrl_base = devm_platform_ioremap_resource_byname(pdev, "ctrl");
306 if (IS_ERR(s32g_pp->ctrl_base))
307 return PTR_ERR(s32g_pp->ctrl_base);
308
309 INIT_LIST_HEAD(&s32g_pp->ports);
310
311 ret = s32g_pcie_parse_ports(dev, s32g_pp);
312 if (ret)
313 return dev_err_probe(dev, ret,
314 "Failed to parse Root Port: %d\n", ret);
315
316 platform_set_drvdata(pdev, s32g_pp);
317
318 return 0;
319 }
320
s32g_pcie_probe(struct platform_device * pdev)321 static int s32g_pcie_probe(struct platform_device *pdev)
322 {
323 struct device *dev = &pdev->dev;
324 struct s32g_pcie *s32g_pp;
325 struct dw_pcie_rp *pp;
326 int ret;
327
328 s32g_pp = devm_kzalloc(dev, sizeof(*s32g_pp), GFP_KERNEL);
329 if (!s32g_pp)
330 return -ENOMEM;
331
332 ret = s32g_pcie_get_resources(pdev, s32g_pp);
333 if (ret)
334 return ret;
335
336 pm_runtime_no_callbacks(dev);
337 devm_pm_runtime_enable(dev);
338 ret = pm_runtime_get_sync(dev);
339 if (ret < 0)
340 goto err_pm_runtime_put;
341
342 ret = s32g_pcie_init(dev, s32g_pp);
343 if (ret)
344 goto err_pm_runtime_put;
345
346 pp = &s32g_pp->pci.pp;
347 pp->ops = &s32g_pcie_host_ops;
348 pp->use_atu_msg = true;
349
350 ret = dw_pcie_host_init(pp);
351 if (ret)
352 goto err_pcie_deinit;
353
354 return 0;
355
356 err_pcie_deinit:
357 s32g_pcie_deinit(s32g_pp);
358 err_pm_runtime_put:
359 pm_runtime_put(dev);
360
361 return ret;
362 }
363
s32g_pcie_suspend_noirq(struct device * dev)364 static int s32g_pcie_suspend_noirq(struct device *dev)
365 {
366 struct s32g_pcie *s32g_pp = dev_get_drvdata(dev);
367 struct dw_pcie *pci = &s32g_pp->pci;
368
369 return dw_pcie_suspend_noirq(pci);
370 }
371
s32g_pcie_resume_noirq(struct device * dev)372 static int s32g_pcie_resume_noirq(struct device *dev)
373 {
374 struct s32g_pcie *s32g_pp = dev_get_drvdata(dev);
375 struct dw_pcie *pci = &s32g_pp->pci;
376
377 return dw_pcie_resume_noirq(pci);
378 }
379
380 static const struct dev_pm_ops s32g_pcie_pm_ops = {
381 NOIRQ_SYSTEM_SLEEP_PM_OPS(s32g_pcie_suspend_noirq,
382 s32g_pcie_resume_noirq)
383 };
384
385 static const struct of_device_id s32g_pcie_of_match[] = {
386 { .compatible = "nxp,s32g2-pcie" },
387 { /* sentinel */ },
388 };
389 MODULE_DEVICE_TABLE(of, s32g_pcie_of_match);
390
391 static struct platform_driver s32g_pcie_driver = {
392 .driver = {
393 .name = "s32g-pcie",
394 .of_match_table = s32g_pcie_of_match,
395 .suppress_bind_attrs = true,
396 .pm = pm_sleep_ptr(&s32g_pcie_pm_ops),
397 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
398 },
399 .probe = s32g_pcie_probe,
400 };
401
402 builtin_platform_driver(s32g_pcie_driver);
403
404 MODULE_AUTHOR("Ionut Vicovan <Ionut.Vicovan@nxp.com>");
405 MODULE_DESCRIPTION("NXP S32G PCIe Host controller driver");
406 MODULE_LICENSE("GPL");
407