Skip to content

Commit a528d1a

Browse files
nxpfranklibjorn-helgaas
authored andcommitted
PCI: imx6: Use DWC common suspend resume method
Call common DWC suspend/resume function. Use DWC common iATU method to send out PME_TURN_OFF message. In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2 register is reserved, so the generic DWC implementation of sending the PME_Turn_Off message using a dummy MMIO write cannot be used. Use the previous method to kick off PME_TURN_OFF message for these platforms. The System Reset Control (SRC) interface is used to toggle 'turnoff_reset' to send PME_TURN_OFF and since the DWC implementation is used, it is not needed now. Replace the imx_pcie_stop_link() and imx_pcie_host_exit() by dw_pcie_suspend_noirq() in imx_pcie_suspend_noirq(). Since dw_pcie_suspend_noirq() already does these, see below call stack: dw_pcie_suspend_noirq() dw_pcie_stop_link() imx_pcie_stop_link() pci->pp.ops->deinit() imx_pcie_host_exit() Replace the imx_pcie_host_init(), dw_pcie_setup_rc() and imx_pcie_start_link() by dw_pcie_resume_noirq() in imx_pcie_resume_noirq(). Since dw_pcie_resume_noirq() already does these, see below call stack: dw_pcie_resume_noirq() pci->pp.ops->init() imx_pcie_host_init() dw_pcie_setup_rc() dw_pcie_start_link() imx_pcie_start_link(; Link: https://lore.kernel.org/r/20241126075702.4099164-9-hongxing.zhu@nxp.com Signed-off-by: Frank Li <Frank.Li@nxp.com> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
1 parent ec57335 commit a528d1a

File tree

1 file changed

+35
-61
lines changed

1 file changed

+35
-61
lines changed

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

Lines changed: 35 additions & 61 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)
@@ -111,19 +112,18 @@ struct imx_pcie_drvdata {
111112
int (*init_phy)(struct imx_pcie *pcie);
112113
int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
113114
int (*core_reset)(struct imx_pcie *pcie, bool assert);
115+
const struct dw_pcie_host_ops *ops;
114116
};
115117

116118
struct imx_pcie {
117119
struct dw_pcie *pci;
118120
struct gpio_desc *reset_gpiod;
119-
bool link_is_up;
120121
struct clk_bulk_data clks[IMX_PCIE_MAX_CLKS];
121122
struct regmap *iomuxc_gpr;
122123
u16 msi_ctrl;
123124
u32 controller_id;
124125
struct reset_control *pciephy_reset;
125126
struct reset_control *apps_reset;
126-
struct reset_control *turnoff_reset;
127127
u32 tx_deemph_gen1;
128128
u32 tx_deemph_gen2_3p5db;
129129
u32 tx_deemph_gen2_6db;
@@ -908,13 +908,11 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
908908
dev_info(dev, "Link: Only Gen1 is enabled\n");
909909
}
910910

911-
imx_pcie->link_is_up = true;
912911
tmp = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
913912
dev_info(dev, "Link up, Gen%i\n", tmp & PCI_EXP_LNKSTA_CLS);
914913
return 0;
915914

916915
err_reset_phy:
917-
imx_pcie->link_is_up = false;
918916
dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
919917
dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0),
920918
dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1));
@@ -1033,9 +1031,31 @@ static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
10331031
return cpu_addr - entry->offset;
10341032
}
10351033

1034+
/*
1035+
* In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2
1036+
* register is reserved, so the generic DWC implementation of sending the
1037+
* PME_Turn_Off message using a dummy MMIO write cannot be used.
1038+
*/
1039+
static void imx_pcie_pme_turn_off(struct dw_pcie_rp *pp)
1040+
{
1041+
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
1042+
struct imx_pcie *imx_pcie = to_imx_pcie(pci);
1043+
1044+
regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_PM_TURN_OFF);
1045+
regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_PM_TURN_OFF);
1046+
1047+
usleep_range(PCIE_PME_TO_L2_TIMEOUT_US/10, PCIE_PME_TO_L2_TIMEOUT_US);
1048+
}
1049+
10361050
static const struct dw_pcie_host_ops imx_pcie_host_ops = {
10371051
.init = imx_pcie_host_init,
10381052
.deinit = imx_pcie_host_exit,
1053+
.pme_turn_off = imx_pcie_pme_turn_off,
1054+
};
1055+
1056+
static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = {
1057+
.init = imx_pcie_host_init,
1058+
.deinit = imx_pcie_host_exit,
10391059
};
10401060

