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
116118struct 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
916915err_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+
10361050static 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
10411061static 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-
12161199static 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)
12361219static 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