Skip to content

Commit 349b434

Browse files
committed
Merge branch 'pci/controller/dwc'
- Fix potential string truncation in dw_pcie_edma_irq_verify() (Niklas Cassel) - Don't wait for link up in DWC core if driver can detect Link Up event (Krishna chaitanya chundru) - If qcom 'global' IRQ is supported for detection of Link Up events, tell DWC core not to wait for link up (Krishna chaitanya chundru) - Update ICC and OPP votes after Link Up events (Krishna chaitanya chundru) - Use dw-rockchip dll_link_up IRQ to detect Link Up and enumerate devices so users don't have to manually rescan (Niklas Cassel) - In dw-rockchip, the 'sys' interrupt is required and detects Link Up events, so tell DWC core not to wait for link up (Niklas Cassel) - Always stop link in dw_pcie_suspend_noirq(), which is required at least for i.MX8QM to re-establish link on resume (Richard Zhu) - Drop racy and unnecessary LTSSM state check before sending PME_TURN_OFF message in dw_pcie_suspend_noirq() (Richard Zhu) - Add stubs for dw_pcie_suspend_noirq() dw_pcie_resume_noirq() when CONFIG_PCIE_DW_HOST is not defined so drivers don't need #ifdefs (Bjorn Helgaas) - Use DWC core suspend/resume functions for imx6 (Frank Li) - Add imx6 suspend/resume support for i.MX8MQ, i.MX8Q, and i.MX95 (Richard Zhu) - Add struct of_pci_range.parent_bus_addr for devices that need their immediate parent bus address, not the CPU address, e.g., to program an internal Address Translation Unit (iATU) (Frank Li) * pci/controller/dwc: PCI: dwc: Simplify config resource lookup of: address: Add parent_bus_addr to struct of_pci_range PCI: imx6: Add i.MX8MQ, i.MX8Q and i.MX95 PM support PCI: imx6: Use DWC common suspend resume method PCI: dwc: Add dw_pcie_suspend_noirq(), dw_pcie_resume_noirq() stubs for !CONFIG_PCIE_DW_HOST PCI: dwc: Remove LTSSM state test in dw_pcie_suspend_noirq() PCI: dwc: Always stop link in the dw_pcie_suspend_noirq PCI: dw-rockchip: Don't wait for link since we can detect Link Up PCI: dw-rockchip: Enumerate endpoints based on dll_link_up IRQ PCI: qcom: Update ICC and OPP values after Link Up event PCI: qcom: Don't wait for link if we can detect Link Up PCI: dwc: Don't wait for link up if driver can detect Link Up event PCI: dwc: Fix potential truncation in dw_pcie_edma_irq_verify() # Conflicts: # drivers/pci/controller/dwc/pci-imx6.c
2 parents 8ee6c61 + 1108d67 commit 349b434

File tree

8 files changed

+161
-98
lines changed

8 files changed

+161
-98
lines changed

drivers/of/address.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,8 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
815815
else
816816
range->cpu_addr = of_translate_address(parser->node,
817817
parser->range + na);
818+
819+
range->parent_bus_addr = of_read_number(parser->range + na, parser->pna);
818820
range->size = of_read_number(parser->range + parser->pna + na, ns);
819821

820822
parser->range += np;

drivers/pci/controller/dwc/pci-imx6.c

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <linux/pm_domain.h>
3434
#include <linux/pm_runtime.h>
3535

36+
#include "../../pci.h"
3637
#include "pcie-designware.h"
3738

3839
#define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9)
@@ -128,19 +129,18 @@ struct imx_pcie_drvdata {
128129
int (*init_phy)(struct imx_pcie *pcie);
129130
int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
130131
int (*core_reset)(struct imx_pcie *pcie, bool assert);
132+
const struct dw_pcie_host_ops *ops;
131133
};
132134

133135
struct imx_pcie {
134136
struct dw_pcie *pci;
135137
struct gpio_desc *reset_gpiod;
136-
bool link_is_up;
137138
struct clk_bulk_data clks[IMX_PCIE_MAX_CLKS];
138139
struct regmap *iomuxc_gpr;
139140
u16 msi_ctrl;
140141
u32 controller_id;
141142
struct reset_control *pciephy_reset;
142143
struct reset_control *apps_reset;
143-
struct reset_control *turnoff_reset;
144144
u32 tx_deemph_gen1;
145145
u32 tx_deemph_gen2_3p5db;
146146
u32 tx_deemph_gen2_6db;
@@ -928,13 +928,11 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
928928
dev_info(dev, "Link: Only Gen1 is enabled\n");
929929
}
930930

931-
imx_pcie->link_is_up = true;
932931
tmp = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
933932
dev_info(dev, "Link up, Gen%i\n", tmp & PCI_EXP_LNKSTA_CLS);
934933
return 0;
935934

