pcie-iproc-platform.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2015 Broadcom Corporation
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/pci.h>
  7. #include <linux/clk.h>
  8. #include <linux/module.h>
  9. #include <linux/slab.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/of_address.h>
  13. #include <linux/of_pci.h>
  14. #include <linux/of_platform.h>
  15. #include <linux/phy/phy.h>
  16. #include "../pci.h"
  17. #include "pcie-iproc.h"
  18. static const struct of_device_id iproc_pcie_of_match_table[] = {
  19. {
  20. .compatible = "brcm,iproc-pcie",
  21. .data = (int *)IPROC_PCIE_PAXB,
  22. }, {
  23. .compatible = "brcm,iproc-pcie-paxb-v2",
  24. .data = (int *)IPROC_PCIE_PAXB_V2,
  25. }, {
  26. .compatible = "brcm,iproc-pcie-paxc",
  27. .data = (int *)IPROC_PCIE_PAXC,
  28. }, {
  29. .compatible = "brcm,iproc-pcie-paxc-v2",
  30. .data = (int *)IPROC_PCIE_PAXC_V2,
  31. },
  32. { /* sentinel */ }
  33. };
  34. MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
  35. static int iproc_pltfm_pcie_probe(struct platform_device *pdev)
  36. {
  37. struct device *dev = &pdev->dev;
  38. struct iproc_pcie *pcie;
  39. struct device_node *np = dev->of_node;
  40. struct resource reg;
  41. struct pci_host_bridge *bridge;
  42. int ret;
  43. bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
  44. if (!bridge)
  45. return -ENOMEM;
  46. pcie = pci_host_bridge_priv(bridge);
  47. pcie->dev = dev;
  48. pcie->type = (uintptr_t)of_device_get_match_data(dev);
  49. ret = of_address_to_resource(np, 0, &reg);
  50. if (ret < 0) {
  51. dev_err(dev, "unable to obtain controller resources\n");
  52. return ret;
  53. }
  54. pcie->base = devm_pci_remap_cfgspace(dev, reg.start,
  55. resource_size(&reg));
  56. if (!pcie->base) {
  57. dev_err(dev, "unable to map controller registers\n");
  58. return -ENOMEM;
  59. }
  60. pcie->base_addr = reg.start;
  61. if (of_property_read_bool(np, "brcm,pcie-ob")) {
  62. u32 val;
  63. ret = of_property_read_u32(np, "brcm,pcie-ob-axi-offset",
  64. &val);
  65. if (ret) {
  66. dev_err(dev,
  67. "missing brcm,pcie-ob-axi-offset property\n");
  68. return ret;
  69. }
  70. pcie->ob.axi_offset = val;
  71. pcie->need_ob_cfg = true;
  72. }
  73. /*
  74. * DT nodes are not used by all platforms that use the iProc PCIe
  75. * core driver. For platforms that require explicit inbound mapping
  76. * configuration, "dma-ranges" would have been present in DT
  77. */
  78. pcie->need_ib_cfg = of_property_read_bool(np, "dma-ranges");
  79. /* PHY use is optional */
  80. pcie->phy = devm_phy_optional_get(dev, "pcie-phy");
  81. if (IS_ERR(pcie->phy))
  82. return PTR_ERR(pcie->phy);
  83. /* PAXC doesn't support legacy IRQs, skip mapping */
  84. switch (pcie->type) {
  85. case IPROC_PCIE_PAXC:
  86. case IPROC_PCIE_PAXC_V2:
  87. pcie->map_irq = NULL;
  88. break;
  89. default:
  90. break;
  91. }
  92. ret = iproc_pcie_setup(pcie, &bridge->windows);
  93. if (ret) {
  94. dev_err(dev, "PCIe controller setup failed\n");
  95. return ret;
  96. }
  97. platform_set_drvdata(pdev, pcie);
  98. return 0;
  99. }
  100. static void iproc_pltfm_pcie_remove(struct platform_device *pdev)
  101. {
  102. struct iproc_pcie *pcie = platform_get_drvdata(pdev);
  103. iproc_pcie_remove(pcie);
  104. }
  105. static void iproc_pltfm_pcie_shutdown(struct platform_device *pdev)
  106. {
  107. struct iproc_pcie *pcie = platform_get_drvdata(pdev);
  108. iproc_pcie_shutdown(pcie);
  109. }
  110. static struct platform_driver iproc_pltfm_pcie_driver = {
  111. .driver = {
  112. .name = "iproc-pcie",
  113. .of_match_table = of_match_ptr(iproc_pcie_of_match_table),
  114. },
  115. .probe = iproc_pltfm_pcie_probe,
  116. .remove_new = iproc_pltfm_pcie_remove,
  117. .shutdown = iproc_pltfm_pcie_shutdown,
  118. };
  119. module_platform_driver(iproc_pltfm_pcie_driver);
  120. MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
  121. MODULE_DESCRIPTION("Broadcom iPROC PCIe platform driver");
  122. MODULE_LICENSE("GPL v2");