1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Common library for PCI host controller drivers 4 * 5 * Copyright (C) 2014 ARM Limited 6 * 7 * Author: Will Deacon <will.deacon@arm.com> 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/gpio/consumer.h> 13 #include <linux/of.h> 14 #include <linux/of_address.h> 15 #include <linux/of_pci.h> 16 #include <linux/pci.h> 17 #include <linux/pci-ecam.h> 18 #include <linux/platform_device.h> 19 20 #include "../pci.h" 21 #include "pci-host-common.h" 22 23 /** 24 * pci_host_common_delete_ports - Cleanup function for port list 25 * @data: Pointer to the port list head 26 */ 27 void pci_host_common_delete_ports(void *data) 28 { 29 struct list_head *ports = data; 30 struct pci_host_perst *perst, *tmp_perst; 31 struct pci_host_port *port, *tmp_port; 32 33 list_for_each_entry_safe(port, tmp_port, ports, list) { 34 list_for_each_entry_safe(perst, tmp_perst, &port->perst, list) 35 list_del(&perst->list); 36 list_del(&port->list); 37 } 38 } 39 EXPORT_SYMBOL_GPL(pci_host_common_delete_ports); 40 41 /** 42 * pci_host_common_parse_perst - Parse PERST# from all nodes, depth first 43 * @dev: Device pointer 44 * @port: PCI host port 45 * @np: Device tree node to start parsing from 46 * 47 * Recursively parse PERST# GPIO from all PCIe bridge nodes starting from 48 * @np in a depth-first manner. 49 * 50 * Return: 0 on success, negative error code on failure. 51 */ 52 static int pci_host_common_parse_perst(struct device *dev, 53 struct pci_host_port *port, 54 struct device_node *np) 55 { 56 struct pci_host_perst *perst; 57 struct gpio_desc *reset; 58 int ret; 59 60 if (!of_property_present(np, "reset-gpios")) 61 goto parse_child_node; 62 63 reset = devm_fwnode_gpiod_get(dev, of_fwnode_handle(np), "reset", 64 GPIOD_ASIS, "PERST#"); 65 if (IS_ERR(reset)) { 66 /* 67 * FIXME: GPIOLIB currently supports exclusive GPIO access only. 68 * Non exclusive access is broken. But shared PERST# requires 69 * non-exclusive access. So once GPIOLIB properly supports it, 70 * implement it here. 71 */ 72 if (PTR_ERR(reset) == -EBUSY) 73 dev_err(dev, "Shared PERST# is not supported\n"); 74 75 return PTR_ERR(reset); 76 } 77 78 perst = devm_kzalloc(dev, sizeof(*perst), GFP_KERNEL); 79 if (!perst) 80 return -ENOMEM; 81 82 INIT_LIST_HEAD(&perst->list); 83 perst->desc = reset; 84 list_add_tail(&perst->list, &port->perst); 85 86 parse_child_node: 87 for_each_available_child_of_node_scoped(np, child) { 88 ret = pci_host_common_parse_perst(dev, port, child); 89 if (ret) 90 return ret; 91 } 92 93 return 0; 94 } 95 96 /** 97 * pci_host_common_parse_port - Parse a single Root Port node 98 * @dev: Device pointer 99 * @bridge: PCI host bridge 100 * @node: Device tree node of the Root Port 101 * 102 * Parse Root Port properties from the device tree. Currently it only 103 * handles the PERST# GPIO (including PERST# GPIOs from all PCIe bridge 104 * nodes under this Root Port), which is optional. 105 * 106 * NOTE: This helper fetches resources (like PERST# GPIO) optionally. If a 107 * controller driver has a hard dependency on certain resources (PHY, 108 * clocks, regulators, etc.), those resources MUST be modeled correctly in 109 * the DT binding and validated in DTS. This helper cannot enforce such 110 * dependencies and the driver may fail to operate if required resources 111 * are missing. 112 * 113 * Return: 0 on success, negative error codes on failure. 114 */ 115 static int pci_host_common_parse_port(struct device *dev, 116 struct pci_host_bridge *bridge, 117 struct device_node *node) 118 { 119 struct pci_host_port *port; 120 int ret; 121 122 port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); 123 if (!port) 124 return -ENOMEM; 125 126 INIT_LIST_HEAD(&port->perst); 127 128 ret = pci_host_common_parse_perst(dev, port, node); 129 if (ret) 130 return ret; 131 132 INIT_LIST_HEAD(&port->list); 133 list_add_tail(&port->list, &bridge->ports); 134 135 return 0; 136 } 137 138 /** 139 * pci_host_common_parse_ports - Parse Root Port nodes from device tree 140 * @dev: Device pointer 141 * @bridge: PCI host bridge 142 * 143 * Iterate through child nodes of the host bridge and parse Root Port 144 * properties (currently only reset GPIOs). 145 * 146 * Return: 0 on success or ports not found, negative error codes on failure. 147 */ 148 int pci_host_common_parse_ports(struct device *dev, struct pci_host_bridge *bridge) 149 { 150 int ret = 0; 151 152 for_each_available_child_of_node_scoped(dev->of_node, of_port) { 153 if (!of_node_is_type(of_port, "pci")) 154 continue; 155 ret = pci_host_common_parse_port(dev, bridge, of_port); 156 if (ret) 157 goto err_cleanup; 158 } 159 160 if (list_empty(&bridge->ports)) 161 return 0; 162 163 return devm_add_action_or_reset(dev, pci_host_common_delete_ports, 164 &bridge->ports); 165 166 err_cleanup: 167 pci_host_common_delete_ports(&bridge->ports); 168 return ret; 169 } 170 EXPORT_SYMBOL_GPL(pci_host_common_parse_ports); 171 172 #define PCI_HOST_D3COLD_ALLOWED BIT(0) 173 #define PCI_HOST_PME_D3COLD_CAPABLE BIT(1) 174 175 176 static void gen_pci_unmap_cfg(void *ptr) 177 { 178 pci_ecam_free((struct pci_config_window *)ptr); 179 } 180 181 struct pci_config_window *pci_host_common_ecam_create(struct device *dev, 182 struct pci_host_bridge *bridge, const struct pci_ecam_ops *ops) 183 { 184 int err; 185 struct resource cfgres; 186 struct resource_entry *bus; 187 struct pci_config_window *cfg; 188 189 err = of_address_to_resource(dev->of_node, 0, &cfgres); 190 if (err) { 191 dev_err(dev, "missing or malformed \"reg\" property\n"); 192 return ERR_PTR(err); 193 } 194 195 bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS); 196 if (!bus) 197 return ERR_PTR(-ENODEV); 198 199 cfg = pci_ecam_create(dev, &cfgres, bus->res, ops); 200 if (IS_ERR(cfg)) 201 return cfg; 202 203 err = devm_add_action_or_reset(dev, gen_pci_unmap_cfg, cfg); 204 if (err) 205 return ERR_PTR(err); 206 207 return cfg; 208 } 209 EXPORT_SYMBOL_GPL(pci_host_common_ecam_create); 210 211 int pci_host_common_init(struct platform_device *pdev, 212 struct pci_host_bridge *bridge, 213 const struct pci_ecam_ops *ops) 214 { 215 struct device *dev = &pdev->dev; 216 struct pci_config_window *cfg; 217 218 of_pci_check_probe_only(); 219 220 platform_set_drvdata(pdev, bridge); 221 222 /* Parse and map our Configuration Space windows */ 223 cfg = pci_host_common_ecam_create(dev, bridge, ops); 224 if (IS_ERR(cfg)) 225 return PTR_ERR(cfg); 226 227 /* Do not reassign bus numbers if probe only */ 228 if (!pci_has_flag(PCI_PROBE_ONLY)) 229 pci_add_flags(PCI_REASSIGN_ALL_BUS); 230 231 bridge->sysdata = cfg; 232 bridge->ops = (struct pci_ops *)&ops->pci_ops; 233 bridge->enable_device = ops->enable_device; 234 bridge->disable_device = ops->disable_device; 235 bridge->msi_domain = true; 236 237 return pci_host_probe(bridge); 238 } 239 EXPORT_SYMBOL_GPL(pci_host_common_init); 240 241 int pci_host_common_probe(struct platform_device *pdev) 242 { 243 const struct pci_ecam_ops *ops; 244 struct pci_host_bridge *bridge; 245 246 ops = of_device_get_match_data(&pdev->dev); 247 if (!ops) 248 return -ENODEV; 249 250 bridge = devm_pci_alloc_host_bridge(&pdev->dev, 0); 251 if (!bridge) 252 return -ENOMEM; 253 254 return pci_host_common_init(pdev, bridge, ops); 255 } 256 EXPORT_SYMBOL_GPL(pci_host_common_probe); 257 258 void pci_host_common_remove(struct platform_device *pdev) 259 { 260 struct pci_host_bridge *bridge = platform_get_drvdata(pdev); 261 262 pci_lock_rescan_remove(); 263 pci_stop_root_bus(bridge->bus); 264 pci_remove_root_bus(bridge->bus); 265 pci_unlock_rescan_remove(); 266 } 267 EXPORT_SYMBOL_GPL(pci_host_common_remove); 268 269 static int __pci_host_common_d3cold_possible(struct pci_dev *pdev, 270 void *userdata) 271 { 272 u32 *flags = userdata; 273 274 if (!pdev->dev.driver && !pci_is_enabled(pdev)) 275 return 0; 276 277 if (pdev->current_state != PCI_D3hot) 278 goto exit; 279 280 if (device_may_wakeup(&pdev->dev)) { 281 if (!pci_pme_capable(pdev, PCI_D3cold)) 282 goto exit; 283 else 284 *flags |= PCI_HOST_PME_D3COLD_CAPABLE; 285 } 286 287 return 0; 288 289 exit: 290 *flags &= ~PCI_HOST_D3COLD_ALLOWED; 291 292 return -EOPNOTSUPP; 293 } 294 295 /** 296 * pci_host_common_d3cold_possible - Determine whether the host bridge can 297 * transition the devices into D3cold. 298 * 299 * @bridge: PCI host bridge to check 300 * @pme_capable: Pointer to update if there is any device capable of generating 301 * PME from D3cold. 302 * 303 * Walk downstream PCIe endpoint devices and determine whether the host bridge 304 * is permitted to transition the devices into D3cold. 305 * 306 * Devices under host bridge can enter D3cold only if all active PCIe 307 * endpoints are in PCI_D3hot and any wakeup-enabled endpoint is capable of 308 * generating PME from D3cold. Inactive endpoints are ignored. 309 * 310 * The @pme_capable output allows PCIe controller drivers to apply 311 * platform-specific handling to preserve wakeup functionality. 312 * 313 * Return: %true if the host bridge may enter D3cold, otherwise %false. 314 */ 315 bool pci_host_common_d3cold_possible(struct pci_host_bridge *bridge, 316 bool *pme_capable) 317 { 318 u32 flags = PCI_HOST_D3COLD_ALLOWED; 319 320 pci_walk_bus(bridge->bus, __pci_host_common_d3cold_possible, &flags); 321 322 *pme_capable = !!(flags & PCI_HOST_PME_D3COLD_CAPABLE); 323 324 return !!(flags & PCI_HOST_D3COLD_ALLOWED); 325 } 326 EXPORT_SYMBOL_GPL(pci_host_common_d3cold_possible); 327 328 static pci_ers_result_t pci_host_reset_root_port(struct pci_dev *dev) 329 { 330 int ret; 331 332 pci_lock_rescan_remove(); 333 ret = pci_bus_error_reset(dev); 334 pci_unlock_rescan_remove(); 335 if (ret) { 336 pci_err(dev, "Failed to reset Root Port: %d\n", ret); 337 return PCI_ERS_RESULT_DISCONNECT; 338 } 339 340 pci_info(dev, "Root Port has been reset\n"); 341 342 return PCI_ERS_RESULT_RECOVERED; 343 } 344 345 static void pci_host_recover_root_port(struct pci_dev *port) 346 { 347 #if IS_ENABLED(CONFIG_PCIEAER) 348 pcie_do_recovery(port, pci_channel_io_frozen, pci_host_reset_root_port); 349 #else 350 pci_host_reset_root_port(port); 351 #endif 352 } 353 354 void pci_host_handle_link_down(struct pci_dev *port) 355 { 356 pci_info(port, "Recovering Root Port due to Link Down\n"); 357 pci_host_recover_root_port(port); 358 } 359 EXPORT_SYMBOL_GPL(pci_host_handle_link_down); 360 361 MODULE_DESCRIPTION("Common library for PCI host controller drivers"); 362 MODULE_LICENSE("GPL v2"); 363