936935
err_reset_phy:
937-
imx_pcie->link_is_up = false;
938936
dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
939937
dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0),
940938
dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1));
@@ -1236,9 +1234,31 @@ static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
12361234
return cpu_addr - entry->offset;
12371235
}
12381236

1237+
/*
1238+
* In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2
1239+
* register is reserved, so the generic DWC implementation of sending the
1240+
* PME_Turn_Off message using a dummy MMIO write cannot be used.
1241+
*/
1242+
static void imx_pcie_pme_turn_off(struct dw_pcie_rp *pp)
1243+
{
1244+
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
1245+
struct imx_pcie *imx_pcie = to_imx_pcie(pci);
1246+
1247+
regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_PM_TURN_OFF);
1248+
regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_PM_TURN_OFF);
1249+
1250+
usleep_range(PCIE_PME_TO_L2_TIMEOUT_US/10, PCIE_PME_TO_L2_TIMEOUT_US);
1251+
}
1252+
12391253
static const struct dw_pcie_host_ops imx_pcie_host_ops = {
12401254
.init = imx_pcie_host_init,
12411255
.deinit = imx_pcie_host_exit,
1256+
.pme_turn_off = imx_pcie_pme_turn_off,
1257+
};
1258+
1259+
static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = {
1260+
.init = imx_pcie_host_init,
1261+
.deinit = imx_pcie_host_exit,
12421262
};
12431263

12441264
static const struct dw_pcie_ops dw_pcie_ops = {
@@ -1379,43 +1399,6 @@ static int imx_add_pcie_ep(struct imx_pcie *imx_pcie,
13791399
return 0;
13801400
}
13811401

1382-
static void imx_pcie_pm_turnoff(struct imx_pcie *imx_pcie)
1383-
{
1384-
struct device *dev = imx_pcie->pci->dev;
1385-
1386-
/* Some variants have a turnoff reset in DT */
1387-
if (imx_pcie->turnoff_reset) {
1388-
reset_control_assert(imx_pcie->turnoff_reset);
1389-
reset_control_deassert(imx_pcie->turnoff_reset);
1390-
goto pm_turnoff_sleep;
1391-
}
1392-
1393-
/* Others poke directly at IOMUXC registers */
1394-
switch (imx_pcie->drvdata->variant) {
1395-
case IMX6SX:
1396-
case IMX6QP:
1397-
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
1398-
IMX6SX_GPR12_PCIE_PM_TURN_OFF,
1399-
IMX6SX_GPR12_PCIE_PM_TURN_OFF);
1400-
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
1401-
IMX6SX_GPR12_PCIE_PM_TURN_OFF, 0);
1402-
break;
1403-
default:
1404-
dev_err(dev, "PME_Turn_Off not implemented\n");
1405-
return;
1406-
}
1407-
1408-
/*
1409-
* Components with an upstream port must respond to
1410-
* PME_Turn_Off with PME_TO_Ack but we can't check.
1411-
*
1412-
* The standard recommends a 1-10ms timeout after which to
1413-
* proceed anyway as if acks were received.
1414-
*/
1415-
pm_turnoff_sleep:
1416-
usleep_range(1000, 10000);
1417-
}
1418-
14191402
static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
14201403
{
14211404
u8 offset;
@@ -1439,7 +1422,6 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
14391422
static int imx_pcie_suspend_noirq(struct device *dev)
14401423
{
14411424
struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
1442-
struct dw_pcie_rp *pp = &imx_pcie->pci->pp;
14431425

14441426
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
14451427
return 0;
@@ -1454,9 +1436,7 @@ static int imx_pcie_suspend_noirq(struct device *dev)
14541436
imx_pcie_assert_core_reset(imx_pcie);
14551437
imx_pcie->drvdata->enable_ref_clk(imx_pcie, false);
14561438
} else {
1457-
imx_pcie_pm_turnoff(imx_pcie);
1458-
imx_pcie_stop_link(imx_pcie->pci);
1459-
imx_pcie_host_exit(pp);
1439+
return dw_pcie_suspend_noirq(imx_pcie->pci);
14601440
}
14611441

14621442
return 0;
@@ -1466,7 +1446,6 @@ static int imx_pcie_resume_noirq(struct device *dev)
14661446
{
14671447
int ret;
14681448
struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
1469-
struct dw_pcie_rp *pp = &imx_pcie->pci->pp;
14701449

14711450
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
14721451
return 0;
@@ -1486,17 +1465,12 @@ static int imx_pcie_resume_noirq(struct device *dev)
14861465
ret = dw_pcie_setup_rc(&imx_pcie->pci->pp);
14871466
if (ret)
14881467
return ret;
1489-
imx_pcie_msi_save_restore(imx_pcie, false);
14901468
} else {
1491-
ret = imx_pcie_host_init(pp);
1469+
ret = dw_pcie_resume_noirq(imx_pcie->pci);
14921470
if (ret)
14931471
return ret;
1494-
imx_pcie_msi_save_restore(imx_pcie, false);
1495-
dw_pcie_setup_rc(pp);
1496-
1497-
if (imx_pcie->link_is_up)
1498-
imx_pcie_start_link(imx_pcie->pci);
14991472
}
1473+
imx_pcie_msi_save_restore(imx_pcie, false);
15001474

15011475
return 0;
15021476
}
@@ -1528,13 +1502,17 @@ static int imx_pcie_probe(struct platform_device *pdev)
15281502

