@@ -122,7 +122,9 @@ static const struct {
122
122
};
123
123
124
124
static void ufs_qcom_get_default_testbus_cfg (struct ufs_qcom_host * host );
125
- static int ufs_qcom_set_core_clk_ctrl (struct ufs_hba * hba , unsigned long freq );
125
+ static unsigned long ufs_qcom_opp_freq_to_clk_freq (struct ufs_hba * hba ,
126
+ unsigned long freq , char * name );
127
+ static int ufs_qcom_set_core_clk_ctrl (struct ufs_hba * hba , bool is_scale_up , unsigned long freq );
126
128
127
129
static struct ufs_qcom_host * rcdev_to_ufs_host (struct reset_controller_dev * rcd )
128
130
{
@@ -656,7 +658,7 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
656
658
return - EINVAL ;
657
659
}
658
660
659
- err = ufs_qcom_set_core_clk_ctrl (hba , ULONG_MAX );
661
+ err = ufs_qcom_set_core_clk_ctrl (hba , true, ULONG_MAX );
660
662
if (err )
661
663
dev_err (hba -> dev , "cfg core clk ctrl failed\n" );
662
664
/*
@@ -1414,29 +1416,46 @@ static int ufs_qcom_set_clk_40ns_cycles(struct ufs_hba *hba,
1414
1416
return ufshcd_dme_set (hba , UIC_ARG_MIB (PA_VS_CORE_CLK_40NS_CYCLES ), reg );
1415
1417
}
1416
1418
1417
- static int ufs_qcom_set_core_clk_ctrl (struct ufs_hba * hba , unsigned long freq )
1419
+ static int ufs_qcom_set_core_clk_ctrl (struct ufs_hba * hba , bool is_scale_up , unsigned long freq )
1418
1420
{
1419
1421
struct ufs_qcom_host * host = ufshcd_get_variant (hba );
1420
1422
struct list_head * head = & hba -> clk_list_head ;
1421
1423
struct ufs_clk_info * clki ;
1422
1424
u32 cycles_in_1us = 0 ;
1423
1425
u32 core_clk_ctrl_reg ;
1426
+ unsigned long clk_freq ;
1424
1427
int err ;
1425
1428
1429
+ if (hba -> use_pm_opp && freq != ULONG_MAX ) {
1430
+ clk_freq = ufs_qcom_opp_freq_to_clk_freq (hba , freq , "core_clk_unipro" );
1431
+ if (clk_freq ) {
1432
+ cycles_in_1us = ceil (clk_freq , HZ_PER_MHZ );
1433
+ goto set_core_clk_ctrl ;
1434
+ }
1435
+ }
1436
+
1426
1437
list_for_each_entry (clki , head , list ) {
1427
1438
if (!IS_ERR_OR_NULL (clki -> clk ) &&
1428
1439
!strcmp (clki -> name , "core_clk_unipro" )) {
1429
- if (!clki -> max_freq )
1440
+ if (!clki -> max_freq ) {
1430
1441
cycles_in_1us = 150 ; /* default for backwards compatibility */
1431
- else if (freq == ULONG_MAX )
1442
+ break ;
1443
+ }
1444
+
1445
+ if (freq == ULONG_MAX ) {
1432
1446
cycles_in_1us = ceil (clki -> max_freq , HZ_PER_MHZ );
1433
- else
1434
- cycles_in_1us = ceil ( freq , HZ_PER_MHZ );
1447
+ break ;
1448
+ }
1435
1449
1450
+ if (is_scale_up )
1451
+ cycles_in_1us = ceil (clki -> max_freq , HZ_PER_MHZ );
1452
+ else
1453
+ cycles_in_1us = ceil (clk_get_rate (clki -> clk ), HZ_PER_MHZ );
1436
1454
break ;
1437
1455
}
1438
1456
}
1439
1457
1458
+ set_core_clk_ctrl :
1440
1459
err = ufshcd_dme_get (hba ,
1441
1460
UIC_ARG_MIB (DME_VS_CORE_CLK_CTRL ),
1442
1461
& core_clk_ctrl_reg );
@@ -1479,7 +1498,7 @@ static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba, unsigned long f
1479
1498
return ret ;
1480
1499
}
1481
1500
/* set unipro core clock attributes and clear clock divider */
1482
- return ufs_qcom_set_core_clk_ctrl (hba , freq );
1501
+ return ufs_qcom_set_core_clk_ctrl (hba , true, freq );
1483
1502
}
1484
1503
1485
1504
static int ufs_qcom_clk_scale_up_post_change (struct ufs_hba * hba )
@@ -1511,7 +1530,7 @@ static int ufs_qcom_clk_scale_down_pre_change(struct ufs_hba *hba)
1511
1530
static int ufs_qcom_clk_scale_down_post_change (struct ufs_hba * hba , unsigned long freq )
1512
1531
{
1513
1532
/* set unipro core clock attributes and clear clock divider */
1514
- return ufs_qcom_set_core_clk_ctrl (hba , freq );
1533
+ return ufs_qcom_set_core_clk_ctrl (hba , false, freq );
1515
1534
}
1516
1535
1517
1536
static int ufs_qcom_clk_scale_notify (struct ufs_hba * hba , bool scale_up ,
@@ -2081,11 +2100,53 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba)
2081
2100
return ret ;
2082
2101
}
2083
2102
2103
+ static unsigned long ufs_qcom_opp_freq_to_clk_freq (struct ufs_hba * hba ,
2104
+ unsigned long freq , char * name )
2105
+ {
2106
+ struct ufs_clk_info * clki ;
2107
+ struct dev_pm_opp * opp ;
2108
+ unsigned long clk_freq ;
2109
+ int idx = 0 ;
2110
+ bool found = false;
2111
+
2112
+ opp = dev_pm_opp_find_freq_exact_indexed (hba -> dev , freq , 0 , true);
2113
+ if (IS_ERR (opp )) {
2114
+ dev_err (hba -> dev , "Failed to find OPP for exact frequency %lu\n" , freq );
2115
+ return 0 ;
2116
+ }
2117
+
2118
+ list_for_each_entry (clki , & hba -> clk_list_head , list ) {
2119
+ if (!strcmp (clki -> name , name )) {
2120
+ found = true;
2121
+ break ;
2122
+ }
2123
+
2124
+ idx ++ ;
2125
+ }
2126
+
2127
+ if (!found ) {
2128
+ dev_err (hba -> dev , "Failed to find clock '%s' in clk list\n" , name );
2129
+ dev_pm_opp_put (opp );
2130
+ return 0 ;
2131
+ }
2132
+
2133
+ clk_freq = dev_pm_opp_get_freq_indexed (opp , idx );
2134
+
2135
+ dev_pm_opp_put (opp );
2136
+
2137
+ return clk_freq ;
2138
+ }
2139
+
2084
2140
static u32 ufs_qcom_freq_to_gear_speed (struct ufs_hba * hba , unsigned long freq )
2085
2141
{
2086
2142
u32 gear = UFS_HS_DONT_CHANGE ;
2143
+ unsigned long unipro_freq ;
2144
+
2145
+ if (!hba -> use_pm_opp )
2146
+ return gear ;
2087
2147
2088
- switch (freq ) {
2148
+ unipro_freq = ufs_qcom_opp_freq_to_clk_freq (hba , freq , "core_clk_unipro" );
2149
+ switch (unipro_freq ) {
2089
2150
case 403000000 :
2090
2151
gear = UFS_HS_G5 ;
2091
2152
break ;
0 commit comments