pcie_ecam_generic.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Generic PCIE host provided by e.g. QEMU
  3. *
  4. * Heavily based on drivers/pci/pcie_xilinx.c
  5. *
  6. * Copyright (C) 2016 Imagination Technologies
  7. *
  8. * SPDX-License-Identifier: GPL-2.0
  9. */
  10. #include <common.h>
  11. #include <dm.h>
  12. #include <pci.h>
  13. #include <asm/io.h>
  14. /**
  15. * struct generic_ecam_pcie - generic_ecam PCIe controller state
  16. * @cfg_base: The base address of memory mapped configuration space
  17. */
  18. struct generic_ecam_pcie {
  19. void *cfg_base;
  20. };
  21. /**
  22. * pci_generic_ecam_conf_address() - Calculate the address of a config access
  23. * @bus: Pointer to the PCI bus
  24. * @bdf: Identifies the PCIe device to access
  25. * @offset: The offset into the device's configuration space
  26. * @paddress: Pointer to the pointer to write the calculates address to
  27. *
  28. * Calculates the address that should be accessed to perform a PCIe
  29. * configuration space access for a given device identified by the PCIe
  30. * controller device @pcie and the bus, device & function numbers in @bdf. If
  31. * access to the device is not valid then the function will return an error
  32. * code. Otherwise the address to access will be written to the pointer pointed
  33. * to by @paddress.
  34. */
  35. static int pci_generic_ecam_conf_address(struct udevice *bus, pci_dev_t bdf,
  36. uint offset, void **paddress)
  37. {
  38. struct generic_ecam_pcie *pcie = dev_get_priv(bus);
  39. void *addr;
  40. addr = pcie->cfg_base;
  41. addr += PCI_BUS(bdf) << 20;
  42. addr += PCI_DEV(bdf) << 15;
  43. addr += PCI_FUNC(bdf) << 12;
  44. addr += offset;
  45. *paddress = addr;
  46. return 0;
  47. }
  48. /**
  49. * pci_generic_ecam_read_config() - Read from configuration space
  50. * @bus: Pointer to the PCI bus
  51. * @bdf: Identifies the PCIe device to access
  52. * @offset: The offset into the device's configuration space
  53. * @valuep: A pointer at which to store the read value
  54. * @size: Indicates the size of access to perform
  55. *
  56. * Read a value of size @size from offset @offset within the configuration
  57. * space of the device identified by the bus, device & function numbers in @bdf
  58. * on the PCI bus @bus.
  59. */
  60. static int pci_generic_ecam_read_config(struct udevice *bus, pci_dev_t bdf,
  61. uint offset, ulong *valuep,
  62. enum pci_size_t size)
  63. {
  64. return pci_generic_mmap_read_config(bus, pci_generic_ecam_conf_address,
  65. bdf, offset, valuep, size);
  66. }
  67. /**
  68. * pci_generic_ecam_write_config() - Write to configuration space
  69. * @bus: Pointer to the PCI bus
  70. * @bdf: Identifies the PCIe device to access
  71. * @offset: The offset into the device's configuration space
  72. * @value: The value to write
  73. * @size: Indicates the size of access to perform
  74. *
  75. * Write the value @value of size @size from offset @offset within the
  76. * configuration space of the device identified by the bus, device & function
  77. * numbers in @bdf on the PCI bus @bus.
  78. */
  79. static int pci_generic_ecam_write_config(struct udevice *bus, pci_dev_t bdf,
  80. uint offset, ulong value,
  81. enum pci_size_t size)
  82. {
  83. return pci_generic_mmap_write_config(bus, pci_generic_ecam_conf_address,
  84. bdf, offset, value, size);
  85. }
  86. /**
  87. * pci_generic_ecam_ofdata_to_platdata() - Translate from DT to device state
  88. * @dev: A pointer to the device being operated on
  89. *
  90. * Translate relevant data from the device tree pertaining to device @dev into
  91. * state that the driver will later make use of. This state is stored in the
  92. * device's private data structure.
  93. *
  94. * Return: 0 on success, else -EINVAL
  95. */
  96. static int pci_generic_ecam_ofdata_to_platdata(struct udevice *dev)
  97. {
  98. struct generic_ecam_pcie *pcie = dev_get_priv(dev);
  99. struct fdt_resource reg_res;
  100. DECLARE_GLOBAL_DATA_PTR;
  101. int err;
  102. err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg",
  103. 0, &reg_res);
  104. if (err < 0) {
  105. pr_err("\"reg\" resource not found\n");
  106. return err;
  107. }
  108. pcie->cfg_base = map_physmem(reg_res.start,
  109. fdt_resource_size(&reg_res),
  110. MAP_NOCACHE);
  111. return 0;
  112. }
  113. static const struct dm_pci_ops pci_generic_ecam_ops = {
  114. .read_config = pci_generic_ecam_read_config,
  115. .write_config = pci_generic_ecam_write_config,
  116. };
  117. static const struct udevice_id pci_generic_ecam_ids[] = {
  118. { .compatible = "pci-host-ecam-generic" },
  119. { }
  120. };
  121. U_BOOT_DRIVER(pci_generic_ecam) = {
  122. .name = "pci_generic_ecam",
  123. .id = UCLASS_PCI,
  124. .of_match = pci_generic_ecam_ids,
  125. .ops = &pci_generic_ecam_ops,
  126. .ofdata_to_platdata = pci_generic_ecam_ofdata_to_platdata,
  127. .priv_auto_alloc_size = sizeof(struct generic_ecam_pcie),
  128. };