Skip to content

Commit 6df14a3

Browse files
Merge patch series "Add UFS RTC support"
Bean Huo <beanhuo@iokpp.de> says: Adding RTC support for embedded storage device UFS in its driver, it is important for a few key reasons: 1. Helps with Regular Maintenance: The RTC provides a basic way to keep track of time, making it useful for scheduling routine maintenance tasks in the storage device. This includes things like making sure data is spread evenly across the storage to extend its life. 2. Figuring Out How Old Data Is: The RTC helps the device estimate how long ago certain parts of the storage were last used. This is handy for deciding when to do maintenance tasks to keep the storage working well over time. 3. Making Devices Last Longer: By using the RTC for regular upkeep, we can make sure the storage device lasts longer and stays reliable. This is especially important for devices that need to work well for a long time. 4.Fitting In with Other Devices: The inclusion of RTC support aligns with existing UFS specifications (starting from UFS Spec 2.0) and is consistent with the prevalent industry practice. Many UFS devices currently on the market utilize RTC for internal timekeeping. By ensuring compatibility with this widely adopted standard, the embedded storage device becomes seamlessly integrable with existing hardware and software ecosystems, reducing the risk of compatibility issues. In short, adding RTC support to embedded storage device UFS helps with regular upkeep, extends the device's life, ensures compatibility, and keeps everything running smoothly with the rest of the system. Link: https://lore.kernel.org/r/20231212220825.85255-1-beanhuo@iokpp.de Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2 parents ae6fd54 + 838f595 commit 6df14a3

File tree

5 files changed

+151
-6
lines changed

5 files changed

+151
-6
lines changed

Documentation/ABI/testing/sysfs-driver-ufs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,3 +1523,10 @@ Description: Indicates status of Write Booster.
15231523

15241524
The file is read only.
15251525

1526+
What: /sys/bus/platform/drivers/ufshcd/*/rtc_update_ms
1527+
What: /sys/bus/platform/devices/*.ufs/rtc_update_ms
1528+
Date: November 2023
1529+
Contact: Bean Huo <beanhuo@micron.com>
1530+
Description:
1531+
rtc_update_ms indicates how often the host should synchronize or update the
1532+
UFS RTC. If set to 0, this will disable UFS RTC periodic update.

drivers/ufs/core/ufs-sysfs.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,35 @@ static ssize_t wb_on_store(struct device *dev, struct device_attribute *attr,
302302
return res < 0 ? res : count;
303303
}
304304

305+
static ssize_t rtc_update_ms_show(struct device *dev, struct device_attribute *attr,
306+
char *buf)
307+
{
308+
struct ufs_hba *hba = dev_get_drvdata(dev);
309+
310+
return sysfs_emit(buf, "%d\n", hba->dev_info.rtc_update_period);
311+
}
312+
313+
static ssize_t rtc_update_ms_store(struct device *dev, struct device_attribute *attr,
314+
const char *buf, size_t count)
315+
{
316+
struct ufs_hba *hba = dev_get_drvdata(dev);
317+
unsigned int ms;
318+
bool resume_period_update = false;
319+
320+
if (kstrtouint(buf, 0, &ms))
321+
return -EINVAL;
322+
323+
if (!hba->dev_info.rtc_update_period && ms > 0)
324+
resume_period_update = true;
325+
/* Minimum and maximum update frequency should be synchronized with all UFS vendors */
326+
hba->dev_info.rtc_update_period = ms;
327+
328+
if (resume_period_update)
329+
schedule_delayed_work(&hba->ufs_rtc_update_work,
330+
msecs_to_jiffies(hba->dev_info.rtc_update_period));
331+
return count;
332+
}
333+
305334
static ssize_t enable_wb_buf_flush_show(struct device *dev,
306335
struct device_attribute *attr,
307336
char *buf)
@@ -386,6 +415,7 @@ static DEVICE_ATTR_RW(auto_hibern8);
386415
static DEVICE_ATTR_RW(wb_on);
387416
static DEVICE_ATTR_RW(enable_wb_buf_flush);
388417
static DEVICE_ATTR_RW(wb_flush_threshold);
418+
static DEVICE_ATTR_RW(rtc_update_ms);
389419

390420
static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
391421
&dev_attr_rpm_lvl.attr,
@@ -398,6 +428,7 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
398428
&dev_attr_wb_on.attr,
399429
&dev_attr_enable_wb_buf_flush.attr,
400430
&dev_attr_wb_flush_threshold.attr,
431+
&dev_attr_rtc_update_ms.attr,
401432
NULL
402433
};
403434

drivers/ufs/core/ufshcd.c

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@
9999
/* Polling time to wait for fDeviceInit */
100100
#define FDEVICEINIT_COMPL_TIMEOUT 1500 /* millisecs */
101101

102+
/* Default RTC update every 10 seconds */
103+
#define UFS_RTC_UPDATE_INTERVAL_MS (10 * MSEC_PER_SEC)
104+
102105
/* UFSHC 4.0 compliant HC support this mode. */
103106
static bool use_mcq_mode = true;
104107