10411061
static const struct dw_pcie_ops dw_pcie_ops = {
@@ -1176,43 +1196,6 @@ static int imx_add_pcie_ep(struct imx_pcie *imx_pcie,
11761196
return 0;
11771197
}
11781198

1179-
static void imx_pcie_pm_turnoff(struct imx_pcie *imx_pcie)
1180-
{
1181-
struct device *dev = imx_pcie->pci->dev;
1182-
1183-
/* Some variants have a turnoff reset in DT */
1184-
if (imx_pcie->turnoff_reset) {
1185-
reset_control_assert(imx_pcie->turnoff_reset);
1186-
reset_control_deassert(imx_pcie->turnoff_reset);
1187-
goto pm_turnoff_sleep;
1188-
}
1189-
1190-
/* Others poke directly at IOMUXC registers */
1191-
switch (imx_pcie->drvdata->variant) {
1192-
case IMX6SX:
1193-
case IMX6QP:
1194-
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
1195-
IMX6SX_GPR12_PCIE_PM_TURN_OFF,
1196-
IMX6SX_GPR12_PCIE_PM_TURN_OFF);
1197-
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
1198-
IMX6SX_GPR12_PCIE_PM_TURN_OFF, 0);
1199-
break;
1200-
default:
1201-
dev_err(dev, "PME_Turn_Off not implemented\n");
1202-
return;
1203-
}
1204-
1205-
/*
1206-
* Components with an upstream port must respond to
1207-
* PME_Turn_Off with PME_TO_Ack but we can't check.
1208-
*
1209-
* The standard recommends a 1-10ms timeout after which to
1210-
* proceed anyway as if acks were received.
1211-
*/
1212-
pm_turnoff_sleep:
1213-
usleep_range(1000, 10000);
1214-
}
1215-
12161199
static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
12171200
{
12181201
u8 offset;
@@ -1236,7 +1219,6 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
12361219
static int imx_pcie_suspend_noirq(struct device *dev)
12371220
{
12381221
struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
1239-
struct dw_pcie_rp *pp = &imx_pcie->pci->pp;
12401222

12411223
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
12421224
return 0;
@@ -1251,9 +1233,7 @@ static int imx_pcie_suspend_noirq(struct device *dev)
12511233
imx_pcie_assert_core_reset(imx_pcie);
12521234
imx_pcie->drvdata->enable_ref_clk(imx_pcie, false);
12531235
} else {
1254-
imx_pcie_pm_turnoff(imx_pcie);
1255-
imx_pcie_stop_link(imx_pcie->pci);
1256-
imx_pcie_host_exit(pp);
1236+
return dw_pcie_suspend_noirq(imx_pcie->pci);
12571237
}
12581238

12591239
return 0;
@@ -1263,7 +1243,6 @@ static int imx_pcie_resume_noirq(struct device *dev)
12631243
{
12641244
int ret;
12651245
struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
1266-
struct dw_pcie_rp *pp = &imx_pcie->pci->pp;
12671246

12681247
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
12691248
return 0;
@@ -1283,17 +1262,12 @@ static int imx_pcie_resume_noirq(struct device *dev)
12831262
ret = dw_pcie_setup_rc(&imx_pcie->pci->pp);
12841263
if (ret)
12851264
return ret;
1286-
imx_pcie_msi_save_restore(imx_pcie, false);
12871265
} else {
1288-
ret = imx_pcie_host_init(pp);
1266+
ret = dw_pcie_resume_noirq(imx_pcie->pci);
12891267
if (ret)
12901268
return ret;
1291-
imx_pcie_msi_save_restore(imx_pcie, false);
1292-
dw_pcie_setup_rc(pp);
1293-
1294-
if (imx_pcie->link_is_up)
1295-
imx_pcie_start_link(imx_pcie->pci);
12961269
}
1270+
imx_pcie_msi_save_restore(imx_pcie, false);
12971271

12981272
return 0;
12991273
}
@@ -1325,11 +1299,15 @@ static int imx_pcie_probe(struct platform_device *pdev)
13251299

13261300
pci->dev = dev;
13271301
pci->ops = &dw_pcie_ops;
1328-
pci->pp.ops = &imx_pcie_host_ops;
13291302

13301303
imx_pcie->pci = pci;
13311304
imx_pcie->drvdata = of_device_get_match_data(dev);
13321305

1306+
if (imx_pcie->drvdata->ops)
1307+
pci->pp.ops = imx_pcie->drvdata->ops;
1308+
else
1309+
pci->pp.ops = &imx_pcie_host_dw_pme_ops;
1310+
13331311
/* Find the PHY if one is defined, only imx7d uses it */
13341312
np = of_parse_phandle(node, "fsl,imx7d-pcie-phy", 0);
13351313
if (np) {
@@ -1399,13 +1377,6 @@ static int imx_pcie_probe(struct platform_device *pdev)
13991377
break;
14001378
}
14011379

1402-
/* Grab turnoff reset */
1403-
imx_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
1404-
if (IS_ERR(imx_pcie->turnoff_reset)) {
1405-
dev_err(dev, "Failed to get TURNOFF reset control\n");
1406-
return PTR_ERR(imx_pcie->turnoff_reset);
1407-
}
1408-
14091380
if (imx_pcie->drvdata->gpr) {
14101381
/* Grab GPR config register range */
14111382
imx_pcie->iomuxc_gpr =
@@ -1484,6 +1455,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
14841455
if (ret < 0)
14851456
return ret;
14861457
} else {
1458+
pci->pp.use_atu_msg = true;
14871459
ret = dw_pcie_host_init(&pci->pp);
14881460
if (ret < 0)
14891461
return ret;
@@ -1548,6 +1520,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
15481520
.init_phy = imx6sx_pcie_init_phy,
15491521
.enable_ref_clk = imx6sx_pcie_enable_ref_clk,
15501522
.core_reset = imx6sx_pcie_core_reset,
1523+
.ops = &imx_pcie_host_ops,
15511524
},
15521525
[IMX6QP] = {
15531526
.variant = IMX6QP,
@@ -1565,6 +1538,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
15651538
.init_phy = imx_pcie_init_phy,
15661539
.enable_ref_clk = imx6q_pcie_enable_ref_clk,
15671540
.core_reset = imx6qp_pcie_core_reset,
1541+
.ops = &imx_pcie_host_ops,
15681542
},
15691543
[IMX7D] = {
15701544
.variant = IMX7D,

0 commit comments

Comments
 (0)