21
21
#include <linux/limits.h>
22
22
#include <linux/init.h>
23
23
#include <linux/of.h>
24
+ #include <linux/of_pci.h>
24
25
#include <linux/pci.h>
26
+ #include <linux/pci-ecam.h>
25
27
#include <linux/pm_opp.h>
26
28
#include <linux/pm_runtime.h>
27
29
#include <linux/platform_device.h>
34
36
#include <linux/units.h>
35
37
36
38
#include "../../pci.h"
39
+ #include "../pci-host-common.h"
37
40
#include "pcie-designware.h"
38
41
#include "pcie-qcom-common.h"
39
42
@@ -255,10 +258,12 @@ struct qcom_pcie_ops {
255
258
* @ops: qcom PCIe ops structure
256
259
* @override_no_snoop: Override NO_SNOOP attribute in TLP to enable cache
257
260
* snooping
261
+ * @firmware_managed: Set if the Root Complex is firmware managed
258
262
*/
259
263
struct qcom_pcie_cfg {
260
264
const struct qcom_pcie_ops * ops ;
261
265
bool override_no_snoop ;
266
+ bool firmware_managed ;
262
267
bool no_l0s ;
263
268
};
264
269
@@ -1426,6 +1431,10 @@ static const struct qcom_pcie_cfg cfg_sc8280xp = {
1426
1431
.no_l0s = true,
1427
1432
};
1428
1433
1434
+ static const struct qcom_pcie_cfg cfg_fw_managed = {
1435
+ .firmware_managed = true,
1436
+ };
1437
+
1429
1438
static const struct dw_pcie_ops dw_pcie_ops = {
1430
1439
.link_up = qcom_pcie_link_up ,
1431
1440
.start_link = qcom_pcie_start_link ,
@@ -1579,6 +1588,49 @@ static irqreturn_t qcom_pcie_global_irq_thread(int irq, void *data)
1579
1588
return IRQ_HANDLED ;
1580
1589
}
1581
1590
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
+
1582
1634
static int qcom_pcie_probe (struct platform_device * pdev )
1583
1635
{
1584
1636
const struct qcom_pcie_cfg * pcie_cfg ;
@@ -1593,24 +1645,62 @@ static int qcom_pcie_probe(struct platform_device *pdev)
1593
1645
char * name ;
1594
1646
1595
1647
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 ;
1599
1651
}
1600
1652
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
+ }
1608
1657
1609
1658
pm_runtime_enable (dev );
1610
1659
ret = pm_runtime_get_sync (dev );
1611
1660
if (ret < 0 )
1612
1661
goto err_pm_runtime_put ;
1613
1662
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
+
1614
1704
pci -> dev = dev ;
1615
1705
pci -> ops = & dw_pcie_ops ;
1616
1706
pp = & pci -> pp ;
@@ -1756,9 +1846,13 @@ static int qcom_pcie_probe(struct platform_device *pdev)
1756
1846
1757
1847
static int qcom_pcie_suspend_noirq (struct device * dev )
1758
1848
{
1759
- struct qcom_pcie * pcie = dev_get_drvdata ( dev ) ;
1849
+ struct qcom_pcie * pcie ;
1760
1850
int ret = 0 ;
1761
1851
1852
+ pcie = dev_get_drvdata (dev );
1853
+ if (!pcie )
1854
+ return 0 ;
1855
+
1762
1856
/*
1763
1857
* Set minimum bandwidth required to keep data path functional during
1764
1858
* suspend.
@@ -1812,9 +1906,13 @@ static int qcom_pcie_suspend_noirq(struct device *dev)
1812
1906
1813
1907
static int qcom_pcie_resume_noirq (struct device * dev )
1814
1908
{
1815
- struct qcom_pcie * pcie = dev_get_drvdata ( dev ) ;
1909
+ struct qcom_pcie * pcie ;
1816
1910
int ret ;
1817
1911
1912
+ pcie = dev_get_drvdata (dev );
1913
+ if (!pcie )
1914
+ return 0 ;
1915
+
1818
1916
if (pm_suspend_target_state != PM_SUSPEND_MEM ) {
1819
1917
ret = icc_enable (pcie -> icc_cpu );
1820
1918
if (ret ) {
@@ -1849,6 +1947,7 @@ static const struct of_device_id qcom_pcie_match[] = {
1849
1947
{ .compatible = "qcom,pcie-ipq9574" , .data = & cfg_2_9_0 },
1850
1948
{ .compatible = "qcom,pcie-msm8996" , .data = & cfg_2_3_2 },
1851
1949
{ .compatible = "qcom,pcie-qcs404" , .data = & cfg_2_4_0 },
1950
+ { .compatible = "qcom,pcie-sa8255p" , .data = & cfg_fw_managed },
1852
1951
{ .compatible = "qcom,pcie-sa8540p" , .data = & cfg_sc8280xp },
1853
1952
{ .compatible = "qcom,pcie-sa8775p" , .data = & cfg_1_34_0 },
1854
1953
{ .compatible = "qcom,pcie-sc7280" , .data = & cfg_1_9_0 },
0 commit comments