xref: /openbmc/linux/drivers/ufs/core/ufs-sysfs.c (revision 7e9609d2)
1dd11376bSBart Van Assche // SPDX-License-Identifier: GPL-2.0
2dd11376bSBart Van Assche // Copyright (C) 2018 Western Digital Corporation
3dd11376bSBart Van Assche 
4dd11376bSBart Van Assche #include <linux/err.h>
5dd11376bSBart Van Assche #include <linux/string.h>
6dd11376bSBart Van Assche #include <linux/bitfield.h>
7dd11376bSBart Van Assche #include <asm/unaligned.h>
8dd11376bSBart Van Assche 
9dd11376bSBart Van Assche #include <ufs/ufs.h>
10dd11376bSBart Van Assche #include "ufs-sysfs.h"
11dd11376bSBart Van Assche #include "ufshcd-priv.h"
12dd11376bSBart Van Assche 
ufshcd_uic_link_state_to_string(enum uic_link_state state)13dd11376bSBart Van Assche static const char *ufshcd_uic_link_state_to_string(
14dd11376bSBart Van Assche 			enum uic_link_state state)
15dd11376bSBart Van Assche {
16dd11376bSBart Van Assche 	switch (state) {
17dd11376bSBart Van Assche 	case UIC_LINK_OFF_STATE:	return "OFF";
18dd11376bSBart Van Assche 	case UIC_LINK_ACTIVE_STATE:	return "ACTIVE";
19dd11376bSBart Van Assche 	case UIC_LINK_HIBERN8_STATE:	return "HIBERN8";
20dd11376bSBart Van Assche 	case UIC_LINK_BROKEN_STATE:	return "BROKEN";
21dd11376bSBart Van Assche 	default:			return "UNKNOWN";
22dd11376bSBart Van Assche 	}
23dd11376bSBart Van Assche }
24dd11376bSBart Van Assche 
ufshcd_ufs_dev_pwr_mode_to_string(enum ufs_dev_pwr_mode state)25dd11376bSBart Van Assche static const char *ufshcd_ufs_dev_pwr_mode_to_string(
26dd11376bSBart Van Assche 			enum ufs_dev_pwr_mode state)
27dd11376bSBart Van Assche {
28dd11376bSBart Van Assche 	switch (state) {
29dd11376bSBart Van Assche 	case UFS_ACTIVE_PWR_MODE:	return "ACTIVE";
30dd11376bSBart Van Assche 	case UFS_SLEEP_PWR_MODE:	return "SLEEP";
31dd11376bSBart Van Assche 	case UFS_POWERDOWN_PWR_MODE:	return "POWERDOWN";
32dd11376bSBart Van Assche 	case UFS_DEEPSLEEP_PWR_MODE:	return "DEEPSLEEP";
33dd11376bSBart Van Assche 	default:			return "UNKNOWN";
34dd11376bSBart Van Assche 	}
35dd11376bSBart Van Assche }
36dd11376bSBart Van Assche 
ufs_sysfs_pm_lvl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count,bool rpm)37dd11376bSBart Van Assche static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
38dd11376bSBart Van Assche 					     struct device_attribute *attr,
39dd11376bSBart Van Assche 					     const char *buf, size_t count,
40dd11376bSBart Van Assche 					     bool rpm)
41dd11376bSBart Van Assche {
42dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
43dd11376bSBart Van Assche 	struct ufs_dev_info *dev_info = &hba->dev_info;
44dd11376bSBart Van Assche 	unsigned long flags, value;
45dd11376bSBart Van Assche 
46dd11376bSBart Van Assche 	if (kstrtoul(buf, 0, &value))
47dd11376bSBart Van Assche 		return -EINVAL;
48dd11376bSBart Van Assche 
49dd11376bSBart Van Assche 	if (value >= UFS_PM_LVL_MAX)
50dd11376bSBart Van Assche 		return -EINVAL;
51dd11376bSBart Van Assche 
52dd11376bSBart Van Assche 	if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE &&
53dd11376bSBart Van Assche 	    (!(hba->caps & UFSHCD_CAP_DEEPSLEEP) ||
54dd11376bSBart Van Assche 	     !(dev_info->wspecversion >= 0x310)))
55dd11376bSBart Van Assche 		return -EINVAL;
56dd11376bSBart Van Assche 
57dd11376bSBart Van Assche 	spin_lock_irqsave(hba->host->host_lock, flags);
58dd11376bSBart Van Assche 	if (rpm)
59dd11376bSBart Van Assche 		hba->rpm_lvl = value;
60dd11376bSBart Van Assche 	else
61dd11376bSBart Van Assche 		hba->spm_lvl = value;
62dd11376bSBart Van Assche 	spin_unlock_irqrestore(hba->host->host_lock, flags);
63dd11376bSBart Van Assche 	return count;
64dd11376bSBart Van Assche }
65dd11376bSBart Van Assche 
rpm_lvl_show(struct device * dev,struct device_attribute * attr,char * buf)66dd11376bSBart Van Assche static ssize_t rpm_lvl_show(struct device *dev,
67dd11376bSBart Van Assche 		struct device_attribute *attr, char *buf)
68dd11376bSBart Van Assche {
69dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
70dd11376bSBart Van Assche 
71dd11376bSBart Van Assche 	return sysfs_emit(buf, "%d\n", hba->rpm_lvl);
72dd11376bSBart Van Assche }
73dd11376bSBart Van Assche 
rpm_lvl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)74dd11376bSBart Van Assche static ssize_t rpm_lvl_store(struct device *dev,
75dd11376bSBart Van Assche 		struct device_attribute *attr, const char *buf, size_t count)
76dd11376bSBart Van Assche {
77dd11376bSBart Van Assche 	return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, true);
78dd11376bSBart Van Assche }
79dd11376bSBart Van Assche 
rpm_target_dev_state_show(struct device * dev,struct device_attribute * attr,char * buf)80dd11376bSBart Van Assche static ssize_t rpm_target_dev_state_show(struct device *dev,
81dd11376bSBart Van Assche 		struct device_attribute *attr, char *buf)
82dd11376bSBart Van Assche {
83dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
84dd11376bSBart Van Assche 
85dd11376bSBart Van Assche 	return sysfs_emit(buf, "%s\n", ufshcd_ufs_dev_pwr_mode_to_string(
86dd11376bSBart Van Assche 			ufs_pm_lvl_states[hba->rpm_lvl].dev_state));
87dd11376bSBart Van Assche }
88dd11376bSBart Van Assche 
rpm_target_link_state_show(struct device * dev,struct device_attribute * attr,char * buf)89dd11376bSBart Van Assche static ssize_t rpm_target_link_state_show(struct device *dev,
90dd11376bSBart Van Assche 		struct device_attribute *attr, char *buf)
91dd11376bSBart Van Assche {
92dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
93dd11376bSBart Van Assche 
94dd11376bSBart Van Assche 	return sysfs_emit(buf, "%s\n", ufshcd_uic_link_state_to_string(
95dd11376bSBart Van Assche 			ufs_pm_lvl_states[hba->rpm_lvl].link_state));
96dd11376bSBart Van Assche }
97dd11376bSBart Van Assche 
spm_lvl_show(struct device * dev,struct device_attribute * attr,char * buf)98dd11376bSBart Van Assche static ssize_t spm_lvl_show(struct device *dev,
99dd11376bSBart Van Assche 		struct device_attribute *attr, char *buf)
100dd11376bSBart Van Assche {
101dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
102dd11376bSBart Van Assche 
103dd11376bSBart Van Assche 	return sysfs_emit(buf, "%d\n", hba->spm_lvl);
104dd11376bSBart Van Assche }
105dd11376bSBart Van Assche 
spm_lvl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)106dd11376bSBart Van Assche static ssize_t spm_lvl_store(struct device *dev,
107dd11376bSBart Van Assche 		struct device_attribute *attr, const char *buf, size_t count)
108dd11376bSBart Van Assche {
109dd11376bSBart Van Assche 	return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false);
110dd11376bSBart Van Assche }
111dd11376bSBart Van Assche 
spm_target_dev_state_show(struct device * dev,struct device_attribute * attr,char * buf)112dd11376bSBart Van Assche static ssize_t spm_target_dev_state_show(struct device *dev,
113dd11376bSBart Van Assche 		struct device_attribute *attr, char *buf)
114dd11376bSBart Van Assche {
115dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
116dd11376bSBart Van Assche 
117dd11376bSBart Van Assche 	return sysfs_emit(buf, "%s\n", ufshcd_ufs_dev_pwr_mode_to_string(
118dd11376bSBart Van Assche 				ufs_pm_lvl_states[hba->spm_lvl].dev_state));
119dd11376bSBart Van Assche }
120dd11376bSBart Van Assche 
spm_target_link_state_show(struct device * dev,struct device_attribute * attr,char * buf)121dd11376bSBart Van Assche static ssize_t spm_target_link_state_show(struct device *dev,
122dd11376bSBart Van Assche 		struct device_attribute *attr, char *buf)
123dd11376bSBart Van Assche {
124dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
125dd11376bSBart Van Assche 
126dd11376bSBart Van Assche 	return sysfs_emit(buf, "%s\n", ufshcd_uic_link_state_to_string(
127dd11376bSBart Van Assche 				ufs_pm_lvl_states[hba->spm_lvl].link_state));
128dd11376bSBart Van Assche }
129dd11376bSBart Van Assche 
130dd11376bSBart Van Assche /* Convert Auto-Hibernate Idle Timer register value to microseconds */
ufshcd_ahit_to_us(u32 ahit)131dd11376bSBart Van Assche static int ufshcd_ahit_to_us(u32 ahit)
132dd11376bSBart Van Assche {
133dd11376bSBart Van Assche 	int timer = FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, ahit);
134dd11376bSBart Van Assche 	int scale = FIELD_GET(UFSHCI_AHIBERN8_SCALE_MASK, ahit);
135dd11376bSBart Van Assche 
136dd11376bSBart Van Assche 	for (; scale > 0; --scale)
137dd11376bSBart Van Assche 		timer *= UFSHCI_AHIBERN8_SCALE_FACTOR;
138dd11376bSBart Van Assche 
139dd11376bSBart Van Assche 	return timer;
140dd11376bSBart Van Assche }
141dd11376bSBart Van Assche 
142dd11376bSBart Van Assche /* Convert microseconds to Auto-Hibernate Idle Timer register value */
ufshcd_us_to_ahit(unsigned int timer)143dd11376bSBart Van Assche static u32 ufshcd_us_to_ahit(unsigned int timer)
144dd11376bSBart Van Assche {
145dd11376bSBart Van Assche 	unsigned int scale;
146dd11376bSBart Van Assche 
147dd11376bSBart Van Assche 	for (scale = 0; timer > UFSHCI_AHIBERN8_TIMER_MASK; ++scale)
148dd11376bSBart Van Assche 		timer /= UFSHCI_AHIBERN8_SCALE_FACTOR;
149dd11376bSBart Van Assche 
150dd11376bSBart Van Assche 	return FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, timer) |
151dd11376bSBart Van Assche 	       FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, scale);
152dd11376bSBart Van Assche }
153dd11376bSBart Van Assche 
auto_hibern8_show(struct device * dev,struct device_attribute * attr,char * buf)154dd11376bSBart Van Assche static ssize_t auto_hibern8_show(struct device *dev,
155dd11376bSBart Van Assche 				 struct device_attribute *attr, char *buf)
156dd11376bSBart Van Assche {
157dd11376bSBart Van Assche 	u32 ahit;
158dd11376bSBart Van Assche 	int ret;
159dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
160dd11376bSBart Van Assche 
161dd11376bSBart Van Assche 	if (!ufshcd_is_auto_hibern8_supported(hba))
162dd11376bSBart Van Assche 		return -EOPNOTSUPP;
163dd11376bSBart Van Assche 
164dd11376bSBart Van Assche 	down(&hba->host_sem);
165dd11376bSBart Van Assche 	if (!ufshcd_is_user_access_allowed(hba)) {
166dd11376bSBart Van Assche 		ret = -EBUSY;
167dd11376bSBart Van Assche 		goto out;
168dd11376bSBart Van Assche 	}
169dd11376bSBart Van Assche 
170dd11376bSBart Van Assche 	pm_runtime_get_sync(hba->dev);
171078f4f4bSBart Van Assche 	ufshcd_hold(hba);
172dd11376bSBart Van Assche 	ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER);
173dd11376bSBart Van Assche 	ufshcd_release(hba);
174dd11376bSBart Van Assche 	pm_runtime_put_sync(hba->dev);
175dd11376bSBart Van Assche 
176dd11376bSBart Van Assche 	ret = sysfs_emit(buf, "%d\n", ufshcd_ahit_to_us(ahit));
177dd11376bSBart Van Assche 
178dd11376bSBart Van Assche out:
179dd11376bSBart Van Assche 	up(&hba->host_sem);
180dd11376bSBart Van Assche 	return ret;
181dd11376bSBart Van Assche }
182dd11376bSBart Van Assche 
auto_hibern8_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)183dd11376bSBart Van Assche static ssize_t auto_hibern8_store(struct device *dev,
184dd11376bSBart Van Assche 				  struct device_attribute *attr,
185dd11376bSBart Van Assche 				  const char *buf, size_t count)
186dd11376bSBart Van Assche {
187dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
188dd11376bSBart Van Assche 	unsigned int timer;
189dd11376bSBart Van Assche 	int ret = 0;
190dd11376bSBart Van Assche 
191dd11376bSBart Van Assche 	if (!ufshcd_is_auto_hibern8_supported(hba))
192dd11376bSBart Van Assche 		return -EOPNOTSUPP;
193dd11376bSBart Van Assche 
194dd11376bSBart Van Assche 	if (kstrtouint(buf, 0, &timer))
195dd11376bSBart Van Assche 		return -EINVAL;
196dd11376bSBart Van Assche 
197dd11376bSBart Van Assche 	if (timer > UFSHCI_AHIBERN8_MAX)
198dd11376bSBart Van Assche 		return -EINVAL;
199dd11376bSBart Van Assche 
200dd11376bSBart Van Assche 	down(&hba->host_sem);
201dd11376bSBart Van Assche 	if (!ufshcd_is_user_access_allowed(hba)) {
202dd11376bSBart Van Assche 		ret = -EBUSY;
203dd11376bSBart Van Assche 		goto out;
204dd11376bSBart Van Assche 	}
205dd11376bSBart Van Assche 
206dd11376bSBart Van Assche 	ufshcd_auto_hibern8_update(hba, ufshcd_us_to_ahit(timer));
207dd11376bSBart Van Assche 
208dd11376bSBart Van Assche out:
209dd11376bSBart Van Assche 	up(&hba->host_sem);
210dd11376bSBart Van Assche 	return ret ? ret : count;
211dd11376bSBart Van Assche }
212dd11376bSBart Van Assche 
wb_on_show(struct device * dev,struct device_attribute * attr,char * buf)213dd11376bSBart Van Assche static ssize_t wb_on_show(struct device *dev, struct device_attribute *attr,
214dd11376bSBart Van Assche 			  char *buf)
215dd11376bSBart Van Assche {
216dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
217dd11376bSBart Van Assche 
218dd11376bSBart Van Assche 	return sysfs_emit(buf, "%d\n", hba->dev_info.wb_enabled);
219dd11376bSBart Van Assche }
220dd11376bSBart Van Assche 
wb_on_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)221dd11376bSBart Van Assche static ssize_t wb_on_store(struct device *dev, struct device_attribute *attr,
222dd11376bSBart Van Assche 			   const char *buf, size_t count)
223dd11376bSBart Van Assche {
224dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
225dd11376bSBart Van Assche 	unsigned int wb_enable;
226dd11376bSBart Van Assche 	ssize_t res;
227dd11376bSBart Van Assche 
22887bd0501SPeter Wang 	if (!ufshcd_is_wb_allowed(hba) || (ufshcd_is_clkscaling_supported(hba)
22987bd0501SPeter Wang 		&& ufshcd_enable_wb_if_scaling_up(hba))) {
230dd11376bSBart Van Assche 		/*
231dd11376bSBart Van Assche 		 * If the platform supports UFSHCD_CAP_CLK_SCALING, turn WB
232dd11376bSBart Van Assche 		 * on/off will be done while clock scaling up/down.
233dd11376bSBart Van Assche 		 */
2344f6b69f3SJinyoung Choi 		dev_warn(dev, "It is not allowed to configure WB!\n");
235dd11376bSBart Van Assche 		return -EOPNOTSUPP;
236dd11376bSBart Van Assche 	}
237dd11376bSBart Van Assche 
238dd11376bSBart Van Assche 	if (kstrtouint(buf, 0, &wb_enable))
239dd11376bSBart Van Assche 		return -EINVAL;
240dd11376bSBart Van Assche 
241dd11376bSBart Van Assche 	if (wb_enable != 0 && wb_enable != 1)
242dd11376bSBart Van Assche 		return -EINVAL;
243dd11376bSBart Van Assche 
244dd11376bSBart Van Assche 	down(&hba->host_sem);
245dd11376bSBart Van Assche 	if (!ufshcd_is_user_access_allowed(hba)) {
246dd11376bSBart Van Assche 		res = -EBUSY;
247dd11376bSBart Van Assche 		goto out;
248dd11376bSBart Van Assche 	}
249dd11376bSBart Van Assche 
250dd11376bSBart Van Assche 	ufshcd_rpm_get_sync(hba);
251dd11376bSBart Van Assche 	res = ufshcd_wb_toggle(hba, wb_enable);
252dd11376bSBart Van Assche 	ufshcd_rpm_put_sync(hba);
253dd11376bSBart Van Assche out:
254dd11376bSBart Van Assche 	up(&hba->host_sem);
255dd11376bSBart Van Assche 	return res < 0 ? res : count;
256dd11376bSBart Van Assche }
257dd11376bSBart Van Assche 
enable_wb_buf_flush_show(struct device * dev,struct device_attribute * attr,char * buf)2586c4148ceSJinyoung Choi static ssize_t enable_wb_buf_flush_show(struct device *dev,
2596c4148ceSJinyoung Choi 				    struct device_attribute *attr,
2606c4148ceSJinyoung Choi 				    char *buf)
2616c4148ceSJinyoung Choi {
2626c4148ceSJinyoung Choi 	struct ufs_hba *hba = dev_get_drvdata(dev);
2636c4148ceSJinyoung Choi 
2646c4148ceSJinyoung Choi 	return sysfs_emit(buf, "%d\n", hba->dev_info.wb_buf_flush_enabled);
2656c4148ceSJinyoung Choi }
2666c4148ceSJinyoung Choi 
enable_wb_buf_flush_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2676c4148ceSJinyoung Choi static ssize_t enable_wb_buf_flush_store(struct device *dev,
2686c4148ceSJinyoung Choi 				     struct device_attribute *attr,
2696c4148ceSJinyoung Choi 				     const char *buf, size_t count)
2706c4148ceSJinyoung Choi {
2716c4148ceSJinyoung Choi 	struct ufs_hba *hba = dev_get_drvdata(dev);
2726c4148ceSJinyoung Choi 	unsigned int enable_wb_buf_flush;
2736c4148ceSJinyoung Choi 	ssize_t res;
2746c4148ceSJinyoung Choi 
27542f8c5cdSJinyoung Choi 	if (!ufshcd_is_wb_buf_flush_allowed(hba)) {
2766c4148ceSJinyoung Choi 		dev_warn(dev, "It is not allowed to configure WB buf flushing!\n");
2776c4148ceSJinyoung Choi 		return -EOPNOTSUPP;
2786c4148ceSJinyoung Choi 	}
2796c4148ceSJinyoung Choi 
2806c4148ceSJinyoung Choi 	if (kstrtouint(buf, 0, &enable_wb_buf_flush))
2816c4148ceSJinyoung Choi 		return -EINVAL;
2826c4148ceSJinyoung Choi 
2836c4148ceSJinyoung Choi 	if (enable_wb_buf_flush != 0 && enable_wb_buf_flush != 1)
2846c4148ceSJinyoung Choi 		return -EINVAL;
2856c4148ceSJinyoung Choi 
2866c4148ceSJinyoung Choi 	down(&hba->host_sem);
2876c4148ceSJinyoung Choi 	if (!ufshcd_is_user_access_allowed(hba)) {
2886c4148ceSJinyoung Choi 		res = -EBUSY;
2896c4148ceSJinyoung Choi 		goto out;
2906c4148ceSJinyoung Choi 	}
2916c4148ceSJinyoung Choi 
2926c4148ceSJinyoung Choi 	ufshcd_rpm_get_sync(hba);
2936c4148ceSJinyoung Choi 	res = ufshcd_wb_toggle_buf_flush(hba, enable_wb_buf_flush);
2946c4148ceSJinyoung Choi 	ufshcd_rpm_put_sync(hba);
2956c4148ceSJinyoung Choi 
2966c4148ceSJinyoung Choi out:
2976c4148ceSJinyoung Choi 	up(&hba->host_sem);
2986c4148ceSJinyoung Choi 	return res < 0 ? res : count;
2996c4148ceSJinyoung Choi }
3006c4148ceSJinyoung Choi 
wb_flush_threshold_show(struct device * dev,struct device_attribute * attr,char * buf)301*e3d55626SLu Hongfei static ssize_t wb_flush_threshold_show(struct device *dev,
302*e3d55626SLu Hongfei 					 struct device_attribute *attr,
303*e3d55626SLu Hongfei 					 char *buf)
304*e3d55626SLu Hongfei {
305*e3d55626SLu Hongfei 	struct ufs_hba *hba = dev_get_drvdata(dev);
306*e3d55626SLu Hongfei 
307*e3d55626SLu Hongfei 	return sysfs_emit(buf, "%u\n", hba->vps->wb_flush_threshold);
308*e3d55626SLu Hongfei }
309*e3d55626SLu Hongfei 
wb_flush_threshold_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)310*e3d55626SLu Hongfei static ssize_t wb_flush_threshold_store(struct device *dev,
311*e3d55626SLu Hongfei 					  struct device_attribute *attr,
312*e3d55626SLu Hongfei 					  const char *buf, size_t count)
313*e3d55626SLu Hongfei {
314*e3d55626SLu Hongfei 	struct ufs_hba *hba = dev_get_drvdata(dev);
315*e3d55626SLu Hongfei 	unsigned int wb_flush_threshold;
316*e3d55626SLu Hongfei 
317*e3d55626SLu Hongfei 	if (kstrtouint(buf, 0, &wb_flush_threshold))
318*e3d55626SLu Hongfei 		return -EINVAL;
319*e3d55626SLu Hongfei 
320*e3d55626SLu Hongfei 	/* The range of values for wb_flush_threshold is (0,10] */
321*e3d55626SLu Hongfei 	if (wb_flush_threshold > UFS_WB_BUF_REMAIN_PERCENT(100) ||
322*e3d55626SLu Hongfei 	    wb_flush_threshold == 0) {
323*e3d55626SLu Hongfei 		dev_err(dev, "The value of wb_flush_threshold is invalid!\n");
324*e3d55626SLu Hongfei 		return -EINVAL;
325*e3d55626SLu Hongfei 	}
326*e3d55626SLu Hongfei 
327*e3d55626SLu Hongfei 	hba->vps->wb_flush_threshold = wb_flush_threshold;
328*e3d55626SLu Hongfei 
329*e3d55626SLu Hongfei 	return count;
330*e3d55626SLu Hongfei }
331*e3d55626SLu Hongfei 
332dd11376bSBart Van Assche static DEVICE_ATTR_RW(rpm_lvl);
333dd11376bSBart Van Assche static DEVICE_ATTR_RO(rpm_target_dev_state);
334dd11376bSBart Van Assche static DEVICE_ATTR_RO(rpm_target_link_state);
335dd11376bSBart Van Assche static DEVICE_ATTR_RW(spm_lvl);
336dd11376bSBart Van Assche static DEVICE_ATTR_RO(spm_target_dev_state);
337dd11376bSBart Van Assche static DEVICE_ATTR_RO(spm_target_link_state);
338dd11376bSBart Van Assche static DEVICE_ATTR_RW(auto_hibern8);
339dd11376bSBart Van Assche static DEVICE_ATTR_RW(wb_on);
3406c4148ceSJinyoung Choi static DEVICE_ATTR_RW(enable_wb_buf_flush);
341*e3d55626SLu Hongfei static DEVICE_ATTR_RW(wb_flush_threshold);
342dd11376bSBart Van Assche 
343dd11376bSBart Van Assche static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
344dd11376bSBart Van Assche 	&dev_attr_rpm_lvl.attr,
345dd11376bSBart Van Assche 	&dev_attr_rpm_target_dev_state.attr,
346dd11376bSBart Van Assche 	&dev_attr_rpm_target_link_state.attr,
347dd11376bSBart Van Assche 	&dev_attr_spm_lvl.attr,
348dd11376bSBart Van Assche 	&dev_attr_spm_target_dev_state.attr,
349dd11376bSBart Van Assche 	&dev_attr_spm_target_link_state.attr,
350dd11376bSBart Van Assche 	&dev_attr_auto_hibern8.attr,
351dd11376bSBart Van Assche 	&dev_attr_wb_on.attr,
3526c4148ceSJinyoung Choi 	&dev_attr_enable_wb_buf_flush.attr,
353*e3d55626SLu Hongfei 	&dev_attr_wb_flush_threshold.attr,
354dd11376bSBart Van Assche 	NULL
355dd11376bSBart Van Assche };
356dd11376bSBart Van Assche 
357dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_default_group = {
358dd11376bSBart Van Assche 	.attrs = ufs_sysfs_ufshcd_attrs,
359dd11376bSBart Van Assche };
360dd11376bSBart Van Assche 
clock_scaling_show(struct device * dev,struct device_attribute * attr,char * buf)3612286ade0SDaniil Lunev static ssize_t clock_scaling_show(struct device *dev, struct device_attribute *attr,
3622286ade0SDaniil Lunev 				  char *buf)
3632286ade0SDaniil Lunev {
3642286ade0SDaniil Lunev 	struct ufs_hba *hba = dev_get_drvdata(dev);
3652286ade0SDaniil Lunev 
3662286ade0SDaniil Lunev 	return sysfs_emit(buf, "%d\n", ufshcd_is_clkscaling_supported(hba));
3672286ade0SDaniil Lunev }
3682286ade0SDaniil Lunev 
write_booster_show(struct device * dev,struct device_attribute * attr,char * buf)3692286ade0SDaniil Lunev static ssize_t write_booster_show(struct device *dev, struct device_attribute *attr,
3702286ade0SDaniil Lunev 				  char *buf)
3712286ade0SDaniil Lunev {
3722286ade0SDaniil Lunev 	struct ufs_hba *hba = dev_get_drvdata(dev);
3732286ade0SDaniil Lunev 
3742286ade0SDaniil Lunev 	return sysfs_emit(buf, "%d\n", ufshcd_is_wb_allowed(hba));
3752286ade0SDaniil Lunev }
3762286ade0SDaniil Lunev 
3772286ade0SDaniil Lunev static DEVICE_ATTR_RO(clock_scaling);
3782286ade0SDaniil Lunev static DEVICE_ATTR_RO(write_booster);
3792286ade0SDaniil Lunev 
3802286ade0SDaniil Lunev /*
3812286ade0SDaniil Lunev  * See Documentation/ABI/testing/sysfs-driver-ufs for the semantics of this
3822286ade0SDaniil Lunev  * group.
3832286ade0SDaniil Lunev  */
3842286ade0SDaniil Lunev static struct attribute *ufs_sysfs_capabilities_attrs[] = {
3852286ade0SDaniil Lunev 	&dev_attr_clock_scaling.attr,
3862286ade0SDaniil Lunev 	&dev_attr_write_booster.attr,
3872286ade0SDaniil Lunev 	NULL
3882286ade0SDaniil Lunev };
3892286ade0SDaniil Lunev 
3902286ade0SDaniil Lunev static const struct attribute_group ufs_sysfs_capabilities_group = {
3912286ade0SDaniil Lunev 	.name = "capabilities",
3922286ade0SDaniil Lunev 	.attrs = ufs_sysfs_capabilities_attrs,
3932286ade0SDaniil Lunev };
3942286ade0SDaniil Lunev 
monitor_enable_show(struct device * dev,struct device_attribute * attr,char * buf)395dd11376bSBart Van Assche static ssize_t monitor_enable_show(struct device *dev,
396dd11376bSBart Van Assche 				   struct device_attribute *attr, char *buf)
397dd11376bSBart Van Assche {
398dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
399dd11376bSBart Van Assche 
400dd11376bSBart Van Assche 	return sysfs_emit(buf, "%d\n", hba->monitor.enabled);
401dd11376bSBart Van Assche }
402dd11376bSBart Van Assche 
monitor_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)403dd11376bSBart Van Assche static ssize_t monitor_enable_store(struct device *dev,
404dd11376bSBart Van Assche 				    struct device_attribute *attr,
405dd11376bSBart Van Assche 				    const char *buf, size_t count)
406dd11376bSBart Van Assche {
407dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
408dd11376bSBart Van Assche 	unsigned long value, flags;
409dd11376bSBart Van Assche 
410dd11376bSBart Van Assche 	if (kstrtoul(buf, 0, &value))
411dd11376bSBart Van Assche 		return -EINVAL;
412dd11376bSBart Van Assche 
413dd11376bSBart Van Assche 	value = !!value;
414dd11376bSBart Van Assche 	spin_lock_irqsave(hba->host->host_lock, flags);
415dd11376bSBart Van Assche 	if (value == hba->monitor.enabled)
416dd11376bSBart Van Assche 		goto out_unlock;
417dd11376bSBart Van Assche 
418dd11376bSBart Van Assche 	if (!value) {
419dd11376bSBart Van Assche 		memset(&hba->monitor, 0, sizeof(hba->monitor));
420dd11376bSBart Van Assche 	} else {
421dd11376bSBart Van Assche 		hba->monitor.enabled = true;
422dd11376bSBart Van Assche 		hba->monitor.enabled_ts = ktime_get();
423dd11376bSBart Van Assche 	}
424dd11376bSBart Van Assche 
425dd11376bSBart Van Assche out_unlock:
426dd11376bSBart Van Assche 	spin_unlock_irqrestore(hba->host->host_lock, flags);
427dd11376bSBart Van Assche 	return count;
428dd11376bSBart Van Assche }
429dd11376bSBart Van Assche 
monitor_chunk_size_show(struct device * dev,struct device_attribute * attr,char * buf)430dd11376bSBart Van Assche static ssize_t monitor_chunk_size_show(struct device *dev,
431dd11376bSBart Van Assche 				   struct device_attribute *attr, char *buf)
432dd11376bSBart Van Assche {
433dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
434dd11376bSBart Van Assche 
435dd11376bSBart Van Assche 	return sysfs_emit(buf, "%lu\n", hba->monitor.chunk_size);
436dd11376bSBart Van Assche }
437dd11376bSBart Van Assche 
monitor_chunk_size_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)438dd11376bSBart Van Assche static ssize_t monitor_chunk_size_store(struct device *dev,
439dd11376bSBart Van Assche 				    struct device_attribute *attr,
440dd11376bSBart Van Assche 				    const char *buf, size_t count)
441dd11376bSBart Van Assche {
442dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
443dd11376bSBart Van Assche 	unsigned long value, flags;
444dd11376bSBart Van Assche 
445dd11376bSBart Van Assche 	if (kstrtoul(buf, 0, &value))
446dd11376bSBart Van Assche 		return -EINVAL;
447dd11376bSBart Van Assche 
448dd11376bSBart Van Assche 	spin_lock_irqsave(hba->host->host_lock, flags);
449dd11376bSBart Van Assche 	/* Only allow chunk size change when monitor is disabled */
450dd11376bSBart Van Assche 	if (!hba->monitor.enabled)
451dd11376bSBart Van Assche 		hba->monitor.chunk_size = value;
452dd11376bSBart Van Assche 	spin_unlock_irqrestore(hba->host->host_lock, flags);
453dd11376bSBart Van Assche 	return count;
454dd11376bSBart Van Assche }
455dd11376bSBart Van Assche 
read_total_sectors_show(struct device * dev,struct device_attribute * attr,char * buf)456dd11376bSBart Van Assche static ssize_t read_total_sectors_show(struct device *dev,
457dd11376bSBart Van Assche 				       struct device_attribute *attr, char *buf)
458dd11376bSBart Van Assche {
459dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
460dd11376bSBart Van Assche 
461dd11376bSBart Van Assche 	return sysfs_emit(buf, "%lu\n", hba->monitor.nr_sec_rw[READ]);
462dd11376bSBart Van Assche }
463dd11376bSBart Van Assche 
read_total_busy_show(struct device * dev,struct device_attribute * attr,char * buf)464dd11376bSBart Van Assche static ssize_t read_total_busy_show(struct device *dev,
465dd11376bSBart Van Assche 				    struct device_attribute *attr, char *buf)
466dd11376bSBart Van Assche {
467dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
468dd11376bSBart Van Assche 
469dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n",
470dd11376bSBart Van Assche 			  ktime_to_us(hba->monitor.total_busy[READ]));
471dd11376bSBart Van Assche }
472dd11376bSBart Van Assche 
read_nr_requests_show(struct device * dev,struct device_attribute * attr,char * buf)473dd11376bSBart Van Assche static ssize_t read_nr_requests_show(struct device *dev,
474dd11376bSBart Van Assche 				     struct device_attribute *attr, char *buf)
475dd11376bSBart Van Assche {
476dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
477dd11376bSBart Van Assche 
478dd11376bSBart Van Assche 	return sysfs_emit(buf, "%lu\n", hba->monitor.nr_req[READ]);
479dd11376bSBart Van Assche }
480dd11376bSBart Van Assche 
read_req_latency_avg_show(struct device * dev,struct device_attribute * attr,char * buf)481dd11376bSBart Van Assche static ssize_t read_req_latency_avg_show(struct device *dev,
482dd11376bSBart Van Assche 					 struct device_attribute *attr,
483dd11376bSBart Van Assche 					 char *buf)
484dd11376bSBart Van Assche {
485dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
486dd11376bSBart Van Assche 	struct ufs_hba_monitor *m = &hba->monitor;
487dd11376bSBart Van Assche 
488dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n", div_u64(ktime_to_us(m->lat_sum[READ]),
489dd11376bSBart Van Assche 						 m->nr_req[READ]));
490dd11376bSBart Van Assche }
491dd11376bSBart Van Assche 
read_req_latency_max_show(struct device * dev,struct device_attribute * attr,char * buf)492dd11376bSBart Van Assche static ssize_t read_req_latency_max_show(struct device *dev,
493dd11376bSBart Van Assche 					 struct device_attribute *attr,
494dd11376bSBart Van Assche 					 char *buf)
495dd11376bSBart Van Assche {
496dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
497dd11376bSBart Van Assche 
498dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n",
499dd11376bSBart Van Assche 			  ktime_to_us(hba->monitor.lat_max[READ]));
500dd11376bSBart Van Assche }
501dd11376bSBart Van Assche 
read_req_latency_min_show(struct device * dev,struct device_attribute * attr,char * buf)502dd11376bSBart Van Assche static ssize_t read_req_latency_min_show(struct device *dev,
503dd11376bSBart Van Assche 					 struct device_attribute *attr,
504dd11376bSBart Van Assche 					 char *buf)
505dd11376bSBart Van Assche {
506dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
507dd11376bSBart Van Assche 
508dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n",
509dd11376bSBart Van Assche 			  ktime_to_us(hba->monitor.lat_min[READ]));
510dd11376bSBart Van Assche }
511dd11376bSBart Van Assche 
read_req_latency_sum_show(struct device * dev,struct device_attribute * attr,char * buf)512dd11376bSBart Van Assche static ssize_t read_req_latency_sum_show(struct device *dev,
513dd11376bSBart Van Assche 					 struct device_attribute *attr,
514dd11376bSBart Van Assche 					 char *buf)
515dd11376bSBart Van Assche {
516dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
517dd11376bSBart Van Assche 
518dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n",
519dd11376bSBart Van Assche 			  ktime_to_us(hba->monitor.lat_sum[READ]));
520dd11376bSBart Van Assche }
521dd11376bSBart Van Assche 
write_total_sectors_show(struct device * dev,struct device_attribute * attr,char * buf)522dd11376bSBart Van Assche static ssize_t write_total_sectors_show(struct device *dev,
523dd11376bSBart Van Assche 					struct device_attribute *attr,
524dd11376bSBart Van Assche 					char *buf)
525dd11376bSBart Van Assche {
526dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
527dd11376bSBart Van Assche 
528dd11376bSBart Van Assche 	return sysfs_emit(buf, "%lu\n", hba->monitor.nr_sec_rw[WRITE]);
529dd11376bSBart Van Assche }
530dd11376bSBart Van Assche 
write_total_busy_show(struct device * dev,struct device_attribute * attr,char * buf)531dd11376bSBart Van Assche static ssize_t write_total_busy_show(struct device *dev,
532dd11376bSBart Van Assche 				     struct device_attribute *attr, char *buf)
533dd11376bSBart Van Assche {
534dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
535dd11376bSBart Van Assche 
536dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n",
537dd11376bSBart Van Assche 			  ktime_to_us(hba->monitor.total_busy[WRITE]));
538dd11376bSBart Van Assche }
539dd11376bSBart Van Assche 
write_nr_requests_show(struct device * dev,struct device_attribute * attr,char * buf)540dd11376bSBart Van Assche static ssize_t write_nr_requests_show(struct device *dev,
541dd11376bSBart Van Assche 				      struct device_attribute *attr, char *buf)
542dd11376bSBart Van Assche {
543dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
544dd11376bSBart Van Assche 
545dd11376bSBart Van Assche 	return sysfs_emit(buf, "%lu\n", hba->monitor.nr_req[WRITE]);
546dd11376bSBart Van Assche }
547dd11376bSBart Van Assche 
write_req_latency_avg_show(struct device * dev,struct device_attribute * attr,char * buf)548dd11376bSBart Van Assche static ssize_t write_req_latency_avg_show(struct device *dev,
549dd11376bSBart Van Assche 					  struct device_attribute *attr,
550dd11376bSBart Van Assche 					  char *buf)
551dd11376bSBart Van Assche {
552dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
553dd11376bSBart Van Assche 	struct ufs_hba_monitor *m = &hba->monitor;
554dd11376bSBart Van Assche 
555dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n", div_u64(ktime_to_us(m->lat_sum[WRITE]),
556dd11376bSBart Van Assche 						 m->nr_req[WRITE]));
557dd11376bSBart Van Assche }
558dd11376bSBart Van Assche 
write_req_latency_max_show(struct device * dev,struct device_attribute * attr,char * buf)559dd11376bSBart Van Assche static ssize_t write_req_latency_max_show(struct device *dev,
560dd11376bSBart Van Assche 					  struct device_attribute *attr,
561dd11376bSBart Van Assche 					  char *buf)
562dd11376bSBart Van Assche {
563dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
564dd11376bSBart Van Assche 
565dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n",
566dd11376bSBart Van Assche 			  ktime_to_us(hba->monitor.lat_max[WRITE]));
567dd11376bSBart Van Assche }
568dd11376bSBart Van Assche 
write_req_latency_min_show(struct device * dev,struct device_attribute * attr,char * buf)569dd11376bSBart Van Assche static ssize_t write_req_latency_min_show(struct device *dev,
570dd11376bSBart Van Assche 					  struct device_attribute *attr,
571dd11376bSBart Van Assche 					  char *buf)
572dd11376bSBart Van Assche {
573dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
574dd11376bSBart Van Assche 
575dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n",
576dd11376bSBart Van Assche 			  ktime_to_us(hba->monitor.lat_min[WRITE]));
577dd11376bSBart Van Assche }
578dd11376bSBart Van Assche 
write_req_latency_sum_show(struct device * dev,struct device_attribute * attr,char * buf)579dd11376bSBart Van Assche static ssize_t write_req_latency_sum_show(struct device *dev,
580dd11376bSBart Van Assche 					  struct device_attribute *attr,
581dd11376bSBart Van Assche 					  char *buf)
582dd11376bSBart Van Assche {
583dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);
584dd11376bSBart Van Assche 
585dd11376bSBart Van Assche 	return sysfs_emit(buf, "%llu\n",
586dd11376bSBart Van Assche 			  ktime_to_us(hba->monitor.lat_sum[WRITE]));
587dd11376bSBart Van Assche }
588dd11376bSBart Van Assche 
589dd11376bSBart Van Assche static DEVICE_ATTR_RW(monitor_enable);
590dd11376bSBart Van Assche static DEVICE_ATTR_RW(monitor_chunk_size);
591dd11376bSBart Van Assche static DEVICE_ATTR_RO(read_total_sectors);
592dd11376bSBart Van Assche static DEVICE_ATTR_RO(read_total_busy);
593dd11376bSBart Van Assche static DEVICE_ATTR_RO(read_nr_requests);
594dd11376bSBart Van Assche static DEVICE_ATTR_RO(read_req_latency_avg);
595dd11376bSBart Van Assche static DEVICE_ATTR_RO(read_req_latency_max);
596dd11376bSBart Van Assche static DEVICE_ATTR_RO(read_req_latency_min);
597dd11376bSBart Van Assche static DEVICE_ATTR_RO(read_req_latency_sum);
598dd11376bSBart Van Assche static DEVICE_ATTR_RO(write_total_sectors);
599dd11376bSBart Van Assche static DEVICE_ATTR_RO(write_total_busy);
600dd11376bSBart Van Assche static DEVICE_ATTR_RO(write_nr_requests);
601dd11376bSBart Van Assche static DEVICE_ATTR_RO(write_req_latency_avg);
602dd11376bSBart Van Assche static DEVICE_ATTR_RO(write_req_latency_max);
603dd11376bSBart Van Assche static DEVICE_ATTR_RO(write_req_latency_min);
604dd11376bSBart Van Assche static DEVICE_ATTR_RO(write_req_latency_sum);
605dd11376bSBart Van Assche 
606dd11376bSBart Van Assche static struct attribute *ufs_sysfs_monitor_attrs[] = {
607dd11376bSBart Van Assche 	&dev_attr_monitor_enable.attr,
608dd11376bSBart Van Assche 	&dev_attr_monitor_chunk_size.attr,
609dd11376bSBart Van Assche 	&dev_attr_read_total_sectors.attr,
610dd11376bSBart Van Assche 	&dev_attr_read_total_busy.attr,
611dd11376bSBart Van Assche 	&dev_attr_read_nr_requests.attr,
612dd11376bSBart Van Assche 	&dev_attr_read_req_latency_avg.attr,
613dd11376bSBart Van Assche 	&dev_attr_read_req_latency_max.attr,
614dd11376bSBart Van Assche 	&dev_attr_read_req_latency_min.attr,
615dd11376bSBart Van Assche 	&dev_attr_read_req_latency_sum.attr,
616dd11376bSBart Van Assche 	&dev_attr_write_total_sectors.attr,
617dd11376bSBart Van Assche 	&dev_attr_write_total_busy.attr,
618dd11376bSBart Van Assche 	&dev_attr_write_nr_requests.attr,
619dd11376bSBart Van Assche 	&dev_attr_write_req_latency_avg.attr,
620dd11376bSBart Van Assche 	&dev_attr_write_req_latency_max.attr,
621dd11376bSBart Van Assche 	&dev_attr_write_req_latency_min.attr,
622dd11376bSBart Van Assche 	&dev_attr_write_req_latency_sum.attr,
623dd11376bSBart Van Assche 	NULL
624dd11376bSBart Van Assche };
625dd11376bSBart Van Assche 
626dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_monitor_group = {
627dd11376bSBart Van Assche 	.name = "monitor",
628dd11376bSBart Van Assche 	.attrs = ufs_sysfs_monitor_attrs,
629dd11376bSBart Van Assche };
630dd11376bSBart Van Assche 
ufs_sysfs_read_desc_param(struct ufs_hba * hba,enum desc_idn desc_id,u8 desc_index,u8 param_offset,u8 * sysfs_buf,u8 param_size)631dd11376bSBart Van Assche static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba,
632dd11376bSBart Van Assche 				  enum desc_idn desc_id,
633dd11376bSBart Van Assche 				  u8 desc_index,
634dd11376bSBart Van Assche 				  u8 param_offset,
635dd11376bSBart Van Assche 				  u8 *sysfs_buf,
636dd11376bSBart Van Assche 				  u8 param_size)
637dd11376bSBart Van Assche {
638dd11376bSBart Van Assche 	u8 desc_buf[8] = {0};
639dd11376bSBart Van Assche 	int ret;
640dd11376bSBart Van Assche 
641dd11376bSBart Van Assche 	if (param_size > 8)
642dd11376bSBart Van Assche 		return -EINVAL;
643dd11376bSBart Van Assche 
644dd11376bSBart Van Assche 	down(&hba->host_sem);
645dd11376bSBart Van Assche 	if (!ufshcd_is_user_access_allowed(hba)) {
646dd11376bSBart Van Assche 		ret = -EBUSY;
647dd11376bSBart Van Assche 		goto out;
648dd11376bSBart Van Assche 	}
649dd11376bSBart Van Assche 
650dd11376bSBart Van Assche 	ufshcd_rpm_get_sync(hba);
651dd11376bSBart Van Assche 	ret = ufshcd_read_desc_param(hba, desc_id, desc_index,
652dd11376bSBart Van Assche 				param_offset, desc_buf, param_size);
653dd11376bSBart Van Assche 	ufshcd_rpm_put_sync(hba);
654dd11376bSBart Van Assche 	if (ret) {
655dd11376bSBart Van Assche 		ret = -EINVAL;
656dd11376bSBart Van Assche 		goto out;
657dd11376bSBart Van Assche 	}
658dd11376bSBart Van Assche 
659dd11376bSBart Van Assche 	switch (param_size) {
660dd11376bSBart Van Assche 	case 1:
661dd11376bSBart Van Assche 		ret = sysfs_emit(sysfs_buf, "0x%02X\n", *desc_buf);
662dd11376bSBart Van Assche 		break;
663dd11376bSBart Van Assche 	case 2:
664dd11376bSBart Van Assche 		ret = sysfs_emit(sysfs_buf, "0x%04X\n",
665dd11376bSBart Van Assche 			get_unaligned_be16(desc_buf));
666dd11376bSBart Van Assche 		break;
667dd11376bSBart Van Assche 	case 4:
668dd11376bSBart Van Assche 		ret = sysfs_emit(sysfs_buf, "0x%08X\n",
669dd11376bSBart Van Assche 			get_unaligned_be32(desc_buf));
670dd11376bSBart Van Assche 		break;
671dd11376bSBart Van Assche 	case 8:
672dd11376bSBart Van Assche 		ret = sysfs_emit(sysfs_buf, "0x%016llX\n",
673dd11376bSBart Van Assche 			get_unaligned_be64(desc_buf));
674dd11376bSBart Van Assche 		break;
675dd11376bSBart Van Assche 	}
676dd11376bSBart Van Assche 
677dd11376bSBart Van Assche out:
678dd11376bSBart Van Assche 	up(&hba->host_sem);
679dd11376bSBart Van Assche 	return ret;
680dd11376bSBart Van Assche }
681dd11376bSBart Van Assche 
682dd11376bSBart Van Assche #define UFS_DESC_PARAM(_name, _puname, _duname, _size)			\
683dd11376bSBart Van Assche static ssize_t _name##_show(struct device *dev,				\
684dd11376bSBart Van Assche 	struct device_attribute *attr, char *buf)			\
685dd11376bSBart Van Assche {									\
686dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);			\
687dd11376bSBart Van Assche 	return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname,	\
688dd11376bSBart Van Assche 		0, _duname##_DESC_PARAM##_puname, buf, _size);		\
689dd11376bSBart Van Assche }									\
690dd11376bSBart Van Assche static DEVICE_ATTR_RO(_name)
691dd11376bSBart Van Assche 
692dd11376bSBart Van Assche #define UFS_DEVICE_DESC_PARAM(_name, _uname, _size)			\
693dd11376bSBart Van Assche 	UFS_DESC_PARAM(_name, _uname, DEVICE, _size)
694dd11376bSBart Van Assche 
695dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(device_type, _DEVICE_TYPE, 1);
696dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(device_class, _DEVICE_CLASS, 1);
697dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(device_sub_class, _DEVICE_SUB_CLASS, 1);
698dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(protocol, _PRTCL, 1);
699dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(number_of_luns, _NUM_LU, 1);
700dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(number_of_wluns, _NUM_WLU, 1);
701dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(boot_enable, _BOOT_ENBL, 1);
702dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(descriptor_access_enable, _DESC_ACCSS_ENBL, 1);
703dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(initial_power_mode, _INIT_PWR_MODE, 1);
704dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(high_priority_lun, _HIGH_PR_LUN, 1);
705dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(secure_removal_type, _SEC_RMV_TYPE, 1);
706dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(support_security_lun, _SEC_LU, 1);
707dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(bkops_termination_latency, _BKOP_TERM_LT, 1);
708dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(initial_active_icc_level, _ACTVE_ICC_LVL, 1);
709dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(specification_version, _SPEC_VER, 2);
710dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(manufacturing_date, _MANF_DATE, 2);
711dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(manufacturer_id, _MANF_ID, 2);
712dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(rtt_capability, _RTT_CAP, 1);
713dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(rtc_update, _FRQ_RTC, 2);
714dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(ufs_features, _UFS_FEAT, 1);
715dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(ffu_timeout, _FFU_TMT, 1);
716dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(queue_depth, _Q_DPTH, 1);
717dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(device_version, _DEV_VER, 2);
718dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(number_of_secure_wpa, _NUM_SEC_WPA, 1);
719dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(psa_max_data_size, _PSA_MAX_DATA, 4);
720dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(psa_state_timeout, _PSA_TMT, 1);
721dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(ext_feature_sup, _EXT_UFS_FEATURE_SUP, 4);
722dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(wb_presv_us_en, _WB_PRESRV_USRSPC_EN, 1);
723dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(wb_type, _WB_TYPE, 1);
724dd11376bSBart Van Assche UFS_DEVICE_DESC_PARAM(wb_shared_alloc_units, _WB_SHARED_ALLOC_UNITS, 4);
725dd11376bSBart Van Assche 
726dd11376bSBart Van Assche static struct attribute *ufs_sysfs_device_descriptor[] = {
727dd11376bSBart Van Assche 	&dev_attr_device_type.attr,
728dd11376bSBart Van Assche 	&dev_attr_device_class.attr,
729dd11376bSBart Van Assche 	&dev_attr_device_sub_class.attr,
730dd11376bSBart Van Assche 	&dev_attr_protocol.attr,
731dd11376bSBart Van Assche 	&dev_attr_number_of_luns.attr,
732dd11376bSBart Van Assche 	&dev_attr_number_of_wluns.attr,
733dd11376bSBart Van Assche 	&dev_attr_boot_enable.attr,
734dd11376bSBart Van Assche 	&dev_attr_descriptor_access_enable.attr,
735dd11376bSBart Van Assche 	&dev_attr_initial_power_mode.attr,
736dd11376bSBart Van Assche 	&dev_attr_high_priority_lun.attr,
737dd11376bSBart Van Assche 	&dev_attr_secure_removal_type.attr,
738dd11376bSBart Van Assche 	&dev_attr_support_security_lun.attr,
739dd11376bSBart Van Assche 	&dev_attr_bkops_termination_latency.attr,
740dd11376bSBart Van Assche 	&dev_attr_initial_active_icc_level.attr,
741dd11376bSBart Van Assche 	&dev_attr_specification_version.attr,
742dd11376bSBart Van Assche 	&dev_attr_manufacturing_date.attr,
743dd11376bSBart Van Assche 	&dev_attr_manufacturer_id.attr,
744dd11376bSBart Van Assche 	&dev_attr_rtt_capability.attr,
745dd11376bSBart Van Assche 	&dev_attr_rtc_update.attr,
746dd11376bSBart Van Assche 	&dev_attr_ufs_features.attr,
747dd11376bSBart Van Assche 	&dev_attr_ffu_timeout.attr,
748dd11376bSBart Van Assche 	&dev_attr_queue_depth.attr,
749dd11376bSBart Van Assche 	&dev_attr_device_version.attr,
750dd11376bSBart Van Assche 	&dev_attr_number_of_secure_wpa.attr,
751dd11376bSBart Van Assche 	&dev_attr_psa_max_data_size.attr,
752dd11376bSBart Van Assche 	&dev_attr_psa_state_timeout.attr,
753dd11376bSBart Van Assche 	&dev_attr_ext_feature_sup.attr,
754dd11376bSBart Van Assche 	&dev_attr_wb_presv_us_en.attr,
755dd11376bSBart Van Assche 	&dev_attr_wb_type.attr,
756dd11376bSBart Van Assche 	&dev_attr_wb_shared_alloc_units.attr,
757dd11376bSBart Van Assche 	NULL,
758dd11376bSBart Van Assche };
759dd11376bSBart Van Assche 
760dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_device_descriptor_group = {
761dd11376bSBart Van Assche 	.name = "device_descriptor",
762dd11376bSBart Van Assche 	.attrs = ufs_sysfs_device_descriptor,
763dd11376bSBart Van Assche };
764dd11376bSBart Van Assche 
765dd11376bSBart Van Assche #define UFS_INTERCONNECT_DESC_PARAM(_name, _uname, _size)		\
766dd11376bSBart Van Assche 	UFS_DESC_PARAM(_name, _uname, INTERCONNECT, _size)
767dd11376bSBart Van Assche 
768dd11376bSBart Van Assche UFS_INTERCONNECT_DESC_PARAM(unipro_version, _UNIPRO_VER, 2);
769dd11376bSBart Van Assche UFS_INTERCONNECT_DESC_PARAM(mphy_version, _MPHY_VER, 2);
770dd11376bSBart Van Assche 
771dd11376bSBart Van Assche static struct attribute *ufs_sysfs_interconnect_descriptor[] = {
772dd11376bSBart Van Assche 	&dev_attr_unipro_version.attr,
773dd11376bSBart Van Assche 	&dev_attr_mphy_version.attr,
774dd11376bSBart Van Assche 	NULL,
775dd11376bSBart Van Assche };
776dd11376bSBart Van Assche 
777dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_interconnect_descriptor_group = {
778dd11376bSBart Van Assche 	.name = "interconnect_descriptor",
779dd11376bSBart Van Assche 	.attrs = ufs_sysfs_interconnect_descriptor,
780dd11376bSBart Van Assche };
781dd11376bSBart Van Assche 
782dd11376bSBart Van Assche #define UFS_GEOMETRY_DESC_PARAM(_name, _uname, _size)			\
783dd11376bSBart Van Assche 	UFS_DESC_PARAM(_name, _uname, GEOMETRY, _size)
784dd11376bSBart Van Assche 
785dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(raw_device_capacity, _DEV_CAP, 8);
786dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(max_number_of_luns, _MAX_NUM_LUN, 1);
787dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(segment_size, _SEG_SIZE, 4);
788dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(allocation_unit_size, _ALLOC_UNIT_SIZE, 1);
789dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(min_addressable_block_size, _MIN_BLK_SIZE, 1);
790dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(optimal_read_block_size, _OPT_RD_BLK_SIZE, 1);
791dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(optimal_write_block_size, _OPT_WR_BLK_SIZE, 1);
792dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(max_in_buffer_size, _MAX_IN_BUF_SIZE, 1);
793dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(max_out_buffer_size, _MAX_OUT_BUF_SIZE, 1);
794dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(rpmb_rw_size, _RPMB_RW_SIZE, 1);
795dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(dyn_capacity_resource_policy, _DYN_CAP_RSRC_PLC, 1);
796dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(data_ordering, _DATA_ORDER, 1);
797dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(max_number_of_contexts, _MAX_NUM_CTX, 1);
798dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(sys_data_tag_unit_size, _TAG_UNIT_SIZE, 1);
799dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(sys_data_tag_resource_size, _TAG_RSRC_SIZE, 1);
800dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(secure_removal_types, _SEC_RM_TYPES, 1);
801dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(memory_types, _MEM_TYPES, 2);
802dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(sys_code_memory_max_alloc_units,
803dd11376bSBart Van Assche 	_SCM_MAX_NUM_UNITS, 4);
804dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(sys_code_memory_capacity_adjustment_factor,
805dd11376bSBart Van Assche 	_SCM_CAP_ADJ_FCTR, 2);
806dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(non_persist_memory_max_alloc_units,
807dd11376bSBart Van Assche 	_NPM_MAX_NUM_UNITS, 4);
808dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(non_persist_memory_capacity_adjustment_factor,
809dd11376bSBart Van Assche 	_NPM_CAP_ADJ_FCTR, 2);
810dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(enh1_memory_max_alloc_units,
811dd11376bSBart Van Assche 	_ENM1_MAX_NUM_UNITS, 4);
812dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(enh1_memory_capacity_adjustment_factor,
813dd11376bSBart Van Assche 	_ENM1_CAP_ADJ_FCTR, 2);
814dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(enh2_memory_max_alloc_units,
815dd11376bSBart Van Assche 	_ENM2_MAX_NUM_UNITS, 4);
816dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(enh2_memory_capacity_adjustment_factor,
817dd11376bSBart Van Assche 	_ENM2_CAP_ADJ_FCTR, 2);
818dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(enh3_memory_max_alloc_units,
819dd11376bSBart Van Assche 	_ENM3_MAX_NUM_UNITS, 4);
820dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(enh3_memory_capacity_adjustment_factor,
821dd11376bSBart Van Assche 	_ENM3_CAP_ADJ_FCTR, 2);
822dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(enh4_memory_max_alloc_units,
823dd11376bSBart Van Assche 	_ENM4_MAX_NUM_UNITS, 4);
824dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(enh4_memory_capacity_adjustment_factor,
825dd11376bSBart Van Assche 	_ENM4_CAP_ADJ_FCTR, 2);
826dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(wb_max_alloc_units, _WB_MAX_ALLOC_UNITS, 4);
827dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(wb_max_wb_luns, _WB_MAX_WB_LUNS, 1);
828dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(wb_buff_cap_adj, _WB_BUFF_CAP_ADJ, 1);
829dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(wb_sup_red_type, _WB_SUP_RED_TYPE, 1);
830dd11376bSBart Van Assche UFS_GEOMETRY_DESC_PARAM(wb_sup_wb_type, _WB_SUP_WB_TYPE, 1);
831dd11376bSBart Van Assche 
832dd11376bSBart Van Assche 
833dd11376bSBart Van Assche static struct attribute *ufs_sysfs_geometry_descriptor[] = {
834dd11376bSBart Van Assche 	&dev_attr_raw_device_capacity.attr,
835dd11376bSBart Van Assche 	&dev_attr_max_number_of_luns.attr,
836dd11376bSBart Van Assche 	&dev_attr_segment_size.attr,
837dd11376bSBart Van Assche 	&dev_attr_allocation_unit_size.attr,
838dd11376bSBart Van Assche 	&dev_attr_min_addressable_block_size.attr,
839dd11376bSBart Van Assche 	&dev_attr_optimal_read_block_size.attr,
840dd11376bSBart Van Assche 	&dev_attr_optimal_write_block_size.attr,
841dd11376bSBart Van Assche 	&dev_attr_max_in_buffer_size.attr,
842dd11376bSBart Van Assche 	&dev_attr_max_out_buffer_size.attr,
843dd11376bSBart Van Assche 	&dev_attr_rpmb_rw_size.attr,
844dd11376bSBart Van Assche 	&dev_attr_dyn_capacity_resource_policy.attr,
845dd11376bSBart Van Assche 	&dev_attr_data_ordering.attr,
846dd11376bSBart Van Assche 	&dev_attr_max_number_of_contexts.attr,
847dd11376bSBart Van Assche 	&dev_attr_sys_data_tag_unit_size.attr,
848dd11376bSBart Van Assche 	&dev_attr_sys_data_tag_resource_size.attr,
849dd11376bSBart Van Assche 	&dev_attr_secure_removal_types.attr,
850dd11376bSBart Van Assche 	&dev_attr_memory_types.attr,
851dd11376bSBart Van Assche 	&dev_attr_sys_code_memory_max_alloc_units.attr,
852dd11376bSBart Van Assche 	&dev_attr_sys_code_memory_capacity_adjustment_factor.attr,
853dd11376bSBart Van Assche 	&dev_attr_non_persist_memory_max_alloc_units.attr,
854dd11376bSBart Van Assche 	&dev_attr_non_persist_memory_capacity_adjustment_factor.attr,
855dd11376bSBart Van Assche 	&dev_attr_enh1_memory_max_alloc_units.attr,
856dd11376bSBart Van Assche 	&dev_attr_enh1_memory_capacity_adjustment_factor.attr,
857dd11376bSBart Van Assche 	&dev_attr_enh2_memory_max_alloc_units.attr,
858dd11376bSBart Van Assche 	&dev_attr_enh2_memory_capacity_adjustment_factor.attr,
859dd11376bSBart Van Assche 	&dev_attr_enh3_memory_max_alloc_units.attr,
860dd11376bSBart Van Assche 	&dev_attr_enh3_memory_capacity_adjustment_factor.attr,
861dd11376bSBart Van Assche 	&dev_attr_enh4_memory_max_alloc_units.attr,
862dd11376bSBart Van Assche 	&dev_attr_enh4_memory_capacity_adjustment_factor.attr,
863dd11376bSBart Van Assche 	&dev_attr_wb_max_alloc_units.attr,
864dd11376bSBart Van Assche 	&dev_attr_wb_max_wb_luns.attr,
865dd11376bSBart Van Assche 	&dev_attr_wb_buff_cap_adj.attr,
866dd11376bSBart Van Assche 	&dev_attr_wb_sup_red_type.attr,
867dd11376bSBart Van Assche 	&dev_attr_wb_sup_wb_type.attr,
868dd11376bSBart Van Assche 	NULL,
869dd11376bSBart Van Assche };
870dd11376bSBart Van Assche 
871dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_geometry_descriptor_group = {
872dd11376bSBart Van Assche 	.name = "geometry_descriptor",
873dd11376bSBart Van Assche 	.attrs = ufs_sysfs_geometry_descriptor,
874dd11376bSBart Van Assche };
875dd11376bSBart Van Assche 
876dd11376bSBart Van Assche #define UFS_HEALTH_DESC_PARAM(_name, _uname, _size)			\
877dd11376bSBart Van Assche 	UFS_DESC_PARAM(_name, _uname, HEALTH, _size)
878dd11376bSBart Van Assche 
879dd11376bSBart Van Assche UFS_HEALTH_DESC_PARAM(eol_info, _EOL_INFO, 1);
880dd11376bSBart Van Assche UFS_HEALTH_DESC_PARAM(life_time_estimation_a, _LIFE_TIME_EST_A, 1);
881dd11376bSBart Van Assche UFS_HEALTH_DESC_PARAM(life_time_estimation_b, _LIFE_TIME_EST_B, 1);
882dd11376bSBart Van Assche 
883dd11376bSBart Van Assche static struct attribute *ufs_sysfs_health_descriptor[] = {
884dd11376bSBart Van Assche 	&dev_attr_eol_info.attr,
885dd11376bSBart Van Assche 	&dev_attr_life_time_estimation_a.attr,
886dd11376bSBart Van Assche 	&dev_attr_life_time_estimation_b.attr,
887dd11376bSBart Van Assche 	NULL,
888dd11376bSBart Van Assche };
889dd11376bSBart Van Assche 
890dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_health_descriptor_group = {
891dd11376bSBart Van Assche 	.name = "health_descriptor",
892dd11376bSBart Van Assche 	.attrs = ufs_sysfs_health_descriptor,
893dd11376bSBart Van Assche };
894dd11376bSBart Van Assche 
895dd11376bSBart Van Assche #define UFS_POWER_DESC_PARAM(_name, _uname, _index)			\
896dd11376bSBart Van Assche static ssize_t _name##_index##_show(struct device *dev,			\
897dd11376bSBart Van Assche 	struct device_attribute *attr, char *buf)			\
898dd11376bSBart Van Assche {									\
899dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);			\
900dd11376bSBart Van Assche 	return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0,	\
901dd11376bSBart Van Assche 		PWR_DESC##_uname##_0 + _index * 2, buf, 2);		\
902dd11376bSBart Van Assche }									\
903dd11376bSBart Van Assche static DEVICE_ATTR_RO(_name##_index)
904dd11376bSBart Van Assche 
905dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 0);
906dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 1);
907dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 2);
908dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 3);
909dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 4);
910dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 5);
911dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 6);
912dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 7);
913dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 8);
914dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 9);
915dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 10);
916dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 11);
917dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 12);
918dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 13);
919dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 14);
920dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vcc, _ACTIVE_LVLS_VCC, 15);
921dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 0);
922dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 1);
923dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 2);
924dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 3);
925dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 4);
926dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 5);
927dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 6);
928dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 7);
929dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 8);
930dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 9);
931dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 10);
932dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 11);
933dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 12);
934dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 13);
935dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 14);
936dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq, _ACTIVE_LVLS_VCCQ, 15);
937dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 0);
938dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 1);
939dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 2);
940dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 3);
941dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 4);
942dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 5);
943dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 6);
944dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 7);
945dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 8);
946dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 9);
947dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 10);
948dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 11);
949dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 12);
950dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 13);
951dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 14);
952dd11376bSBart Van Assche UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, _ACTIVE_LVLS_VCCQ2, 15);
953dd11376bSBart Van Assche 
954dd11376bSBart Van Assche static struct attribute *ufs_sysfs_power_descriptor[] = {
955dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc0.attr,
956dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc1.attr,
957dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc2.attr,
958dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc3.attr,
959dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc4.attr,
960dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc5.attr,
961dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc6.attr,
962dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc7.attr,
963dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc8.attr,
964dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc9.attr,
965dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc10.attr,
966dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc11.attr,
967dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc12.attr,
968dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc13.attr,
969dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc14.attr,
970dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vcc15.attr,
971dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq0.attr,
972dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq1.attr,
973dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq2.attr,
974dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq3.attr,
975dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq4.attr,
976dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq5.attr,
977dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq6.attr,
978dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq7.attr,
979dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq8.attr,
980dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq9.attr,
981dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq10.attr,
982dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq11.attr,
983dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq12.attr,
984dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq13.attr,
985dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq14.attr,
986dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq15.attr,
987dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq20.attr,
988dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq21.attr,
989dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq22.attr,
990dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq23.attr,
991dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq24.attr,
992dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq25.attr,
993dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq26.attr,
994dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq27.attr,
995dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq28.attr,
996dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq29.attr,
997dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq210.attr,
998dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq211.attr,
999dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq212.attr,
1000dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq213.attr,
1001dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq214.attr,
1002dd11376bSBart Van Assche 	&dev_attr_active_icc_levels_vccq215.attr,
1003dd11376bSBart Van Assche 	NULL,
1004dd11376bSBart Van Assche };
1005dd11376bSBart Van Assche 
1006dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_power_descriptor_group = {
1007dd11376bSBart Van Assche 	.name = "power_descriptor",
1008dd11376bSBart Van Assche 	.attrs = ufs_sysfs_power_descriptor,
1009dd11376bSBart Van Assche };
1010dd11376bSBart Van Assche 
1011dd11376bSBart Van Assche #define UFS_STRING_DESCRIPTOR(_name, _pname)				\
1012dd11376bSBart Van Assche static ssize_t _name##_show(struct device *dev,				\
1013dd11376bSBart Van Assche 	struct device_attribute *attr, char *buf)			\
1014dd11376bSBart Van Assche {									\
1015dd11376bSBart Van Assche 	u8 index;							\
1016dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);			\
1017dd11376bSBart Van Assche 	int ret;							\
1018dd11376bSBart Van Assche 	int desc_len = QUERY_DESC_MAX_SIZE;				\
1019dd11376bSBart Van Assche 	u8 *desc_buf;							\
1020dd11376bSBart Van Assche 									\
1021dd11376bSBart Van Assche 	down(&hba->host_sem);						\
1022dd11376bSBart Van Assche 	if (!ufshcd_is_user_access_allowed(hba)) {			\
1023dd11376bSBart Van Assche 		up(&hba->host_sem);					\
1024dd11376bSBart Van Assche 		return -EBUSY;						\
1025dd11376bSBart Van Assche 	}								\
1026dd11376bSBart Van Assche 	desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC);		\
1027dd11376bSBart Van Assche 	if (!desc_buf) {						\
1028dd11376bSBart Van Assche 		up(&hba->host_sem);					\
1029dd11376bSBart Van Assche 		return -ENOMEM;						\
1030dd11376bSBart Van Assche 	}								\
1031dd11376bSBart Van Assche 	ufshcd_rpm_get_sync(hba);					\
1032dd11376bSBart Van Assche 	ret = ufshcd_query_descriptor_retry(hba,			\
1033dd11376bSBart Van Assche 		UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE,	\
1034dd11376bSBart Van Assche 		0, 0, desc_buf, &desc_len);				\
1035dd11376bSBart Van Assche 	if (ret) {							\
1036dd11376bSBart Van Assche 		ret = -EINVAL;						\
1037dd11376bSBart Van Assche 		goto out;						\
1038dd11376bSBart Van Assche 	}								\
1039dd11376bSBart Van Assche 	index = desc_buf[DEVICE_DESC_PARAM##_pname];			\
1040dd11376bSBart Van Assche 	kfree(desc_buf);						\
1041dd11376bSBart Van Assche 	desc_buf = NULL;						\
1042dd11376bSBart Van Assche 	ret = ufshcd_read_string_desc(hba, index, &desc_buf,		\
1043dd11376bSBart Van Assche 				      SD_ASCII_STD);			\
1044dd11376bSBart Van Assche 	if (ret < 0)							\
1045dd11376bSBart Van Assche 		goto out;						\
1046dd11376bSBart Van Assche 	ret = sysfs_emit(buf, "%s\n", desc_buf);			\
1047dd11376bSBart Van Assche out:									\
1048dd11376bSBart Van Assche 	ufshcd_rpm_put_sync(hba);					\
1049dd11376bSBart Van Assche 	kfree(desc_buf);						\
1050dd11376bSBart Van Assche 	up(&hba->host_sem);						\
1051dd11376bSBart Van Assche 	return ret;							\
1052dd11376bSBart Van Assche }									\
1053dd11376bSBart Van Assche static DEVICE_ATTR_RO(_name)
1054dd11376bSBart Van Assche 
1055dd11376bSBart Van Assche UFS_STRING_DESCRIPTOR(manufacturer_name, _MANF_NAME);
1056dd11376bSBart Van Assche UFS_STRING_DESCRIPTOR(product_name, _PRDCT_NAME);
1057dd11376bSBart Van Assche UFS_STRING_DESCRIPTOR(oem_id, _OEM_ID);
1058dd11376bSBart Van Assche UFS_STRING_DESCRIPTOR(serial_number, _SN);
1059dd11376bSBart Van Assche UFS_STRING_DESCRIPTOR(product_revision, _PRDCT_REV);
1060dd11376bSBart Van Assche 
1061dd11376bSBart Van Assche static struct attribute *ufs_sysfs_string_descriptors[] = {
1062dd11376bSBart Van Assche 	&dev_attr_manufacturer_name.attr,
1063dd11376bSBart Van Assche 	&dev_attr_product_name.attr,
1064dd11376bSBart Van Assche 	&dev_attr_oem_id.attr,
1065dd11376bSBart Van Assche 	&dev_attr_serial_number.attr,
1066dd11376bSBart Van Assche 	&dev_attr_product_revision.attr,
1067dd11376bSBart Van Assche 	NULL,
1068dd11376bSBart Van Assche };
1069dd11376bSBart Van Assche 
1070dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_string_descriptors_group = {
1071dd11376bSBart Van Assche 	.name = "string_descriptors",
1072dd11376bSBart Van Assche 	.attrs = ufs_sysfs_string_descriptors,
1073dd11376bSBart Van Assche };
1074dd11376bSBart Van Assche 
ufshcd_is_wb_flags(enum flag_idn idn)1075dd11376bSBart Van Assche static inline bool ufshcd_is_wb_flags(enum flag_idn idn)
1076dd11376bSBart Van Assche {
1077dd11376bSBart Van Assche 	return idn >= QUERY_FLAG_IDN_WB_EN &&
1078dd11376bSBart Van Assche 		idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8;
1079dd11376bSBart Van Assche }
1080dd11376bSBart Van Assche 
1081dd11376bSBart Van Assche #define UFS_FLAG(_name, _uname)						\
1082dd11376bSBart Van Assche static ssize_t _name##_show(struct device *dev,				\
1083dd11376bSBart Van Assche 	struct device_attribute *attr, char *buf)			\
1084dd11376bSBart Van Assche {									\
1085dd11376bSBart Van Assche 	bool flag;							\
1086dd11376bSBart Van Assche 	u8 index = 0;							\
1087dd11376bSBart Van Assche 	int ret;							\
1088dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);			\
1089dd11376bSBart Van Assche 									\
1090dd11376bSBart Van Assche 	down(&hba->host_sem);						\
1091dd11376bSBart Van Assche 	if (!ufshcd_is_user_access_allowed(hba)) {			\
1092dd11376bSBart Van Assche 		up(&hba->host_sem);					\
1093dd11376bSBart Van Assche 		return -EBUSY;						\
1094dd11376bSBart Van Assche 	}								\
1095dd11376bSBart Van Assche 	if (ufshcd_is_wb_flags(QUERY_FLAG_IDN##_uname))			\
1096dd11376bSBart Van Assche 		index = ufshcd_wb_get_query_index(hba);			\
1097dd11376bSBart Van Assche 	ufshcd_rpm_get_sync(hba);					\
1098dd11376bSBart Van Assche 	ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,	\
1099dd11376bSBart Van Assche 		QUERY_FLAG_IDN##_uname, index, &flag);			\
1100dd11376bSBart Van Assche 	ufshcd_rpm_put_sync(hba);					\
1101dd11376bSBart Van Assche 	if (ret) {							\
1102dd11376bSBart Van Assche 		ret = -EINVAL;						\
1103dd11376bSBart Van Assche 		goto out;						\
1104dd11376bSBart Van Assche 	}								\
1105dd11376bSBart Van Assche 	ret = sysfs_emit(buf, "%s\n", flag ? "true" : "false");		\
1106dd11376bSBart Van Assche out:									\
1107dd11376bSBart Van Assche 	up(&hba->host_sem);						\
1108dd11376bSBart Van Assche 	return ret;							\
1109dd11376bSBart Van Assche }									\
1110dd11376bSBart Van Assche static DEVICE_ATTR_RO(_name)
1111dd11376bSBart Van Assche 
1112dd11376bSBart Van Assche UFS_FLAG(device_init, _FDEVICEINIT);
1113dd11376bSBart Van Assche UFS_FLAG(permanent_wpe, _PERMANENT_WPE);
1114dd11376bSBart Van Assche UFS_FLAG(power_on_wpe, _PWR_ON_WPE);
1115dd11376bSBart Van Assche UFS_FLAG(bkops_enable, _BKOPS_EN);
1116dd11376bSBart Van Assche UFS_FLAG(life_span_mode_enable, _LIFE_SPAN_MODE_ENABLE);
1117dd11376bSBart Van Assche UFS_FLAG(phy_resource_removal, _FPHYRESOURCEREMOVAL);
1118dd11376bSBart Van Assche UFS_FLAG(busy_rtc, _BUSY_RTC);
1119dd11376bSBart Van Assche UFS_FLAG(disable_fw_update, _PERMANENTLY_DISABLE_FW_UPDATE);
1120dd11376bSBart Van Assche UFS_FLAG(wb_enable, _WB_EN);
1121dd11376bSBart Van Assche UFS_FLAG(wb_flush_en, _WB_BUFF_FLUSH_EN);
1122dd11376bSBart Van Assche UFS_FLAG(wb_flush_during_h8, _WB_BUFF_FLUSH_DURING_HIBERN8);
1123dd11376bSBart Van Assche 
1124dd11376bSBart Van Assche static struct attribute *ufs_sysfs_device_flags[] = {
1125dd11376bSBart Van Assche 	&dev_attr_device_init.attr,
1126dd11376bSBart Van Assche 	&dev_attr_permanent_wpe.attr,
1127dd11376bSBart Van Assche 	&dev_attr_power_on_wpe.attr,
1128dd11376bSBart Van Assche 	&dev_attr_bkops_enable.attr,
1129dd11376bSBart Van Assche 	&dev_attr_life_span_mode_enable.attr,
1130dd11376bSBart Van Assche 	&dev_attr_phy_resource_removal.attr,
1131dd11376bSBart Van Assche 	&dev_attr_busy_rtc.attr,
1132dd11376bSBart Van Assche 	&dev_attr_disable_fw_update.attr,
1133dd11376bSBart Van Assche 	&dev_attr_wb_enable.attr,
1134dd11376bSBart Van Assche 	&dev_attr_wb_flush_en.attr,
1135dd11376bSBart Van Assche 	&dev_attr_wb_flush_during_h8.attr,
1136dd11376bSBart Van Assche 	NULL,
1137dd11376bSBart Van Assche };
1138dd11376bSBart Van Assche 
1139dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_flags_group = {
1140dd11376bSBart Van Assche 	.name = "flags",
1141dd11376bSBart Van Assche 	.attrs = ufs_sysfs_device_flags,
1142dd11376bSBart Van Assche };
1143dd11376bSBart Van Assche 
ufshcd_is_wb_attrs(enum attr_idn idn)1144dd11376bSBart Van Assche static inline bool ufshcd_is_wb_attrs(enum attr_idn idn)
1145dd11376bSBart Van Assche {
1146dd11376bSBart Van Assche 	return idn >= QUERY_ATTR_IDN_WB_FLUSH_STATUS &&
1147dd11376bSBart Van Assche 		idn <= QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE;
1148dd11376bSBart Van Assche }
1149dd11376bSBart Van Assche 
1150dd11376bSBart Van Assche #define UFS_ATTRIBUTE(_name, _uname)					\
1151dd11376bSBart Van Assche static ssize_t _name##_show(struct device *dev,				\
1152dd11376bSBart Van Assche 	struct device_attribute *attr, char *buf)			\
1153dd11376bSBart Van Assche {									\
1154dd11376bSBart Van Assche 	struct ufs_hba *hba = dev_get_drvdata(dev);			\
1155dd11376bSBart Van Assche 	u32 value;							\
1156dd11376bSBart Van Assche 	int ret;							\
1157dd11376bSBart Van Assche 	u8 index = 0;							\
1158dd11376bSBart Van Assche 									\
1159dd11376bSBart Van Assche 	down(&hba->host_sem);						\
1160dd11376bSBart Van Assche 	if (!ufshcd_is_user_access_allowed(hba)) {			\
1161dd11376bSBart Van Assche 		up(&hba->host_sem);					\
1162dd11376bSBart Van Assche 		return -EBUSY;						\
1163dd11376bSBart Van Assche 	}								\
1164dd11376bSBart Van Assche 	if (ufshcd_is_wb_attrs(QUERY_ATTR_IDN##_uname))			\
1165dd11376bSBart Van Assche 		index = ufshcd_wb_get_query_index(hba);			\
1166dd11376bSBart Van Assche 	ufshcd_rpm_get_sync(hba);					\
1167dd11376bSBart Van Assche 	ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,	\
1168dd11376bSBart Van Assche 		QUERY_ATTR_IDN##_uname, index, 0, &value);		\
1169dd11376bSBart Van Assche 	ufshcd_rpm_put_sync(hba);					\
1170dd11376bSBart Van Assche 	if (ret) {							\
1171dd11376bSBart Van Assche 		ret = -EINVAL;						\
1172dd11376bSBart Van Assche 		goto out;						\
1173dd11376bSBart Van Assche 	}								\
1174dd11376bSBart Van Assche 	ret = sysfs_emit(buf, "0x%08X\n", value);			\
1175dd11376bSBart Van Assche out:									\
1176dd11376bSBart Van Assche 	up(&hba->host_sem);						\
1177dd11376bSBart Van Assche 	return ret;							\
1178dd11376bSBart Van Assche }									\
1179dd11376bSBart Van Assche static DEVICE_ATTR_RO(_name)
1180dd11376bSBart Van Assche 
1181dd11376bSBart Van Assche UFS_ATTRIBUTE(boot_lun_enabled, _BOOT_LU_EN);
1182dd11376bSBart Van Assche UFS_ATTRIBUTE(current_power_mode, _POWER_MODE);
1183dd11376bSBart Van Assche UFS_ATTRIBUTE(active_icc_level, _ACTIVE_ICC_LVL);
1184dd11376bSBart Van Assche UFS_ATTRIBUTE(ooo_data_enabled, _OOO_DATA_EN);
1185dd11376bSBart Van Assche UFS_ATTRIBUTE(bkops_status, _BKOPS_STATUS);
1186dd11376bSBart Van Assche UFS_ATTRIBUTE(purge_status, _PURGE_STATUS);
1187dd11376bSBart Van Assche UFS_ATTRIBUTE(max_data_in_size, _MAX_DATA_IN);
1188dd11376bSBart Van Assche UFS_ATTRIBUTE(max_data_out_size, _MAX_DATA_OUT);
1189dd11376bSBart Van Assche UFS_ATTRIBUTE(reference_clock_frequency, _REF_CLK_FREQ);
1190dd11376bSBart Van Assche UFS_ATTRIBUTE(configuration_descriptor_lock, _CONF_DESC_LOCK);
1191dd11376bSBart Van Assche UFS_ATTRIBUTE(max_number_of_rtt, _MAX_NUM_OF_RTT);
1192dd11376bSBart Van Assche UFS_ATTRIBUTE(exception_event_control, _EE_CONTROL);
1193dd11376bSBart Van Assche UFS_ATTRIBUTE(exception_event_status, _EE_STATUS);
1194dd11376bSBart Van Assche UFS_ATTRIBUTE(ffu_status, _FFU_STATUS);
1195dd11376bSBart Van Assche UFS_ATTRIBUTE(psa_state, _PSA_STATE);
1196dd11376bSBart Van Assche UFS_ATTRIBUTE(psa_data_size, _PSA_DATA_SIZE);
1197dd11376bSBart Van Assche UFS_ATTRIBUTE(wb_flush_status, _WB_FLUSH_STATUS);
1198dd11376bSBart Van Assche UFS_ATTRIBUTE(wb_avail_buf, _AVAIL_WB_BUFF_SIZE);
1199dd11376bSBart Van Assche UFS_ATTRIBUTE(wb_life_time_est, _WB_BUFF_LIFE_TIME_EST);
1200dd11376bSBart Van Assche UFS_ATTRIBUTE(wb_cur_buf, _CURR_WB_BUFF_SIZE);
1201dd11376bSBart Van Assche 
1202dd11376bSBart Van Assche 
1203dd11376bSBart Van Assche static struct attribute *ufs_sysfs_attributes[] = {
1204dd11376bSBart Van Assche 	&dev_attr_boot_lun_enabled.attr,
1205dd11376bSBart Van Assche 	&dev_attr_current_power_mode.attr,
1206dd11376bSBart Van Assche 	&dev_attr_active_icc_level.attr,
1207dd11376bSBart Van Assche 	&dev_attr_ooo_data_enabled.attr,
1208dd11376bSBart Van Assche 	&dev_attr_bkops_status.attr,
1209dd11376bSBart Van Assche 	&dev_attr_purge_status.attr,
1210dd11376bSBart Van Assche 	&dev_attr_max_data_in_size.attr,
1211dd11376bSBart Van Assche 	&dev_attr_max_data_out_size.attr,
1212dd11376bSBart Van Assche 	&dev_attr_reference_clock_frequency.attr,
1213dd11376bSBart Van Assche 	&dev_attr_configuration_descriptor_lock.attr,
1214dd11376bSBart Van Assche 	&dev_attr_max_number_of_rtt.attr,
1215dd11376bSBart Van Assche 	&dev_attr_exception_event_control.attr,
1216dd11376bSBart Van Assche 	&dev_attr_exception_event_status.attr,
1217dd11376bSBart Van Assche 	&dev_attr_ffu_status.attr,
1218dd11376bSBart Van Assche 	&dev_attr_psa_state.attr,
1219dd11376bSBart Van Assche 	&dev_attr_psa_data_size.attr,
1220dd11376bSBart Van Assche 	&dev_attr_wb_flush_status.attr,
1221dd11376bSBart Van Assche 	&dev_attr_wb_avail_buf.attr,
1222dd11376bSBart Van Assche 	&dev_attr_wb_life_time_est.attr,
1223dd11376bSBart Van Assche 	&dev_attr_wb_cur_buf.attr,
1224dd11376bSBart Van Assche 	NULL,
1225dd11376bSBart Van Assche };
1226dd11376bSBart Van Assche 
1227dd11376bSBart Van Assche static const struct attribute_group ufs_sysfs_attributes_group = {
1228dd11376bSBart Van Assche 	.name = "attributes",
1229dd11376bSBart Van Assche 	.attrs = ufs_sysfs_attributes,
1230dd11376bSBart Van Assche };
1231dd11376bSBart Van Assche 
1232dd11376bSBart Van Assche static const struct attribute_group *ufs_sysfs_groups[] = {
1233dd11376bSBart Van Assche 	&ufs_sysfs_default_group,
12342286ade0SDaniil Lunev 	&ufs_sysfs_capabilities_group,
1235dd11376bSBart Van Assche 	&ufs_sysfs_monitor_group,
1236dd11376bSBart Van Assche 	&ufs_sysfs_device_descriptor_group,
1237dd11376bSBart Van Assche 	&ufs_sysfs_interconnect_descriptor_group,
1238dd11376bSBart Van Assche 	&ufs_sysfs_geometry_descriptor_group,
1239dd11376bSBart Van Assche 	&ufs_sysfs_health_descriptor_group,
1240dd11376bSBart Van Assche 	&ufs_sysfs_power_descriptor_group,
1241dd11376bSBart Van Assche 	&ufs_sysfs_string_descriptors_group,
1242dd11376bSBart Van Assche 	&ufs_sysfs_flags_group,
1243dd11376bSBart Van Assche 	&ufs_sysfs_attributes_group,
1244dd11376bSBart Van Assche 	NULL,
1245dd11376bSBart Van Assche };
1246dd11376bSBart Van Assche 
1247dd11376bSBart Van Assche #define UFS_LUN_DESC_PARAM(_pname, _puname, _duname, _size)		\
1248dd11376bSBart Van Assche static ssize_t _pname##_show(struct device *dev,			\
1249dd11376bSBart Van Assche 	struct device_attribute *attr, char *buf)			\
1250dd11376bSBart Van Assche {									\
1251dd11376bSBart Van Assche 	struct scsi_device *sdev = to_scsi_device(dev);			\
1252dd11376bSBart Van Assche 	struct ufs_hba *hba = shost_priv(sdev->host);			\
1253dd11376bSBart Van Assche 	u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);			\
1254b43678eaSBean Huo 	if (!ufs_is_valid_unit_desc_lun(&hba->dev_info, lun))		\
1255dd11376bSBart Van Assche 		return -EINVAL;						\
1256dd11376bSBart Van Assche 	return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname,	\
1257dd11376bSBart Van Assche 		lun, _duname##_DESC_PARAM##_puname, buf, _size);	\
1258dd11376bSBart Van Assche }									\
1259dd11376bSBart Van Assche static DEVICE_ATTR_RO(_pname)
1260dd11376bSBart Van Assche 
1261dd11376bSBart Van Assche #define UFS_UNIT_DESC_PARAM(_name, _uname, _size)			\
1262dd11376bSBart Van Assche 	UFS_LUN_DESC_PARAM(_name, _uname, UNIT, _size)
1263dd11376bSBart Van Assche 
1264dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(lu_enable, _LU_ENABLE, 1);
1265dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(boot_lun_id, _BOOT_LUN_ID, 1);
1266dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(lun_write_protect, _LU_WR_PROTECT, 1);
1267dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(lun_queue_depth, _LU_Q_DEPTH, 1);
1268dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(psa_sensitive, _PSA_SENSITIVE, 1);
1269dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(lun_memory_type, _MEM_TYPE, 1);
1270dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(data_reliability, _DATA_RELIABILITY, 1);
1271dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(logical_block_size, _LOGICAL_BLK_SIZE, 1);
1272dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(logical_block_count, _LOGICAL_BLK_COUNT, 8);
1273dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(erase_block_size, _ERASE_BLK_SIZE, 4);
1274dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(provisioning_type, _PROVISIONING_TYPE, 1);
1275dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(physical_memory_resourse_count, _PHY_MEM_RSRC_CNT, 8);
1276dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(context_capabilities, _CTX_CAPABILITIES, 2);
1277dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(large_unit_granularity, _LARGE_UNIT_SIZE_M1, 1);
1278dd11376bSBart Van Assche UFS_UNIT_DESC_PARAM(wb_buf_alloc_units, _WB_BUF_ALLOC_UNITS, 4);
1279dd11376bSBart Van Assche 
1280dd11376bSBart Van Assche static struct attribute *ufs_sysfs_unit_descriptor[] = {
1281dd11376bSBart Van Assche 	&dev_attr_lu_enable.attr,
1282dd11376bSBart Van Assche 	&dev_attr_boot_lun_id.attr,
1283dd11376bSBart Van Assche 	&dev_attr_lun_write_protect.attr,
1284dd11376bSBart Van Assche 	&dev_attr_lun_queue_depth.attr,
1285dd11376bSBart Van Assche 	&dev_attr_psa_sensitive.attr,
1286dd11376bSBart Van Assche 	&dev_attr_lun_memory_type.attr,
1287dd11376bSBart Van Assche 	&dev_attr_data_reliability.attr,
1288dd11376bSBart Van Assche 	&dev_attr_logical_block_size.attr,
1289dd11376bSBart Van Assche 	&dev_attr_logical_block_count.attr,
1290dd11376bSBart Van Assche 	&dev_attr_erase_block_size.attr,
1291dd11376bSBart Van Assche 	&dev_attr_provisioning_type.attr,
1292dd11376bSBart Van Assche 	&dev_attr_physical_memory_resourse_count.attr,
1293dd11376bSBart Van Assche 	&dev_attr_context_capabilities.attr,
1294dd11376bSBart Van Assche 	&dev_attr_large_unit_granularity.attr,
1295dd11376bSBart Van Assche 	&dev_attr_wb_buf_alloc_units.attr,
1296dd11376bSBart Van Assche 	NULL,
1297dd11376bSBart Van Assche };
1298dd11376bSBart Van Assche 
ufs_unit_descriptor_is_visible(struct kobject * kobj,struct attribute * attr,int n)12999d266e79SBean Huo static umode_t ufs_unit_descriptor_is_visible(struct kobject *kobj, struct attribute *attr, int n)
13009d266e79SBean Huo {
13019d266e79SBean Huo 	struct device *dev = container_of(kobj, struct device, kobj);
13029d266e79SBean Huo 	struct scsi_device *sdev = to_scsi_device(dev);
13039d266e79SBean Huo 	u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);
13049d266e79SBean Huo 	umode_t mode = attr->mode;
13059d266e79SBean Huo 
13069d266e79SBean Huo 	if (lun == UFS_UPIU_BOOT_WLUN || lun == UFS_UPIU_UFS_DEVICE_WLUN)
13079d266e79SBean Huo 		/* Boot and device WLUN have no unit descriptors */
13089d266e79SBean Huo 		mode = 0;
13099d266e79SBean Huo 	if (lun == UFS_UPIU_RPMB_WLUN && attr == &dev_attr_wb_buf_alloc_units.attr)
13109d266e79SBean Huo 		mode = 0;
13119d266e79SBean Huo 
13129d266e79SBean Huo 	return mode;
13139d266e79SBean Huo }
13149d266e79SBean Huo 
13159d266e79SBean Huo 
1316dd11376bSBart Van Assche const struct attribute_group ufs_sysfs_unit_descriptor_group = {
1317dd11376bSBart Van Assche 	.name = "unit_descriptor",
1318dd11376bSBart Van Assche 	.attrs = ufs_sysfs_unit_descriptor,
13199d266e79SBean Huo 	.is_visible = ufs_unit_descriptor_is_visible,
1320dd11376bSBart Van Assche };
1321dd11376bSBart Van Assche 
dyn_cap_needed_attribute_show(struct device * dev,struct device_attribute * attr,char * buf)1322dd11376bSBart Van Assche static ssize_t dyn_cap_needed_attribute_show(struct device *dev,
1323dd11376bSBart Van Assche 	struct device_attribute *attr, char *buf)
1324dd11376bSBart Van Assche {
1325dd11376bSBart Van Assche 	u32 value;
1326dd11376bSBart Van Assche 	struct scsi_device *sdev = to_scsi_device(dev);
1327dd11376bSBart Van Assche 	struct ufs_hba *hba = shost_priv(sdev->host);
1328dd11376bSBart Van Assche 	u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);
1329dd11376bSBart Van Assche 	int ret;
1330dd11376bSBart Van Assche 
1331dd11376bSBart Van Assche 	down(&hba->host_sem);
1332dd11376bSBart Van Assche 	if (!ufshcd_is_user_access_allowed(hba)) {
1333dd11376bSBart Van Assche 		ret = -EBUSY;
1334dd11376bSBart Van Assche 		goto out;
1335dd11376bSBart Van Assche 	}
1336dd11376bSBart Van Assche 
1337dd11376bSBart Van Assche 	ufshcd_rpm_get_sync(hba);
1338dd11376bSBart Van Assche 	ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
1339dd11376bSBart Van Assche 		QUERY_ATTR_IDN_DYN_CAP_NEEDED, lun, 0, &value);
1340dd11376bSBart Van Assche 	ufshcd_rpm_put_sync(hba);
1341dd11376bSBart Van Assche 	if (ret) {
1342dd11376bSBart Van Assche 		ret = -EINVAL;
1343dd11376bSBart Van Assche 		goto out;
1344dd11376bSBart Van Assche 	}
1345dd11376bSBart Van Assche 
1346dd11376bSBart Van Assche 	ret = sysfs_emit(buf, "0x%08X\n", value);
1347dd11376bSBart Van Assche 
1348dd11376bSBart Van Assche out:
1349dd11376bSBart Van Assche 	up(&hba->host_sem);
1350dd11376bSBart Van Assche 	return ret;
1351dd11376bSBart Van Assche }
1352dd11376bSBart Van Assche static DEVICE_ATTR_RO(dyn_cap_needed_attribute);
1353dd11376bSBart Van Assche 
1354dd11376bSBart Van Assche static struct attribute *ufs_sysfs_lun_attributes[] = {
1355dd11376bSBart Van Assche 	&dev_attr_dyn_cap_needed_attribute.attr,
1356dd11376bSBart Van Assche 	NULL,
1357dd11376bSBart Van Assche };
1358dd11376bSBart Van Assche 
1359dd11376bSBart Van Assche const struct attribute_group ufs_sysfs_lun_attributes_group = {
1360dd11376bSBart Van Assche 	.attrs = ufs_sysfs_lun_attributes,
1361dd11376bSBart Van Assche };
1362dd11376bSBart Van Assche 
ufs_sysfs_add_nodes(struct device * dev)1363dd11376bSBart Van Assche void ufs_sysfs_add_nodes(struct device *dev)
1364dd11376bSBart Van Assche {
1365dd11376bSBart Van Assche 	int ret;
1366dd11376bSBart Van Assche 
1367dd11376bSBart Van Assche 	ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups);
1368dd11376bSBart Van Assche 	if (ret)
1369dd11376bSBart Van Assche 		dev_err(dev,
1370dd11376bSBart Van Assche 			"%s: sysfs groups creation failed (err = %d)\n",
1371dd11376bSBart Van Assche 			__func__, ret);
1372dd11376bSBart Van Assche }
1373dd11376bSBart Van Assche 
ufs_sysfs_remove_nodes(struct device * dev)1374dd11376bSBart Van Assche void ufs_sysfs_remove_nodes(struct device *dev)
1375dd11376bSBart Van Assche {
1376dd11376bSBart Van Assche 	sysfs_remove_groups(&dev->kobj, ufs_sysfs_groups);
1377dd11376bSBart Van Assche }
1378