indirect_pci.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Support for indirect PCI bridges.
  4. *
  5. * Copyright (C) 1998 Gabriel Paubert.
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/pci.h>
  9. #include <linux/delay.h>
  10. #include <linux/string.h>
  11. #include <linux/init.h>
  12. #include <linux/io.h>
  13. #include <asm/pci-bridge.h>
  14. static int
  15. indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
  16. int len, u32 *val)
  17. {
  18. struct pci_controller *hose = pci_bus_to_host(bus);
  19. volatile void __iomem *cfg_data;
  20. u8 cfg_type = 0;
  21. u32 bus_no, reg;
  22. if (hose->indirect_type & INDIRECT_TYPE_NO_PCIE_LINK) {
  23. if (bus->number != hose->first_busno)
  24. return PCIBIOS_DEVICE_NOT_FOUND;
  25. if (devfn != 0)
  26. return PCIBIOS_DEVICE_NOT_FOUND;
  27. }
  28. if (hose->indirect_type & INDIRECT_TYPE_SET_CFG_TYPE)
  29. if (bus->number != hose->first_busno)
  30. cfg_type = 1;
  31. bus_no = (bus->number == hose->first_busno) ?
  32. hose->self_busno : bus->number;
  33. if (hose->indirect_type & INDIRECT_TYPE_EXT_REG)
  34. reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
  35. else
  36. reg = offset & 0xfc; /* Only 3 bits for function */
  37. if (hose->indirect_type & INDIRECT_TYPE_BIG_ENDIAN)
  38. out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
  39. (devfn << 8) | reg | cfg_type));
  40. else
  41. out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
  42. (devfn << 8) | reg | cfg_type));
  43. /*
  44. * Note: the caller has already checked that offset is
  45. * suitably aligned and that len is 1, 2 or 4.
  46. */
  47. cfg_data = hose->cfg_data + (offset & 3); /* Only 3 bits for function */
  48. switch (len) {
  49. case 1:
  50. *val = in_8(cfg_data);
  51. break;
  52. case 2:
  53. *val = in_le16(cfg_data);
  54. break;
  55. default:
  56. *val = in_le32(cfg_data);
  57. break;
  58. }
  59. return PCIBIOS_SUCCESSFUL;
  60. }
  61. static int
  62. indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
  63. int len, u32 val)
  64. {
  65. struct pci_controller *hose = pci_bus_to_host(bus);
  66. volatile void __iomem *cfg_data;
  67. u8 cfg_type = 0;
  68. u32 bus_no, reg;
  69. if (hose->indirect_type & INDIRECT_TYPE_NO_PCIE_LINK) {
  70. if (bus->number != hose->first_busno)
  71. return PCIBIOS_DEVICE_NOT_FOUND;
  72. if (devfn != 0)
  73. return PCIBIOS_DEVICE_NOT_FOUND;
  74. }
  75. if (hose->indirect_type & INDIRECT_TYPE_SET_CFG_TYPE)
  76. if (bus->number != hose->first_busno)
  77. cfg_type = 1;
  78. bus_no = (bus->number == hose->first_busno) ?
  79. hose->self_busno : bus->number;
  80. if (hose->indirect_type & INDIRECT_TYPE_EXT_REG)
  81. reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
  82. else
  83. reg = offset & 0xfc;
  84. if (hose->indirect_type & INDIRECT_TYPE_BIG_ENDIAN)
  85. out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
  86. (devfn << 8) | reg | cfg_type));
  87. else
  88. out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
  89. (devfn << 8) | reg | cfg_type));
  90. /* suppress setting of PCI_PRIMARY_BUS */
  91. if (hose->indirect_type & INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
  92. if ((offset == PCI_PRIMARY_BUS) &&
  93. (bus->number == hose->first_busno))
  94. val &= 0xffffff00;
  95. /* Workaround for PCI_28 Errata in 440EPx/GRx */
  96. if ((hose->indirect_type & INDIRECT_TYPE_BROKEN_MRM) &&
  97. offset == PCI_CACHE_LINE_SIZE) {
  98. val = 0;
  99. }
  100. /*
  101. * Note: the caller has already checked that offset is
  102. * suitably aligned and that len is 1, 2 or 4.
  103. */
  104. cfg_data = hose->cfg_data + (offset & 3);
  105. switch (len) {
  106. case 1:
  107. out_8(cfg_data, val);
  108. break;
  109. case 2:
  110. out_le16(cfg_data, val);
  111. break;
  112. default:
  113. out_le32(cfg_data, val);
  114. break;
  115. }
  116. return PCIBIOS_SUCCESSFUL;
  117. }
  118. static struct pci_ops indirect_pci_ops = {
  119. .read = indirect_read_config,
  120. .write = indirect_write_config,
  121. };
  122. void __init
  123. setup_indirect_pci(struct pci_controller *hose,
  124. resource_size_t cfg_addr,
  125. resource_size_t cfg_data, u32 flags)
  126. {
  127. resource_size_t base = cfg_addr & PAGE_MASK;
  128. void __iomem *mbase;
  129. mbase = ioremap(base, PAGE_SIZE);
  130. hose->cfg_addr = mbase + (cfg_addr & ~PAGE_MASK);
  131. if ((cfg_data & PAGE_MASK) != base)
  132. mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
  133. hose->cfg_data = mbase + (cfg_data & ~PAGE_MASK);
  134. hose->ops = &indirect_pci_ops;
  135. hose->indirect_type = flags;
  136. }