pcie-tegra194-acpi.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * ACPI quirks for Tegra194 PCIe host controller
  4. *
  5. * Copyright (C) 2021 NVIDIA Corporation.
  6. *
  7. * Author: Vidya Sagar <[email protected]>
  8. */
  9. #include <linux/pci.h>
  10. #include <linux/pci-acpi.h>
  11. #include <linux/pci-ecam.h>
  12. #include "pcie-designware.h"
  13. struct tegra194_pcie_ecam {
  14. void __iomem *config_base;
  15. void __iomem *iatu_base;
  16. void __iomem *dbi_base;
  17. };
  18. static int tegra194_acpi_init(struct pci_config_window *cfg)
  19. {
  20. struct device *dev = cfg->parent;
  21. struct tegra194_pcie_ecam *pcie_ecam;
  22. pcie_ecam = devm_kzalloc(dev, sizeof(*pcie_ecam), GFP_KERNEL);
  23. if (!pcie_ecam)
  24. return -ENOMEM;
  25. pcie_ecam->config_base = cfg->win;
  26. pcie_ecam->iatu_base = cfg->win + SZ_256K;
  27. pcie_ecam->dbi_base = cfg->win + SZ_512K;
  28. cfg->priv = pcie_ecam;
  29. return 0;
  30. }
  31. static void atu_reg_write(struct tegra194_pcie_ecam *pcie_ecam, int index,
  32. u32 val, u32 reg)
  33. {
  34. u32 offset = PCIE_ATU_UNROLL_BASE(PCIE_ATU_REGION_DIR_OB, index) +
  35. PCIE_ATU_VIEWPORT_BASE;
  36. writel(val, pcie_ecam->iatu_base + offset + reg);
  37. }
  38. static void program_outbound_atu(struct tegra194_pcie_ecam *pcie_ecam,
  39. int index, int type, u64 cpu_addr,
  40. u64 pci_addr, u64 size)
  41. {
  42. atu_reg_write(pcie_ecam, index, lower_32_bits(cpu_addr),
  43. PCIE_ATU_LOWER_BASE);
  44. atu_reg_write(pcie_ecam, index, upper_32_bits(cpu_addr),
  45. PCIE_ATU_UPPER_BASE);
  46. atu_reg_write(pcie_ecam, index, lower_32_bits(pci_addr),
  47. PCIE_ATU_LOWER_TARGET);
  48. atu_reg_write(pcie_ecam, index, lower_32_bits(cpu_addr + size - 1),
  49. PCIE_ATU_LIMIT);
  50. atu_reg_write(pcie_ecam, index, upper_32_bits(pci_addr),
  51. PCIE_ATU_UPPER_TARGET);
  52. atu_reg_write(pcie_ecam, index, type, PCIE_ATU_REGION_CTRL1);
  53. atu_reg_write(pcie_ecam, index, PCIE_ATU_ENABLE, PCIE_ATU_REGION_CTRL2);
  54. }
  55. static void __iomem *tegra194_map_bus(struct pci_bus *bus,
  56. unsigned int devfn, int where)
  57. {
  58. struct pci_config_window *cfg = bus->sysdata;
  59. struct tegra194_pcie_ecam *pcie_ecam = cfg->priv;
  60. u32 busdev;
  61. int type;
  62. if (bus->number < cfg->busr.start || bus->number > cfg->busr.end)
  63. return NULL;
  64. if (bus->number == cfg->busr.start) {
  65. if (PCI_SLOT(devfn) == 0)
  66. return pcie_ecam->dbi_base + where;
  67. else
  68. return NULL;
  69. }
  70. busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
  71. PCIE_ATU_FUNC(PCI_FUNC(devfn));
  72. if (bus->parent->number == cfg->busr.start) {
  73. if (PCI_SLOT(devfn) == 0)
  74. type = PCIE_ATU_TYPE_CFG0;
  75. else
  76. return NULL;
  77. } else {
  78. type = PCIE_ATU_TYPE_CFG1;
  79. }
  80. program_outbound_atu(pcie_ecam, 0, type, cfg->res.start, busdev,
  81. SZ_256K);
  82. return pcie_ecam->config_base + where;
  83. }
  84. const struct pci_ecam_ops tegra194_pcie_ops = {
  85. .init = tegra194_acpi_init,
  86. .pci_ops = {
  87. .map_bus = tegra194_map_bus,
  88. .read = pci_generic_config_read,
  89. .write = pci_generic_config_write,
  90. }
  91. };