rpi_pci_svc.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
  3. * Copyright (c) 2024, Mario Bălănică <mariobalanica02@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. *
  7. * The RPi has a single nonstandard PCI config region. It is broken into two
  8. * pieces, the root port config registers and a window to a single device's
  9. * config space which can move between devices. There isn't (yet) an
  10. * authoritative public document on this since the available BCM2711 reference
  11. * notes that there is a PCIe root port in the memory map but doesn't describe
  12. * it. Given that it's not ECAM compliant yet reasonably simple, it makes for
  13. * an excellent example of the PCI SMCCC interface.
  14. *
  15. * The PCI SMCCC interface is described in DEN0115 available from:
  16. * https://developer.arm.com/documentation/den0115/latest
  17. */
  18. #include <assert.h>
  19. #include <stdint.h>
  20. #include <common/debug.h>
  21. #include <common/runtime_svc.h>
  22. #include <lib/pmf/pmf.h>
  23. #include <lib/runtime_instr.h>
  24. #include <services/pci_svc.h>
  25. #include <services/sdei.h>
  26. #include <services/std_svc.h>
  27. #include <smccc_helpers.h>
  28. #include <lib/mmio.h>
  29. #define PCIE_MISC_PCIE_STATUS 0x4068
  30. #define PCIE_EXT_CFG_INDEX 0x9000
  31. #define PCIE_EXT_CFG_DATA 0x8000
  32. #define PCIE_EXT_CFG_BDF_SHIFT 12
  33. #define INVALID_PCI_ADDR 0xFFFFFFFF
  34. static spinlock_t pci_lock;
  35. static uint64_t pcie_rc_bases[] = { RPI_PCIE_RC_BASES };
  36. static uint64_t pci_segment_lib_get_base(uint32_t address, uint32_t offset)
  37. {
  38. uint64_t base;
  39. uint32_t seg, bus, dev, fun;
  40. seg = PCI_ADDR_SEG(address);
  41. if (seg >= ARRAY_SIZE(pcie_rc_bases)) {
  42. return INVALID_PCI_ADDR;
  43. }
  44. /* The root port is at the base of the PCIe register space */
  45. base = pcie_rc_bases[seg];
  46. bus = PCI_ADDR_BUS(address);
  47. dev = PCI_ADDR_DEV(address);
  48. fun = PCI_ADDR_FUN(address);
  49. /* There can only be the root port on bus 0 */
  50. if ((bus == 0U) && ((dev > 0U) || (fun > 0U))) {
  51. return INVALID_PCI_ADDR;
  52. }
  53. /* There can only be one device on bus 1 */
  54. if ((bus == 1U) && (dev > 0U)) {
  55. return INVALID_PCI_ADDR;
  56. }
  57. if (bus > 0) {
  58. #if RPI_PCIE_ECAM_SERROR_QUIRK
  59. uint32_t status = mmio_read_32(base + PCIE_MISC_PCIE_STATUS);
  60. /* Assure link up before accessing downstream of root port */
  61. if ((status & 0x30) == 0U) {
  62. return INVALID_PCI_ADDR;
  63. }
  64. #endif
  65. /*
  66. * Device function is mapped at CFG_DATA, a 4 KB window
  67. * movable by writing its B/D/F location to CFG_INDEX.
  68. */
  69. mmio_write_32(base + PCIE_EXT_CFG_INDEX, address << PCIE_EXT_CFG_BDF_SHIFT);
  70. base += PCIE_EXT_CFG_DATA;
  71. }
  72. return base + (offset & PCI_OFFSET_MASK);
  73. }
  74. /**
  75. * pci_read_config() - Performs a config space read at addr
  76. * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115
  77. * @off: register offset of function described by @addr to read
  78. * @sz: size of read (8,16,32) bits.
  79. * @val: returned zero extended value read from config space
  80. *
  81. * sz bits of PCI config space is read at addr:offset, and the value
  82. * is returned in val. Invalid segment/offset values return failure.
  83. * Reads to valid functions that don't exist return INVALID_PCI_ADDR
  84. * as is specified by PCI for requests that aren't completed by EPs.
  85. * The boilerplate in pci_svc.c tends to do basic segment, off
  86. * and sz validation. This routine should avoid duplicating those
  87. * checks.
  88. *
  89. * This function maps directly to the PCI_READ function in DEN0115
  90. * where detailed requirements may be found.
  91. *
  92. * Return: SMC_PCI_CALL_SUCCESS with val set
  93. * SMC_PCI_CALL_INVAL_PARAM, on parameter error
  94. */
  95. uint32_t pci_read_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t *val)
  96. {
  97. uint32_t ret = SMC_PCI_CALL_SUCCESS;
  98. uint64_t base;
  99. spin_lock(&pci_lock);
  100. base = pci_segment_lib_get_base(addr, off);
  101. if (base == INVALID_PCI_ADDR) {
  102. *val = base;
  103. } else {
  104. switch (sz) {
  105. case SMC_PCI_SZ_8BIT:
  106. *val = mmio_read_8(base);
  107. break;
  108. case SMC_PCI_SZ_16BIT:
  109. *val = mmio_read_16(base);
  110. break;
  111. case SMC_PCI_SZ_32BIT:
  112. *val = mmio_read_32(base);
  113. break;
  114. default: /* should be unreachable */
  115. *val = 0U;
  116. ret = SMC_PCI_CALL_INVAL_PARAM;
  117. }
  118. }
  119. spin_unlock(&pci_lock);
  120. return ret;
  121. }
  122. /**
  123. * pci_write_config() - Performs a config space write at addr
  124. * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115
  125. * @off: register offset of function described by @addr to write
  126. * @sz: size of write (8,16,32) bits.
  127. * @val: value to be written
  128. *
  129. * sz bits of PCI config space is written at addr:offset. Invalid
  130. * segment/BDF values return failure. Writes to valid functions
  131. * without valid EPs are ignored, as is specified by PCI.
  132. * The boilerplate in pci_svc.c tends to do basic segment, off
  133. * and sz validation, so it shouldn't need to be repeated here.
  134. *
  135. * This function maps directly to the PCI_WRITE function in DEN0115
  136. * where detailed requirements may be found.
  137. *
  138. * Return: SMC_PCI_CALL_SUCCESS
  139. * SMC_PCI_CALL_INVAL_PARAM, on parameter error
  140. */
  141. uint32_t pci_write_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t val)
  142. {
  143. uint32_t ret = SMC_PCI_CALL_SUCCESS;
  144. uint64_t base;
  145. spin_lock(&pci_lock);
  146. base = pci_segment_lib_get_base(addr, off);
  147. if (base != INVALID_PCI_ADDR) {
  148. switch (sz) {
  149. case SMC_PCI_SZ_8BIT:
  150. mmio_write_8(base, val);
  151. break;
  152. case SMC_PCI_SZ_16BIT:
  153. mmio_write_16(base, val);
  154. break;
  155. case SMC_PCI_SZ_32BIT:
  156. mmio_write_32(base, val);
  157. break;
  158. default: /* should be unreachable */
  159. ret = SMC_PCI_CALL_INVAL_PARAM;
  160. }
  161. }
  162. spin_unlock(&pci_lock);
  163. return ret;
  164. }
  165. /**
  166. * pci_get_bus_for_seg() - returns the start->end bus range for a segment
  167. * @seg: segment being queried
  168. * @bus_range: returned bus begin + (end << 8)
  169. * @nseg: returns next segment in this machine or 0 for end
  170. *
  171. * pci_get_bus_for_seg is called to check if a given segment is
  172. * valid on this machine. If it is valid, then its bus ranges are
  173. * returned along with the next valid segment on the machine. If
  174. * this is the last segment, then nseg must be 0.
  175. *
  176. * This function maps directly to the PCI_GET_SEG_INFO function
  177. * in DEN0115 where detailed requirements may be found.
  178. *
  179. * Return: SMC_PCI_CALL_SUCCESS, and appropriate bus_range and nseg
  180. * SMC_PCI_CALL_NOT_IMPL, if the segment is invalid
  181. */
  182. uint32_t pci_get_bus_for_seg(uint32_t seg, uint32_t *bus_range, uint32_t *nseg)
  183. {
  184. uint32_t ret = SMC_PCI_CALL_SUCCESS;
  185. uint32_t rc_count = ARRAY_SIZE(pcie_rc_bases);
  186. *nseg = (seg < rc_count - 1U) ? seg + 1U : 0U;
  187. if (seg < rc_count) {
  188. *bus_range = 0U + (0xFF << 8); /* start 0, end 255 */
  189. } else {
  190. *bus_range = 0U;
  191. ret = SMC_PCI_CALL_NOT_IMPL;
  192. }
  193. return ret;
  194. }