@@ -235,6 +238,12 @@ ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state,
235238
return UFS_PM_LVL_0;
236239
}
237240

241+
static bool ufshcd_is_ufs_dev_busy(struct ufs_hba *hba)
242+
{
243+
return (hba->clk_gating.active_reqs || hba->outstanding_reqs || hba->outstanding_tasks ||
244+
hba->active_uic_cmd || hba->uic_async_done);
245+
}
246+
238247
static const struct ufs_dev_quirk ufs_fixups[] = {
239248
/* UFS cards deviations table */
240249
{ .wmanufacturerid = UFS_VENDOR_MICRON,
@@ -679,6 +688,8 @@ static void ufshcd_device_reset(struct ufs_hba *hba)
679688
hba->dev_info.wb_enabled = false;
680689
hba->dev_info.wb_buf_flush_enabled = false;
681690
}
691+
if (hba->dev_info.rtc_type == UFS_RTC_RELATIVE)
692+
hba->dev_info.rtc_time_baseline = 0;
682693
}
683694
if (err != -EOPNOTSUPP)
684695
ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, err);
@@ -1919,10 +1930,7 @@ static void ufshcd_gate_work(struct work_struct *work)
19191930
goto rel_lock;
19201931
}
19211932

1922-
if (hba->clk_gating.active_reqs
1923-
|| hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL
1924-
|| hba->outstanding_reqs || hba->outstanding_tasks
1925-
|| hba->active_uic_cmd || hba->uic_async_done)
1933+
if (ufshcd_is_ufs_dev_busy(hba) || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL)
19261934
goto rel_lock;
19271935

19281936
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -8189,6 +8197,79 @@ static void ufs_fixup_device_setup(struct ufs_hba *hba)
81898197
ufshcd_vops_fixup_dev_quirks(hba);
81908198
}
81918199

8200+
static void ufshcd_update_rtc(struct ufs_hba *hba)
8201+
{
8202+
struct timespec64 ts64;
8203+
int err;
8204+
u32 val;
8205+
8206+
ktime_get_real_ts64(&ts64);
8207+
8208+
if (ts64.tv_sec < hba->dev_info.rtc_time_baseline) {
8209+
dev_warn_once(hba->dev, "%s: Current time precedes previous setting!\n", __func__);
8210+
return;
8211+
}
8212+
8213+
/*
8214+
* The Absolute RTC mode has a 136-year limit, spanning from 2010 to 2146. If a time beyond
8215+
* 2146 is required, it is recommended to choose the relative RTC mode.
8216+
*/
8217+
val = ts64.tv_sec - hba->dev_info.rtc_time_baseline;
8218+
8219+
ufshcd_rpm_get_sync(hba);
8220+
err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_SECONDS_PASSED,
8221+
0, 0, &val);
8222+
ufshcd_rpm_put_sync(hba);
8223+
8224+
if (err)
8225+
dev_err(hba->dev, "%s: Failed to update rtc %d\n", __func__, err);
8226+
else if (hba->dev_info.rtc_type == UFS_RTC_RELATIVE)
8227+
hba->dev_info.rtc_time_baseline = ts64.tv_sec;
8228+
}
8229+
8230+
static void ufshcd_rtc_work(struct work_struct *work)
8231+
{
8232+
struct ufs_hba *hba;
8233+
8234+
hba = container_of(to_delayed_work(work), struct ufs_hba, ufs_rtc_update_work);
8235+
8236+
/* Update RTC only when there are no requests in progress and UFSHCI is operational */
8237+
if (!ufshcd_is_ufs_dev_busy(hba) && hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL)
8238+
ufshcd_update_rtc(hba);
8239+
8240+
if (ufshcd_is_ufs_dev_active(hba) && hba->dev_info.rtc_update_period)
8241+
schedule_delayed_work(&hba->ufs_rtc_update_work,
8242+
msecs_to_jiffies(hba->dev_info.rtc_update_period));
8243+
}
8244+
8245+
static void ufs_init_rtc(struct ufs_hba *hba, u8 *desc_buf)
8246+
{
8247+
u16 periodic_rtc_update = get_unaligned_be16(&desc_buf[DEVICE_DESC_PARAM_FRQ_RTC]);
8248+
struct ufs_dev_info *dev_info = &hba->dev_info;
8249+
8250+
if (periodic_rtc_update & UFS_RTC_TIME_BASELINE) {
8251+
dev_info->rtc_type = UFS_RTC_ABSOLUTE;
8252+
8253+
/*
8254+
* The concept of measuring time in Linux as the number of seconds elapsed since
8255+
* 00:00:00 UTC on January 1, 1970, and UFS ABS RTC is elapsed from January 1st
8256+
* 2010 00:00, here we need to adjust ABS baseline.
8257+
*/
8258+
dev_info->rtc_time_baseline = mktime64(2010, 1, 1, 0, 0, 0) -
8259+
mktime64(1970, 1, 1, 0, 0, 0);
8260+
} else {
8261+
dev_info->rtc_type = UFS_RTC_RELATIVE;
8262+
dev_info->rtc_time_baseline = 0;
8263+
}
8264+
8265+
/*
8266+
* We ignore TIME_PERIOD defined in wPeriodicRTCUpdate because Spec does not clearly state
8267+
* how to calculate the specific update period for each time unit. And we disable periodic
8268+
* RTC update work, let user configure by sysfs node according to specific circumstance.
8269+
*/
8270+
dev_info->rtc_update_period = 0;
8271+
}
8272+
81928273
static int ufs_get_device_desc(struct ufs_hba *hba)
81938274
{
81948275
int err;
@@ -8241,6 +8322,8 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
82418322

82428323
ufshcd_temp_notif_probe(hba, desc_buf);
82438324

8325+
ufs_init_rtc(hba, desc_buf);
8326+
82448327
if (hba->ext_iid_sup)
82458328
ufshcd_ext_iid_probe(hba, desc_buf);
82468329

@@ -8794,6 +8877,8 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
87948877
ufshcd_force_reset_auto_bkops(hba);
87958878

87968879
ufshcd_set_timestamp_attr(hba);
8880+
schedule_delayed_work(&hba->ufs_rtc_update_work,
8881+
msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS));
87978882

