|
94 | 94 | /* default delay of autosuspend: 2000 ms */
|
95 | 95 | #define RPM_AUTOSUSPEND_DELAY_MS 2000
|
96 | 96 |
|
| 97 | +/* Default delay of RPM device flush delayed work */ |
| 98 | +#define RPM_DEV_FLUSH_RECHECK_WORK_DELAY_MS 5000 |
| 99 | + |
97 | 100 | /* Default value of wait time before gating device ref clock */
|
98 | 101 | #define UFSHCD_REF_CLK_GATING_WAIT_US 0xFF /* microsecs */
|
99 | 102 |
|
@@ -5314,7 +5317,7 @@ static bool ufshcd_wb_presrv_usrspc_keep_vcc_on(struct ufs_hba *hba,
|
5314 | 5317 | return false;
|
5315 | 5318 | }
|
5316 | 5319 |
|
5317 |
| -static bool ufshcd_wb_keep_vcc_on(struct ufs_hba *hba) |
| 5320 | +static bool ufshcd_wb_need_flush(struct ufs_hba *hba) |
5318 | 5321 | {
|
5319 | 5322 | int ret;
|
5320 | 5323 | u32 avail_buf;
|
@@ -5352,6 +5355,21 @@ static bool ufshcd_wb_keep_vcc_on(struct ufs_hba *hba)
|
5352 | 5355 | return ufshcd_wb_presrv_usrspc_keep_vcc_on(hba, avail_buf);
|
5353 | 5356 | }
|
5354 | 5357 |
|
| 5358 | +static void ufshcd_rpm_dev_flush_recheck_work(struct work_struct *work) |
| 5359 | +{ |
| 5360 | + struct ufs_hba *hba = container_of(to_delayed_work(work), |
| 5361 | + struct ufs_hba, |
| 5362 | + rpm_dev_flush_recheck_work); |
| 5363 | + /* |
| 5364 | + * To prevent unnecessary VCC power drain after device finishes |
| 5365 | + * WriteBooster buffer flush or Auto BKOPs, force runtime resume |
| 5366 | + * after a certain delay to recheck the threshold by next runtime |
| 5367 | + * suspend. |
| 5368 | + */ |
| 5369 | + pm_runtime_get_sync(hba->dev); |
| 5370 | + pm_runtime_put_sync(hba->dev); |
| 5371 | +} |
| 5372 | + |
5355 | 5373 | /**
|
5356 | 5374 | * ufshcd_exception_event_handler - handle exceptions raised by device
|
5357 | 5375 | * @work: pointer to work data
|
@@ -8099,8 +8117,7 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
|
8099 | 8117 | !hba->dev_info.is_lu_power_on_wp) {
|
8100 | 8118 | ufshcd_setup_vreg(hba, false);
|
8101 | 8119 | } else if (!ufshcd_is_ufs_dev_active(hba)) {
|
8102 |
| - if (!hba->dev_info.keep_vcc_on) |
8103 |
| - ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); |
| 8120 | + ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); |
8104 | 8121 | if (!ufshcd_is_link_active(hba)) {
|
8105 | 8122 | ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
|
8106 | 8123 | ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
|
@@ -8225,27 +8242,30 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
8225 | 8242 | ufshcd_disable_auto_bkops(hba);
|
8226 | 8243 | }
|
8227 | 8244 | /*
|
8228 |
| - * With wb enabled, if the bkops is enabled or if the |
8229 |
| - * configured WB type is 70% full, keep vcc ON |
8230 |
| - * for the device to flush the wb buffer |
| 8245 | + * If device needs to do BKOP or WB buffer flush during |
| 8246 | + * Hibern8, keep device power mode as "active power mode" |
| 8247 | + * and VCC supply. |
8231 | 8248 | */
|
8232 |
| - if ((hba->auto_bkops_enabled && ufshcd_is_wb_allowed(hba)) || |
8233 |
| - ufshcd_wb_keep_vcc_on(hba)) |
8234 |
| - hba->dev_info.keep_vcc_on = true; |
8235 |
| - else |
8236 |
| - hba->dev_info.keep_vcc_on = false; |
8237 |
| - } else { |
8238 |
| - hba->dev_info.keep_vcc_on = false; |
8239 |
| - } |
| 8249 | + hba->dev_info.b_rpm_dev_flush_capable = |
| 8250 | + hba->auto_bkops_enabled || |
| 8251 | + (((req_link_state == UIC_LINK_HIBERN8_STATE) || |
| 8252 | + ((req_link_state == UIC_LINK_ACTIVE_STATE) && |
| 8253 | + ufshcd_is_auto_hibern8_enabled(hba))) && |
| 8254 | + ufshcd_wb_need_flush(hba)); |
| 8255 | + } |
| 8256 | + |
| 8257 | + if (req_dev_pwr_mode != hba->curr_dev_pwr_mode) { |
| 8258 | + if ((ufshcd_is_runtime_pm(pm_op) && !hba->auto_bkops_enabled) || |
| 8259 | + !ufshcd_is_runtime_pm(pm_op)) { |
| 8260 | + /* ensure that bkops is disabled */ |
| 8261 | + ufshcd_disable_auto_bkops(hba); |
| 8262 | + } |
8240 | 8263 |
|
8241 |
| - if ((req_dev_pwr_mode != hba->curr_dev_pwr_mode) && |
8242 |
| - ((ufshcd_is_runtime_pm(pm_op) && !hba->auto_bkops_enabled) || |
8243 |
| - !ufshcd_is_runtime_pm(pm_op))) { |
8244 |
| - /* ensure that bkops is disabled */ |
8245 |
| - ufshcd_disable_auto_bkops(hba); |
8246 |
| - ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode); |
8247 |
| - if (ret) |
8248 |
| - goto enable_gating; |
| 8264 | + if (!hba->dev_info.b_rpm_dev_flush_capable) { |
| 8265 | + ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode); |
| 8266 | + if (ret) |
| 8267 | + goto enable_gating; |
| 8268 | + } |
8249 | 8269 | }
|
8250 | 8270 |
|
8251 | 8271 | flush_work(&hba->eeh_work);
|
@@ -8298,9 +8318,16 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
8298 | 8318 | if (hba->clk_scaling.is_allowed)
|
8299 | 8319 | ufshcd_resume_clkscaling(hba);
|
8300 | 8320 | hba->clk_gating.is_suspended = false;
|
| 8321 | + hba->dev_info.b_rpm_dev_flush_capable = false; |
8301 | 8322 | ufshcd_release(hba);
|
8302 | 8323 | out:
|
| 8324 | + if (hba->dev_info.b_rpm_dev_flush_capable) { |
| 8325 | + schedule_delayed_work(&hba->rpm_dev_flush_recheck_work, |
| 8326 | + msecs_to_jiffies(RPM_DEV_FLUSH_RECHECK_WORK_DELAY_MS)); |
| 8327 | + } |
| 8328 | + |
8303 | 8329 | hba->pm_op_in_progress = 0;
|
| 8330 | + |
8304 | 8331 | if (ret)
|
8305 | 8332 | ufshcd_update_reg_hist(&hba->ufs_stats.suspend_err, (u32)ret);
|
8306 | 8333 | return ret;
|
@@ -8389,6 +8416,11 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
8389 | 8416 | /* Enable Auto-Hibernate if configured */
|
8390 | 8417 | ufshcd_auto_hibern8_enable(hba);
|
8391 | 8418 |
|
| 8419 | + if (hba->dev_info.b_rpm_dev_flush_capable) { |
| 8420 | + hba->dev_info.b_rpm_dev_flush_capable = false; |
| 8421 | + cancel_delayed_work(&hba->rpm_dev_flush_recheck_work); |
| 8422 | + } |
| 8423 | + |
8392 | 8424 | /* Schedule clock gating in case of no access to UFS device yet */
|
8393 | 8425 | ufshcd_release(hba);
|
8394 | 8426 |
|
@@ -8862,6 +8894,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
|
8862 | 8894 | UFS_SLEEP_PWR_MODE,
|
8863 | 8895 | UIC_LINK_HIBERN8_STATE);
|
8864 | 8896 |
|
| 8897 | + INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work, |
| 8898 | + ufshcd_rpm_dev_flush_recheck_work); |
| 8899 | + |
8865 | 8900 | /* Set the default auto-hiberate idle timer value to 150 ms */
|
8866 | 8901 | if (ufshcd_is_auto_hibern8_supported(hba) && !hba->ahit) {
|
8867 | 8902 | hba->ahit = FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, 150) |
|
|
0 commit comments