@@ -416,7 +416,7 @@ static void ufs_mtk_dbg_sel(struct ufs_hba *hba)
416416 }
417417}
418418
419- static void ufs_mtk_wait_idle_state (struct ufs_hba * hba ,
419+ static int ufs_mtk_wait_idle_state (struct ufs_hba * hba ,
420420 unsigned long retry_ms )
421421{
422422 u64 timeout , time_checked ;
@@ -452,8 +452,12 @@ static void ufs_mtk_wait_idle_state(struct ufs_hba *hba,
452452 break ;
453453 } while (time_checked < timeout );
454454
455- if (wait_idle && sm != VS_HCE_BASE )
455+ if (wait_idle && sm != VS_HCE_BASE ) {
456456 dev_info (hba -> dev , "wait idle tmo: 0x%x\n" , val );
457+ return - ETIMEDOUT ;
458+ }
459+
460+ return 0 ;
457461}
458462
459463static int ufs_mtk_wait_link_state (struct ufs_hba * hba , u32 state ,
@@ -1429,19 +1433,53 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba,
14291433 return ret ;
14301434}
14311435
1436+ static int ufs_mtk_auto_hibern8_disable (struct ufs_hba * hba )
1437+ {
1438+ int ret ;
1439+
1440+ /* disable auto-hibern8 */
1441+ ufshcd_writel (hba , 0 , REG_AUTO_HIBERNATE_IDLE_TIMER );
1442+
1443+ /* wait host return to idle state when auto-hibern8 off */
1444+ ret = ufs_mtk_wait_idle_state (hba , 5 );
1445+ if (ret )
1446+ goto out ;
1447+
1448+ ret = ufs_mtk_wait_link_state (hba , VS_LINK_UP , 100 );
1449+
1450+ out :
1451+ if (ret ) {
1452+ dev_warn (hba -> dev , "exit h8 state fail, ret=%d\n" , ret );
1453+
1454+ ufshcd_force_error_recovery (hba );
1455+
1456+ /* trigger error handler and break suspend */
1457+ ret = - EBUSY ;
1458+ }
1459+
1460+ return ret ;
1461+ }
1462+
14321463static int ufs_mtk_pwr_change_notify (struct ufs_hba * hba ,
14331464 enum ufs_notify_change_status stage ,
14341465 const struct ufs_pa_layer_attr * dev_max_params ,
14351466 struct ufs_pa_layer_attr * dev_req_params )
14361467{
14371468 int ret = 0 ;
1469+ static u32 reg ;
14381470
14391471 switch (stage ) {
14401472 case PRE_CHANGE :
1473+ if (ufshcd_is_auto_hibern8_supported (hba )) {
1474+ reg = ufshcd_readl (hba , REG_AUTO_HIBERNATE_IDLE_TIMER );
1475+ ufs_mtk_auto_hibern8_disable (hba );
1476+ }
14411477 ret = ufs_mtk_pre_pwr_change (hba , dev_max_params ,
14421478 dev_req_params );
14431479 break ;
14441480 case POST_CHANGE :
1481+ if (ufshcd_is_auto_hibern8_supported (hba ))
1482+ ufshcd_writel (hba , reg , REG_AUTO_HIBERNATE_IDLE_TIMER );
14451483 break ;
14461484 default :
14471485 ret = - EINVAL ;
@@ -1513,8 +1551,19 @@ static int ufs_mtk_pre_link(struct ufs_hba *hba)
15131551
15141552 return ret ;
15151553}
1554+
15161555static void ufs_mtk_post_link (struct ufs_hba * hba )
15171556{
1557+ struct ufs_mtk_host * host = ufshcd_get_variant (hba );
1558+ u32 tmp ;
1559+
1560+ /* fix device PA_INIT no adapt */
1561+ if (host -> ip_ver >= IP_VER_MT6899 ) {
1562+ ufshcd_dme_get (hba , UIC_ARG_MIB (VS_DEBUGOMC ), & tmp );
1563+ tmp |= 0x100 ;
1564+ ufshcd_dme_set (hba , UIC_ARG_MIB (VS_DEBUGOMC ), tmp );
1565+ }
1566+
15181567 /* enable unipro clock gating feature */
15191568 ufs_mtk_cfg_unipro_cg (hba , true);
15201569}
@@ -1584,7 +1633,11 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba)
15841633 return err ;
15851634
15861635 /* Check link state to make sure exit h8 success */
1587- ufs_mtk_wait_idle_state (hba , 5 );
1636+ err = ufs_mtk_wait_idle_state (hba , 5 );
1637+ if (err ) {
1638+ dev_warn (hba -> dev , "wait idle fail, err=%d\n" , err );
1639+ return err ;
1640+ }
15881641 err = ufs_mtk_wait_link_state (hba , VS_LINK_UP , 100 );
15891642 if (err ) {
15901643 dev_warn (hba -> dev , "exit h8 state fail, err=%d\n" , err );
@@ -1686,21 +1739,6 @@ static void ufs_mtk_dev_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
16861739 }
16871740}
16881741
1689- static void ufs_mtk_auto_hibern8_disable (struct ufs_hba * hba )
1690- {
1691- int ret ;
1692-
1693- /* disable auto-hibern8 */
1694- ufshcd_writel (hba , 0 , REG_AUTO_HIBERNATE_IDLE_TIMER );
1695-
1696- /* wait host return to idle state when auto-hibern8 off */
1697- ufs_mtk_wait_idle_state (hba , 5 );
1698-
1699- ret = ufs_mtk_wait_link_state (hba , VS_LINK_UP , 100 );
1700- if (ret )
1701- dev_warn (hba -> dev , "exit h8 state fail, ret=%d\n" , ret );
1702- }
1703-
17041742static int ufs_mtk_suspend (struct ufs_hba * hba , enum ufs_pm_op pm_op ,
17051743 enum ufs_notify_change_status status )
17061744{
@@ -1709,7 +1747,7 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
17091747
17101748 if (status == PRE_CHANGE ) {
17111749 if (ufshcd_is_auto_hibern8_supported (hba ))
1712- ufs_mtk_auto_hibern8_disable (hba );
1750+ return ufs_mtk_auto_hibern8_disable (hba );
17131751 return 0 ;
17141752 }
17151753
@@ -1767,8 +1805,21 @@ static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
17671805 }
17681806
17691807 return 0 ;
1808+
17701809fail :
1771- return ufshcd_link_recovery (hba );
1810+ /*
1811+ * Check if the platform (parent) device has resumed, and ensure that
1812+ * power, clock, and MTCMOS are all turned on.
1813+ */
1814+ err = ufshcd_link_recovery (hba );
1815+ if (err ) {
1816+ dev_err (hba -> dev , "Device PM: req=%d, status:%d, err:%d\n" ,
1817+ hba -> dev -> power .request ,
1818+ hba -> dev -> power .runtime_status ,
1819+ hba -> dev -> power .runtime_error );
1820+ }
1821+
1822+ return 0 ; /* Cannot return a failure, otherwise, the I/O will hang. */
17721823}
17731824
17741825static void ufs_mtk_dbg_register_dump (struct ufs_hba * hba )
@@ -2139,6 +2190,7 @@ static int ufs_mtk_config_mcq_irq(struct ufs_hba *hba)
21392190 return ret ;
21402191 }
21412192 }
2193+ host -> is_mcq_intr_enabled = true;
21422194
21432195 return 0 ;
21442196}
@@ -2222,10 +2274,12 @@ static const struct ufs_hba_variant_ops ufs_hba_mtk_vops = {
22222274static int ufs_mtk_probe (struct platform_device * pdev )
22232275{
22242276 int err ;
2225- struct device * dev = & pdev -> dev ;
2226- struct device_node * reset_node ;
2227- struct platform_device * reset_pdev ;
2277+ struct device * dev = & pdev -> dev , * phy_dev = NULL ;
2278+ struct device_node * reset_node , * phy_node = NULL ;
2279+ struct platform_device * reset_pdev , * phy_pdev = NULL ;
22282280 struct device_link * link ;
2281+ struct ufs_hba * hba ;
2282+ struct ufs_mtk_host * host ;
22292283
22302284 reset_node = of_find_compatible_node (NULL , NULL ,
22312285 "ti,syscon-reset" );
@@ -2252,13 +2306,51 @@ static int ufs_mtk_probe(struct platform_device *pdev)
22522306 }
22532307
22542308skip_reset :
2309+ /* find phy node */
2310+ phy_node = of_parse_phandle (dev -> of_node , "phys" , 0 );
2311+
2312+ if (phy_node ) {
2313+ phy_pdev = of_find_device_by_node (phy_node );
2314+ if (!phy_pdev )
2315+ goto skip_phy ;
2316+ phy_dev = & phy_pdev -> dev ;
2317+
2318+ pm_runtime_set_active (phy_dev );
2319+ pm_runtime_enable (phy_dev );
2320+ pm_runtime_get_sync (phy_dev );
2321+
2322+ put_device (phy_dev );
2323+ dev_info (dev , "phys node found\n" );
2324+ } else {
2325+ dev_notice (dev , "phys node not found\n" );
2326+ }
2327+
2328+ skip_phy :
22552329 /* perform generic probe */
22562330 err = ufshcd_pltfrm_init (pdev , & ufs_hba_mtk_vops );
2257-
2258- out :
2259- if (err )
2331+ if (err ) {
22602332 dev_err (dev , "probe failed %d\n" , err );
2333+ goto out ;
2334+ }
2335+
2336+ hba = platform_get_drvdata (pdev );
2337+ if (!hba )
2338+ goto out ;
2339+
2340+ if (phy_node && phy_dev ) {
2341+ host = ufshcd_get_variant (hba );
2342+ host -> phy_dev = phy_dev ;
2343+ }
22612344
2345+ /*
2346+ * Because the default power setting of VSx (the upper layer of
2347+ * VCCQ/VCCQ2) is HWLP, we need to prevent VCCQ/VCCQ2 from
2348+ * entering LPM.
2349+ */
2350+ ufs_mtk_dev_vreg_set_lpm (hba , false);
2351+
2352+ out :
2353+ of_node_put (phy_node );
22622354 of_node_put (reset_node );
22632355 return err ;
22642356}
@@ -2283,34 +2375,46 @@ static int ufs_mtk_system_suspend(struct device *dev)
22832375
22842376 ret = ufshcd_system_suspend (dev );
22852377 if (ret )
2286- return ret ;
2378+ goto out ;
2379+
2380+ if (pm_runtime_suspended (hba -> dev ))
2381+ goto out ;
22872382
22882383 ufs_mtk_dev_vreg_set_lpm (hba , true);
22892384
22902385 if (ufs_mtk_is_rtff_mtcmos (hba ))
22912386 ufs_mtk_mtcmos_ctrl (false, res );
22922387
2293- return 0 ;
2388+ out :
2389+ return ret ;
22942390}
22952391
22962392static int ufs_mtk_system_resume (struct device * dev )
22972393{
2394+ int ret = 0 ;
22982395 struct ufs_hba * hba = dev_get_drvdata (dev );
22992396 struct arm_smccc_res res ;
23002397
2301- ufs_mtk_dev_vreg_set_lpm (hba , false);
2398+ if (pm_runtime_suspended (hba -> dev ))
2399+ goto out ;
23022400
23032401 if (ufs_mtk_is_rtff_mtcmos (hba ))
23042402 ufs_mtk_mtcmos_ctrl (true, res );
23052403
2306- return ufshcd_system_resume (dev );
2404+ ufs_mtk_dev_vreg_set_lpm (hba , false);
2405+
2406+ out :
2407+ ret = ufshcd_system_resume (dev );
2408+
2409+ return ret ;
23072410}
23082411#endif
23092412
23102413#ifdef CONFIG_PM
23112414static int ufs_mtk_runtime_suspend (struct device * dev )
23122415{
23132416 struct ufs_hba * hba = dev_get_drvdata (dev );
2417+ struct ufs_mtk_host * host = ufshcd_get_variant (hba );
23142418 struct arm_smccc_res res ;
23152419 int ret = 0 ;
23162420
@@ -2323,17 +2427,24 @@ static int ufs_mtk_runtime_suspend(struct device *dev)
23232427 if (ufs_mtk_is_rtff_mtcmos (hba ))
23242428 ufs_mtk_mtcmos_ctrl (false, res );
23252429
2430+ if (host -> phy_dev )
2431+ pm_runtime_put_sync (host -> phy_dev );
2432+
23262433 return 0 ;
23272434}
23282435
23292436static int ufs_mtk_runtime_resume (struct device * dev )
23302437{
23312438 struct ufs_hba * hba = dev_get_drvdata (dev );
2439+ struct ufs_mtk_host * host = ufshcd_get_variant (hba );
23322440 struct arm_smccc_res res ;
23332441
23342442 if (ufs_mtk_is_rtff_mtcmos (hba ))
23352443 ufs_mtk_mtcmos_ctrl (true, res );
23362444
2445+ if (host -> phy_dev )
2446+ pm_runtime_get_sync (host -> phy_dev );
2447+
23372448 ufs_mtk_dev_vreg_set_lpm (hba , false);
23382449
23392450 return ufshcd_runtime_resume (dev );
0 commit comments