ecam.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2016 Broadcom
  4. */
  5. #include <linux/device.h>
  6. #include <linux/io.h>
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <linux/pci.h>
  10. #include <linux/pci-ecam.h>
  11. #include <linux/slab.h>
  12. /*
  13. * On 64-bit systems, we do a single ioremap for the whole config space
  14. * since we have enough virtual address range available. On 32-bit, we
  15. * ioremap the config space for each bus individually.
  16. */
  17. static const bool per_bus_mapping = !IS_ENABLED(CONFIG_64BIT);
  18. /*
  19. * Create a PCI config space window
  20. * - reserve mem region
  21. * - alloc struct pci_config_window with space for all mappings
  22. * - ioremap the config space
  23. */
  24. struct pci_config_window *pci_ecam_create(struct device *dev,
  25. struct resource *cfgres, struct resource *busr,
  26. struct pci_ecam_ops *ops)
  27. {
  28. struct pci_config_window *cfg;
  29. unsigned int bus_range, bus_range_max, bsz;
  30. struct resource *conflict;
  31. int i, err;
  32. if (busr->start > busr->end)
  33. return ERR_PTR(-EINVAL);
  34. cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
  35. if (!cfg)
  36. return ERR_PTR(-ENOMEM);
  37. cfg->parent = dev;
  38. cfg->ops = ops;
  39. cfg->busr.start = busr->start;
  40. cfg->busr.end = busr->end;
  41. cfg->busr.flags = IORESOURCE_BUS;
  42. bus_range = resource_size(&cfg->busr);
  43. bus_range_max = resource_size(cfgres) >> ops->bus_shift;
  44. if (bus_range > bus_range_max) {
  45. bus_range = bus_range_max;
  46. cfg->busr.end = busr->start + bus_range - 1;
  47. dev_warn(dev, "ECAM area %pR can only accommodate %pR (reduced from %pR desired)\n",
  48. cfgres, &cfg->busr, busr);
  49. }
  50. bsz = 1 << ops->bus_shift;
  51. cfg->res.start = cfgres->start;
  52. cfg->res.end = cfgres->end;
  53. cfg->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
  54. cfg->res.name = "PCI ECAM";
  55. conflict = request_resource_conflict(&iomem_resource, &cfg->res);
  56. if (conflict) {
  57. err = -EBUSY;
  58. dev_err(dev, "can't claim ECAM area %pR: address conflict with %s %pR\n",
  59. &cfg->res, conflict->name, conflict);
  60. goto err_exit;
  61. }
  62. if (per_bus_mapping) {
  63. cfg->winp = kcalloc(bus_range, sizeof(*cfg->winp), GFP_KERNEL);
  64. if (!cfg->winp)
  65. goto err_exit_malloc;
  66. for (i = 0; i < bus_range; i++) {
  67. cfg->winp[i] =
  68. pci_remap_cfgspace(cfgres->start + i * bsz,
  69. bsz);
  70. if (!cfg->winp[i])
  71. goto err_exit_iomap;
  72. }
  73. } else {
  74. cfg->win = pci_remap_cfgspace(cfgres->start, bus_range * bsz);
  75. if (!cfg->win)
  76. goto err_exit_iomap;
  77. }
  78. if (ops->init) {
  79. err = ops->init(cfg);
  80. if (err)
  81. goto err_exit;
  82. }
  83. dev_info(dev, "ECAM at %pR for %pR\n", &cfg->res, &cfg->busr);
  84. return cfg;
  85. err_exit_iomap:
  86. dev_err(dev, "ECAM ioremap failed\n");
  87. err_exit_malloc:
  88. err = -ENOMEM;
  89. err_exit:
  90. pci_ecam_free(cfg);
  91. return ERR_PTR(err);
  92. }
  93. void pci_ecam_free(struct pci_config_window *cfg)
  94. {
  95. int i;
  96. if (per_bus_mapping) {
  97. if (cfg->winp) {
  98. for (i = 0; i < resource_size(&cfg->busr); i++)
  99. if (cfg->winp[i])
  100. iounmap(cfg->winp[i]);
  101. kfree(cfg->winp);
  102. }
  103. } else {
  104. if (cfg->win)
  105. iounmap(cfg->win);
  106. }
  107. if (cfg->res.parent)
  108. release_resource(&cfg->res);
  109. kfree(cfg);
  110. }
  111. /*
  112. * Function to implement the pci_ops ->map_bus method
  113. */
  114. void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
  115. int where)
  116. {
  117. struct pci_config_window *cfg = bus->sysdata;
  118. unsigned int devfn_shift = cfg->ops->bus_shift - 8;
  119. unsigned int busn = bus->number;
  120. void __iomem *base;
  121. if (busn < cfg->busr.start || busn > cfg->busr.end)
  122. return NULL;
  123. busn -= cfg->busr.start;
  124. if (per_bus_mapping)
  125. base = cfg->winp[busn];
  126. else
  127. base = cfg->win + (busn << cfg->ops->bus_shift);
  128. return base + (devfn << devfn_shift) + where;
  129. }
  130. /* ECAM ops */
  131. struct pci_ecam_ops pci_generic_ecam_ops = {
  132. .bus_shift = 20,
  133. .pci_ops = {
  134. .map_bus = pci_ecam_map_bus,
  135. .read = pci_generic_config_read,
  136. .write = pci_generic_config_write,
  137. }
  138. };
  139. #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
  140. /* ECAM ops for 32-bit access only (non-compliant) */
  141. struct pci_ecam_ops pci_32b_ops = {
  142. .bus_shift = 20,
  143. .pci_ops = {
  144. .map_bus = pci_ecam_map_bus,
  145. .read = pci_generic_config_read32,
  146. .write = pci_generic_config_write32,
  147. }
  148. };
  149. #endif