2929#include <linux/types.h>
3030#include <linux/interrupt.h>
3131#include <linux/reset.h>
32+ #include <linux/phy/phy.h>
3233#include <linux/pm_domain.h>
3334#include <linux/pm_runtime.h>
3435
@@ -49,6 +50,7 @@ enum imx6_pcie_variants {
4950 IMX6QP ,
5051 IMX7D ,
5152 IMX8MQ ,
53+ IMX8MM ,
5254};
5355
5456#define IMX6_PCIE_FLAG_IMX6_PHY BIT(0)
@@ -88,6 +90,7 @@ struct imx6_pcie {
8890 struct device * pd_pcie ;
8991 /* power domain for pcie phy */
9092 struct device * pd_pcie_phy ;
93+ struct phy * phy ;
9194 const struct imx6_pcie_drvdata * drvdata ;
9295};
9396
@@ -372,6 +375,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
372375 case IMX7D :
373376 case IMX8MQ :
374377 reset_control_assert (imx6_pcie -> pciephy_reset );
378+ fallthrough ;
379+ case IMX8MM :
375380 reset_control_assert (imx6_pcie -> apps_reset );
376381 break ;
377382 case IMX6SX :
@@ -407,7 +412,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
407412
408413static unsigned int imx6_pcie_grp_offset (const struct imx6_pcie * imx6_pcie )
409414{
410- WARN_ON (imx6_pcie -> drvdata -> variant != IMX8MQ );
415+ WARN_ON (imx6_pcie -> drvdata -> variant != IMX8MQ &&
416+ imx6_pcie -> drvdata -> variant != IMX8MM );
411417 return imx6_pcie -> controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14 ;
412418}
413419
@@ -446,6 +452,11 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
446452 break ;
447453 case IMX7D :
448454 break ;
455+ case IMX8MM :
456+ ret = clk_prepare_enable (imx6_pcie -> pcie_aux );
457+ if (ret )
458+ dev_err (dev , "unable to enable pcie_aux clock\n" );
459+ break ;
449460 case IMX8MQ :
450461 ret = clk_prepare_enable (imx6_pcie -> pcie_aux );
451462 if (ret ) {
@@ -522,6 +533,14 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
522533 goto err_ref_clk ;
523534 }
524535
536+ switch (imx6_pcie -> drvdata -> variant ) {
537+ case IMX8MM :
538+ if (phy_power_on (imx6_pcie -> phy ))
539+ dev_err (dev , "unable to power on PHY\n" );
540+ break ;
541+ default :
542+ break ;
543+ }
525544 /* allow the clocks to stabilize */
526545 usleep_range (200 , 500 );
527546
@@ -538,6 +557,10 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
538557 case IMX8MQ :
539558 reset_control_deassert (imx6_pcie -> pciephy_reset );
540559 break ;
560+ case IMX8MM :
561+ if (phy_init (imx6_pcie -> phy ))
562+ dev_err (dev , "waiting for phy ready timeout!\n" );
563+ break ;
541564 case IMX7D :
542565 reset_control_deassert (imx6_pcie -> pciephy_reset );
543566
@@ -614,6 +637,12 @@ static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
614637static void imx6_pcie_init_phy (struct imx6_pcie * imx6_pcie )
615638{
616639 switch (imx6_pcie -> drvdata -> variant ) {
640+ case IMX8MM :
641+ /*
642+ * The PHY initialization had been done in the PHY
643+ * driver, break here directly.
644+ */
645+ break ;
617646 case IMX8MQ :
618647 /*
619648 * TODO: Currently this code assumes external
@@ -753,6 +782,7 @@ static void imx6_pcie_ltssm_enable(struct device *dev)
753782 break ;
754783 case IMX7D :
755784 case IMX8MQ :
785+ case IMX8MM :
756786 reset_control_deassert (imx6_pcie -> apps_reset );
757787 break ;
758788 }
@@ -871,6 +901,7 @@ static void imx6_pcie_ltssm_disable(struct device *dev)
871901 IMX6Q_GPR12_PCIE_CTL_2 , 0 );
872902 break ;
873903 case IMX7D :
904+ case IMX8MM :
874905 reset_control_assert (imx6_pcie -> apps_reset );
875906 break ;
876907 default :
@@ -930,6 +961,7 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
930961 IMX7D_GPR12_PCIE_PHY_REFCLK_SEL );
931962 break ;
932963 case IMX8MQ :
964+ case IMX8MM :
933965 clk_disable_unprepare (imx6_pcie -> pcie_aux );
934966 break ;
935967 default :
@@ -945,8 +977,16 @@ static int imx6_pcie_suspend_noirq(struct device *dev)
945977 return 0 ;
946978
947979 imx6_pcie_pm_turnoff (imx6_pcie );
948- imx6_pcie_clk_disable (imx6_pcie );
949980 imx6_pcie_ltssm_disable (dev );
981+ imx6_pcie_clk_disable (imx6_pcie );
982+ switch (imx6_pcie -> drvdata -> variant ) {
983+ case IMX8MM :
984+ if (phy_power_off (imx6_pcie -> phy ))
985+ dev_err (dev , "unable to power off PHY\n" );
986+ break ;
987+ default :
988+ break ;
989+ }
950990
951991 return 0 ;
952992}
@@ -1043,11 +1083,6 @@ static int imx6_pcie_probe(struct platform_device *pdev)
10431083 }
10441084
10451085 /* Fetch clocks */
1046- imx6_pcie -> pcie_phy = devm_clk_get (dev , "pcie_phy" );
1047- if (IS_ERR (imx6_pcie -> pcie_phy ))
1048- return dev_err_probe (dev , PTR_ERR (imx6_pcie -> pcie_phy ),
1049- "pcie_phy clock source missing or invalid\n" );
1050-
10511086 imx6_pcie -> pcie_bus = devm_clk_get (dev , "pcie_bus" );
10521087 if (IS_ERR (imx6_pcie -> pcie_bus ))
10531088 return dev_err_probe (dev , PTR_ERR (imx6_pcie -> pcie_bus ),
@@ -1089,10 +1124,35 @@ static int imx6_pcie_probe(struct platform_device *pdev)
10891124 dev_err (dev , "Failed to get PCIE APPS reset control\n" );
10901125 return PTR_ERR (imx6_pcie -> apps_reset );
10911126 }
1127+ break ;
1128+ case IMX8MM :
1129+ imx6_pcie -> pcie_aux = devm_clk_get (dev , "pcie_aux" );
1130+ if (IS_ERR (imx6_pcie -> pcie_aux ))
1131+ return dev_err_probe (dev , PTR_ERR (imx6_pcie -> pcie_aux ),
1132+ "pcie_aux clock source missing or invalid\n" );
1133+ imx6_pcie -> apps_reset = devm_reset_control_get_exclusive (dev ,
1134+ "apps" );
1135+ if (IS_ERR (imx6_pcie -> apps_reset ))
1136+ return dev_err_probe (dev , PTR_ERR (imx6_pcie -> apps_reset ),
1137+ "failed to get pcie apps reset control\n" );
1138+
1139+ imx6_pcie -> phy = devm_phy_get (dev , "pcie-phy" );
1140+ if (IS_ERR (imx6_pcie -> phy ))
1141+ return dev_err_probe (dev , PTR_ERR (imx6_pcie -> phy ),
1142+ "failed to get pcie phy\n" );
1143+
10921144 break ;
10931145 default :
10941146 break ;
10951147 }
1148+ /* Don't fetch the pcie_phy clock, if it has abstract PHY driver */
1149+ if (imx6_pcie -> phy == NULL ) {
1150+ imx6_pcie -> pcie_phy = devm_clk_get (dev , "pcie_phy" );
1151+ if (IS_ERR (imx6_pcie -> pcie_phy ))
1152+ return dev_err_probe (dev , PTR_ERR (imx6_pcie -> pcie_phy ),
1153+ "pcie_phy clock source missing or invalid\n" );
1154+ }
1155+
10961156
10971157 /* Grab turnoff reset */
10981158 imx6_pcie -> turnoff_reset = devm_reset_control_get_optional_exclusive (dev , "turnoff" );
@@ -1202,14 +1262,19 @@ static const struct imx6_pcie_drvdata drvdata[] = {
12021262 [IMX8MQ ] = {
12031263 .variant = IMX8MQ ,
12041264 },
1265+ [IMX8MM ] = {
1266+ .variant = IMX8MM ,
1267+ .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND ,
1268+ },
12051269};
12061270
12071271static const struct of_device_id imx6_pcie_of_match [] = {
12081272 { .compatible = "fsl,imx6q-pcie" , .data = & drvdata [IMX6Q ], },
12091273 { .compatible = "fsl,imx6sx-pcie" , .data = & drvdata [IMX6SX ], },
12101274 { .compatible = "fsl,imx6qp-pcie" , .data = & drvdata [IMX6QP ], },
12111275 { .compatible = "fsl,imx7d-pcie" , .data = & drvdata [IMX7D ], },
1212- { .compatible = "fsl,imx8mq-pcie" , .data = & drvdata [IMX8MQ ], } ,
1276+ { .compatible = "fsl,imx8mq-pcie" , .data = & drvdata [IMX8MQ ], },
1277+ { .compatible = "fsl,imx8mm-pcie" , .data = & drvdata [IMX8MM ], },
12131278 {},
12141279};
12151280
0 commit comments