From 6bf999e0eb41850d5c857102535d5c53b2ede224 Mon Sep 17 00:00:00 2001 From: Bean Huo Date: Tue, 12 Dec 2023 23:08:24 +0100 Subject: scsi: ufs: core: Add UFS RTC support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Real Time Clock (RTC) support for UFS device. This enhancement is crucial for the internal maintenance operations of the UFS device. The patch enables the device to handle both absolute and relative time information. Furthermore, it includes periodic task to update the RTC in accordance with the UFS Spec, ensuring the accuracy of RTC information for the device's internal processes. RTC and qTimestamp serve distinct purposes. The RTC provides a coarse level of granularity with, at best, approximate single-second resolution. This makes the RTC well-suited for the device to determine the approximate age of programmed blocks after being updated by the host. On the other hand, qTimestamp offers nanosecond granularity and is specifically designed for synchronizing Device Error Log entries with corresponding host-side logs. Given that the RTC has been a standard feature since UFS Spec 2.0, and qTimestamp was introduced in UFS Spec 4.0, the majority of UFS devices currently on the market rely on RTC. Therefore, it is advisable to continue supporting RTC in the Linux kernel. This ensures compatibility with the prevailing UFS device implementations and facilitates seamless integration with existing hardware. By maintaining support for RTC, we ensure broad compatibility and avoid potential issues arising from deviations in device specifications across different UFS versions. Signed-off-by: Bean Huo Signed-off-by: Mike Bi Signed-off-by: Luca Porzio Link: https://lore.kernel.org/r/20231212220825.85255-3-beanhuo@iokpp.de Acked-by: Avri Altman Reviewed-by: Thomas Weißschuh Signed-off-by: Martin K. Petersen --- include/ufs/ufs.h | 13 +++++++++++++ include/ufs/ufshcd.h | 4 ++++ 2 files changed, 17 insertions(+) (limited to 'include') diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index e77ab1786856..7e7169d94596 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -14,6 +14,7 @@ #include #include #include +#include /* * Using static_assert() is not allowed in UAPI header files. Hence the check @@ -551,6 +552,14 @@ struct ufs_vreg_info { struct ufs_vreg *vdd_hba; }; +/* UFS device descriptor wPeriodicRTCUpdate bit9 defines RTC time baseline */ +#define UFS_RTC_TIME_BASELINE BIT(9) + +enum ufs_rtc_time { + UFS_RTC_RELATIVE, + UFS_RTC_ABSOLUTE +}; + struct ufs_dev_info { bool f_power_on_wp_en; /* Keeps information if any of the LU is power on write protected */ @@ -578,6 +587,10 @@ struct ufs_dev_info { /* UFS EXT_IID Enable */ bool b_ext_iid_en; + + /* UFS RTC */ + enum ufs_rtc_time rtc_type; + time64_t rtc_time_baseline; }; /* diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 7f0b2c5599cd..7bdda92fcb1c 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -911,6 +911,8 @@ enum ufshcd_mcq_opr { * @mcq_base: Multi circular queue registers base address * @uhq: array of supported hardware queues * @dev_cmd_queue: Queue for issuing device management commands + * @mcq_opr: MCQ operation and runtime registers + * @ufs_rtc_update_work: A work for UFS RTC periodic update */ struct ufs_hba { void __iomem *mmio_base; @@ -1071,6 +1073,8 @@ struct ufs_hba { struct ufs_hw_queue *uhq; struct ufs_hw_queue *dev_cmd_queue; struct ufshcd_mcq_opr_info_t mcq_opr[OPR_MAX]; + + struct delayed_work ufs_rtc_update_work; }; /** -- cgit v1.2.3 From 838f595a567257e3ac0ac33cdb6bb644ca326cc1 Mon Sep 17 00:00:00 2001 From: Bean Huo Date: Tue, 12 Dec 2023 23:08:25 +0100 Subject: scsi: ufs: core: Add sysfs node for UFS RTC update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a sysfs node named 'rtc_update_ms' within the kernel, enabling user to adjust the RTC periodic update frequency to suit the specific requirements of the system and UFS. Also, this patch allows the user to disable/enable periodic update RTC in the UFS idle time. Signed-off-by: Bean Huo Link: https://lore.kernel.org/r/20231212220825.85255-4-beanhuo@iokpp.de Acked-by: Avri Altman Reviewed-by: Thomas Weißschuh Signed-off-by: Martin K. Petersen --- Documentation/ABI/testing/sysfs-driver-ufs | 7 +++++++ drivers/ufs/core/ufs-sysfs.c | 31 ++++++++++++++++++++++++++++++ drivers/ufs/core/ufshcd.c | 11 +++++++++-- include/ufs/ufs.h | 1 + 4 files changed, 48 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 0c7efaf62de0..ef1e27584fff 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -1474,3 +1474,10 @@ Description: Indicates status of Write Booster. The file is read only. +What: /sys/bus/platform/drivers/ufshcd/*/rtc_update_ms +What: /sys/bus/platform/devices/*.ufs/rtc_update_ms +Date: November 2023 +Contact: Bean Huo +Description: + rtc_update_ms indicates how often the host should synchronize or update the + UFS RTC. If set to 0, this will disable UFS RTC periodic update. diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c index c95906443d5f..4ead1e3bdb12 100644 --- a/drivers/ufs/core/ufs-sysfs.c +++ b/drivers/ufs/core/ufs-sysfs.c @@ -255,6 +255,35 @@ out: return res < 0 ? res : count; } +static ssize_t rtc_update_ms_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%d\n", hba->dev_info.rtc_update_period); +} + +static ssize_t rtc_update_ms_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + unsigned int ms; + bool resume_period_update = false; + + if (kstrtouint(buf, 0, &ms)) + return -EINVAL; + + if (!hba->dev_info.rtc_update_period && ms > 0) + resume_period_update = true; + /* Minimum and maximum update frequency should be synchronized with all UFS vendors */ + hba->dev_info.rtc_update_period = ms; + + if (resume_period_update) + schedule_delayed_work(&hba->ufs_rtc_update_work, + msecs_to_jiffies(hba->dev_info.rtc_update_period)); + return count; +} + static ssize_t enable_wb_buf_flush_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -339,6 +368,7 @@ static DEVICE_ATTR_RW(auto_hibern8); static DEVICE_ATTR_RW(wb_on); static DEVICE_ATTR_RW(enable_wb_buf_flush); static DEVICE_ATTR_RW(wb_flush_threshold); +static DEVICE_ATTR_RW(rtc_update_ms); static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_rpm_lvl.attr, @@ -351,6 +381,7 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_wb_on.attr, &dev_attr_enable_wb_buf_flush.attr, &dev_attr_wb_flush_threshold.attr, + &dev_attr_rtc_update_ms.attr, NULL }; diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 99ad9b769048..5c4ef4b072c3 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -8233,9 +8233,9 @@ static void ufshcd_rtc_work(struct work_struct *work) if (!ufshcd_is_ufs_dev_busy(hba) && hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) ufshcd_update_rtc(hba); - if (ufshcd_is_ufs_dev_active(hba)) + if (ufshcd_is_ufs_dev_active(hba) && hba->dev_info.rtc_update_period) schedule_delayed_work(&hba->ufs_rtc_update_work, - msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS)); + msecs_to_jiffies(hba->dev_info.rtc_update_period)); } static void ufs_init_rtc(struct ufs_hba *hba, u8 *desc_buf) @@ -8257,6 +8257,13 @@ static void ufs_init_rtc(struct ufs_hba *hba, u8 *desc_buf) dev_info->rtc_type = UFS_RTC_RELATIVE; dev_info->rtc_time_baseline = 0; } + + /* + * We ignore TIME_PERIOD defined in wPeriodicRTCUpdate because Spec does not clearly state + * how to calculate the specific update period for each time unit. And we disable periodic + * RTC update work, let user configure by sysfs node according to specific circumstance. + */ + dev_info->rtc_update_period = 0; } static int ufs_get_device_desc(struct ufs_hba *hba) diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index 7e7169d94596..b6003749bc83 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -591,6 +591,7 @@ struct ufs_dev_info { /* UFS RTC */ enum ufs_rtc_time rtc_type; time64_t rtc_time_baseline; + u32 rtc_update_period; }; /* -- cgit v1.2.3