15291503
pci->dev = dev;
15301504
pci->ops = &dw_pcie_ops;
1531-
pci->pp.ops = &imx_pcie_host_ops;
15321505

15331506
imx_pcie->pci = pci;
15341507
imx_pcie->drvdata = of_device_get_match_data(dev);
15351508

15361509
mutex_init(&imx_pcie->lock);
15371510

1511+
if (imx_pcie->drvdata->ops)
1512+
pci->pp.ops = imx_pcie->drvdata->ops;
1513+
else
1514+
pci->pp.ops = &imx_pcie_host_dw_pme_ops;
1515+
15381516
/* Find the PHY if one is defined, only imx7d uses it */
15391517
np = of_parse_phandle(node, "fsl,imx7d-pcie-phy", 0);
15401518
if (np) {
@@ -1604,13 +1582,6 @@ static int imx_pcie_probe(struct platform_device *pdev)
16041582
break;
16051583
}
16061584

1607-
/* Grab turnoff reset */
1608-
imx_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
1609-
if (IS_ERR(imx_pcie->turnoff_reset)) {
1610-
dev_err(dev, "Failed to get TURNOFF reset control\n");
1611-
return PTR_ERR(imx_pcie->turnoff_reset);
1612-
}
1613-
16141585
if (imx_pcie->drvdata->gpr) {
16151586
/* Grab GPR config register range */
16161587
imx_pcie->iomuxc_gpr =
@@ -1689,6 +1660,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
16891660
if (ret < 0)
16901661
return ret;
16911662
} else {
1663+
pci->pp.use_atu_msg = true;
16921664
ret = dw_pcie_host_init(&pci->pp);
16931665
if (ret < 0)
16941666
return ret;
@@ -1753,6 +1725,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
17531725
.init_phy = imx6sx_pcie_init_phy,
17541726
.enable_ref_clk = imx6sx_pcie_enable_ref_clk,
17551727
.core_reset = imx6sx_pcie_core_reset,
1728+
.ops = &imx_pcie_host_ops,
17561729
},
17571730
[IMX6QP] = {
17581731
.variant = IMX6QP,
@@ -1770,6 +1743,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
17701743
.init_phy = imx_pcie_init_phy,
17711744
.enable_ref_clk = imx6q_pcie_enable_ref_clk,
17721745
.core_reset = imx6qp_pcie_core_reset,
1746+
.ops = &imx_pcie_host_ops,
17731747
},
17741748
[IMX7D] = {
17751749
.variant = IMX7D,
@@ -1788,7 +1762,8 @@ static const struct imx_pcie_drvdata drvdata[] = {
17881762
[IMX8MQ] = {
17891763
.variant = IMX8MQ,
17901764
.flags = IMX_PCIE_FLAG_HAS_APP_RESET |
1791-
IMX_PCIE_FLAG_HAS_PHY_RESET,
1765+
IMX_PCIE_FLAG_HAS_PHY_RESET |
1766+
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
17921767
.gpr = "fsl,imx8mq-iomuxc-gpr",
17931768
.clk_names = imx8mq_clks,
17941769
.clks_cnt = ARRAY_SIZE(imx8mq_clks),
@@ -1826,14 +1801,16 @@ static const struct imx_pcie_drvdata drvdata[] = {
18261801
[IMX8Q] = {
18271802
.variant = IMX8Q,
18281803
.flags = IMX_PCIE_FLAG_HAS_PHYDRV |
1829-
IMX_PCIE_FLAG_CPU_ADDR_FIXUP,
1804+
IMX_PCIE_FLAG_CPU_ADDR_FIXUP |
1805+
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
18301806
.clk_names = imx8q_clks,
18311807
.clks_cnt = ARRAY_SIZE(imx8q_clks),
18321808
},
18331809
[IMX95] = {
18341810
.variant = IMX95,
18351811
.flags = IMX_PCIE_FLAG_HAS_SERDES |
1836-
IMX_PCIE_FLAG_HAS_LUT,
1812+
IMX_PCIE_FLAG_HAS_LUT |
1813+
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
18371814
.clk_names = imx8mq_clks,
18381815
.clks_cnt = ARRAY_SIZE(imx8mq_clks),
18391816
.ltssm_off = IMX95_PE0_GEN_CTRL_3,

drivers/pci/controller/dwc/pcie-designware-host.c

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -436,18 +436,18 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
436436
return ret;
437437

438438
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
439-
if (res) {
440-
pp->cfg0_size = resource_size(res);
441-
pp->cfg0_base = res->start;
442-
443-
pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
444-
if (IS_ERR(pp->va_cfg0_base))
445-
return PTR_ERR(pp->va_cfg0_base);
446-
} else {
447-
dev_err(dev, "Missing *config* reg space\n");
439+
if (!res) {
440+
dev_err(dev, "Missing \"config\" reg space\n");
448441
return -ENODEV;
449442
}
450443

444+
pp->cfg0_size = resource_size(res);
445+
pp->cfg0_base = res->start;
446+
447+
pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
448+
if (IS_ERR(pp->va_cfg0_base))
449+
return PTR_ERR(pp->va_cfg0_base);
450+
451451
bridge = devm_pci_alloc_host_bridge(dev, 0);
452452
if (!bridge)
453453
return -ENOMEM;
@@ -530,8 +530,14 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
530530
goto err_remove_edma;
531531
}
532532

533-
/* Ignore errors, the link may come up later */
534-
dw_pcie_wait_for_link(pci);
533+
/*
534+
* Note: Skip the link up delay only when a Link Up IRQ is present.
535+
* If there is no Link Up IRQ, we should not bypass the delay
536+
* because that would require users to manually rescan for devices.
537+
*/
538+
if (!pp->use_linkup_irq)
539+
/* Ignore errors, the link may come up later */
540+
dw_pcie_wait_for_link(pci);
535541

536542
bridge->sysdata = pp;
537543

@@ -918,7 +924,7 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
918924
{
919925
u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
920926
u32 val;
921-
int ret = 0;
927+
int ret;
922928

923929
/*
924930
* If L1SS is supported, then do not put the link into L2 as some
@@ -927,25 +933,33 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
927933
if (dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKCTL) & PCI_EXP_LNKCTL_ASPM_L1)
928934
return 0;
929935

930-
if (dw_pcie_get_ltssm(pci) <= DW_PCIE_LTSSM_DETECT_ACT)
931-
return 0;
932-
933-
if (pci->pp.ops->pme_turn_off)
936+
if (pci->pp.ops->pme_turn_off) {
934937
pci->pp.ops->pme_turn_off(&pci->pp);
935-
else
938+
} else {
936939
ret = dw_pcie_pme_turn_off(pci);
940+
if (ret)
941+
return ret;
942+
}
937943

938-
if (ret)
939-
return ret;
940-
941-
ret = read_poll_timeout(dw_pcie_get_ltssm, val, val == DW_PCIE_LTSSM_L2_IDLE,
944+
ret = read_poll_timeout(dw_pcie_get_ltssm, val,
945+
val == DW_PCIE_LTSSM_L2_IDLE ||
946+
val <= DW_PCIE_LTSSM_DETECT_WAIT,
942947
PCIE_PME_TO_L2_TIMEOUT_US/10,
943948
PCIE_PME_TO_L2_TIMEOUT_US, false, pci);
944949
if (ret) {
950+
/* Only log message when LTSSM isn't in DETECT or POLL */
945951
dev_err(pci->dev, "Timeout waiting for L2 entry! LTSSM: 0x%x\n", val);
946952
return ret;
947953
}
948954

955+
/*
956+
* Per PCIe r6.0, sec 5.3.3.2.1, software should wait at least
957+
* 100ns after L2/L3 Ready before turning off refclock and
958+
* main power. This is harmless when no endpoint is connected.
959+
*/
960+
udelay(1);
961+
962+
dw_pcie_stop_link(pci);
949963
if (pci->pp.ops->deinit)
950964
pci->pp.ops->deinit(&pci->pp);
951965

drivers/pci/controller/dwc/pcie-designware.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ static int dw_pcie_edma_irq_verify(struct dw_pcie *pci)
971971
{
972972
struct platform_device *pdev = to_platform_device(pci->dev);
973973
u16 ch_cnt = pci->edma.ll_wr_cnt + pci->edma.ll_rd_cnt;
974-
char name[6];
974+
char name[15];
975975
int ret;
976976

977977
if (pci->edma.nr_irqs == 1)

0 commit comments

Comments
 (0)