Skip to content

Commit a1af5d2

Browse files
petegriffinvinodkoul
authored andcommitted
phy: samsung: gs101-ufs: Add .notify_phystate() & hibern8 enter/exit values
Implement the .notify_phystate() callback and provide the gs101 specific phy values that need to be programmed when entering and exiting the hibern8 state. Signed-off-by: Peter Griffin <peter.griffin@linaro.org> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> Link: https://patch.msgid.link/20251112-phy-notify-pmstate-v5-2-39df622d8fcb@linaro.org Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 4edf654 commit a1af5d2

3 files changed

Lines changed: 75 additions & 0 deletions

File tree

drivers/phy/samsung/phy-gs101-ufs.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,39 @@ static const struct samsung_ufs_phy_cfg tensor_gs101_post_pwr_hs_config[] = {
108108
END_UFS_PHY_CFG,
109109
};
110110

111+
static const struct samsung_ufs_phy_cfg tensor_gs101_post_h8_enter[] = {
112+
PHY_TRSV_REG_CFG_GS101(0x262, 0x08, PWR_MODE_ANY),
113+
PHY_TRSV_REG_CFG_GS101(0x265, 0x0A, PWR_MODE_ANY),
114+
PHY_COMN_REG_CFG(0x1, 0x8, PWR_MODE_ANY),
115+
PHY_COMN_REG_CFG(0x0, 0x86, PWR_MODE_ANY),
116+
PHY_COMN_REG_CFG(0x8, 0x60, PWR_MODE_HS_ANY),
117+
PHY_TRSV_REG_CFG_GS101(0x222, 0x08, PWR_MODE_HS_ANY),
118+
PHY_TRSV_REG_CFG_GS101(0x246, 0x01, PWR_MODE_HS_ANY),
119+
END_UFS_PHY_CFG,
120+
};
121+
122+
static const struct samsung_ufs_phy_cfg tensor_gs101_pre_h8_exit[] = {
123+
PHY_COMN_REG_CFG(0x0, 0xC6, PWR_MODE_ANY),
124+
PHY_COMN_REG_CFG(0x1, 0x0C, PWR_MODE_ANY),
125+
PHY_TRSV_REG_CFG_GS101(0x262, 0x00, PWR_MODE_ANY),
126+
PHY_TRSV_REG_CFG_GS101(0x265, 0x00, PWR_MODE_ANY),
127+
PHY_COMN_REG_CFG(0x8, 0xE0, PWR_MODE_HS_ANY),
128+
PHY_TRSV_REG_CFG_GS101(0x246, 0x03, PWR_MODE_HS_ANY),
129+
PHY_TRSV_REG_CFG_GS101(0x222, 0x18, PWR_MODE_HS_ANY),
130+
END_UFS_PHY_CFG,
131+
};
132+
111133
static const struct samsung_ufs_phy_cfg *tensor_gs101_ufs_phy_cfgs[CFG_TAG_MAX] = {
112134
[CFG_PRE_INIT] = tensor_gs101_pre_init_cfg,
113135
[CFG_PRE_PWR_HS] = tensor_gs101_pre_pwr_hs_config,
114136
[CFG_POST_PWR_HS] = tensor_gs101_post_pwr_hs_config,
115137
};
116138

139+
static const struct samsung_ufs_phy_cfg *tensor_gs101_hibern8_cfgs[] = {
140+
[CFG_POST_HIBERN8_ENTER] = tensor_gs101_post_h8_enter,
141+
[CFG_PRE_HIBERN8_EXIT] = tensor_gs101_pre_h8_exit,
142+
};
143+
117144
static const char * const tensor_gs101_ufs_phy_clks[] = {
118145
"ref_clk",
119146
};
@@ -170,6 +197,7 @@ static int gs101_phy_wait_for_cdr_lock(struct phy *phy, u8 lane)
170197

