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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 goto err_port; 286 } 287 288 err_port: 289 list_for_each_entry_safe(port, tmp, &s32g_pp->ports, list) 290 list_del(&port->list); 291 292 return ret; 293 } 294 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 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 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 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