87988883
/* Gear up to HS gear if supported */
87998884
if (hba->max_pwr_info.is_valid) {
@@ -9751,6 +9836,8 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
97519836
ret = ufshcd_vops_suspend(hba, pm_op, POST_CHANGE);
97529837
if (ret)
97539838
goto set_link_active;
9839+
9840+
cancel_delayed_work_sync(&hba->ufs_rtc_update_work);
97549841
goto out;
97559842

97569843
set_link_active:
@@ -9845,6 +9932,8 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
98459932
if (ret)
98469933
goto set_old_link_state;
98479934
ufshcd_set_timestamp_attr(hba);
9935+
schedule_delayed_work(&hba->ufs_rtc_update_work,
9936+
msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS));
98489937
}
98499938

98509939
if (ufshcd_keep_autobkops_enabled_except_suspend(hba))
@@ -10541,8 +10630,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
1054110630
UFS_SLEEP_PWR_MODE,
1054210631
UIC_LINK_HIBERN8_STATE);
1054310632

10544-
INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work,
10545-
ufshcd_rpm_dev_flush_recheck_work);
10633+
INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work, ufshcd_rpm_dev_flush_recheck_work);
10634+
INIT_DELAYED_WORK(&hba->ufs_rtc_update_work, ufshcd_rtc_work);
1054610635

1054710636
/* Set the default auto-hiberate idle timer value to 150 ms */
1054810637
if (ufshcd_is_auto_hibern8_supported(hba) && !hba->ahit) {

include/ufs/ufs.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/bitops.h>
1515
#include <linux/types.h>
1616
#include <uapi/scsi/scsi_bsg_ufs.h>
17+
#include <linux/time64.h>
1718

1819
/*
1920
* Using static_assert() is not allowed in UAPI header files. Hence the check
@@ -551,6 +552,14 @@ struct ufs_vreg_info {
551552
struct ufs_vreg *vdd_hba;
552553
};
553554

555+
/* UFS device descriptor wPeriodicRTCUpdate bit9 defines RTC time baseline */
556+
#define UFS_RTC_TIME_BASELINE BIT(9)
557+
558+
enum ufs_rtc_time {
559+
UFS_RTC_RELATIVE,
560+
UFS_RTC_ABSOLUTE
561+
};
562+
554563
struct ufs_dev_info {
555564
bool f_power_on_wp_en;
556565
/* Keeps information if any of the LU is power on write protected */
@@ -578,6 +587,11 @@ struct ufs_dev_info {
578587

579588
/* UFS EXT_IID Enable */
580589
bool b_ext_iid_en;
590+
591+
/* UFS RTC */
592+
enum ufs_rtc_time rtc_type;
593+
time64_t rtc_time_baseline;
594+
u32 rtc_update_period;
581595
};
582596

583597
/*

include/ufs/ufshcd.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,8 @@ enum ufshcd_mcq_opr {
912912
* @mcq_base: Multi circular queue registers base address
913913
* @uhq: array of supported hardware queues
914914
* @dev_cmd_queue: Queue for issuing device management commands
915+
* @mcq_opr: MCQ operation and runtime registers
916+
* @ufs_rtc_update_work: A work for UFS RTC periodic update
915917
*/
916918
struct ufs_hba {
917919
void __iomem *mmio_base;
@@ -1076,6 +1078,8 @@ struct ufs_hba {
10761078
struct ufs_hw_queue *uhq;
10771079
struct ufs_hw_queue *dev_cmd_queue;
10781080
struct ufshcd_mcq_opr_info_t mcq_opr[OPR_MAX];
1081+
1082+
struct delayed_work ufs_rtc_update_work;
10791083
};
10801084

10811085
/**

0 commit comments

Comments
 (0)