Skip to content

Commit a53dfc0

Browse files
Nitin Rawatmartinkpetersen
authored andcommitted
scsi: ufs: qcom: Add support to configure PA_VS_CORE_CLK_40NS_CYCLES
PA_VS_CORE_CLK_40NS_CYCLES attribute represents the required number of Qunipro core clock for 40 nanoseconds. For UFS host controller V4 and above PA_VS_CORE_CLK_40NS_CYCLES needs to be programmed as per frequency of unipro core clk of UFS host controller. Add Support to configure PA_VS_CORE_CLK_40NS_CYCLES for Controller V4 and above to align with the hardware specification and to avoid functionality issues like h8 enter/exit failure, command timeout. Co-developed-by: Naveen Kumar Goud Arepalli <[email protected]> Signed-off-by: Naveen Kumar Goud Arepalli <[email protected]> Signed-off-by: Nitin Rawat <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Can Guo <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent b4e13e1 commit a53dfc0

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

drivers/ufs/host/ufs-qcom.c

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,77 @@ static void ufs_qcom_exit(struct ufs_hba *hba)
12921292
phy_exit(host->generic_phy);
12931293
}
12941294

1295+
/**
1296+
* ufs_qcom_set_clk_40ns_cycles - Configure 40ns clk cycles
1297+
*
1298+
* @hba: host controller instance
1299+
* @cycles_in_1us: No of cycles in 1us to be configured
1300+
*
1301+
* Returns error if dme get/set configuration for 40ns fails
1302+
* and returns zero on success.
1303+
*/
1304+
static int ufs_qcom_set_clk_40ns_cycles(struct ufs_hba *hba,
1305+
u32 cycles_in_1us)
1306+
{
1307+
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
1308+
u32 cycles_in_40ns;
1309+
u32 reg;
1310+
int err;
1311+
1312+
/*
1313+
* UFS host controller V4.0.0 onwards needs to program
1314+
* PA_VS_CORE_CLK_40NS_CYCLES attribute per programmed
1315+
* frequency of unipro core clk of UFS host controller.
1316+
*/
1317+
if (host->hw_ver.major < 4)
1318+
return 0;
1319+
1320+
/*
1321+
* Generic formulae for cycles_in_40ns = (freq_unipro/25) is not
1322+
* applicable for all frequencies. For ex: ceil(37.5 MHz/25) will
1323+
* be 2 and ceil(403 MHZ/25) will be 17 whereas Hardware
1324+
* specification expect to be 16. Hence use exact hardware spec
1325+
* mandated value for cycles_in_40ns instead of calculating using
1326+
* generic formulae.
1327+
*/
1328+
switch (cycles_in_1us) {
1329+
case UNIPRO_CORE_CLK_FREQ_403_MHZ:
1330+
cycles_in_40ns = 16;
1331+
break;
1332+
case UNIPRO_CORE_CLK_FREQ_300_MHZ:
1333+
cycles_in_40ns = 12;
1334+
break;
1335+
case UNIPRO_CORE_CLK_FREQ_201_5_MHZ:
1336+
cycles_in_40ns = 8;
1337+
break;
1338+
case UNIPRO_CORE_CLK_FREQ_150_MHZ:
1339+
cycles_in_40ns = 6;
1340+
break;
1341+
case UNIPRO_CORE_CLK_FREQ_100_MHZ:
1342+
cycles_in_40ns = 4;
1343+
break;
1344+
case UNIPRO_CORE_CLK_FREQ_75_MHZ:
1345+
cycles_in_40ns = 3;
1346+
break;
1347+
case UNIPRO_CORE_CLK_FREQ_37_5_MHZ:
1348+
cycles_in_40ns = 2;
1349+
break;
1350+
default:
1351+
dev_err(hba->dev, "UNIPRO clk freq %u MHz not supported\n",
1352+
cycles_in_1us);
1353+
return -EINVAL;
1354+
}
1355+
1356+
err = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_VS_CORE_CLK_40NS_CYCLES), &reg);
1357+
if (err)
1358+
return err;
1359+
1360+
reg &= ~PA_VS_CORE_CLK_40NS_CYCLES_MASK;
1361+
reg |= cycles_in_40ns;
1362+
1363+
return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_VS_CORE_CLK_40NS_CYCLES), reg);
1364+
}
1365+
12951366
static int ufs_qcom_set_core_clk_ctrl(struct ufs_hba *hba, bool is_scale_up)
12961367
{
12971368
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -1334,9 +1405,14 @@ static int ufs_qcom_set_core_clk_ctrl(struct ufs_hba *hba, bool is_scale_up)
13341405
/* Clear CORE_CLK_DIV_EN */
13351406
core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT;
13361407

1337-
return ufshcd_dme_set(hba,
1408+
err = ufshcd_dme_set(hba,
13381409
UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
13391410
core_clk_ctrl_reg);
1411+
if (err)
1412+
return err;
1413+
1414+
/* Configure unipro core clk 40ns attribute */
1415+
return ufs_qcom_set_clk_40ns_cycles(hba, cycles_in_1us);
13401416
}
13411417

13421418
static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba)

drivers/ufs/host/ufs-qcom.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,18 @@ enum {
132132
#define CLK_1US_CYCLES_MASK_V4 GENMASK(27, 16)
133133
#define CLK_1US_CYCLES_MASK GENMASK(7, 0)
134134
#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8)
135+
#define PA_VS_CORE_CLK_40NS_CYCLES 0x9007
136+
#define PA_VS_CORE_CLK_40NS_CYCLES_MASK GENMASK(6, 0)
137+
138+
139+
/* QCOM UFS host controller core clk frequencies */
140+
#define UNIPRO_CORE_CLK_FREQ_37_5_MHZ 38
141+
#define UNIPRO_CORE_CLK_FREQ_75_MHZ 75
142+
#define UNIPRO_CORE_CLK_FREQ_100_MHZ 100
143+
#define UNIPRO_CORE_CLK_FREQ_150_MHZ 150
144+
#define UNIPRO_CORE_CLK_FREQ_300_MHZ 300
145+
#define UNIPRO_CORE_CLK_FREQ_201_5_MHZ 202
146+
#define UNIPRO_CORE_CLK_FREQ_403_MHZ 403
135147

136148
static inline void
137149
ufs_qcom_get_controller_revision(struct ufs_hba *hba,

0 commit comments

Comments
 (0)