18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci// Copyright (C) 2018 Western Digital Corporation
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/err.h>
58c2ecf20Sopenharmony_ci#include <linux/string.h>
68c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
78c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "ufs.h"
108c2ecf20Sopenharmony_ci#include "ufs-sysfs.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistatic const char *ufschd_uic_link_state_to_string(
138c2ecf20Sopenharmony_ci			enum uic_link_state state)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	switch (state) {
168c2ecf20Sopenharmony_ci	case UIC_LINK_OFF_STATE:	return "OFF";
178c2ecf20Sopenharmony_ci	case UIC_LINK_ACTIVE_STATE:	return "ACTIVE";
188c2ecf20Sopenharmony_ci	case UIC_LINK_HIBERN8_STATE:	return "HIBERN8";
198c2ecf20Sopenharmony_ci	case UIC_LINK_BROKEN_STATE:	return "BROKEN";
208c2ecf20Sopenharmony_ci	default:			return "UNKNOWN";
218c2ecf20Sopenharmony_ci	}
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic const char *ufschd_ufs_dev_pwr_mode_to_string(
258c2ecf20Sopenharmony_ci			enum ufs_dev_pwr_mode state)
268c2ecf20Sopenharmony_ci{
278c2ecf20Sopenharmony_ci	switch (state) {
288c2ecf20Sopenharmony_ci	case UFS_ACTIVE_PWR_MODE:	return "ACTIVE";
298c2ecf20Sopenharmony_ci	case UFS_SLEEP_PWR_MODE:	return "SLEEP";
308c2ecf20Sopenharmony_ci	case UFS_POWERDOWN_PWR_MODE:	return "POWERDOWN";
318c2ecf20Sopenharmony_ci	default:			return "UNKNOWN";
328c2ecf20Sopenharmony_ci	}
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
368c2ecf20Sopenharmony_ci					     struct device_attribute *attr,
378c2ecf20Sopenharmony_ci					     const char *buf, size_t count,
388c2ecf20Sopenharmony_ci					     bool rpm)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
418c2ecf20Sopenharmony_ci	unsigned long flags, value;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (kstrtoul(buf, 0, &value))
448c2ecf20Sopenharmony_ci		return -EINVAL;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	if (value >= UFS_PM_LVL_MAX)
478c2ecf20Sopenharmony_ci		return -EINVAL;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	spin_lock_irqsave(hba->host->host_lock, flags);
508c2ecf20Sopenharmony_ci	if (rpm)
518c2ecf20Sopenharmony_ci		hba->rpm_lvl = value;
528c2ecf20Sopenharmony_ci	else
538c2ecf20Sopenharmony_ci		hba->spm_lvl = value;
548c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(hba->host->host_lock, flags);
558c2ecf20Sopenharmony_ci	return count;
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic ssize_t rpm_lvl_show(struct device *dev,
598c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", hba->rpm_lvl);
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic ssize_t rpm_lvl_store(struct device *dev,
678c2ecf20Sopenharmony_ci		struct device_attribute *attr, const char *buf, size_t count)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, true);
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic ssize_t rpm_target_dev_state_show(struct device *dev,
738c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", ufschd_ufs_dev_pwr_mode_to_string(
788c2ecf20Sopenharmony_ci			ufs_pm_lvl_states[hba->rpm_lvl].dev_state));
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic ssize_t rpm_target_link_state_show(struct device *dev,
828c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", ufschd_uic_link_state_to_string(
878c2ecf20Sopenharmony_ci			ufs_pm_lvl_states[hba->rpm_lvl].link_state));
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistatic ssize_t spm_lvl_show(struct device *dev,
918c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", hba->spm_lvl);
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic ssize_t spm_lvl_store(struct device *dev,
998c2ecf20Sopenharmony_ci		struct device_attribute *attr, const char *buf, size_t count)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic ssize_t spm_target_dev_state_show(struct device *dev,
1058c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", ufschd_ufs_dev_pwr_mode_to_string(
1108c2ecf20Sopenharmony_ci				ufs_pm_lvl_states[hba->spm_lvl].dev_state));
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic ssize_t spm_target_link_state_show(struct device *dev,
1148c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", ufschd_uic_link_state_to_string(
1198c2ecf20Sopenharmony_ci				ufs_pm_lvl_states[hba->spm_lvl].link_state));
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci/* Convert Auto-Hibernate Idle Timer register value to microseconds */
1238c2ecf20Sopenharmony_cistatic int ufshcd_ahit_to_us(u32 ahit)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	int timer = FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, ahit);
1268c2ecf20Sopenharmony_ci	int scale = FIELD_GET(UFSHCI_AHIBERN8_SCALE_MASK, ahit);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	for (; scale > 0; --scale)
1298c2ecf20Sopenharmony_ci		timer *= UFSHCI_AHIBERN8_SCALE_FACTOR;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	return timer;
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci/* Convert microseconds to Auto-Hibernate Idle Timer register value */
1358c2ecf20Sopenharmony_cistatic u32 ufshcd_us_to_ahit(unsigned int timer)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	unsigned int scale;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	for (scale = 0; timer > UFSHCI_AHIBERN8_TIMER_MASK; ++scale)
1408c2ecf20Sopenharmony_ci		timer /= UFSHCI_AHIBERN8_SCALE_FACTOR;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	return FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, timer) |
1438c2ecf20Sopenharmony_ci	       FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, scale);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic ssize_t auto_hibern8_show(struct device *dev,
1478c2ecf20Sopenharmony_ci				 struct device_attribute *attr, char *buf)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	u32 ahit;
1508c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	if (!ufshcd_is_auto_hibern8_supported(hba))
1538c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	pm_runtime_get_sync(hba->dev);
1568c2ecf20Sopenharmony_ci	ufshcd_hold(hba, false);
1578c2ecf20Sopenharmony_ci	ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER);
1588c2ecf20Sopenharmony_ci	ufshcd_release(hba);
1598c2ecf20Sopenharmony_ci	pm_runtime_put_sync(hba->dev);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "%d\n", ufshcd_ahit_to_us(ahit));
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic ssize_t auto_hibern8_store(struct device *dev,
1658c2ecf20Sopenharmony_ci				  struct device_attribute *attr,
1668c2ecf20Sopenharmony_ci				  const char *buf, size_t count)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);
1698c2ecf20Sopenharmony_ci	unsigned int timer;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (!ufshcd_is_auto_hibern8_supported(hba))
1728c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	if (kstrtouint(buf, 0, &timer))
1758c2ecf20Sopenharmony_ci		return -EINVAL;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	if (timer > UFSHCI_AHIBERN8_MAX)
1788c2ecf20Sopenharmony_ci		return -EINVAL;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	ufshcd_auto_hibern8_update(hba, ufshcd_us_to_ahit(timer));
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	return count;
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(rpm_lvl);
1868c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(rpm_target_dev_state);
1878c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(rpm_target_link_state);
1888c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(spm_lvl);
1898c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(spm_target_dev_state);
1908c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(spm_target_link_state);
1918c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(auto_hibern8);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_ufshcd_attrs[] = {
1948c2ecf20Sopenharmony_ci	&dev_attr_rpm_lvl.attr,
1958c2ecf20Sopenharmony_ci	&dev_attr_rpm_target_dev_state.attr,
1968c2ecf20Sopenharmony_ci	&dev_attr_rpm_target_link_state.attr,
1978c2ecf20Sopenharmony_ci	&dev_attr_spm_lvl.attr,
1988c2ecf20Sopenharmony_ci	&dev_attr_spm_target_dev_state.attr,
1998c2ecf20Sopenharmony_ci	&dev_attr_spm_target_link_state.attr,
2008c2ecf20Sopenharmony_ci	&dev_attr_auto_hibern8.attr,
2018c2ecf20Sopenharmony_ci	NULL
2028c2ecf20Sopenharmony_ci};
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_default_group = {
2058c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_ufshcd_attrs,
2068c2ecf20Sopenharmony_ci};
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba,
2098c2ecf20Sopenharmony_ci				  enum desc_idn desc_id,
2108c2ecf20Sopenharmony_ci				  u8 desc_index,
2118c2ecf20Sopenharmony_ci				  u8 param_offset,
2128c2ecf20Sopenharmony_ci				  u8 *sysfs_buf,
2138c2ecf20Sopenharmony_ci				  u8 param_size)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	u8 desc_buf[8] = {0};
2168c2ecf20Sopenharmony_ci	int ret;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	if (param_size > 8)
2198c2ecf20Sopenharmony_ci		return -EINVAL;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	pm_runtime_get_sync(hba->dev);
2228c2ecf20Sopenharmony_ci	ret = ufshcd_read_desc_param(hba, desc_id, desc_index,
2238c2ecf20Sopenharmony_ci				param_offset, desc_buf, param_size);
2248c2ecf20Sopenharmony_ci	pm_runtime_put_sync(hba->dev);
2258c2ecf20Sopenharmony_ci	if (ret)
2268c2ecf20Sopenharmony_ci		return -EINVAL;
2278c2ecf20Sopenharmony_ci	switch (param_size) {
2288c2ecf20Sopenharmony_ci	case 1:
2298c2ecf20Sopenharmony_ci		ret = sprintf(sysfs_buf, "0x%02X\n", *desc_buf);
2308c2ecf20Sopenharmony_ci		break;
2318c2ecf20Sopenharmony_ci	case 2:
2328c2ecf20Sopenharmony_ci		ret = sprintf(sysfs_buf, "0x%04X\n",
2338c2ecf20Sopenharmony_ci			get_unaligned_be16(desc_buf));
2348c2ecf20Sopenharmony_ci		break;
2358c2ecf20Sopenharmony_ci	case 4:
2368c2ecf20Sopenharmony_ci		ret = sprintf(sysfs_buf, "0x%08X\n",
2378c2ecf20Sopenharmony_ci			get_unaligned_be32(desc_buf));
2388c2ecf20Sopenharmony_ci		break;
2398c2ecf20Sopenharmony_ci	case 8:
2408c2ecf20Sopenharmony_ci		ret = sprintf(sysfs_buf, "0x%016llX\n",
2418c2ecf20Sopenharmony_ci			get_unaligned_be64(desc_buf));
2428c2ecf20Sopenharmony_ci		break;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	return ret;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci#define UFS_DESC_PARAM(_name, _puname, _duname, _size)			\
2498c2ecf20Sopenharmony_cistatic ssize_t _name##_show(struct device *dev,				\
2508c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)			\
2518c2ecf20Sopenharmony_ci{									\
2528c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);			\
2538c2ecf20Sopenharmony_ci	return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname,	\
2548c2ecf20Sopenharmony_ci		0, _duname##_DESC_PARAM##_puname, buf, _size);		\
2558c2ecf20Sopenharmony_ci}									\
2568c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(_name)
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size)			\
2598c2ecf20Sopenharmony_ci	UFS_DESC_PARAM(_name, _uname, DEVICE, _size)
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(device_type, _DEVICE_TYPE, 1);
2628c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(device_class, _DEVICE_CLASS, 1);
2638c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(device_sub_class, _DEVICE_SUB_CLASS, 1);
2648c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(protocol, _PRTCL, 1);
2658c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(number_of_luns, _NUM_LU, 1);
2668c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(number_of_wluns, _NUM_WLU, 1);
2678c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(boot_enable, _BOOT_ENBL, 1);
2688c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(descriptor_access_enable, _DESC_ACCSS_ENBL, 1);
2698c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(initial_power_mode, _INIT_PWR_MODE, 1);
2708c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(high_priority_lun, _HIGH_PR_LUN, 1);
2718c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(secure_removal_type, _SEC_RMV_TYPE, 1);
2728c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(support_security_lun, _SEC_LU, 1);
2738c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(bkops_termination_latency, _BKOP_TERM_LT, 1);
2748c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(initial_active_icc_level, _ACTVE_ICC_LVL, 1);
2758c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(specification_version, _SPEC_VER, 2);
2768c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(manufacturing_date, _MANF_DATE, 2);
2778c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(manufacturer_id, _MANF_ID, 2);
2788c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(rtt_capability, _RTT_CAP, 1);
2798c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(rtc_update, _FRQ_RTC, 2);
2808c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(ufs_features, _UFS_FEAT, 1);
2818c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(ffu_timeout, _FFU_TMT, 1);
2828c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(queue_depth, _Q_DPTH, 1);
2838c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(device_version, _DEV_VER, 2);
2848c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(number_of_secure_wpa, _NUM_SEC_WPA, 1);
2858c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(psa_max_data_size, _PSA_MAX_DATA, 4);
2868c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(psa_state_timeout, _PSA_TMT, 1);
2878c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(ext_feature_sup, _EXT_UFS_FEATURE_SUP, 4);
2888c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(wb_presv_us_en, _WB_PRESRV_USRSPC_EN, 1);
2898c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(wb_type, _WB_TYPE, 1);
2908c2ecf20Sopenharmony_ciUFS_DEVICE_DESC_PARAM(wb_shared_alloc_units, _WB_SHARED_ALLOC_UNITS, 4);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_device_descriptor[] = {
2938c2ecf20Sopenharmony_ci	&dev_attr_device_type.attr,
2948c2ecf20Sopenharmony_ci	&dev_attr_device_class.attr,
2958c2ecf20Sopenharmony_ci	&dev_attr_device_sub_class.attr,
2968c2ecf20Sopenharmony_ci	&dev_attr_protocol.attr,
2978c2ecf20Sopenharmony_ci	&dev_attr_number_of_luns.attr,
2988c2ecf20Sopenharmony_ci	&dev_attr_number_of_wluns.attr,
2998c2ecf20Sopenharmony_ci	&dev_attr_boot_enable.attr,
3008c2ecf20Sopenharmony_ci	&dev_attr_descriptor_access_enable.attr,
3018c2ecf20Sopenharmony_ci	&dev_attr_initial_power_mode.attr,
3028c2ecf20Sopenharmony_ci	&dev_attr_high_priority_lun.attr,
3038c2ecf20Sopenharmony_ci	&dev_attr_secure_removal_type.attr,
3048c2ecf20Sopenharmony_ci	&dev_attr_support_security_lun.attr,
3058c2ecf20Sopenharmony_ci	&dev_attr_bkops_termination_latency.attr,
3068c2ecf20Sopenharmony_ci	&dev_attr_initial_active_icc_level.attr,
3078c2ecf20Sopenharmony_ci	&dev_attr_specification_version.attr,
3088c2ecf20Sopenharmony_ci	&dev_attr_manufacturing_date.attr,
3098c2ecf20Sopenharmony_ci	&dev_attr_manufacturer_id.attr,
3108c2ecf20Sopenharmony_ci	&dev_attr_rtt_capability.attr,
3118c2ecf20Sopenharmony_ci	&dev_attr_rtc_update.attr,
3128c2ecf20Sopenharmony_ci	&dev_attr_ufs_features.attr,
3138c2ecf20Sopenharmony_ci	&dev_attr_ffu_timeout.attr,
3148c2ecf20Sopenharmony_ci	&dev_attr_queue_depth.attr,
3158c2ecf20Sopenharmony_ci	&dev_attr_device_version.attr,
3168c2ecf20Sopenharmony_ci	&dev_attr_number_of_secure_wpa.attr,
3178c2ecf20Sopenharmony_ci	&dev_attr_psa_max_data_size.attr,
3188c2ecf20Sopenharmony_ci	&dev_attr_psa_state_timeout.attr,
3198c2ecf20Sopenharmony_ci	&dev_attr_ext_feature_sup.attr,
3208c2ecf20Sopenharmony_ci	&dev_attr_wb_presv_us_en.attr,
3218c2ecf20Sopenharmony_ci	&dev_attr_wb_type.attr,
3228c2ecf20Sopenharmony_ci	&dev_attr_wb_shared_alloc_units.attr,
3238c2ecf20Sopenharmony_ci	NULL,
3248c2ecf20Sopenharmony_ci};
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_device_descriptor_group = {
3278c2ecf20Sopenharmony_ci	.name = "device_descriptor",
3288c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_device_descriptor,
3298c2ecf20Sopenharmony_ci};
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci#define UFS_INTERCONNECT_DESC_PARAM(_name, _uname, _size)		\
3328c2ecf20Sopenharmony_ci	UFS_DESC_PARAM(_name, _uname, INTERCONNECT, _size)
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ciUFS_INTERCONNECT_DESC_PARAM(unipro_version, _UNIPRO_VER, 2);
3358c2ecf20Sopenharmony_ciUFS_INTERCONNECT_DESC_PARAM(mphy_version, _MPHY_VER, 2);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_interconnect_descriptor[] = {
3388c2ecf20Sopenharmony_ci	&dev_attr_unipro_version.attr,
3398c2ecf20Sopenharmony_ci	&dev_attr_mphy_version.attr,
3408c2ecf20Sopenharmony_ci	NULL,
3418c2ecf20Sopenharmony_ci};
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_interconnect_descriptor_group = {
3448c2ecf20Sopenharmony_ci	.name = "interconnect_descriptor",
3458c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_interconnect_descriptor,
3468c2ecf20Sopenharmony_ci};
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci#define UFS_GEOMETRY_DESC_PARAM(_name, _uname, _size)			\
3498c2ecf20Sopenharmony_ci	UFS_DESC_PARAM(_name, _uname, GEOMETRY, _size)
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(raw_device_capacity, _DEV_CAP, 8);
3528c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(max_number_of_luns, _MAX_NUM_LUN, 1);
3538c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(segment_size, _SEG_SIZE, 4);
3548c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(allocation_unit_size, _ALLOC_UNIT_SIZE, 1);
3558c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(min_addressable_block_size, _MIN_BLK_SIZE, 1);
3568c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(optimal_read_block_size, _OPT_RD_BLK_SIZE, 1);
3578c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(optimal_write_block_size, _OPT_WR_BLK_SIZE, 1);
3588c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(max_in_buffer_size, _MAX_IN_BUF_SIZE, 1);
3598c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(max_out_buffer_size, _MAX_OUT_BUF_SIZE, 1);
3608c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(rpmb_rw_size, _RPMB_RW_SIZE, 1);
3618c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(dyn_capacity_resource_policy, _DYN_CAP_RSRC_PLC, 1);
3628c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(data_ordering, _DATA_ORDER, 1);
3638c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(max_number_of_contexts, _MAX_NUM_CTX, 1);
3648c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(sys_data_tag_unit_size, _TAG_UNIT_SIZE, 1);
3658c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(sys_data_tag_resource_size, _TAG_RSRC_SIZE, 1);
3668c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(secure_removal_types, _SEC_RM_TYPES, 1);
3678c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(memory_types, _MEM_TYPES, 2);
3688c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(sys_code_memory_max_alloc_units,
3698c2ecf20Sopenharmony_ci	_SCM_MAX_NUM_UNITS, 4);
3708c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(sys_code_memory_capacity_adjustment_factor,
3718c2ecf20Sopenharmony_ci	_SCM_CAP_ADJ_FCTR, 2);
3728c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(non_persist_memory_max_alloc_units,
3738c2ecf20Sopenharmony_ci	_NPM_MAX_NUM_UNITS, 4);
3748c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(non_persist_memory_capacity_adjustment_factor,
3758c2ecf20Sopenharmony_ci	_NPM_CAP_ADJ_FCTR, 2);
3768c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(enh1_memory_max_alloc_units,
3778c2ecf20Sopenharmony_ci	_ENM1_MAX_NUM_UNITS, 4);
3788c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(enh1_memory_capacity_adjustment_factor,
3798c2ecf20Sopenharmony_ci	_ENM1_CAP_ADJ_FCTR, 2);
3808c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(enh2_memory_max_alloc_units,
3818c2ecf20Sopenharmony_ci	_ENM2_MAX_NUM_UNITS, 4);
3828c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(enh2_memory_capacity_adjustment_factor,
3838c2ecf20Sopenharmony_ci	_ENM2_CAP_ADJ_FCTR, 2);
3848c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(enh3_memory_max_alloc_units,
3858c2ecf20Sopenharmony_ci	_ENM3_MAX_NUM_UNITS, 4);
3868c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(enh3_memory_capacity_adjustment_factor,
3878c2ecf20Sopenharmony_ci	_ENM3_CAP_ADJ_FCTR, 2);
3888c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(enh4_memory_max_alloc_units,
3898c2ecf20Sopenharmony_ci	_ENM4_MAX_NUM_UNITS, 4);
3908c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(enh4_memory_capacity_adjustment_factor,
3918c2ecf20Sopenharmony_ci	_ENM4_CAP_ADJ_FCTR, 2);
3928c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(wb_max_alloc_units, _WB_MAX_ALLOC_UNITS, 4);
3938c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(wb_max_wb_luns, _WB_MAX_WB_LUNS, 1);
3948c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(wb_buff_cap_adj, _WB_BUFF_CAP_ADJ, 1);
3958c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(wb_sup_red_type, _WB_SUP_RED_TYPE, 1);
3968c2ecf20Sopenharmony_ciUFS_GEOMETRY_DESC_PARAM(wb_sup_wb_type, _WB_SUP_WB_TYPE, 1);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_geometry_descriptor[] = {
4008c2ecf20Sopenharmony_ci	&dev_attr_raw_device_capacity.attr,
4018c2ecf20Sopenharmony_ci	&dev_attr_max_number_of_luns.attr,
4028c2ecf20Sopenharmony_ci	&dev_attr_segment_size.attr,
4038c2ecf20Sopenharmony_ci	&dev_attr_allocation_unit_size.attr,
4048c2ecf20Sopenharmony_ci	&dev_attr_min_addressable_block_size.attr,
4058c2ecf20Sopenharmony_ci	&dev_attr_optimal_read_block_size.attr,
4068c2ecf20Sopenharmony_ci	&dev_attr_optimal_write_block_size.attr,
4078c2ecf20Sopenharmony_ci	&dev_attr_max_in_buffer_size.attr,
4088c2ecf20Sopenharmony_ci	&dev_attr_max_out_buffer_size.attr,
4098c2ecf20Sopenharmony_ci	&dev_attr_rpmb_rw_size.attr,
4108c2ecf20Sopenharmony_ci	&dev_attr_dyn_capacity_resource_policy.attr,
4118c2ecf20Sopenharmony_ci	&dev_attr_data_ordering.attr,
4128c2ecf20Sopenharmony_ci	&dev_attr_max_number_of_contexts.attr,
4138c2ecf20Sopenharmony_ci	&dev_attr_sys_data_tag_unit_size.attr,
4148c2ecf20Sopenharmony_ci	&dev_attr_sys_data_tag_resource_size.attr,
4158c2ecf20Sopenharmony_ci	&dev_attr_secure_removal_types.attr,
4168c2ecf20Sopenharmony_ci	&dev_attr_memory_types.attr,
4178c2ecf20Sopenharmony_ci	&dev_attr_sys_code_memory_max_alloc_units.attr,
4188c2ecf20Sopenharmony_ci	&dev_attr_sys_code_memory_capacity_adjustment_factor.attr,
4198c2ecf20Sopenharmony_ci	&dev_attr_non_persist_memory_max_alloc_units.attr,
4208c2ecf20Sopenharmony_ci	&dev_attr_non_persist_memory_capacity_adjustment_factor.attr,
4218c2ecf20Sopenharmony_ci	&dev_attr_enh1_memory_max_alloc_units.attr,
4228c2ecf20Sopenharmony_ci	&dev_attr_enh1_memory_capacity_adjustment_factor.attr,
4238c2ecf20Sopenharmony_ci	&dev_attr_enh2_memory_max_alloc_units.attr,
4248c2ecf20Sopenharmony_ci	&dev_attr_enh2_memory_capacity_adjustment_factor.attr,
4258c2ecf20Sopenharmony_ci	&dev_attr_enh3_memory_max_alloc_units.attr,
4268c2ecf20Sopenharmony_ci	&dev_attr_enh3_memory_capacity_adjustment_factor.attr,
4278c2ecf20Sopenharmony_ci	&dev_attr_enh4_memory_max_alloc_units.attr,
4288c2ecf20Sopenharmony_ci	&dev_attr_enh4_memory_capacity_adjustment_factor.attr,
4298c2ecf20Sopenharmony_ci	&dev_attr_wb_max_alloc_units.attr,
4308c2ecf20Sopenharmony_ci	&dev_attr_wb_max_wb_luns.attr,
4318c2ecf20Sopenharmony_ci	&dev_attr_wb_buff_cap_adj.attr,
4328c2ecf20Sopenharmony_ci	&dev_attr_wb_sup_red_type.attr,
4338c2ecf20Sopenharmony_ci	&dev_attr_wb_sup_wb_type.attr,
4348c2ecf20Sopenharmony_ci	NULL,
4358c2ecf20Sopenharmony_ci};
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_geometry_descriptor_group = {
4388c2ecf20Sopenharmony_ci	.name = "geometry_descriptor",
4398c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_geometry_descriptor,
4408c2ecf20Sopenharmony_ci};
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci#define UFS_HEALTH_DESC_PARAM(_name, _uname, _size)			\
4438c2ecf20Sopenharmony_ci	UFS_DESC_PARAM(_name, _uname, HEALTH, _size)
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ciUFS_HEALTH_DESC_PARAM(eol_info, _EOL_INFO, 1);
4468c2ecf20Sopenharmony_ciUFS_HEALTH_DESC_PARAM(life_time_estimation_a, _LIFE_TIME_EST_A, 1);
4478c2ecf20Sopenharmony_ciUFS_HEALTH_DESC_PARAM(life_time_estimation_b, _LIFE_TIME_EST_B, 1);
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_health_descriptor[] = {
4508c2ecf20Sopenharmony_ci	&dev_attr_eol_info.attr,
4518c2ecf20Sopenharmony_ci	&dev_attr_life_time_estimation_a.attr,
4528c2ecf20Sopenharmony_ci	&dev_attr_life_time_estimation_b.attr,
4538c2ecf20Sopenharmony_ci	NULL,
4548c2ecf20Sopenharmony_ci};
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_health_descriptor_group = {
4578c2ecf20Sopenharmony_ci	.name = "health_descriptor",
4588c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_health_descriptor,
4598c2ecf20Sopenharmony_ci};
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci#define UFS_POWER_DESC_PARAM(_name, _uname, _index)			\
4628c2ecf20Sopenharmony_cistatic ssize_t _name##_index##_show(struct device *dev,			\
4638c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)			\
4648c2ecf20Sopenharmony_ci{									\
4658c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);			\
4668c2ecf20Sopenharmony_ci	return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0,	\
4678c2ecf20Sopenharmony_ci		PWR_DESC##_uname##_0 + _index * 2, buf, 2);		\
4688c2ecf20Sopenharmony_ci}									\
4698c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(_name##_index)
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 0);
4728c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 1);
4738c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 2);
4748c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 3);
4758c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 4);
4768c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 5);
4778c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 6);
4788c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 7);
4798c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 8);
4808c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 9);
4818c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 10);
4828c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 11);
4838c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 12);
4848c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 13);
4858c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 14);
4868c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 15);
4878c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 0);
4888c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 1);
4898c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 2);
4908c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 3);
4918c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 4);
4928c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 5);
4938c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 6);
4948c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 7);
4958c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 8);
4968c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 9);
4978c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 10);
4988c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 11);
4998c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 12);
5008c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 13);
5018c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 14);
5028c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 15);
5038c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 0);
5048c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 1);
5058c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 2);
5068c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 3);
5078c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 4);
5088c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 5);
5098c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 6);
5108c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 7);
5118c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 8);
5128c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 9);
5138c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 10);
5148c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 11);
5158c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 12);
5168c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 13);
5178c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 14);
5188c2ecf20Sopenharmony_ciUFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 15);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_power_descriptor[] = {
5218c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc0.attr,
5228c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc1.attr,
5238c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc2.attr,
5248c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc3.attr,
5258c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc4.attr,
5268c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc5.attr,
5278c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc6.attr,
5288c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc7.attr,
5298c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc8.attr,
5308c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc9.attr,
5318c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc10.attr,
5328c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc11.attr,
5338c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc12.attr,
5348c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc13.attr,
5358c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc14.attr,
5368c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vcc15.attr,
5378c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq0.attr,
5388c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq1.attr,
5398c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq2.attr,
5408c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq3.attr,
5418c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq4.attr,
5428c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq5.attr,
5438c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq6.attr,
5448c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq7.attr,
5458c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq8.attr,
5468c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq9.attr,
5478c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq10.attr,
5488c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq11.attr,
5498c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq12.attr,
5508c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq13.attr,
5518c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq14.attr,
5528c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq15.attr,
5538c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq20.attr,
5548c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq21.attr,
5558c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq22.attr,
5568c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq23.attr,
5578c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq24.attr,
5588c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq25.attr,
5598c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq26.attr,
5608c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq27.attr,
5618c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq28.attr,
5628c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq29.attr,
5638c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq210.attr,
5648c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq211.attr,
5658c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq212.attr,
5668c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq213.attr,
5678c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq214.attr,
5688c2ecf20Sopenharmony_ci	&dev_attr_active_icc_levels_vccq215.attr,
5698c2ecf20Sopenharmony_ci	NULL,
5708c2ecf20Sopenharmony_ci};
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_power_descriptor_group = {
5738c2ecf20Sopenharmony_ci	.name = "power_descriptor",
5748c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_power_descriptor,
5758c2ecf20Sopenharmony_ci};
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci#define UFS_STRING_DESCRIPTOR(_name, _pname)				\
5788c2ecf20Sopenharmony_cistatic ssize_t _name##_show(struct device *dev,				\
5798c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)			\
5808c2ecf20Sopenharmony_ci{									\
5818c2ecf20Sopenharmony_ci	u8 index;							\
5828c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);			\
5838c2ecf20Sopenharmony_ci	int ret;							\
5848c2ecf20Sopenharmony_ci	int desc_len = QUERY_DESC_MAX_SIZE;				\
5858c2ecf20Sopenharmony_ci	u8 *desc_buf;							\
5868c2ecf20Sopenharmony_ci									\
5878c2ecf20Sopenharmony_ci	desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC);		\
5888c2ecf20Sopenharmony_ci	if (!desc_buf)                                                  \
5898c2ecf20Sopenharmony_ci		return -ENOMEM;                                         \
5908c2ecf20Sopenharmony_ci	pm_runtime_get_sync(hba->dev);					\
5918c2ecf20Sopenharmony_ci	ret = ufshcd_query_descriptor_retry(hba,			\
5928c2ecf20Sopenharmony_ci		UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE,	\
5938c2ecf20Sopenharmony_ci		0, 0, desc_buf, &desc_len);				\
5948c2ecf20Sopenharmony_ci	if (ret) {							\
5958c2ecf20Sopenharmony_ci		ret = -EINVAL;						\
5968c2ecf20Sopenharmony_ci		goto out;						\
5978c2ecf20Sopenharmony_ci	}								\
5988c2ecf20Sopenharmony_ci	index = desc_buf[DEVICE_DESC_PARAM##_pname];			\
5998c2ecf20Sopenharmony_ci	kfree(desc_buf);						\
6008c2ecf20Sopenharmony_ci	desc_buf = NULL;						\
6018c2ecf20Sopenharmony_ci	ret = ufshcd_read_string_desc(hba, index, &desc_buf,		\
6028c2ecf20Sopenharmony_ci				      SD_ASCII_STD);			\
6038c2ecf20Sopenharmony_ci	if (ret < 0)							\
6048c2ecf20Sopenharmony_ci		goto out;						\
6058c2ecf20Sopenharmony_ci	ret = snprintf(buf, PAGE_SIZE, "%s\n", desc_buf);		\
6068c2ecf20Sopenharmony_ciout:									\
6078c2ecf20Sopenharmony_ci	pm_runtime_put_sync(hba->dev);					\
6088c2ecf20Sopenharmony_ci	kfree(desc_buf);						\
6098c2ecf20Sopenharmony_ci	return ret;							\
6108c2ecf20Sopenharmony_ci}									\
6118c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(_name)
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ciUFS_STRING_DESCRIPTOR(manufacturer_name, _MANF_NAME);
6148c2ecf20Sopenharmony_ciUFS_STRING_DESCRIPTOR(product_name, _PRDCT_NAME);
6158c2ecf20Sopenharmony_ciUFS_STRING_DESCRIPTOR(oem_id, _OEM_ID);
6168c2ecf20Sopenharmony_ciUFS_STRING_DESCRIPTOR(serial_number, _SN);
6178c2ecf20Sopenharmony_ciUFS_STRING_DESCRIPTOR(product_revision, _PRDCT_REV);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_string_descriptors[] = {
6208c2ecf20Sopenharmony_ci	&dev_attr_manufacturer_name.attr,
6218c2ecf20Sopenharmony_ci	&dev_attr_product_name.attr,
6228c2ecf20Sopenharmony_ci	&dev_attr_oem_id.attr,
6238c2ecf20Sopenharmony_ci	&dev_attr_serial_number.attr,
6248c2ecf20Sopenharmony_ci	&dev_attr_product_revision.attr,
6258c2ecf20Sopenharmony_ci	NULL,
6268c2ecf20Sopenharmony_ci};
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_string_descriptors_group = {
6298c2ecf20Sopenharmony_ci	.name = "string_descriptors",
6308c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_string_descriptors,
6318c2ecf20Sopenharmony_ci};
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_wb_flags(enum flag_idn idn)
6348c2ecf20Sopenharmony_ci{
6358c2ecf20Sopenharmony_ci	return ((idn >= QUERY_FLAG_IDN_WB_EN) &&
6368c2ecf20Sopenharmony_ci		(idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8));
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci#define UFS_FLAG(_name, _uname)						\
6408c2ecf20Sopenharmony_cistatic ssize_t _name##_show(struct device *dev,				\
6418c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)			\
6428c2ecf20Sopenharmony_ci{									\
6438c2ecf20Sopenharmony_ci	bool flag;							\
6448c2ecf20Sopenharmony_ci	u8 index = 0;							\
6458c2ecf20Sopenharmony_ci	int ret;							\
6468c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);			\
6478c2ecf20Sopenharmony_ci	if (ufshcd_is_wb_flags(QUERY_FLAG_IDN##_uname))			\
6488c2ecf20Sopenharmony_ci		index = ufshcd_wb_get_query_index(hba);			\
6498c2ecf20Sopenharmony_ci	pm_runtime_get_sync(hba->dev);					\
6508c2ecf20Sopenharmony_ci	ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,	\
6518c2ecf20Sopenharmony_ci		QUERY_FLAG_IDN##_uname, index, &flag);			\
6528c2ecf20Sopenharmony_ci	pm_runtime_put_sync(hba->dev);					\
6538c2ecf20Sopenharmony_ci	if (ret)							\
6548c2ecf20Sopenharmony_ci		return -EINVAL;						\
6558c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", flag ? "true" : "false"); \
6568c2ecf20Sopenharmony_ci}									\
6578c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(_name)
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ciUFS_FLAG(device_init, _FDEVICEINIT);
6608c2ecf20Sopenharmony_ciUFS_FLAG(permanent_wpe, _PERMANENT_WPE);
6618c2ecf20Sopenharmony_ciUFS_FLAG(power_on_wpe, _PWR_ON_WPE);
6628c2ecf20Sopenharmony_ciUFS_FLAG(bkops_enable, _BKOPS_EN);
6638c2ecf20Sopenharmony_ciUFS_FLAG(life_span_mode_enable, _LIFE_SPAN_MODE_ENABLE);
6648c2ecf20Sopenharmony_ciUFS_FLAG(phy_resource_removal, _FPHYRESOURCEREMOVAL);
6658c2ecf20Sopenharmony_ciUFS_FLAG(busy_rtc, _BUSY_RTC);
6668c2ecf20Sopenharmony_ciUFS_FLAG(disable_fw_update, _PERMANENTLY_DISABLE_FW_UPDATE);
6678c2ecf20Sopenharmony_ciUFS_FLAG(wb_enable, _WB_EN);
6688c2ecf20Sopenharmony_ciUFS_FLAG(wb_flush_en, _WB_BUFF_FLUSH_EN);
6698c2ecf20Sopenharmony_ciUFS_FLAG(wb_flush_during_h8, _WB_BUFF_FLUSH_DURING_HIBERN8);
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_device_flags[] = {
6728c2ecf20Sopenharmony_ci	&dev_attr_device_init.attr,
6738c2ecf20Sopenharmony_ci	&dev_attr_permanent_wpe.attr,
6748c2ecf20Sopenharmony_ci	&dev_attr_power_on_wpe.attr,
6758c2ecf20Sopenharmony_ci	&dev_attr_bkops_enable.attr,
6768c2ecf20Sopenharmony_ci	&dev_attr_life_span_mode_enable.attr,
6778c2ecf20Sopenharmony_ci	&dev_attr_phy_resource_removal.attr,
6788c2ecf20Sopenharmony_ci	&dev_attr_busy_rtc.attr,
6798c2ecf20Sopenharmony_ci	&dev_attr_disable_fw_update.attr,
6808c2ecf20Sopenharmony_ci	&dev_attr_wb_enable.attr,
6818c2ecf20Sopenharmony_ci	&dev_attr_wb_flush_en.attr,
6828c2ecf20Sopenharmony_ci	&dev_attr_wb_flush_during_h8.attr,
6838c2ecf20Sopenharmony_ci	NULL,
6848c2ecf20Sopenharmony_ci};
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_flags_group = {
6878c2ecf20Sopenharmony_ci	.name = "flags",
6888c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_device_flags,
6898c2ecf20Sopenharmony_ci};
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic inline bool ufshcd_is_wb_attrs(enum attr_idn idn)
6928c2ecf20Sopenharmony_ci{
6938c2ecf20Sopenharmony_ci	return ((idn >= QUERY_ATTR_IDN_WB_FLUSH_STATUS) &&
6948c2ecf20Sopenharmony_ci		(idn <= QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE));
6958c2ecf20Sopenharmony_ci}
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci#define UFS_ATTRIBUTE(_name, _uname)					\
6988c2ecf20Sopenharmony_cistatic ssize_t _name##_show(struct device *dev,				\
6998c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)			\
7008c2ecf20Sopenharmony_ci{									\
7018c2ecf20Sopenharmony_ci	struct ufs_hba *hba = dev_get_drvdata(dev);			\
7028c2ecf20Sopenharmony_ci	u32 value;							\
7038c2ecf20Sopenharmony_ci	int ret;							\
7048c2ecf20Sopenharmony_ci	u8 index = 0;							\
7058c2ecf20Sopenharmony_ci	if (ufshcd_is_wb_attrs(QUERY_ATTR_IDN##_uname))			\
7068c2ecf20Sopenharmony_ci		index = ufshcd_wb_get_query_index(hba);			\
7078c2ecf20Sopenharmony_ci	pm_runtime_get_sync(hba->dev);					\
7088c2ecf20Sopenharmony_ci	ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,	\
7098c2ecf20Sopenharmony_ci		QUERY_ATTR_IDN##_uname, index, 0, &value);		\
7108c2ecf20Sopenharmony_ci	pm_runtime_put_sync(hba->dev);					\
7118c2ecf20Sopenharmony_ci	if (ret)							\
7128c2ecf20Sopenharmony_ci		return -EINVAL;						\
7138c2ecf20Sopenharmony_ci	return sprintf(buf, "0x%08X\n", value);				\
7148c2ecf20Sopenharmony_ci}									\
7158c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(_name)
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(boot_lun_enabled, _BOOT_LU_EN);
7188c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(current_power_mode, _POWER_MODE);
7198c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(active_icc_level, _ACTIVE_ICC_LVL);
7208c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(ooo_data_enabled, _OOO_DATA_EN);
7218c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(bkops_status, _BKOPS_STATUS);
7228c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(purge_status, _PURGE_STATUS);
7238c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(max_data_in_size, _MAX_DATA_IN);
7248c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(max_data_out_size, _MAX_DATA_OUT);
7258c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(reference_clock_frequency, _REF_CLK_FREQ);
7268c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(configuration_descriptor_lock, _CONF_DESC_LOCK);
7278c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(max_number_of_rtt, _MAX_NUM_OF_RTT);
7288c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(exception_event_control, _EE_CONTROL);
7298c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(exception_event_status, _EE_STATUS);
7308c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(ffu_status, _FFU_STATUS);
7318c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(psa_state, _PSA_STATE);
7328c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(psa_data_size, _PSA_DATA_SIZE);
7338c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(wb_flush_status, _WB_FLUSH_STATUS);
7348c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(wb_avail_buf, _AVAIL_WB_BUFF_SIZE);
7358c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(wb_life_time_est, _WB_BUFF_LIFE_TIME_EST);
7368c2ecf20Sopenharmony_ciUFS_ATTRIBUTE(wb_cur_buf, _CURR_WB_BUFF_SIZE);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_attributes[] = {
7408c2ecf20Sopenharmony_ci	&dev_attr_boot_lun_enabled.attr,
7418c2ecf20Sopenharmony_ci	&dev_attr_current_power_mode.attr,
7428c2ecf20Sopenharmony_ci	&dev_attr_active_icc_level.attr,
7438c2ecf20Sopenharmony_ci	&dev_attr_ooo_data_enabled.attr,
7448c2ecf20Sopenharmony_ci	&dev_attr_bkops_status.attr,
7458c2ecf20Sopenharmony_ci	&dev_attr_purge_status.attr,
7468c2ecf20Sopenharmony_ci	&dev_attr_max_data_in_size.attr,
7478c2ecf20Sopenharmony_ci	&dev_attr_max_data_out_size.attr,
7488c2ecf20Sopenharmony_ci	&dev_attr_reference_clock_frequency.attr,
7498c2ecf20Sopenharmony_ci	&dev_attr_configuration_descriptor_lock.attr,
7508c2ecf20Sopenharmony_ci	&dev_attr_max_number_of_rtt.attr,
7518c2ecf20Sopenharmony_ci	&dev_attr_exception_event_control.attr,
7528c2ecf20Sopenharmony_ci	&dev_attr_exception_event_status.attr,
7538c2ecf20Sopenharmony_ci	&dev_attr_ffu_status.attr,
7548c2ecf20Sopenharmony_ci	&dev_attr_psa_state.attr,
7558c2ecf20Sopenharmony_ci	&dev_attr_psa_data_size.attr,
7568c2ecf20Sopenharmony_ci	&dev_attr_wb_flush_status.attr,
7578c2ecf20Sopenharmony_ci	&dev_attr_wb_avail_buf.attr,
7588c2ecf20Sopenharmony_ci	&dev_attr_wb_life_time_est.attr,
7598c2ecf20Sopenharmony_ci	&dev_attr_wb_cur_buf.attr,
7608c2ecf20Sopenharmony_ci	NULL,
7618c2ecf20Sopenharmony_ci};
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_cistatic const struct attribute_group ufs_sysfs_attributes_group = {
7648c2ecf20Sopenharmony_ci	.name = "attributes",
7658c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_attributes,
7668c2ecf20Sopenharmony_ci};
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_cistatic const struct attribute_group *ufs_sysfs_groups[] = {
7698c2ecf20Sopenharmony_ci	&ufs_sysfs_default_group,
7708c2ecf20Sopenharmony_ci	&ufs_sysfs_device_descriptor_group,
7718c2ecf20Sopenharmony_ci	&ufs_sysfs_interconnect_descriptor_group,
7728c2ecf20Sopenharmony_ci	&ufs_sysfs_geometry_descriptor_group,
7738c2ecf20Sopenharmony_ci	&ufs_sysfs_health_descriptor_group,
7748c2ecf20Sopenharmony_ci	&ufs_sysfs_power_descriptor_group,
7758c2ecf20Sopenharmony_ci	&ufs_sysfs_string_descriptors_group,
7768c2ecf20Sopenharmony_ci	&ufs_sysfs_flags_group,
7778c2ecf20Sopenharmony_ci	&ufs_sysfs_attributes_group,
7788c2ecf20Sopenharmony_ci	NULL,
7798c2ecf20Sopenharmony_ci};
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci#define UFS_LUN_DESC_PARAM(_pname, _puname, _duname, _size)		\
7828c2ecf20Sopenharmony_cistatic ssize_t _pname##_show(struct device *dev,			\
7838c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)			\
7848c2ecf20Sopenharmony_ci{									\
7858c2ecf20Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);			\
7868c2ecf20Sopenharmony_ci	struct ufs_hba *hba = shost_priv(sdev->host);			\
7878c2ecf20Sopenharmony_ci	u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);			\
7888c2ecf20Sopenharmony_ci	if (!ufs_is_valid_unit_desc_lun(&hba->dev_info, lun,		\
7898c2ecf20Sopenharmony_ci				_duname##_DESC_PARAM##_puname))		\
7908c2ecf20Sopenharmony_ci		return -EINVAL;						\
7918c2ecf20Sopenharmony_ci	return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname,	\
7928c2ecf20Sopenharmony_ci		lun, _duname##_DESC_PARAM##_puname, buf, _size);	\
7938c2ecf20Sopenharmony_ci}									\
7948c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(_pname)
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci#define UFS_UNIT_DESC_PARAM(_name, _uname, _size)			\
7978c2ecf20Sopenharmony_ci	UFS_LUN_DESC_PARAM(_name, _uname, UNIT, _size)
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(boot_lun_id, _BOOT_LUN_ID, 1);
8008c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(lun_write_protect, _LU_WR_PROTECT, 1);
8018c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(lun_queue_depth, _LU_Q_DEPTH, 1);
8028c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(psa_sensitive, _PSA_SENSITIVE, 1);
8038c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(lun_memory_type, _MEM_TYPE, 1);
8048c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(data_reliability, _DATA_RELIABILITY, 1);
8058c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(logical_block_size, _LOGICAL_BLK_SIZE, 1);
8068c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(logical_block_count, _LOGICAL_BLK_COUNT, 8);
8078c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(erase_block_size, _ERASE_BLK_SIZE, 4);
8088c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(provisioning_type, _PROVISIONING_TYPE, 1);
8098c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(physical_memory_resourse_count, _PHY_MEM_RSRC_CNT, 8);
8108c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(context_capabilities, _CTX_CAPABILITIES, 2);
8118c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(large_unit_granularity, _LARGE_UNIT_SIZE_M1, 1);
8128c2ecf20Sopenharmony_ciUFS_UNIT_DESC_PARAM(wb_buf_alloc_units, _WB_BUF_ALLOC_UNITS, 4);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_unit_descriptor[] = {
8168c2ecf20Sopenharmony_ci	&dev_attr_boot_lun_id.attr,
8178c2ecf20Sopenharmony_ci	&dev_attr_lun_write_protect.attr,
8188c2ecf20Sopenharmony_ci	&dev_attr_lun_queue_depth.attr,
8198c2ecf20Sopenharmony_ci	&dev_attr_psa_sensitive.attr,
8208c2ecf20Sopenharmony_ci	&dev_attr_lun_memory_type.attr,
8218c2ecf20Sopenharmony_ci	&dev_attr_data_reliability.attr,
8228c2ecf20Sopenharmony_ci	&dev_attr_logical_block_size.attr,
8238c2ecf20Sopenharmony_ci	&dev_attr_logical_block_count.attr,
8248c2ecf20Sopenharmony_ci	&dev_attr_erase_block_size.attr,
8258c2ecf20Sopenharmony_ci	&dev_attr_provisioning_type.attr,
8268c2ecf20Sopenharmony_ci	&dev_attr_physical_memory_resourse_count.attr,
8278c2ecf20Sopenharmony_ci	&dev_attr_context_capabilities.attr,
8288c2ecf20Sopenharmony_ci	&dev_attr_large_unit_granularity.attr,
8298c2ecf20Sopenharmony_ci	&dev_attr_wb_buf_alloc_units.attr,
8308c2ecf20Sopenharmony_ci	NULL,
8318c2ecf20Sopenharmony_ci};
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ciconst struct attribute_group ufs_sysfs_unit_descriptor_group = {
8348c2ecf20Sopenharmony_ci	.name = "unit_descriptor",
8358c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_unit_descriptor,
8368c2ecf20Sopenharmony_ci};
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_cistatic ssize_t dyn_cap_needed_attribute_show(struct device *dev,
8398c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)
8408c2ecf20Sopenharmony_ci{
8418c2ecf20Sopenharmony_ci	u32 value;
8428c2ecf20Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
8438c2ecf20Sopenharmony_ci	struct ufs_hba *hba = shost_priv(sdev->host);
8448c2ecf20Sopenharmony_ci	u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);
8458c2ecf20Sopenharmony_ci	int ret;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	pm_runtime_get_sync(hba->dev);
8488c2ecf20Sopenharmony_ci	ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
8498c2ecf20Sopenharmony_ci		QUERY_ATTR_IDN_DYN_CAP_NEEDED, lun, 0, &value);
8508c2ecf20Sopenharmony_ci	pm_runtime_put_sync(hba->dev);
8518c2ecf20Sopenharmony_ci	if (ret)
8528c2ecf20Sopenharmony_ci		return -EINVAL;
8538c2ecf20Sopenharmony_ci	return sprintf(buf, "0x%08X\n", value);
8548c2ecf20Sopenharmony_ci}
8558c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(dyn_cap_needed_attribute);
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_cistatic struct attribute *ufs_sysfs_lun_attributes[] = {
8588c2ecf20Sopenharmony_ci	&dev_attr_dyn_cap_needed_attribute.attr,
8598c2ecf20Sopenharmony_ci	NULL,
8608c2ecf20Sopenharmony_ci};
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ciconst struct attribute_group ufs_sysfs_lun_attributes_group = {
8638c2ecf20Sopenharmony_ci	.attrs = ufs_sysfs_lun_attributes,
8648c2ecf20Sopenharmony_ci};
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_civoid ufs_sysfs_add_nodes(struct device *dev)
8678c2ecf20Sopenharmony_ci{
8688c2ecf20Sopenharmony_ci	int ret;
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci	ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups);
8718c2ecf20Sopenharmony_ci	if (ret)
8728c2ecf20Sopenharmony_ci		dev_err(dev,
8738c2ecf20Sopenharmony_ci			"%s: sysfs groups creation failed (err = %d)\n",
8748c2ecf20Sopenharmony_ci			__func__, ret);
8758c2ecf20Sopenharmony_ci}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_civoid ufs_sysfs_remove_nodes(struct device *dev)
8788c2ecf20Sopenharmony_ci{
8798c2ecf20Sopenharmony_ci	sysfs_remove_groups(&dev->kobj, ufs_sysfs_groups);
8808c2ecf20Sopenharmony_ci}
881