pcie_octeon.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2020 Stefan Roese <sr@denx.de>
  4. */
  5. #include <dm.h>
  6. #include <errno.h>
  7. #include <fdtdec.h>
  8. #include <log.h>
  9. #include <pci.h>
  10. #include <linux/delay.h>
  11. #include <mach/octeon-model.h>
  12. #include <mach/octeon_pci.h>
  13. #include <mach/cvmx-regs.h>
  14. #include <mach/cvmx-pcie.h>
  15. #include <mach/cvmx-pemx-defs.h>
  16. struct octeon_pcie {
  17. void *base;
  18. int first_busno;
  19. u32 port;
  20. struct udevice *dev;
  21. int pcie_port;
  22. };
  23. static bool octeon_bdf_invalid(pci_dev_t bdf, int first_busno)
  24. {
  25. /*
  26. * In PCIe only a single device (0) can exist on the local bus.
  27. * Beyound the local bus, there might be a switch and everything
  28. * is possible.
  29. */
  30. if ((PCI_BUS(bdf) == first_busno) && (PCI_DEV(bdf) > 0))
  31. return true;
  32. return false;
  33. }
  34. static int pcie_octeon_write_config(struct udevice *bus, pci_dev_t bdf,
  35. uint offset, ulong value,
  36. enum pci_size_t size)
  37. {
  38. struct octeon_pcie *pcie = dev_get_priv(bus);
  39. struct pci_controller *hose = dev_get_uclass_priv(bus);
  40. int busno;
  41. int port;
  42. debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
  43. PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
  44. debug("(addr,size,val)=(0x%04x, %d, 0x%08lx)\n", offset, size, value);
  45. port = pcie->pcie_port;
  46. busno = PCI_BUS(bdf) - hose->first_busno + 1;
  47. switch (size) {
  48. case PCI_SIZE_8:
  49. cvmx_pcie_config_write8(port, busno, PCI_DEV(bdf),
  50. PCI_FUNC(bdf), offset, value);
  51. break;
  52. case PCI_SIZE_16:
  53. cvmx_pcie_config_write16(port, busno, PCI_DEV(bdf),
  54. PCI_FUNC(bdf), offset, value);
  55. break;
  56. case PCI_SIZE_32:
  57. cvmx_pcie_config_write32(port, busno, PCI_DEV(bdf),
  58. PCI_FUNC(bdf), offset, value);
  59. break;
  60. default:
  61. printf("Invalid size\n");
  62. };
  63. return 0;
  64. }
  65. static int pcie_octeon_read_config(const struct udevice *bus, pci_dev_t bdf,
  66. uint offset, ulong *valuep,
  67. enum pci_size_t size)
  68. {
  69. struct octeon_pcie *pcie = dev_get_priv(bus);
  70. struct pci_controller *hose = dev_get_uclass_priv(bus);
  71. int busno;
  72. int port;
  73. port = pcie->pcie_port;
  74. busno = PCI_BUS(bdf) - hose->first_busno + 1;
  75. if (octeon_bdf_invalid(bdf, pcie->first_busno)) {
  76. *valuep = pci_get_ff(size);
  77. return 0;
  78. }
  79. switch (size) {
  80. case PCI_SIZE_8:
  81. *valuep = cvmx_pcie_config_read8(port, busno, PCI_DEV(bdf),
  82. PCI_FUNC(bdf), offset);
  83. break;
  84. case PCI_SIZE_16:
  85. *valuep = cvmx_pcie_config_read16(port, busno, PCI_DEV(bdf),
  86. PCI_FUNC(bdf), offset);
  87. break;
  88. case PCI_SIZE_32:
  89. *valuep = cvmx_pcie_config_read32(port, busno, PCI_DEV(bdf),
  90. PCI_FUNC(bdf), offset);
  91. break;
  92. default:
  93. printf("Invalid size\n");
  94. };
  95. debug("%02x.%02x.%02x: u%d %x -> %lx\n",
  96. PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), size, offset, *valuep);
  97. return 0;
  98. }
  99. static int pcie_octeon_probe(struct udevice *dev)
  100. {
  101. struct octeon_pcie *pcie = dev_get_priv(dev);
  102. int node = cvmx_get_node_num();
  103. int pcie_port;
  104. int ret = 0;
  105. /* Get port number, lane number and memory target / attr */
  106. if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-port",
  107. &pcie->port)) {
  108. ret = -ENODEV;
  109. goto err;
  110. }
  111. pcie->first_busno = dev_seq(dev);
  112. pcie_port = ((node << 4) | pcie->port);
  113. ret = cvmx_pcie_rc_initialize(pcie_port);
  114. if (ret != 0)
  115. return ret;
  116. return 0;
  117. err:
  118. return ret;
  119. }
  120. static const struct dm_pci_ops pcie_octeon_ops = {
  121. .read_config = pcie_octeon_read_config,
  122. .write_config = pcie_octeon_write_config,
  123. };
  124. static const struct udevice_id pcie_octeon_ids[] = {
  125. { .compatible = "marvell,pcie-host-octeon" },
  126. { }
  127. };
  128. U_BOOT_DRIVER(pcie_octeon) = {
  129. .name = "pcie_octeon",
  130. .id = UCLASS_PCI,
  131. .of_match = pcie_octeon_ids,
  132. .ops = &pcie_octeon_ops,
  133. .probe = pcie_octeon_probe,
  134. .priv_auto = sizeof(struct octeon_pcie),
  135. .flags = DM_FLAG_PRE_RELOC,
  136. };