2121#include <linux/limits.h>
2222#include <linux/init.h>
2323#include <linux/of.h>
24+ #include <linux/of_pci.h>
2425#include <linux/pci.h>
26+ #include <linux/pci-ecam.h>
2527#include <linux/pm_opp.h>
2628#include <linux/pm_runtime.h>
2729#include <linux/platform_device.h>
3436#include <linux/units.h>
3537
3638#include "../../pci.h"
39+ #include "../pci-host-common.h"
3740#include "pcie-designware.h"
3841#include "pcie-qcom-common.h"
3942
@@ -255,10 +258,12 @@ struct qcom_pcie_ops {
255258 * @ops: qcom PCIe ops structure
256259 * @override_no_snoop: Override NO_SNOOP attribute in TLP to enable cache
257260 * snooping
261+ * @firmware_managed: Set if the Root Complex is firmware managed
258262 */
259263struct qcom_pcie_cfg {
260264 const struct qcom_pcie_ops * ops ;
261265 bool override_no_snoop ;
266+ bool firmware_managed ;
262267 bool no_l0s ;
263268};
264269
@@ -1426,6 +1431,10 @@ static const struct qcom_pcie_cfg cfg_sc8280xp = {
14261431 .no_l0s = true,
14271432};
14281433
1434+ static const struct qcom_pcie_cfg cfg_fw_managed = {
1435+ .firmware_managed = true,
1436+ };
1437+
14291438static const struct dw_pcie_ops dw_pcie_ops = {
14301439 .link_up = qcom_pcie_link_up ,
14311440 .start_link = qcom_pcie_start_link ,
@@ -1579,6 +1588,49 @@ static irqreturn_t qcom_pcie_global_irq_thread(int irq, void *data)
15791588 return IRQ_HANDLED ;
15801589}
15811590
1591+ static void qcom_pci_free_msi (void * ptr )
1592+ {
1593+ struct dw_pcie_rp * pp = (struct dw_pcie_rp * )ptr ;
1594+
1595+ if (pp && pp -> has_msi_ctrl )
1596+ dw_pcie_free_msi (pp );
1597+ }
1598+
1599+ static int qcom_pcie_ecam_host_init (struct pci_config_window * cfg )
1600+ {
1601+ struct device * dev = cfg -> parent ;
1602+ struct dw_pcie_rp * pp ;
1603+ struct dw_pcie * pci ;
1604+ int ret ;
1605+
1606+ pci = devm_kzalloc (dev , sizeof (* pci ), GFP_KERNEL );
1607+ if (!pci )
1608+ return - ENOMEM ;
1609+
1610+ pci -> dev = dev ;
1611+ pp = & pci -> pp ;
1612+ pci -> dbi_base = cfg -> win ;
1613+ pp -> num_vectors = MSI_DEF_NUM_VECTORS ;
1614+
1615+ ret = dw_pcie_msi_host_init (pp );
1616+ if (ret )
1617+ return ret ;
1618+
1619+ pp -> has_msi_ctrl = true;
1620+ dw_pcie_msi_init (pp );
1621+
1622+ return devm_add_action_or_reset (dev , qcom_pci_free_msi , pp );
1623+ }
1624+
1625+ static const struct pci_ecam_ops pci_qcom_ecam_ops = {
1626+ .init = qcom_pcie_ecam_host_init ,
1627+ .pci_ops = {
1628+ .map_bus = pci_ecam_map_bus ,
1629+ .read = pci_generic_config_read ,
1630+ .write = pci_generic_config_write ,
1631+ }
1632+ };
1633+
15821634static int qcom_pcie_probe (struct platform_device * pdev )
15831635{
15841636 const struct qcom_pcie_cfg * pcie_cfg ;
@@ -1593,24 +1645,62 @@ static int qcom_pcie_probe(struct platform_device *pdev)
15931645 char * name ;
15941646
15951647 pcie_cfg = of_device_get_match_data (dev );
1596- if (!pcie_cfg || ! pcie_cfg -> ops ) {
1597- dev_err (dev , "Invalid platform data\n" );
1598- return - EINVAL ;
1648+ if (!pcie_cfg ) {
1649+ dev_err (dev , "No platform data\n" );
1650+ return - ENODATA ;
15991651 }
16001652
1601- pcie = devm_kzalloc (dev , sizeof (* pcie ), GFP_KERNEL );
1602- if (!pcie )
1603- return - ENOMEM ;
1604-
1605- pci = devm_kzalloc (dev , sizeof (* pci ), GFP_KERNEL );
1606- if (!pci )
1607- return - ENOMEM ;
1653+ if (!pcie_cfg -> firmware_managed && !pcie_cfg -> ops ) {
1654+ dev_err (dev , "No platform ops\n" );
1655+ return - ENODATA ;
1656+ }
16081657
16091658 pm_runtime_enable (dev );
16101659 ret = pm_runtime_get_sync (dev );
16111660 if (ret < 0 )
16121661 goto err_pm_runtime_put ;
16131662
1663+ if (pcie_cfg -> firmware_managed ) {
1664+ struct pci_host_bridge * bridge ;
1665+ struct pci_config_window * cfg ;
1666+
1667+ bridge = devm_pci_alloc_host_bridge (dev , 0 );
1668+ if (!bridge ) {
1669+ ret = - ENOMEM ;
1670+ goto err_pm_runtime_put ;
1671+ }
1672+
1673+ /* Parse and map our ECAM configuration space area */
1674+ cfg = pci_host_common_ecam_create (dev , bridge ,
1675+ & pci_qcom_ecam_ops );
1676+ if (IS_ERR (cfg )) {
1677+ ret = PTR_ERR (cfg );
1678+ goto err_pm_runtime_put ;
1679+ }
1680+
1681+ bridge -> sysdata = cfg ;
1682+ bridge -> ops = (struct pci_ops * )& pci_qcom_ecam_ops .pci_ops ;
1683+ bridge -> msi_domain = true;
1684+
1685+ ret = pci_host_probe (bridge );
1686+ if (ret )
1687+ goto err_pm_runtime_put ;
1688+
1689+ return 0 ;
1690+ }
1691+
1692+ pcie = devm_kzalloc (dev , sizeof (* pcie ), GFP_KERNEL );
1693+ if (!pcie ) {
1694+ ret = - ENOMEM ;
1695+ goto err_pm_runtime_put ;
1696+ }
1697+
1698+ pci = devm_kzalloc (dev , sizeof (* pci ), GFP_KERNEL );
1699+ if (!pci ) {
1700+ ret = - ENOMEM ;
1701+ goto err_pm_runtime_put ;
1702+ }
1703+
16141704 pci -> dev = dev ;
16151705 pci -> ops = & dw_pcie_ops ;
16161706 pp = & pci -> pp ;
@@ -1756,9 +1846,13 @@ static int qcom_pcie_probe(struct platform_device *pdev)
17561846
17571847static int qcom_pcie_suspend_noirq (struct device * dev )
17581848{
1759- struct qcom_pcie * pcie = dev_get_drvdata ( dev ) ;
1849+ struct qcom_pcie * pcie ;
17601850 int ret = 0 ;
17611851
1852+ pcie = dev_get_drvdata (dev );
1853+ if (!pcie )
1854+ return 0 ;
1855+
17621856 /*
17631857 * Set minimum bandwidth required to keep data path functional during
17641858 * suspend.
@@ -1812,9 +1906,13 @@ static int qcom_pcie_suspend_noirq(struct device *dev)
18121906
18131907static int qcom_pcie_resume_noirq (struct device * dev )
18141908{
1815- struct qcom_pcie * pcie = dev_get_drvdata ( dev ) ;
1909+ struct qcom_pcie * pcie ;
18161910 int ret ;
18171911
1912+ pcie = dev_get_drvdata (dev );
1913+ if (!pcie )
1914+ return 0 ;
1915+
18181916 if (pm_suspend_target_state != PM_SUSPEND_MEM ) {
18191917 ret = icc_enable (pcie -> icc_cpu );
18201918 if (ret ) {
@@ -1849,6 +1947,7 @@ static const struct of_device_id qcom_pcie_match[] = {
18491947 { .compatible = "qcom,pcie-ipq9574" , .data = & cfg_2_9_0 },
18501948 { .compatible = "qcom,pcie-msm8996" , .data = & cfg_2_3_2 },
18511949 { .compatible = "qcom,pcie-qcs404" , .data = & cfg_2_4_0 },
1950+ { .compatible = "qcom,pcie-sa8255p" , .data = & cfg_fw_managed },
18521951 { .compatible = "qcom,pcie-sa8540p" , .data = & cfg_sc8280xp },
18531952 { .compatible = "qcom,pcie-sa8775p" , .data = & cfg_1_34_0 },
18541953 { .compatible = "qcom,pcie-sc7280" , .data = & cfg_1_9_0 },
0 commit comments