|
99 | 99 | /* Polling time to wait for fDeviceInit */
|
100 | 100 | #define FDEVICEINIT_COMPL_TIMEOUT 1500 /* millisecs */
|
101 | 101 |
|
| 102 | +/* Default RTC update every 10 seconds */ |
| 103 | +#define UFS_RTC_UPDATE_INTERVAL_MS (10 * MSEC_PER_SEC) |
| 104 | + |
102 | 105 | /* UFSHC 4.0 compliant HC support this mode. */
|
103 | 106 | static bool use_mcq_mode = true;
|
104 | 107 |
|
@@ -683,6 +686,8 @@ static void ufshcd_device_reset(struct ufs_hba *hba)
|
683 | 686 | hba->dev_info.wb_enabled = false;
|
684 | 687 | hba->dev_info.wb_buf_flush_enabled = false;
|
685 | 688 | }
|
| 689 | + if (hba->dev_info.rtc_type == UFS_RTC_RELATIVE) |
| 690 | + hba->dev_info.rtc_time_baseline = 0; |
686 | 691 | }
|
687 | 692 | if (err != -EOPNOTSUPP)
|
688 | 693 | ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, err);
|
@@ -8188,6 +8193,72 @@ static void ufs_fixup_device_setup(struct ufs_hba *hba)
|
8188 | 8193 | ufshcd_vops_fixup_dev_quirks(hba);
|
8189 | 8194 | }
|
8190 | 8195 |
|
| 8196 | +static void ufshcd_update_rtc(struct ufs_hba *hba) |
| 8197 | +{ |
| 8198 | + struct timespec64 ts64; |
| 8199 | + int err; |
| 8200 | + u32 val; |
| 8201 | + |
| 8202 | + ktime_get_real_ts64(&ts64); |
| 8203 | + |
| 8204 | + if (ts64.tv_sec < hba->dev_info.rtc_time_baseline) { |
| 8205 | + dev_warn_once(hba->dev, "%s: Current time precedes previous setting!\n", __func__); |
| 8206 | + return; |
| 8207 | + } |
| 8208 | + |
| 8209 | + /* |
| 8210 | + * The Absolute RTC mode has a 136-year limit, spanning from 2010 to 2146. If a time beyond |
| 8211 | + * 2146 is required, it is recommended to choose the relative RTC mode. |
| 8212 | + */ |
| 8213 | + val = ts64.tv_sec - hba->dev_info.rtc_time_baseline; |
| 8214 | + |
| 8215 | + ufshcd_rpm_get_sync(hba); |
| 8216 | + err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_SECONDS_PASSED, |
| 8217 | + 0, 0, &val); |
| 8218 | + ufshcd_rpm_put_sync(hba); |
| 8219 | + |
| 8220 | + if (err) |
| 8221 | + dev_err(hba->dev, "%s: Failed to update rtc %d\n", __func__, err); |
| 8222 | + else if (hba->dev_info.rtc_type == UFS_RTC_RELATIVE) |
| 8223 | + hba->dev_info.rtc_time_baseline = ts64.tv_sec; |
| 8224 | +} |
| 8225 | + |
| 8226 | +static void ufshcd_rtc_work(struct work_struct *work) |
| 8227 | +{ |
| 8228 | + struct ufs_hba *hba; |
| 8229 | + |
| 8230 | + hba = container_of(to_delayed_work(work), struct ufs_hba, ufs_rtc_update_work); |
| 8231 | + |
| 8232 | + /* Update RTC only when there are no requests in progress and UFSHCI is operational */ |
| 8233 | + if (!ufshcd_is_ufs_dev_busy(hba) && hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) |
| 8234 | + ufshcd_update_rtc(hba); |
| 8235 | + |
| 8236 | + if (ufshcd_is_ufs_dev_active(hba)) |
| 8237 | + schedule_delayed_work(&hba->ufs_rtc_update_work, |
| 8238 | + msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS)); |
| 8239 | +} |
| 8240 | + |
| 8241 | +static void ufs_init_rtc(struct ufs_hba *hba, u8 *desc_buf) |
| 8242 | +{ |
| 8243 | + u16 periodic_rtc_update = get_unaligned_be16(&desc_buf[DEVICE_DESC_PARAM_FRQ_RTC]); |
| 8244 | + struct ufs_dev_info *dev_info = &hba->dev_info; |
| 8245 | + |
| 8246 | + if (periodic_rtc_update & UFS_RTC_TIME_BASELINE) { |
| 8247 | + dev_info->rtc_type = UFS_RTC_ABSOLUTE; |
| 8248 | + |
| 8249 | + /* |
| 8250 | + * The concept of measuring time in Linux as the number of seconds elapsed since |
| 8251 | + * 00:00:00 UTC on January 1, 1970, and UFS ABS RTC is elapsed from January 1st |
| 8252 | + * 2010 00:00, here we need to adjust ABS baseline. |
| 8253 | + */ |
| 8254 | + dev_info->rtc_time_baseline = mktime64(2010, 1, 1, 0, 0, 0) - |
| 8255 | + mktime64(1970, 1, 1, 0, 0, 0); |
| 8256 | + } else { |
| 8257 | + dev_info->rtc_type = UFS_RTC_RELATIVE; |
| 8258 | + dev_info->rtc_time_baseline = 0; |
| 8259 | + } |
| 8260 | +} |
| 8261 | + |
8191 | 8262 | static int ufs_get_device_desc(struct ufs_hba *hba)
|
8192 | 8263 | {
|
8193 | 8264 | int err;
|
@@ -8240,6 +8311,8 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
|
8240 | 8311 |
|
8241 | 8312 | ufshcd_temp_notif_probe(hba, desc_buf);
|
8242 | 8313 |
|
| 8314 | + ufs_init_rtc(hba, desc_buf); |
| 8315 | + |
8243 | 8316 | if (hba->ext_iid_sup)
|
8244 | 8317 | ufshcd_ext_iid_probe(hba, desc_buf);
|
8245 | 8318 |
|
@@ -8793,6 +8866,8 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
|
8793 | 8866 | ufshcd_force_reset_auto_bkops(hba);
|
8794 | 8867 |
|
8795 | 8868 | ufshcd_set_timestamp_attr(hba);
|
| 8869 | + schedule_delayed_work(&hba->ufs_rtc_update_work, |
| 8870 | + msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS)); |
8796 | 8871 |
|
8797 | 8872 | /* Gear up to HS gear if supported */
|
8798 | 8873 | if (hba->max_pwr_info.is_valid) {
|
@@ -9749,6 +9824,8 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
9749 | 9824 | ret = ufshcd_vops_suspend(hba, pm_op, POST_CHANGE);
|
9750 | 9825 | if (ret)
|
9751 | 9826 | goto set_link_active;
|
| 9827 | + |
| 9828 | + cancel_delayed_work_sync(&hba->ufs_rtc_update_work); |
9752 | 9829 | goto out;
|
9753 | 9830 |
|
9754 | 9831 | set_link_active:
|
@@ -9843,6 +9920,8 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
9843 | 9920 | if (ret)
|
9844 | 9921 | goto set_old_link_state;
|
9845 | 9922 | ufshcd_set_timestamp_attr(hba);
|
| 9923 | + schedule_delayed_work(&hba->ufs_rtc_update_work, |
| 9924 | + msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS)); |
9846 | 9925 | }
|
9847 | 9926 |
|
9848 | 9927 | if (ufshcd_keep_autobkops_enabled_except_suspend(hba))
|
@@ -10539,8 +10618,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
|
10539 | 10618 | UFS_SLEEP_PWR_MODE,
|
10540 | 10619 | UIC_LINK_HIBERN8_STATE);
|
10541 | 10620 |
|
10542 |
| - INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work, |
10543 |
| - ufshcd_rpm_dev_flush_recheck_work); |
| 10621 | + INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work, ufshcd_rpm_dev_flush_recheck_work); |
| 10622 | + INIT_DELAYED_WORK(&hba->ufs_rtc_update_work, ufshcd_rtc_work); |
10544 | 10623 |
|
10545 | 10624 | /* Set the default auto-hiberate idle timer value to 150 ms */
|
10546 | 10625 | if (ufshcd_is_auto_hibern8_supported(hba) && !hba->ahit) {
|
|
0 commit comments