diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-15 16:49:59 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-15 16:49:59 -0800 |
commit | 489e9fea66f31086f85d9a18e61e4791d94a56a4 (patch) | |
tree | 0283bc742248a64ba2df8793572fae526eb23cf4 /drivers/pci/controller/dwc/pcie-qcom.c | |
parent | aab7ce2b099bd9df82573cd3170acf6518fdebeb (diff) | |
parent | 255b2d524884e4ec60333131aa0ca0ef19826dc2 (diff) |
Merge tag 'pci-v5.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
"Enumeration:
- Decode PCIe 64 GT/s link speed (Gustavo Pimentel)
- Remove unused HAVE_PCI_SET_MWI (Heiner Kallweit)
- Reduce pci_set_cacheline_size() message to debug level (Heiner
Kallweit)
- Fix pci_slot_release() NULL pointer dereference (Jubin Zhong)
- Unify ECAM constants in native PCI Express drivers (Krzysztof
Wilczyński)
- Return u8 from pci_find_capability() and similar (Puranjay Mohan)
- Return u16 from pci_find_ext_capability() and similar (Bjorn
Helgaas)
- Fix ACPI companion lookup for device 0 on the root bus (Rafael J.
Wysocki)
Resource management:
- Keep both device and resource name for config space remaps
(Alexander Lobakin)
- Bounds-check command-line resource alignment requests (Bjorn
Helgaas)
- Fix overflow in command-line resource alignment requests (Colin Ian
King)
Driver binding:
- Avoid duplicate IDs in driver dynamic IDs list (Zhenzhong Duan)
Power management:
- Save/restore Precision Time Measurement Capability for
suspend/resume (David E. Box)
- Disable PTM during suspend to save power (David E. Box)
- Add sysfs attribute for device power state (Maximilian Luz)
- Rename pci_wakeup_bus() to pci_resume_bus() (Mika Westerberg)
- Do not generate wakeup event when runtime resuming device (Mika
Westerberg)
- Save/restore ASPM L1SS Capability for suspend/resume (Vidya Sagar)
Virtualization:
- Mark AMD Raven iGPU ATS as broken in some platforms (Alex Deucher)
- Add function 1 DMA alias quirk for Marvell 9215 SATA controller
(Bjorn Helgaas)
MSI:
- Disable MSI for Pericom PCIe-USB adapter (Andy Shevchenko)
- Improve warnings for 32-bit-limited MSI support (Vidya Sagar)
Error handling:
- Cache RCEC EA Capability offset in pci_init_capabilities() (Sean V
Kelley)
- Rename reset_link() to reset_subordinates() (Sean V Kelley)
- Write AER Capability only when we control it (Sean V Kelley)
- Clear AER status only when we control AER (Sean V Kelley)
- Bind RCEC devices to the Root Port driver (Qiuxu Zhuo)
- Recover from RCiEP AER errors (Qiuxu Zhuo)
- Recover from RCEC AER errors (Sean V Kelley)
- Add pcie_link_rcec() to associate RCiEPs (Sean V Kelley)
- Add pcie_walk_rcec() to RCEC AER handling (Sean V Kelley)
- Add pcie_walk_rcec() to RCEC PME handling (Sean V Kelley)
- Add RCEC AER error injection support (Qiuxu Zhuo)
Broadcom iProc PCIe controller driver:
- Fix out-of-bound array accesses (Bharat Gooty)
- Invalidate correct PAXB inbound windows (Roman Bacik)
- Enhance PCIe Link information display (Srinath Mannam)
Cadence PCIe controller driver:
- Make "cdns,max-outbound-regions" property optional (Kishon Vijay
Abraham I)
Intel VMD host bridge driver:
- Offset client MSI-X vectors (Jon Derrick)
- Update type of __iomem pointers (Krzysztof Wilczyński)
NVIDIA Tegra PCIe controller driver:
- Move "dbi" accesses to post common DWC initialization (Vidya Sagar)
- Read "dbi" base address to program in application logic (Vidya
Sagar)
- Fix ASPM-L1SS advertisement disable code (Vidya Sagar)
- Set DesignWare IP version (Vidya Sagar)
- Continue unconfig sequence even if parts fail (Vidya Sagar)
- Check return value of tegra_pcie_init_controller() (Vidya Sagar)
- Disable LTSSM during L2 entry (Vidya Sagar)
Qualcomm PCIe controller driver:
- Document PCIe bindings for SM8250 SoC (Manivannan Sadhasivam)
- Add SM8250 SoC support (Manivannan Sadhasivam)
- Add support for configuring BDF to SID mapping for SM8250
(Manivannan Sadhasivam)
Renesas R-Car PCIe controller driver:
- rcar: Drop unused members from struct rcar_pcie_host (Lad
Prabhakar)
- PCI: rcar-pci-host: Document r8a774e1 bindings (Lad Prabhakar)
- PCI: rcar-pci-host: Convert bindings to json-schema (Yoshihiro
Shimoda)
- PCI: rcar-pci-host: Document r8a77965 bindings (Yoshihiro Shimoda)
Samsung Exynos PCIe controller driver:
- Rework driver to support Exynos5433 PCIe PHY (Jaehoon Chung)
- Rework driver to support Exynos5433 variant (Jaehoon Chung)
- Drop samsung,exynos5440-pcie binding (Marek Szyprowski)
- Add the samsung,exynos-pcie binding (Marek Szyprowski)
- Add the samsung,exynos-pcie-phy binding (Marek Szyprowski)
Synopsys DesignWare PCIe controller driver:
- Support multiple ATU memory regions (Rob Herring)
- Move intel-gw ATU offset out of driver match data (Rob Herring)
- Move "dbi", "dbi2", and "addr_space" resource setup into common
code (Rob Herring)
- Remove intel-gw unneeded function wrappers (Rob Herring)
- Ensure all outbound ATU windows are reset (Rob Herring)
- Use the common MSI irq_chip in dra7xx (Rob Herring)
- Drop the .set_num_vectors() host op (Rob Herring)
- Move MSI interrupt setup into DWC common code (Rob Herring)
- Rework MSI initialization (Rob Herring)
- Move link handling into common code (Rob Herring)
- Move dw_pcie_msi_init() into core (Rob Herring)
- Move dw_pcie_setup_rc() to DWC common code (Rob Herring)
- Remove unnecessary wrappers around dw_pcie_host_init() (Rob
Herring)
- Drop keystone duplicated 'num-viewport'" (Rob Herring)
- Move inbound and outbound windows to common struct (Rob Herring)
- Detect number of iATU windows (Rob Herring)
- Warn if non-prefetchable memory aperture size is > 32-bit (Vidya
Sagar)
- Add support to program ATU for >4GB memory (Vidya Sagar)
- Set 32-bit DMA mask for MSI target address allocation (Vidya Sagar)
TI J721E PCIe driver:
- Fix "ti,syscon-pcie-ctrl" to take argument (Kishon Vijay Abraham I)
- Add host mode dt-bindings for TI's J7200 SoC (Kishon Vijay Abraham
I)
- Add EP mode dt-bindings for TI's J7200 SoC (Kishon Vijay Abraham I)
- Get offset within "syscon" from "ti,syscon-pcie-ctrl" phandle arg
(Kishon Vijay Abraham I)
TI Keystone PCIe controller driver:
- Enable compile-testing on !ARM (Alex Dewar)"
* tag 'pci-v5.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (100 commits)
PCI: Add function 1 DMA alias quirk for Marvell 9215 SATA controller
PCI/ACPI: Fix companion lookup for device 0 on the root bus
PCI: Keep both device and resource name for config space remaps
PCI: xgene: Removed unused ".bus_shift" initialisers from pci-xgene.c
PCI: vmd: Update type of the __iomem pointers
PCI: iproc: Convert to use the new ECAM constants
PCI: thunder-pem: Add constant for custom ".bus_shift" initialiser
PCI: Unify ECAM constants in native PCI Express drivers
PCI: Disable PTM during suspend to save power
PCI/PTM: Save/restore Precision Time Measurement Capability for suspend/resume
PCI: Mark AMD Raven iGPU ATS as broken in some platforms
PCI: j721e: Get offset within "syscon" from "ti,syscon-pcie-ctrl" phandle arg
dt-bindings: PCI: Add EP mode dt-bindings for TI's J7200 SoC
dt-bindings: PCI: Add host mode dt-bindings for TI's J7200 SoC
dt-bindings: pci: ti,j721e: Fix "ti,syscon-pcie-ctrl" to take argument
PCI: dwc: Set 32-bit DMA mask for MSI target address allocation
PCI: qcom: Add support for configuring BDF to SID mapping for SM8250
PCI: Reduce pci_set_cacheline_size() message to debug level
PCI: Remove unused HAVE_PCI_SET_MWI
PCI: qcom: Add SM8250 SoC support
...
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-qcom.c')
-rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom.c | 127 |
1 files changed, 99 insertions, 28 deletions
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index b4761640ffd9..affa2713bf80 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -9,6 +9,7 @@ */ #include <linux/clk.h> +#include <linux/crc8.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/interrupt.h> @@ -57,6 +58,7 @@ #define PCIE20_PARF_SID_OFFSET 0x234 #define PCIE20_PARF_BDF_TRANSLATE_CFG 0x24C #define PCIE20_PARF_DEVICE_TYPE 0x1000 +#define PCIE20_PARF_BDF_TO_SID_TABLE_N 0x2000 #define PCIE20_ELBI_SYS_CTRL 0x04 #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0) @@ -97,6 +99,9 @@ #define QCOM_PCIE_2_1_0_MAX_SUPPLY 3 #define QCOM_PCIE_2_1_0_MAX_CLOCKS 5 + +#define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) + struct qcom_pcie_resources_2_1_0 { struct clk_bulk_data clks[QCOM_PCIE_2_1_0_MAX_CLOCKS]; struct reset_control *pci_reset; @@ -179,6 +184,7 @@ struct qcom_pcie_ops { void (*deinit)(struct qcom_pcie *pcie); void (*post_deinit)(struct qcom_pcie *pcie); void (*ltssm_enable)(struct qcom_pcie *pcie); + int (*config_sid)(struct qcom_pcie *pcie); }; struct qcom_pcie { @@ -207,18 +213,15 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); } -static int qcom_pcie_establish_link(struct qcom_pcie *pcie) +static int qcom_pcie_start_link(struct dw_pcie *pci) { - struct dw_pcie *pci = pcie->pci; - - if (dw_pcie_link_up(pci)) - return 0; + struct qcom_pcie *pcie = to_qcom_pcie(pci); /* Enable Link Training state machine */ if (pcie->ops->ltssm_enable) pcie->ops->ltssm_enable(pcie); - return dw_pcie_wait_for_link(pci); + return 0; } static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie) @@ -1261,6 +1264,77 @@ static int qcom_pcie_link_up(struct dw_pcie *pci) return !!(val & PCI_EXP_LNKSTA_DLLLA); } +static int qcom_pcie_config_sid_sm8250(struct qcom_pcie *pcie) +{ + /* iommu map structure */ + struct { + u32 bdf; + u32 phandle; + u32 smmu_sid; + u32 smmu_sid_len; + } *map; + void __iomem *bdf_to_sid_base = pcie->parf + PCIE20_PARF_BDF_TO_SID_TABLE_N; + struct device *dev = pcie->pci->dev; + u8 qcom_pcie_crc8_table[CRC8_TABLE_SIZE]; + int i, nr_map, size = 0; + u32 smmu_sid_base; + + of_get_property(dev->of_node, "iommu-map", &size); + if (!size) + return 0; + + map = kzalloc(size, GFP_KERNEL); + if (!map) + return -ENOMEM; + + of_property_read_u32_array(dev->of_node, + "iommu-map", (u32 *)map, size / sizeof(u32)); + + nr_map = size / (sizeof(*map)); + + crc8_populate_msb(qcom_pcie_crc8_table, QCOM_PCIE_CRC8_POLYNOMIAL); + + /* Registers need to be zero out first */ + memset_io(bdf_to_sid_base, 0, CRC8_TABLE_SIZE * sizeof(u32)); + + /* Extract the SMMU SID base from the first entry of iommu-map */ + smmu_sid_base = map[0].smmu_sid; + + /* Look for an available entry to hold the mapping */ + for (i = 0; i < nr_map; i++) { + u16 bdf_be = cpu_to_be16(map[i].bdf); + u32 val; + u8 hash; + + hash = crc8(qcom_pcie_crc8_table, (u8 *)&bdf_be, sizeof(bdf_be), + 0); + + val = readl(bdf_to_sid_base + hash * sizeof(u32)); + + /* If the register is already populated, look for next available entry */ + while (val) { + u8 current_hash = hash++; + u8 next_mask = 0xff; + + /* If NEXT field is NULL then update it with next hash */ + if (!(val & next_mask)) { + val |= (u32)hash; + writel(val, bdf_to_sid_base + current_hash * sizeof(u32)); + } + + val = readl(bdf_to_sid_base + hash * sizeof(u32)); + } + + /* BDF [31:16] | SID [15:8] | NEXT [7:0] */ + val = map[i].bdf << 16 | (map[i].smmu_sid - smmu_sid_base) << 8 | 0; + writel(val, bdf_to_sid_base + hash * sizeof(u32)); + } + + kfree(map); + + return 0; +} + static int qcom_pcie_host_init(struct pcie_port *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -1283,16 +1357,16 @@ static int qcom_pcie_host_init(struct pcie_port *pp) goto err_disable_phy; } - dw_pcie_setup_rc(pp); - dw_pcie_msi_init(pp); - qcom_ep_reset_deassert(pcie); - ret = qcom_pcie_establish_link(pcie); - if (ret) - goto err; + if (pcie->ops->config_sid) { + ret = pcie->ops->config_sid(pcie); + if (ret) + goto err; + } return 0; + err: qcom_ep_reset_assert(pcie); if (pcie->ops->post_deinit) @@ -1361,14 +1435,25 @@ static const struct qcom_pcie_ops ops_2_7_0 = { .post_deinit = qcom_pcie_post_deinit_2_7_0, }; +/* Qcom IP rev.: 1.9.0 */ +static const struct qcom_pcie_ops ops_1_9_0 = { + .get_resources = qcom_pcie_get_resources_2_7_0, + .init = qcom_pcie_init_2_7_0, + .deinit = qcom_pcie_deinit_2_7_0, + .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, + .post_init = qcom_pcie_post_init_2_7_0, + .post_deinit = qcom_pcie_post_deinit_2_7_0, + .config_sid = qcom_pcie_config_sid_sm8250, +}; + static const struct dw_pcie_ops dw_pcie_ops = { .link_up = qcom_pcie_link_up, + .start_link = qcom_pcie_start_link, }; static int qcom_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct pcie_port *pp; struct dw_pcie *pci; struct qcom_pcie *pcie; @@ -1407,13 +1492,6 @@ static int qcom_pcie_probe(struct platform_device *pdev) goto err_pm_runtime_put; } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); - pci->dbi_base = devm_pci_remap_cfg_resource(dev, res); - if (IS_ERR(pci->dbi_base)) { - ret = PTR_ERR(pci->dbi_base); - goto err_pm_runtime_put; - } - pcie->elbi = devm_platform_ioremap_resource_byname(pdev, "elbi"); if (IS_ERR(pcie->elbi)) { ret = PTR_ERR(pcie->elbi); @@ -1432,14 +1510,6 @@ static int qcom_pcie_probe(struct platform_device *pdev) pp->ops = &qcom_pcie_dw_ops; - if (IS_ENABLED(CONFIG_PCI_MSI)) { - pp->msi_irq = platform_get_irq_byname(pdev, "msi"); - if (pp->msi_irq < 0) { - ret = pp->msi_irq; - goto err_pm_runtime_put; - } - } - ret = phy_init(pcie->phy); if (ret) { pm_runtime_disable(&pdev->dev); @@ -1474,6 +1544,7 @@ static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,pcie-ipq4019", .data = &ops_2_4_0 }, { .compatible = "qcom,pcie-qcs404", .data = &ops_2_4_0 }, { .compatible = "qcom,pcie-sdm845", .data = &ops_2_7_0 }, + { .compatible = "qcom,pcie-sm8250", .data = &ops_1_9_0 }, { } }; |