162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// Copyright (c) 2017 Cadence 362306a36Sopenharmony_ci// Cadence PCIe controller driver. 462306a36Sopenharmony_ci// Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/kernel.h> 762306a36Sopenharmony_ci#include <linux/of.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "pcie-cadence.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_civoid cdns_pcie_detect_quiet_min_delay_set(struct cdns_pcie *pcie) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci u32 delay = 0x3; 1462306a36Sopenharmony_ci u32 ltssm_control_cap; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci /* 1762306a36Sopenharmony_ci * Set the LTSSM Detect Quiet state min. delay to 2ms. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci ltssm_control_cap = cdns_pcie_readl(pcie, CDNS_PCIE_LTSSM_CONTROL_CAP); 2062306a36Sopenharmony_ci ltssm_control_cap = ((ltssm_control_cap & 2162306a36Sopenharmony_ci ~CDNS_PCIE_DETECT_QUIET_MIN_DELAY_MASK) | 2262306a36Sopenharmony_ci CDNS_PCIE_DETECT_QUIET_MIN_DELAY(delay)); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_LTSSM_CONTROL_CAP, ltssm_control_cap); 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_civoid cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn, 2862306a36Sopenharmony_ci u32 r, bool is_io, 2962306a36Sopenharmony_ci u64 cpu_addr, u64 pci_addr, size_t size) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci /* 3262306a36Sopenharmony_ci * roundup_pow_of_two() returns an unsigned long, which is not suited 3362306a36Sopenharmony_ci * for 64bit values. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci u64 sz = 1ULL << fls64(size - 1); 3662306a36Sopenharmony_ci int nbits = ilog2(sz); 3762306a36Sopenharmony_ci u32 addr0, addr1, desc0, desc1; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci if (nbits < 8) 4062306a36Sopenharmony_ci nbits = 8; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci /* Set the PCI address */ 4362306a36Sopenharmony_ci addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(nbits) | 4462306a36Sopenharmony_ci (lower_32_bits(pci_addr) & GENMASK(31, 8)); 4562306a36Sopenharmony_ci addr1 = upper_32_bits(pci_addr); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(r), addr0); 4862306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(r), addr1); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /* Set the PCIe header descriptor */ 5162306a36Sopenharmony_ci if (is_io) 5262306a36Sopenharmony_ci desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_IO; 5362306a36Sopenharmony_ci else 5462306a36Sopenharmony_ci desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_MEM; 5562306a36Sopenharmony_ci desc1 = 0; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* 5862306a36Sopenharmony_ci * Whatever Bit [23] is set or not inside DESC0 register of the outbound 5962306a36Sopenharmony_ci * PCIe descriptor, the PCI function number must be set into 6062306a36Sopenharmony_ci * Bits [26:24] of DESC0 anyway. 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * In Root Complex mode, the function number is always 0 but in Endpoint 6362306a36Sopenharmony_ci * mode, the PCIe controller may support more than one function. This 6462306a36Sopenharmony_ci * function number needs to be set properly into the outbound PCIe 6562306a36Sopenharmony_ci * descriptor. 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * Besides, setting Bit [23] is mandatory when in Root Complex mode: 6862306a36Sopenharmony_ci * then the driver must provide the bus, resp. device, number in 6962306a36Sopenharmony_ci * Bits [7:0] of DESC1, resp. Bits[31:27] of DESC0. Like the function 7062306a36Sopenharmony_ci * number, the device number is always 0 in Root Complex mode. 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * However when in Endpoint mode, we can clear Bit [23] of DESC0, hence 7362306a36Sopenharmony_ci * the PCIe controller will use the captured values for the bus and 7462306a36Sopenharmony_ci * device numbers. 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci if (pcie->is_rc) { 7762306a36Sopenharmony_ci /* The device and function numbers are always 0. */ 7862306a36Sopenharmony_ci desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID | 7962306a36Sopenharmony_ci CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0); 8062306a36Sopenharmony_ci desc1 |= CDNS_PCIE_AT_OB_REGION_DESC1_BUS(busnr); 8162306a36Sopenharmony_ci } else { 8262306a36Sopenharmony_ci /* 8362306a36Sopenharmony_ci * Use captured values for bus and device numbers but still 8462306a36Sopenharmony_ci * need to set the function number. 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_ci desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(fn); 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(r), desc0); 9062306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(r), desc1); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* Set the CPU address */ 9362306a36Sopenharmony_ci if (pcie->ops->cpu_addr_fixup) 9462306a36Sopenharmony_ci cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(nbits) | 9762306a36Sopenharmony_ci (lower_32_bits(cpu_addr) & GENMASK(31, 8)); 9862306a36Sopenharmony_ci addr1 = upper_32_bits(cpu_addr); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0); 10162306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_civoid cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie, 10562306a36Sopenharmony_ci u8 busnr, u8 fn, 10662306a36Sopenharmony_ci u32 r, u64 cpu_addr) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci u32 addr0, addr1, desc0, desc1; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_NORMAL_MSG; 11162306a36Sopenharmony_ci desc1 = 0; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* See cdns_pcie_set_outbound_region() comments above. */ 11462306a36Sopenharmony_ci if (pcie->is_rc) { 11562306a36Sopenharmony_ci desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID | 11662306a36Sopenharmony_ci CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0); 11762306a36Sopenharmony_ci desc1 |= CDNS_PCIE_AT_OB_REGION_DESC1_BUS(busnr); 11862306a36Sopenharmony_ci } else { 11962306a36Sopenharmony_ci desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(fn); 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci /* Set the CPU address */ 12362306a36Sopenharmony_ci if (pcie->ops->cpu_addr_fixup) 12462306a36Sopenharmony_ci cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(17) | 12762306a36Sopenharmony_ci (lower_32_bits(cpu_addr) & GENMASK(31, 8)); 12862306a36Sopenharmony_ci addr1 = upper_32_bits(cpu_addr); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(r), 0); 13162306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(r), 0); 13262306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(r), desc0); 13362306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(r), desc1); 13462306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0); 13562306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1); 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_civoid cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(r), 0); 14162306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(r), 0); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(r), 0); 14462306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(r), 0); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), 0); 14762306a36Sopenharmony_ci cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), 0); 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_civoid cdns_pcie_disable_phy(struct cdns_pcie *pcie) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci int i = pcie->phy_count; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci while (i--) { 15562306a36Sopenharmony_ci phy_power_off(pcie->phy[i]); 15662306a36Sopenharmony_ci phy_exit(pcie->phy[i]); 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ciint cdns_pcie_enable_phy(struct cdns_pcie *pcie) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci int ret; 16362306a36Sopenharmony_ci int i; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci for (i = 0; i < pcie->phy_count; i++) { 16662306a36Sopenharmony_ci ret = phy_init(pcie->phy[i]); 16762306a36Sopenharmony_ci if (ret < 0) 16862306a36Sopenharmony_ci goto err_phy; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci ret = phy_power_on(pcie->phy[i]); 17162306a36Sopenharmony_ci if (ret < 0) { 17262306a36Sopenharmony_ci phy_exit(pcie->phy[i]); 17362306a36Sopenharmony_ci goto err_phy; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci return 0; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cierr_phy: 18062306a36Sopenharmony_ci while (--i >= 0) { 18162306a36Sopenharmony_ci phy_power_off(pcie->phy[i]); 18262306a36Sopenharmony_ci phy_exit(pcie->phy[i]); 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci return ret; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ciint cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci struct device_node *np = dev->of_node; 19162306a36Sopenharmony_ci int phy_count; 19262306a36Sopenharmony_ci struct phy **phy; 19362306a36Sopenharmony_ci struct device_link **link; 19462306a36Sopenharmony_ci int i; 19562306a36Sopenharmony_ci int ret; 19662306a36Sopenharmony_ci const char *name; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci phy_count = of_property_count_strings(np, "phy-names"); 19962306a36Sopenharmony_ci if (phy_count < 1) { 20062306a36Sopenharmony_ci dev_err(dev, "no phy-names. PHY will not be initialized\n"); 20162306a36Sopenharmony_ci pcie->phy_count = 0; 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci phy = devm_kcalloc(dev, phy_count, sizeof(*phy), GFP_KERNEL); 20662306a36Sopenharmony_ci if (!phy) 20762306a36Sopenharmony_ci return -ENOMEM; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci link = devm_kcalloc(dev, phy_count, sizeof(*link), GFP_KERNEL); 21062306a36Sopenharmony_ci if (!link) 21162306a36Sopenharmony_ci return -ENOMEM; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci for (i = 0; i < phy_count; i++) { 21462306a36Sopenharmony_ci of_property_read_string_index(np, "phy-names", i, &name); 21562306a36Sopenharmony_ci phy[i] = devm_phy_get(dev, name); 21662306a36Sopenharmony_ci if (IS_ERR(phy[i])) { 21762306a36Sopenharmony_ci ret = PTR_ERR(phy[i]); 21862306a36Sopenharmony_ci goto err_phy; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci link[i] = device_link_add(dev, &phy[i]->dev, DL_FLAG_STATELESS); 22162306a36Sopenharmony_ci if (!link[i]) { 22262306a36Sopenharmony_ci devm_phy_put(dev, phy[i]); 22362306a36Sopenharmony_ci ret = -EINVAL; 22462306a36Sopenharmony_ci goto err_phy; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci pcie->phy_count = phy_count; 22962306a36Sopenharmony_ci pcie->phy = phy; 23062306a36Sopenharmony_ci pcie->link = link; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci ret = cdns_pcie_enable_phy(pcie); 23362306a36Sopenharmony_ci if (ret) 23462306a36Sopenharmony_ci goto err_phy; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci return 0; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cierr_phy: 23962306a36Sopenharmony_ci while (--i >= 0) { 24062306a36Sopenharmony_ci device_link_del(link[i]); 24162306a36Sopenharmony_ci devm_phy_put(dev, phy[i]); 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return ret; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic int cdns_pcie_suspend_noirq(struct device *dev) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci struct cdns_pcie *pcie = dev_get_drvdata(dev); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci cdns_pcie_disable_phy(pcie); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return 0; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int cdns_pcie_resume_noirq(struct device *dev) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci struct cdns_pcie *pcie = dev_get_drvdata(dev); 25962306a36Sopenharmony_ci int ret; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci ret = cdns_pcie_enable_phy(pcie); 26262306a36Sopenharmony_ci if (ret) { 26362306a36Sopenharmony_ci dev_err(dev, "failed to enable phy\n"); 26462306a36Sopenharmony_ci return ret; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci return 0; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ciconst struct dev_pm_ops cdns_pcie_pm_ops = { 27162306a36Sopenharmony_ci NOIRQ_SYSTEM_SLEEP_PM_OPS(cdns_pcie_suspend_noirq, 27262306a36Sopenharmony_ci cdns_pcie_resume_noirq) 27362306a36Sopenharmony_ci}; 274