171198
const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy = {
172199
.cfgs = tensor_gs101_ufs_phy_cfgs,
200+
.cfgs_hibern8 = tensor_gs101_hibern8_cfgs,
173201
.isol = {
174202
.offset = TENSOR_GS101_PHY_CTRL,
175203
.mask = TENSOR_GS101_PHY_CTRL_MASK,

drivers/phy/samsung/phy-samsung-ufs.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,44 @@ static int samsung_ufs_phy_set_mode(struct phy *generic_phy,
217217
return 0;
218218
}
219219

220+
static int samsung_ufs_phy_notify_state(struct phy *phy,
221+
union phy_notify state)
222+
{
223+
struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy);
224+
const struct samsung_ufs_phy_cfg *cfg;
225+
int i, err = -EINVAL;
226+
227+
if (!ufs_phy->cfgs_hibern8)
228+
return 0;
229+
230+
if (state.ufs_state == PHY_UFS_HIBERN8_ENTER)
231+
cfg = ufs_phy->cfgs_hibern8[CFG_POST_HIBERN8_ENTER];
232+
else if (state.ufs_state == PHY_UFS_HIBERN8_EXIT)
233+
cfg = ufs_phy->cfgs_hibern8[CFG_PRE_HIBERN8_EXIT];
234+
else
235+
goto err_out;
236+
237+
for_each_phy_cfg(cfg) {
238+
for_each_phy_lane(ufs_phy, i) {
239+
samsung_ufs_phy_config(ufs_phy, cfg, i);
240+
}
241+
}
242+
243+
if (state.ufs_state == PHY_UFS_HIBERN8_EXIT) {
244+
for_each_phy_lane(ufs_phy, i) {
245+
if (ufs_phy->drvdata->wait_for_cdr) {
246+
err = ufs_phy->drvdata->wait_for_cdr(phy, i);
247+
if (err)
248+
goto err_out;
249+
}
250+
}
251+
}
252+
253+
return 0;
254+
err_out:
255+
return err;
256+
}
257+
220258
static int samsung_ufs_phy_exit(struct phy *phy)
221259
{
222260
struct samsung_ufs_phy *ss_phy = get_samsung_ufs_phy(phy);
@@ -233,6 +271,7 @@ static const struct phy_ops samsung_ufs_phy_ops = {
233271
.power_off = samsung_ufs_phy_power_off,
234272
.calibrate = samsung_ufs_phy_calibrate,
235273
.set_mode = samsung_ufs_phy_set_mode,
274+
.notify_phystate = samsung_ufs_phy_notify_state,
236275
.owner = THIS_MODULE,
237276
};
238277

@@ -287,6 +326,7 @@ static int samsung_ufs_phy_probe(struct platform_device *pdev)
287326
phy->dev = dev;
288327
phy->drvdata = drvdata;
289328
phy->cfgs = drvdata->cfgs;
329+
phy->cfgs_hibern8 = drvdata->cfgs_hibern8;
290330
memcpy(&phy->isol, &drvdata->isol, sizeof(phy->isol));
291331

292332
if (!of_property_read_u32_index(dev->of_node, "samsung,pmu-syscon", 1,

drivers/phy/samsung/phy-samsung-ufs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ enum {
9292
CFG_TAG_MAX,
9393
};
9494

95+
enum {
96+
CFG_POST_HIBERN8_ENTER,
97+
CFG_PRE_HIBERN8_EXIT,
98+
};
99+
95100
struct samsung_ufs_phy_cfg {
96101
u32 off_0;
97102
u32 off_1;
@@ -108,6 +113,7 @@ struct samsung_ufs_phy_pmu_isol {
108113

109114
struct samsung_ufs_phy_drvdata {
110115
const struct samsung_ufs_phy_cfg **cfgs;
116+
const struct samsung_ufs_phy_cfg **cfgs_hibern8;
111117
struct samsung_ufs_phy_pmu_isol isol;
112118
const char * const *clk_list;
113119
int num_clks;
@@ -124,6 +130,7 @@ struct samsung_ufs_phy {
124130
struct clk_bulk_data *clks;
125131
const struct samsung_ufs_phy_drvdata *drvdata;
126132
const struct samsung_ufs_phy_cfg * const *cfgs;
133+
const struct samsung_ufs_phy_cfg * const *cfgs_hibern8;
127134
struct samsung_ufs_phy_pmu_isol isol;
128135
u8 lane_cnt;
129136
int ufs_phy_state;

0 commit comments

Comments
 (0)