xref: /freebsd/sys/dev/ufshci/ufshci.h (revision 7d748c594ef0ddc45b3b8d0c4d368150e975724e)
1 /*-
2  * Copyright (c) 2025, Samsung Electronics Co., Ltd.
3  * Written by Jaeyoon Choi
4  *
5  * SPDX-License-Identifier: BSD-2-Clause
6  */
7 
8 #ifndef __UFSHCI_H__
9 #define __UFSHCI_H__
10 
11 #include <sys/param.h>
12 #include <sys/endian.h>
13 
14 /*
15  * Note: This driver currently assumes a little-endian architecture.
16  * Big-endian support is not yet implemented.
17  */
18 
19 /* MIPI UniPro spec 2.0, section 5.8.1 "PHY Adapter Common Attributes" */
20 #define PA_AvailTxDataLanes 0x1520
21 #define PA_AvailRxDataLanes 0x1540
22 
23 /*
24  * MIPI UniPro spec 2.0, section 5.8.2 "PHY Adapter M-PHY-Specific
25  * Attributes"
26  */
27 #define PA_ConnectedTxDataLanes 0x1561
28 #define PA_ConnectedRxDataLanes 0x1581
29 #define PA_MaxRxHSGear		0x1587
30 #define PA_Granularity		0x15AA
31 #define PA_TActivate		0x15A8
32 
33 #define PA_RemoteVerInfo	0x15A0
34 #define PA_LocalVerInfo		0x15A9
35 
36 /* UFSHCI spec 4.1, section 7.4 "UIC Power Mode Change" */
37 #define PA_ActiveTxDataLanes		 0x1560
38 #define PA_ActiveRxDataLanes		 0x1580
39 #define PA_TxGear			 0x1568
40 #define PA_RxGear			 0x1583
41 #define PA_TxTermination		 0x1569
42 #define PA_RxTermination		 0x1584
43 #define PA_HSSeries			 0x156A
44 #define PA_PWRModeUserData0		 0x15B0
45 #define PA_PWRModeUserData1		 0x15B1
46 #define PA_PWRModeUserData2		 0x15B2
47 #define PA_PWRModeUserData3		 0x15B3
48 #define PA_PWRModeUserData4		 0x15B4
49 #define PA_PWRModeUserData5		 0x15B5
50 
51 #define PA_TxHsAdaptType		 0x15D4
52 #define PA_PWRMode			 0x1571
53 
54 #define DME_LocalFC0ProtectionTimeOutVal 0xD041
55 #define DME_LocalTC0ReplayTimeOutVal	 0xD042
56 #define DME_LocalAFC0ReqTimeOutVal	 0xD043
57 
58 /* Currently, UFS uses TC0 only. */
59 #define DL_FC0ProtectionTimeOutVal_Default 8191
60 #define DL_TC0ReplayTimeOutVal_Default	   65535
61 #define DL_AFC0ReqTimeOutVal_Default	   32767
62 
63 /* UFS Spec 4.1, section 6.4 "Reference Clock" */
64 enum ufshci_attribute_reference_clock {
65 	UFSHCI_REF_CLK_19_2MHz = 0x0,
66 	UFSHCI_REF_CLK_26MHz = 0x1,
67 	UFSHCI_REF_CLK_38_4MHz = 0x2,
68 	UFSHCI_REF_CLK_OBSOLETE = 0x3,
69 };
70 
71 /* UFS spec 4.1, section 9 "UFS UIC Layer: MIPI Unipro" */
72 enum ufshci_uic_cmd_opcode {
73 	/* Configuration */
74 	UFSHCI_DME_GET = 0x01,
75 	UFSHCI_DME_SET = 0x02,
76 	UFSHCI_DME_PEER_GET = 0x03,
77 	UFSHCI_DME_PEER_SET = 0x04,
78 	/* Controll */
79 	UFSHCI_DME_POWER_ON = 0x10,
80 	UFSHCI_DME_POWER_OFF = 0x11,
81 	UFSHCI_DME_ENABLE = 0x12,
82 	UFSHCI_DME_RESET = 0x14,
83 	UFSHCI_DME_ENDPOINT_RESET = 0x15,
84 	UFSHCI_DME_LINK_STARTUP = 0x16,
85 	UFSHCI_DME_HIBERNATE_ENTER = 0x17,
86 	UFSHCI_DME_HIBERNATE_EXIT = 0x18,
87 	UFSHCI_DME_TEST_MODE = 0x1a,
88 };
89 
90 /* UFSHCI spec 4.1, section 5.6.3 "Offset 98h: UICCMDARG2 – UIC Command
91  * Argument" */
92 enum ufshci_uic_cmd_attr_set_type {
93 	UFSHCI_ATTR_SET_TYPE_NORMAL = 0, /* volatile value */
94 	UFSHCI_ATTR_SET_TYPE_STATIC = 1, /* non-volatile reset value */
95 };
96 
97 struct ufshci_uic_cmd {
98 	uint8_t opcode;
99 	uint32_t argument1;
100 	uint32_t argument2;
101 	uint32_t argument3;
102 };
103 
104 /* UFS spec 4.1, section 10.5 "UPIU Transactions" */
105 enum transaction_code {
106 	UFSHCI_UPIU_TRANSACTION_CODE_NOP_OUT = 0x00,
107 	UFSHCI_UPIU_TRANSACTION_CODE_COMMAND = 0x01,
108 	UFSHCI_UPIU_TRANSACTION_CODE_DATA_OUT = 0x02,
109 	UFSHCI_UPIU_TRANSACTION_CODE_TASK_MANAGEMENT_REQUEST = 0x04,
110 	UFSHCI_UPIU_TRANSACTION_CODE_QUERY_REQUEST = 0x16,
111 	UFSHCI_UPIU_TRANSACTION_CODE_NOP_IN = 0x20,
112 	UFSHCI_UPIU_TRANSACTION_CODE_RESPONSE = 0x21,
113 	UFSHCI_UPIU_TRANSACTION_CODE_DATA_IN = 0x22,
114 	UFSHCI_UPIU_TRANSACTION_CODE_TASK_MANAGEMENT_RESPONSE = 0x24,
115 	UFSHCI_UPIU_TRANSACTION_CODE_READY_TO_TRANSFER = 0x31,
116 	UFSHCI_UPIU_TRANSACTION_CODE_QUERY_RESPONSE = 0x36,
117 	UFSHCI_UPIU_TRANSACTION_CODE_REJECT_UPIU = 0x3f,
118 };
119 
120 enum overall_command_status {
121 	UFSHCI_DESC_SUCCESS = 0x0,
122 	UFSHCI_DESC_INVALID_COMMAND_TABLE_ATTRIBUTES = 0x01,
123 	UFSHCI_DESC_INVALID_PRDT_ATTRIBUTES = 0x02,
124 	UFSHCI_DESC_MISMATCH_DATA_BUFFER_SIZE = 0x03,
125 	UFSHCI_DESC_MISMATCH_RESPONSE_UPIU_SIZE = 0x04,
126 	UFSHCI_DESC_COMMUNICATION_FAILURE_WITHIN_UIC_LAYERS = 0x05,
127 	UFSHCI_DESC_ABORTED = 0x06,
128 	UFSHCI_DESC_HOST_CONTROLLER_FATAL_ERROR = 0x07,
129 	UFSHCI_DESC_DEVICEFATALERROR = 0x08,
130 	UFSHCI_DESC_INVALID_CRYPTO_CONFIGURATION = 0x09,
131 	UFSHCI_DESC_GENERAL_CRYPTO_ERROR = 0x0A,
132 	UFSHCI_DESC_INVALID = 0x0F,
133 };
134 
135 enum response_code {
136 	UFSHCI_RESPONSE_CODE_TARGET_SUCCESS = 0x00,
137 	UFSHCI_RESPONSE_CODE_TARGET_FAILURE = 0x01,
138 	UFSHCI_RESPONSE_CODE_PARAMETER_NOTREADABLE = 0xF6,
139 	UFSHCI_RESPONSE_CODE_PARAMETER_NOTWRITEABLE = 0xF7,
140 	UFSHCI_RESPONSE_CODE_PARAMETER_ALREADYWRITTEN = 0xF8,
141 	UFSHCI_RESPONSE_CODE_INVALID_LENGTH = 0xF9,
142 	UFSHCI_RESPONSE_CODE_INVALID_VALUE = 0xFA,
143 	UFSHCI_RESPONSE_CODE_INVALID_SELECTOR = 0xFB,
144 	UFSHCI_RESPONSE_CODE_INVALID_INDEX = 0xFC,
145 	UFSHCI_RESPONSE_CODE_INVALID_IDN = 0xFD,
146 	UFSHCI_RESPONSE_CODE_INVALID_OPCODE = 0xFE,
147 	UFSHCI_RESPONSE_CODE_GENERAL_FAILURE = 0xFF,
148 };
149 
150 /* UFSHCI spec 4.1, section 6.1.1 "UTP Transfer Request Descriptor" */
151 enum ufshci_command_type {
152 	UFSHCI_COMMAND_TYPE_UFS_STORAGE = 0x01,
153 	UFSHCI_COMMAND_TYPE_NULLIFIED_UTRD = 0x0F,
154 };
155 
156 enum ufshci_data_direction {
157 	UFSHCI_DATA_DIRECTION_NO_DATA_TRANSFER = 0x00,
158 	UFSHCI_DATA_DIRECTION_FROM_SYS_TO_TGT = 0x01,
159 	UFSHCI_DATA_DIRECTION_FROM_TGT_TO_SYS = 0x10,
160 	UFSHCI_DATA_DIRECTION_RESERVED = 0b11,
161 };
162 
163 enum ufshci_utr_overall_command_status {
164 	UFSHCI_UTR_OCS_SUCCESS = 0x0,
165 	UFSHCI_UTR_OCS_INVALID_COMMAND_TABLE_ATTRIBUTES = 0x01,
166 	UFSHCI_UTR_OCS_INVALID_PRDT_ATTRIBUTES = 0x02,
167 	UFSHCI_UTR_OCS_MISMATCH_DATA_BUFFER_SIZE = 0x03,
168 	UFSHCI_UTR_OCS_MISMATCH_RESPONSE_UPIU_SIZE = 0x04,
169 	UFSHCI_UTR_OCS_COMMUNICATION_FAILURE_WITHIN_UIC_LAYERS = 0x05,
170 	UFSHCI_UTR_OCS_ABORTED = 0x06,
171 	UFSHCI_UTR_OCS_HOST_CONTROLLER_FATAL_ERROR = 0x07,
172 	UFSHCI_UTR_OCS_DEVICE_FATAL_ERROR = 0x08,
173 	UFSHCI_UTR_OCS_INVALID_CRYPTO_CONFIGURATION = 0x09,
174 	UFSHCI_UTR_OCS_GENERAL_CRYPTO_ERROR = 0x0A,
175 	UFSHCI_UTR_OCS_INVALID = 0xF,
176 };
177 
178 struct ufshci_utp_xfer_req_desc {
179 	/* dword 0 */
180 	uint32_t cci : 8;	       /* [7:0] */
181 	uint32_t total_ehs_length : 8; /* [15:8] */
182 	uint32_t reserved0 : 7;	       /* [22:16] */
183 	uint32_t ce : 1;	       /* [23] */
184 	uint32_t interrupt : 1;	       /* [24] */
185 	uint32_t data_direction : 2;   /* [26:25] */
186 	uint32_t reserved1 : 1;	       /* [27] */
187 	uint32_t command_type : 4;     /* [31:28] */
188 
189 	/* dword 1 */
190 	uint32_t data_unit_number_lower; /* [31:0] */
191 
192 	/* dword 2 */
193 	uint8_t overall_command_status; /* [7:0] */
194 	uint8_t common_data_size;	/* [15:8] */
195 	uint16_t last_data_byte_count;	/* [31:16] */
196 
197 	/* dword 3 */
198 	uint32_t data_unit_number_upper; /* [31:0] */
199 
200 	/* dword 4 */
201 	uint32_t utp_command_descriptor_base_address; /* [31:0] */
202 
203 	/* dword 5 */
204 	uint32_t utp_command_descriptor_base_address_upper; /* [31:0] */
205 
206 	/* dword 6 */
207 	uint16_t response_upiu_length; /* [15:0] */
208 	uint16_t response_upiu_offset; /* [31:16] */
209 
210 	/* dword 7 */
211 	uint16_t prdt_length; /* [15:0] */
212 	uint16_t prdt_offset; /* [31:16] */
213 } __packed __aligned(8);
214 
215 _Static_assert(sizeof(struct ufshci_utp_xfer_req_desc) == 32,
216     "ufshci_utp_xfer_req_desc must be 32 bytes");
217 
218 /*
219  * According to the UFSHCI specification, the size of the UTP command
220  * descriptor is as follows. The size of the transfer request is not limited,
221  * a transfer response can be as long as 65535 * dwords, and a PRDT can be as
222  * long as 65565 * PRDT entry size(16 bytes). However, for ease of use, this
223  * UFSHCI Driver imposes the following limits. The size of the transfer
224  * request and the transfer response is 1024 bytes or less. The PRDT region
225  * limits the number of scatter gathers to 256 + 1, using a total of 4096 +
226  * 16 bytes. Therefore, only 8KB size is allocated for the UTP command
227  * descriptor.
228  */
229 #define UFSHCI_UTP_COMMAND_DESCRIPTOR_SIZE 8192
230 #define UFSHCI_UTP_XFER_REQ_SIZE	   512
231 #define UFSHCI_UTP_XFER_RESP_SIZE	   512
232 
233 /*
234  * To reduce the size of the UTP Command Descriptor(8KB), we must use only
235  * 256 + 1 PRDT entries. The reason for adding the 1 is that if the data is
236  * not aligned, one additional PRDT_ENTRY is used.
237  */
238 #define UFSHCI_MAX_PRDT_ENTRY_COUNT (256 + 1)
239 
240 /* UFSHCI spec 4.1, section 6.1.2 "UTP Command Descriptor" */
241 struct ufshci_prdt_entry {
242 	/* dword 0 */
243 	uint32_t data_base_address; /* [31:0] */
244 
245 	/* dword 1 */
246 	uint32_t data_base_address_upper; /* [31:0] */
247 
248 	/* dword 2 */
249 	uint32_t reserved; /* [31:0] */
250 
251 	/* dword 3 */
252 	uint32_t data_byte_count; /* [17:0] Maximum byte
253 				   * count is 256KB */
254 } __packed __aligned(8);
255 
256 _Static_assert(sizeof(struct ufshci_prdt_entry) == 16,
257     "ufshci_prdt_entry must be 16 bytes");
258 
259 struct ufshci_utp_cmd_desc {
260 	uint8_t command_upiu[UFSHCI_UTP_XFER_REQ_SIZE];
261 	uint8_t response_upiu[UFSHCI_UTP_XFER_RESP_SIZE];
262 	uint8_t prd_table[sizeof(struct ufshci_prdt_entry) *
263 	    UFSHCI_MAX_PRDT_ENTRY_COUNT];
264 	uint8_t padding[3072 - sizeof(struct ufshci_prdt_entry)];
265 } __packed __aligned(128);
266 
267 _Static_assert(sizeof(struct ufshci_utp_cmd_desc) ==
268 	UFSHCI_UTP_COMMAND_DESCRIPTOR_SIZE,
269     "ufshci_utp_cmd_desc must be 8192 bytes");
270 
271 #define UFSHCI_UTP_TASK_MGMT_REQ_SIZE  32
272 #define UFSHCI_UTP_TASK_MGMT_RESP_SIZE 32
273 
274 enum ufshci_utmr_overall_command_status {
275 	UFSHCI_UTMR_OCS_SUCCESS = 0x0,
276 	UFSHCI_UTMR_OCS_INVALID_TASK_MANAGEMENT_FUNCTION_ATTRIBUTES = 0x01,
277 	UFSHCI_UTMR_OCS_MISMATCH_TASK_MANAGEMENT_REQUEST_SIZE = 0x02,
278 	UFSHCI_UTMR_OCS_MISMATCH_TASK_MANAGEMENT_RESPONSE_SIZE = 0x03,
279 	UFSHCI_UTMR_OCS_PEER_COMMUNICATION_FAILURE = 0x04,
280 	UFSHCI_UTMR_OCS_ABORTED = 0x05,
281 	UFSHCI_UTMR_OCS_FATAL_ERROR = 0x06,
282 	UFSHCI_UTMR_OCS_DEVICE_FATAL_ERROR = 0x07,
283 	UFSHCI_UTMR_OCS_INVALID = 0xF,
284 };
285 
286 /* UFSHCI spec 4.1, section 6.3.1 "UTP Task Management Request Descriptor" */
287 struct ufshci_utp_task_mgmt_req_desc {
288 	/* dword 0 */
289 	uint32_t reserved0 : 24; /* [23:0] */
290 	uint32_t interrupt : 1;	 /* [24] */
291 	uint32_t reserved1 : 7;	 /* [31:25] */
292 
293 	/* dword 1 */
294 	uint32_t reserved2; /* [31:0] */
295 
296 	/* dword 2 */
297 	uint8_t overall_command_status; /* [7:0] */
298 	uint8_t reserved3;		/* [15:8] */
299 	uint16_t reserved4;		/* [31:16] */
300 
301 	/* dword 3 */
302 	uint32_t reserved5; /* [31:0] */
303 
304 	/* dword 4-11 */
305 	uint8_t request_upiu[UFSHCI_UTP_TASK_MGMT_REQ_SIZE];
306 
307 	/* dword 12-19 */
308 	uint8_t response_upiu[UFSHCI_UTP_TASK_MGMT_RESP_SIZE];
309 
310 } __packed __aligned(8);
311 
312 _Static_assert(sizeof(struct ufshci_utp_task_mgmt_req_desc) == 80,
313     "ufshci_utp_task_mgmt_req_desc must be 80 bytes");
314 
315 /* UFS spec 4.1, section 10.6.2 "Basic Header Format" */
316 struct ufshci_upiu_header {
317 	/* dword 0 */
318 	union {
319 		struct {
320 			uint8_t trans_code : 6; /* [5:0] */
321 			uint8_t dd : 1;		/* [6] */
322 			uint8_t hd : 1;		/* [7] */
323 		};
324 		uint8_t trans_type;
325 	};
326 	union {
327 		struct {
328 			uint8_t task_attribute : 2;	  /* [1:0] */
329 			uint8_t cp : 1;			  /* [2] */
330 			uint8_t retransmit_indicator : 1; /* [3] */
331 #define UFSHCI_OPERATIONAL_FLAG_W 0x2
332 #define UFSHCI_OPERATIONAL_FLAG_R 0x4
333 			uint8_t operational_flags : 4; /* [7:4] */
334 		};
335 		uint8_t flags;
336 	};
337 	uint8_t lun;
338 	uint8_t task_tag;
339 
340 	/* dword 1 */
341 #define UFSHCI_COMMAND_SET_TYPE_SCSI 0
342 	uint8_t cmd_set_type : 4; /* [3:0] */
343 	uint8_t iid : 4;	  /* [7:4] */
344 	uint8_t ext_iid_or_function;
345 	uint8_t response;
346 	uint8_t ext_iid_or_status;
347 
348 	/* dword 2 */
349 	uint8_t ehs_length;
350 	uint8_t device_infomation;
351 	uint16_t data_segment_length; /* (Big-endian) */
352 } __packed __aligned(4);
353 
354 _Static_assert(sizeof(struct ufshci_upiu_header) == 12,
355     "ufshci_upiu_header must be 12 bytes");
356 
357 #define UFSHCI_MAX_UPIU_SIZE  512
358 #define UFSHCI_UPIU_ALIGNMENT 8 /* UPIU requires 64-bit alignment. */
359 
360 struct ufshci_upiu {
361 	/* dword 0-2 */
362 	struct ufshci_upiu_header header;
363 	/* dword 3-127 */
364 	uint8_t
365 	    reserved[UFSHCI_MAX_UPIU_SIZE - sizeof(struct ufshci_upiu_header)];
366 } __packed __aligned(8);
367 
368 _Static_assert(sizeof(struct ufshci_upiu) == 512,
369     "ufshci_upiu must be 512 bytes");
370 
371 /* UFS Spec 4.1, section 10.7.1 "COMMAND UPIU" */
372 struct ufshci_cmd_command_upiu {
373 	/* dword 0-2 */
374 	struct ufshci_upiu_header header;
375 	/* dword 3 */
376 	uint32_t expected_data_transfer_length; /* (Big-endian) */
377 
378 	/* dword 4-7 */
379 	uint8_t cdb[16];
380 
381 } __packed __aligned(4);
382 
383 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) == 32,
384     "bad size for ufshci_cmd_command_upiu");
385 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) <=
386 	UFSHCI_UTP_XFER_REQ_SIZE,
387     "bad size for ufshci_cmd_command_upiu");
388 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) % UFSHCI_UPIU_ALIGNMENT ==
389 	0,
390     "UPIU requires 64-bit alignment");
391 
392 /* UFS Spec 4.1, section 10.7.2 "RESPONSE UPIU" */
393 struct ufshci_cmd_response_upiu {
394 	/* dword 0-2 */
395 	struct ufshci_upiu_header header;
396 	/* dword 3 */
397 	uint32_t residual_transfer_count; /* (Big-endian) */
398 
399 	/* dword 4-7 */
400 	uint8_t reserved[16];
401 
402 	/* Sense Data */
403 	uint16_t sense_data_len; /* (Big-endian) */
404 	uint8_t sense_data[18];
405 
406 	/* Add padding to align the kUpiuAlignment. */
407 	uint8_t padding[4];
408 } __packed __aligned(4);
409 
410 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) == 56,
411     "bad size for ufshci_cmd_response_upiu");
412 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) <=
413 	UFSHCI_UTP_XFER_RESP_SIZE,
414     "bad size for ufshci_cmd_response_upiu");
415 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) %
416 	    UFSHCI_UPIU_ALIGNMENT ==
417 	0,
418     "UPIU requires 64-bit alignment");
419 
420 enum task_management_function {
421 	UFSHCI_TASK_MGMT_FUNCTION_ABORT_TASK = 0x01,
422 	UFSHCI_TASK_MGMT_FUNCTION_ABORT_TASK_SET = 0x02,
423 	UFSHCI_TASK_MGMT_FUNCTION_CLEAR_TASK_SET = 0x04,
424 	UFSHCI_TASK_MGMT_FUNCTION_LOGICAL_UNIT_RESET = 0x08,
425 	UFSHCI_TASK_MGMT_FUNCTION_QUERY_TASK = 0x80,
426 	UFSHCI_TASK_MGMT_FUNCTION_QUERY_TASKSET = 0x81,
427 };
428 
429 /* UFS Spec 4.1, section 10.7.6 "TASK MANAGEMENT REQUEST UPIU" */
430 struct ufshci_task_mgmt_request_upiu {
431 	/* dword 0-2 */
432 	struct ufshci_upiu_header header;
433 	/* dword 3 */
434 	uint32_t input_param1; /* (Big-endian) */
435 	/* dword 4 */
436 	uint32_t input_param2; /* (Big-endian) */
437 	/* dword 5 */
438 	uint32_t input_param3; /* (Big-endian) */
439 	/* dword 6-7 */
440 	uint8_t reserved[8];
441 } __packed __aligned(4);
442 
443 _Static_assert(sizeof(struct ufshci_task_mgmt_request_upiu) == 32,
444     "bad size for ufshci_task_mgmt_request_upiu");
445 _Static_assert(sizeof(struct ufshci_task_mgmt_request_upiu) <=
446 	UFSHCI_UTP_XFER_RESP_SIZE,
447     "bad size for ufshci_task_mgmt_request_upiu");
448 _Static_assert(sizeof(struct ufshci_task_mgmt_request_upiu) %
449 	    UFSHCI_UPIU_ALIGNMENT ==
450 	0,
451     "UPIU requires 64-bit alignment");
452 
453 enum task_management_service_response {
454 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_COMPLETE = 0x00,
455 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_NOT_SUPPORTED = 0x04,
456 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_FAILED = 0x05,
457 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_SUCCEEDED = 0x08,
458 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_INCORRECT_LUN = 0x09,
459 };
460 
461 /* UFS Spec 4.1, section 10.7.7 "TASK MANAGEMENT RESPONSE UPIU" */
462 struct ufshci_task_mgmt_response_upiu {
463 	/* dword 0-2 */
464 	struct ufshci_upiu_header header;
465 	/* dword 3 */
466 	uint32_t output_param1; /* (Big-endian) */
467 	/* dword 4 */
468 	uint32_t output_param2; /* (Big-endian) */
469 	/* dword 5-7 */
470 	uint8_t reserved[12];
471 } __packed __aligned(4);
472 
473 _Static_assert(sizeof(struct ufshci_task_mgmt_response_upiu) == 32,
474     "bad size for ufshci_task_mgmt_response_upiu");
475 _Static_assert(sizeof(struct ufshci_task_mgmt_response_upiu) <=
476 	UFSHCI_UTP_XFER_RESP_SIZE,
477     "bad size for ufshci_task_mgmt_response_upiu");
478 _Static_assert(sizeof(struct ufshci_task_mgmt_response_upiu) %
479 	    UFSHCI_UPIU_ALIGNMENT ==
480 	0,
481     "UPIU requires 64-bit alignment");
482 
483 /* UFS Spec 4.1, section 10.7.8 "QUERY REQUEST UPIU" */
484 enum ufshci_query_function {
485 	UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01,
486 	UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81,
487 };
488 
489 enum ufshci_query_opcode {
490 	UFSHCI_QUERY_OPCODE_NOP = 0,
491 	UFSHCI_QUERY_OPCODE_READ_DESCRIPTOR,
492 	UFSHCI_QUERY_OPCODE_WRITE_DESCRIPTOR,
493 	UFSHCI_QUERY_OPCODE_READ_ATTRIBUTE,
494 	UFSHCI_QUERY_OPCODE_WRITE_ATTRIBUTE,
495 	UFSHCI_QUERY_OPCODE_READ_FLAG,
496 	UFSHCI_QUERY_OPCODE_SET_FLAG,
497 	UFSHCI_QUERY_OPCODE_CLEAR_FLAG,
498 	UFSHCI_QUERY_OPCODE_TOGGLE_FLAG,
499 };
500 
501 struct ufshci_query_param {
502 	enum ufshci_query_function function;
503 	enum ufshci_query_opcode opcode;
504 	uint8_t type;
505 	uint8_t index;
506 	uint8_t selector;
507 	uint64_t value;
508 	size_t desc_size;
509 };
510 
511 struct ufshci_query_request_upiu {
512 	/* dword 0-2 */
513 	struct ufshci_upiu_header header;
514 	/* dword 3 */
515 	uint8_t opcode;
516 	uint8_t idn;
517 	uint8_t index;
518 	uint8_t selector;
519 
520 	/* dword 4-5 */
521 	union {
522 		/* The Write Attribute opcode uses 64 - bit value. */
523 		uint64_t value_64; /* (Big-endian) */
524 		struct {
525 			uint8_t reserved1[2];
526 			uint16_t length;   /* (Big-endian) */
527 			uint32_t value_32; /* (Big-endian) */
528 		};
529 	} __packed __aligned(4);
530 
531 	/* dword 6 */
532 	uint32_t reserved2;
533 
534 	/* dword 7 */
535 	uint32_t reserved3;
536 
537 	uint8_t command_data[256];
538 } __packed __aligned(4);
539 
540 _Static_assert(sizeof(struct ufshci_query_request_upiu) == 288,
541     "bad size for ufshci_query_request_upiu");
542 _Static_assert(sizeof(struct ufshci_query_request_upiu) <=
543 	UFSHCI_UTP_XFER_REQ_SIZE,
544     "bad size for ufshci_query_request_upiu");
545 _Static_assert(sizeof(struct ufshci_query_request_upiu) %
546 	    UFSHCI_UPIU_ALIGNMENT ==
547 	0,
548     "UPIU requires 64-bit alignment");
549 
550 /* UFS Spec 4.1, section 10.7.9 "QUERY RESPONSE UPIU" */
551 enum ufshci_query_response_code {
552 	UFSHCI_QUERY_RESP_CODE_SUCCESS = 0x00,
553 	UFSHCI_QUERY_RESP_CODE_PARAMETER_NOT_READABLE = 0xf6,
554 	UFSHCI_QUERY_RESP_CODE_PARAMETER_NOT_WRITEABLE = 0xf7,
555 	UFSHCI_QUERY_RESP_CODE_PARAMETER_ALREADY_WRITTEN = 0xf8,
556 	UFSHCI_QUERY_RESP_CODE_INVALID_LENGTH = 0xf9,
557 	UFSHCI_QUERY_RESP_CODE_INVALID_VALUE = 0xfa,
558 	UFSHCI_QUERY_RESP_CODE_INVALID_SELECTOR = 0xfb,
559 	UFSHCI_QUERY_RESP_CODE_INVALID_INDEX = 0xfc,
560 	UFSHCI_QUERY_RESP_CODE_INVALID_IDN = 0xfd,
561 	UFSHCI_QUERY_RESP_CODE_INVALID_OPCODE = 0xfe,
562 	UFSHCI_QUERY_RESP_CODE_GENERAL_FAILURE = 0xff,
563 };
564 
565 struct ufshci_query_response_upiu {
566 	/* dword 0-2 */
567 	struct ufshci_upiu_header header;
568 	/* dword 3 */
569 	uint8_t opcode;
570 	uint8_t idn;
571 	uint8_t index;
572 	uint8_t selector;
573 
574 	/* dword 4-5 */
575 	union {
576 		/* The Read / Write Attribute opcodes use 64 - bit value. */
577 		uint64_t value_64; /* (Big-endian) */
578 		struct {
579 			uint8_t reserved1[2];
580 			uint16_t length; /* (Big-endian) */
581 			union {
582 				uint32_t value_32; /* (Big-endian) */
583 				struct {
584 					uint8_t reserved2[3];
585 					uint8_t flag_value;
586 				};
587 			};
588 		};
589 	} __packed __aligned(4);
590 
591 	/* dword 6 */
592 	uint8_t reserved3[4];
593 
594 	/* dword 7 */
595 	uint8_t reserved4[4];
596 
597 	uint8_t command_data[256];
598 } __packed __aligned(4);
599 
600 _Static_assert(sizeof(struct ufshci_query_response_upiu) == 288,
601     "bad size for ufshci_query_response_upiu");
602 _Static_assert(sizeof(struct ufshci_query_response_upiu) <=
603 	UFSHCI_UTP_XFER_RESP_SIZE,
604     "bad size for ufshci_query_response_upiu");
605 _Static_assert(sizeof(struct ufshci_query_response_upiu) %
606 	    UFSHCI_UPIU_ALIGNMENT ==
607 	0,
608     "UPIU requires 64-bit alignment");
609 
610 /* UFS 4.1, section 10.7.11 "NOP OUT UPIU" */
611 struct ufshci_nop_out_upiu {
612 	/* dword 0-2 */
613 	struct ufshci_upiu_header header;
614 	/* dword 3-7 */
615 	uint8_t reserved[20];
616 } __packed __aligned(8);
617 _Static_assert(sizeof(struct ufshci_nop_out_upiu) == 32,
618     "ufshci_upiu_nop_out must be 32 bytes");
619 
620 /* UFS 4.1, section 10.7.12 "NOP IN UPIU" */
621 struct ufshci_nop_in_upiu {
622 	/* dword 0-2 */
623 	struct ufshci_upiu_header header;
624 	/* dword 3-7 */
625 	uint8_t reserved[20];
626 } __packed __aligned(8);
627 _Static_assert(sizeof(struct ufshci_nop_in_upiu) == 32,
628     "ufshci_upiu_nop_in must be 32 bytes");
629 
630 union ufshci_reponse_upiu {
631 	struct ufshci_upiu_header header;
632 	struct ufshci_cmd_response_upiu cmd_response_upiu;
633 	struct ufshci_query_response_upiu query_response_upiu;
634 	struct ufshci_task_mgmt_response_upiu task_mgmt_response_upiu;
635 	struct ufshci_nop_in_upiu nop_in_upiu;
636 };
637 
638 struct ufshci_completion {
639 	union ufshci_reponse_upiu response_upiu;
640 	size_t size;
641 };
642 
643 typedef void (*ufshci_cb_fn_t)(void *, const struct ufshci_completion *, bool);
644 
645 /*
646  * UFS Spec 4.1, section 14.1 "UFS Descriptors"
647  * All descriptors use big-endian byte ordering.
648  */
649 enum ufshci_descriptor_type {
650 	UFSHCI_DESC_TYPE_DEVICE = 0x00,
651 	UFSHCI_DESC_TYPE_CONFIGURATION = 0x01,
652 	UFSHCI_DESC_TYPE_UNIT = 0x02,
653 	UFSHCI_DESC_TYPE_INTERCONNECT = 0x04,
654 	UFSHCI_DESC_TYPE_STRING = 0x05,
655 	UFSHCI_DESC_TYPE_GEOMETRY = 0X07,
656 	UFSHCI_DESC_TYPE_POWER = 0x08,
657 	UFSHCI_DESC_TYPE_DEVICE_HEALTH = 0x09,
658 	UFSHCI_DESC_TYPE_FBO_EXTENSION_SPECIFICATION = 0x0a,
659 };
660 
661 /*
662  * UFS Spec 4.1, section 14.1.5.2 "Device Descriptor"
663  * DeviceDescriptor use big-endian byte ordering.
664  */
665 struct ufshci_device_descriptor {
666 	uint8_t bLength;
667 	uint8_t bDescriptorIDN;
668 	uint8_t bDevice;
669 	uint8_t bDeviceClass;
670 	uint8_t bDeviceSubClass;
671 	uint8_t bProtocol;
672 	uint8_t bNumberLU;
673 	uint8_t bNumberWLU;
674 	uint8_t bBootEnable;
675 	uint8_t bDescrAccessEn;
676 	uint8_t bInitPowerMode;
677 	uint8_t bHighPriorityLUN;
678 	uint8_t bSecureRemovalType;
679 	uint8_t bSecurityLU;
680 	uint8_t bBackgroundOpsTermLat;
681 	uint8_t bInitActiveICCLevel;
682 	/* 0x10 */
683 	uint16_t wSpecVersion;
684 	uint16_t wManufactureDate;
685 	uint8_t iManufacturerName;
686 	uint8_t iProductName;
687 	uint8_t iSerialNumber;
688 	uint8_t iOemID;
689 	uint16_t wManufacturerID;
690 	uint8_t bUD0BaseOffset;
691 	uint8_t bUDConfigPLength;
692 	uint8_t bDeviceRTTCap;
693 	uint16_t wPeriodicRTCUpdate;
694 	uint8_t bUfsFeaturesSupport;
695 	/* 0x20 */
696 	uint8_t bFFUTimeout;
697 	uint8_t bQueueDepth;
698 	uint16_t wDeviceVersion;
699 	uint8_t bNumSecureWPArea;
700 	uint32_t dPSAMaxDataSize;
701 	uint8_t bPSAStateTimeout;
702 	uint8_t iProductRevisionLevel;
703 	uint8_t Reserved[5];
704 	/* 0x2a */
705 	/* 0x30 */
706 	uint8_t ReservedUME[16];
707 	/* 0x40 */
708 	uint8_t ReservedHpb[3];
709 	uint8_t Reserved2[12];
710 	uint32_t dExtendedUfsFeaturesSupport;
711 	uint8_t bWriteBoosterBufferPreserveUserSpaceEn;
712 	uint8_t bWriteBoosterBufferType;
713 	uint32_t dNumSharedWriteBoosterBufferAllocUnits;
714 } __packed;
715 
716 _Static_assert(sizeof(struct ufshci_device_descriptor) == 89,
717     "bad size for ufshci_device_descriptor");
718 
719 /* Defines the bit field of dExtendedUfsFeaturesSupport. */
720 enum ufshci_desc_wb_ext_ufs_feature {
721 	UFSHCI_DESC_EXT_UFS_FEATURE_FFU = (1 << 0),
722 	UFSHCI_DESC_EXT_UFS_FEATURE_PSA = (1 << 1),
723 	UFSHCI_DESC_EXT_UFS_FEATURE_DEV_LIFE_SPAN = (1 << 2),
724 	UFSHCI_DESC_EXT_UFS_FEATURE_REFRESH_OP = (1 << 3),
725 	UFSHCI_DESC_EXT_UFS_FEATURE_TOO_HIGH_TEMP = (1 << 4),
726 	UFSHCI_DESC_EXT_UFS_FEATURE_TOO_LOW_TEMP = (1 << 5),
727 	UFSHCI_DESC_EXT_UFS_FEATURE_EXT_TEMP = (1 << 6),
728 	UFSHCI_DESC_EXT_UFS_FEATURE_HPB_SUPPORT = (1 << 7),
729 	UFSHCI_DESC_EXT_UFS_FEATURE_WRITE_BOOSTER = (1 << 8),
730 	UFSHCI_DESC_EXT_UFS_FEATURE_PERF_THROTTLING = (1 << 9),
731 	UFSHCI_DESC_EXT_UFS_FEATURE_ADVANCED_RPMB = (1 << 10),
732 	UFSHCI_DESC_EXT_UFS_FEATURE_ZONED_UFS_EXTENSION = (1 << 11),
733 	UFSHCI_DESC_EXT_UFS_FEATURE_DEV_LEVEL_EXCEPTION = (1 << 12),
734 	UFSHCI_DESC_EXT_UFS_FEATURE_HID = (1 << 13),
735 	UFSHCI_DESC_EXT_UFS_FEATURE_BARRIER = (1 << 14),
736 	UFSHCI_DESC_EXT_UFS_FEATURE_CLEAR_ERROR_HISTORY = (1 << 15),
737 	UFSHCI_DESC_EXT_UFS_FEATURE_EXT_IID = (1 << 16),
738 	UFSHCI_DESC_EXT_UFS_FEATURE_FBO = (1 << 17),
739 	UFSHCI_DESC_EXT_UFS_FEATURE_FAST_RECOVERY_MODE = (1 << 18),
740 	UFSHCI_DESC_EXT_UFS_FEATURE_RPMB_VENDOR_CMD = (1 << 19),
741 };
742 
743 /* Defines the bit field of bWriteBoosterBufferType. */
744 enum ufshci_desc_wb_buffer_type {
745 	UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED = 0x00,
746 	UFSHCI_DESC_WB_BUF_TYPE_SINGLE_SHARED = 0x01,
747 };
748 
749 /* Defines the bit field of bWriteBoosterBufferPreserveUserSpaceEn. */
750 enum ufshci_desc_user_space_config {
751 	UFSHCI_DESC_WB_BUF_USER_SPACE_REDUCTION = 0x00,
752 	UFSHCI_DESC_WB_BUF_PRESERVE_USER_SPACE = 0x01,
753 };
754 
755 /*
756  * UFS Spec 4.1, section 14.1.5.3 "Configuration Descriptor"
757  * ConfigurationDescriptor use big-endian byte ordering.
758  */
759 struct ufshci_unit_descriptor_configurable_parameters {
760 	uint8_t bLUEnable;
761 	uint8_t bBootLunID;
762 	uint8_t bLUWriteProtect;
763 	uint8_t bMemoryType;
764 	uint32_t dNumAllocUnits;
765 	uint8_t bDataReliability;
766 	uint8_t bLogicalBlockSize;
767 	uint8_t bProvisioningType;
768 	uint16_t wContextCapabilities;
769 	union {
770 		struct {
771 			uint8_t Reserved[3];
772 			uint8_t ReservedHpb[6];
773 		} __packed;
774 		uint16_t wZoneBufferAllocUnits;
775 	};
776 	uint32_t dLUNumWriteBoosterBufferAllocUnits;
777 } __packed;
778 
779 _Static_assert(sizeof(struct ufshci_unit_descriptor_configurable_parameters) ==
780 	27,
781     "bad size for ufshci_unit_descriptor_configurable_parameters");
782 
783 #define UFSHCI_CONFIGURATION_DESCEIPTOR_LU_NUM 8
784 
785 struct ufshci_configuration_descriptor {
786 	uint8_t bLength;
787 	uint8_t bDescriptorIDN;
788 	uint8_t bConfDescContinue;
789 	uint8_t bBootEnable;
790 	uint8_t bDescrAccessEn;
791 	uint8_t bInitPowerMode;
792 	uint8_t bHighPriorityLUN;
793 	uint8_t bSecureRemovalType;
794 	uint8_t bInitActiveICCLevel;
795 	uint16_t wPeriodicRTCUpdate;
796 	uint8_t Reserved;
797 	uint8_t bRPMBRegionEnable;
798 	uint8_t bRPMBRegion1Size;
799 	uint8_t bRPMBRegion2Size;
800 	uint8_t bRPMBRegion3Size;
801 	uint8_t bWriteBoosterBufferPreserveUserSpaceEn;
802 	uint8_t bWriteBoosterBufferType;
803 	uint32_t dNumSharedWriteBoosterBufferAllocUnits;
804 	/* 0x16 */
805 	struct ufshci_unit_descriptor_configurable_parameters
806 	    unit_config_params[UFSHCI_CONFIGURATION_DESCEIPTOR_LU_NUM];
807 } __packed;
808 
809 _Static_assert(sizeof(struct ufshci_configuration_descriptor) == (22 + 27 * 8),
810     "bad size for ufshci_configuration_descriptor");
811 
812 /*
813  * UFS Spec 4.1, section 14.1.5.4 "Geometry Descriptor"
814  * GeometryDescriptor use big-endian byte ordering.
815  */
816 struct ufshci_geometry_descriptor {
817 	uint8_t bLength;
818 	uint8_t bDescriptorIDN;
819 	uint8_t bMediaTechnology;
820 	uint8_t Reserved;
821 	uint64_t qTotalRawDeviceCapacity;
822 	uint8_t bMaxNumberLU;
823 	uint32_t dSegmentSize;
824 	/* 0x11 */
825 	uint8_t bAllocationUnitSize;
826 	uint8_t bMinAddrBlockSize;
827 	uint8_t bOptimalReadBlockSize;
828 	uint8_t bOptimalWriteBlockSize;
829 	uint8_t bMaxInBufferSize;
830 	uint8_t bMaxOutBufferSize;
831 	uint8_t bRPMB_ReadWriteSize;
832 	uint8_t bDynamicCapacityResourcePolicy;
833 	uint8_t bDataOrdering;
834 	uint8_t bMaxContexIDNumber;
835 	uint8_t bSysDataTagUnitSize;
836 	uint8_t bSysDataTagResSize;
837 	uint8_t bSupportedSecRTypes;
838 	uint16_t wSupportedMemoryTypes;
839 	/* 0x20 */
840 	uint32_t dSystemCodeMaxNAllocU;
841 	uint16_t wSystemCodeCapAdjFac;
842 	uint32_t dNonPersistMaxNAllocU;
843 	uint16_t wNonPersistCapAdjFac;
844 	uint32_t dEnhanced1MaxNAllocU;
845 	/* 0x30 */
846 	uint16_t wEnhanced1CapAdjFac;
847 	uint32_t dEnhanced2MaxNAllocU;
848 	uint16_t wEnhanced2CapAdjFac;
849 	uint32_t dEnhanced3MaxNAllocU;
850 	uint16_t wEnhanced3CapAdjFac;
851 	uint32_t dEnhanced4MaxNAllocU;
852 	/* 0x42 */
853 	uint16_t wEnhanced4CapAdjFac;
854 	uint32_t dOptimalLogicalBlockSize;
855 	uint8_t ReservedHpb[5];
856 	uint8_t Reserved2[2];
857 	uint32_t dWriteBoosterBufferMaxNAllocUnits;
858 	uint8_t bDeviceMaxWriteBoosterLUs;
859 	uint8_t bWriteBoosterBufferCapAdjFac;
860 	uint8_t bSupportedWriteBoosterBufferUserSpaceReductionTypes;
861 	uint8_t bSupportedWriteBoosterBufferTypes;
862 } __packed;
863 
864 _Static_assert(sizeof(struct ufshci_geometry_descriptor) == 87,
865     "bad size for ufshci_geometry_descriptor");
866 
867 /*
868  * UFS Spec 4.1, section 14.1.5.5 "Unit Descriptor"
869  * UnitDescriptor use big-endian byte ordering.
870  */
871 struct ufshci_unit_descriptor {
872 	uint8_t bLength;
873 	uint8_t bDescriptorIDN;
874 	uint8_t bUnitIndex;
875 	uint8_t bLUEnable;
876 	uint8_t bBootLunID;
877 	uint8_t bLUWriteProtect;
878 	uint8_t bLUQueueDepth;
879 	uint8_t bPSASensitive;
880 	uint8_t bMemoryType;
881 	uint8_t bDataReliability;
882 	uint8_t bLogicalBlockSize;
883 	uint64_t qLogicalBlockCount;
884 	/* 0x13 */
885 	uint32_t dEraseBlockSize;
886 	uint8_t bProvisioningType;
887 	uint64_t qPhyMemResourceCount;
888 	/* 0x20 */
889 	uint16_t wContextCapabilities;
890 	uint8_t bLargeUnitGranularity_M1;
891 	uint8_t ReservedHpb[6];
892 	uint32_t dLUNumWriteBoosterBufferAllocUnits;
893 } __packed;
894 _Static_assert(sizeof(struct ufshci_unit_descriptor) == 45,
895     "bad size for ufshci_unit_descriptor");
896 
897 enum LUWriteProtect {
898 	kNoWriteProtect = 0x00,
899 	kPowerOnWriteProtect = 0x01,
900 	kPermanentWriteProtect = 0x02,
901 };
902 
903 /*
904  * UFS Spec 4.1, section 14.1.5.6 "RPMB Unit Descriptor"
905  * RpmbUnitDescriptor use big-endian byte ordering.
906  */
907 struct ufshci_rpmb_unit_descriptor {
908 	uint8_t bLength;
909 	uint8_t bDescriptorIDN;
910 	uint8_t bUnitIndex;
911 	uint8_t bLUEnable;
912 	uint8_t bBootLunID;
913 	uint8_t bLUWriteProtect;
914 	uint8_t bLUQueueDepth;
915 	uint8_t bPSASensitive;
916 	uint8_t bMemoryType;
917 	uint8_t Reserved;
918 	uint8_t bLogicalBlockSize;
919 	uint64_t qLogicalBlockCount;
920 	/* 0x13 */
921 	uint32_t dEraseBlockSize;
922 	uint8_t bProvisioningType;
923 	uint64_t qPhyMemResourceCount;
924 	/* 0x20 */
925 	uint8_t Reserved1[3];
926 } __packed;
927 _Static_assert(sizeof(struct ufshci_rpmb_unit_descriptor) == 35,
928     "bad size for RpmbUnitDescriptor");
929 
930 /*
931  * UFS Spec 4.1, section 14.1.5.7 "Power Parameters Descriptor"
932  * PowerParametersDescriptor use big-endian byte ordering.
933  */
934 struct ufshci_power_parameters_descriptor {
935 	uint8_t bLength;
936 	uint8_t bDescriptorIDN;
937 	uint16_t wActiveICCLevelsVCC[16];
938 	uint16_t wActiveICCLevelsVCCQ[16];
939 	uint16_t wActiveICCLevelsVCCQ2[16];
940 } __packed;
941 _Static_assert(sizeof(struct ufshci_power_parameters_descriptor) == 98,
942     "bad size for PowerParametersDescriptor");
943 
944 /*
945  * UFS Spec 4.1, section 14.1.5.8 "Interconnect Descriptor"
946  * InterconnectDescriptor use big-endian byte ordering.
947  */
948 struct ufshci_interconnect_descriptor {
949 	uint8_t bLength;
950 	uint8_t bDescriptorIDN;
951 	uint16_t bcdUniproVersion;
952 	uint16_t bcdMphyVersion;
953 } __packed;
954 _Static_assert(sizeof(struct ufshci_interconnect_descriptor) == 6,
955     "bad size for InterconnectDescriptor");
956 
957 /*
958  * UFS Spec 4.1, section 14.1.5.9-13 "String Descriptor"
959  * StringDescriptor use big-endian byte ordering.
960  */
961 struct ufshci_string_descriptor {
962 	uint8_t bLength;
963 	uint8_t bDescriptorIDN;
964 	uint16_t UC[126];
965 } __packed;
966 _Static_assert(sizeof(struct ufshci_string_descriptor) == 254,
967     "bad size for StringDescriptor");
968 
969 /*
970  * UFS Spec 4.1, section 14.1.5.14 "Device Health Descriptor"
971  * DeviceHealthDescriptor use big-endian byte ordering.
972  */
973 struct ufshci_device_healthd_descriptor {
974 	uint8_t bLength;
975 	uint8_t bDescriptorIDN;
976 	uint8_t bPreEOLInfo;
977 	uint8_t bDeviceLifeTimeEstA;
978 	uint8_t bDeviceLifeTimeEstB;
979 	uint8_t VendorPropInfo[32];
980 	uint32_t dRefreshTotalCount;
981 	uint32_t dRefreshProgress;
982 } __packed;
983 _Static_assert(sizeof(struct ufshci_device_healthd_descriptor) == 45,
984     "bad size for DeviceHealthDescriptor");
985 
986 /*
987  * UFS Spec 4.1, section 14.1.5.15 "Vendor Specific Descriptor"
988  * VendorSpecificDescriptor use big-endian byte ordering.
989  */
990 struct ufshci_vendor_specific_descriptor {
991 	uint8_t bLength;
992 	uint8_t bDescriptorIDN;
993 	uint8_t DATA[254];
994 } __packed;
995 _Static_assert(sizeof(struct ufshci_vendor_specific_descriptor) == 256,
996     "bad size for VendorSpecificDescriptor");
997 
998 /* UFS Spec 4.1, section 14.2 "Flags" */
999 enum ufshci_flags {
1000 	UFSHCI_FLAG_F_RESERVED = 0x00,
1001 	UFSHCI_FLAG_F_DEVICE_INIT = 0x01,
1002 	UFSHCI_FLAG_F_PERMANENT_WP_EN = 0x02,
1003 	UFSHCI_FLAS_F_POWER_ON_WP_EN = 0x03,
1004 	UFSHCI_FLAG_F_BACKGROUND_OPS_EN = 0x04,
1005 	UFSHCI_FLAG_F_DEVICE_LIFE_SPAN_MODE_EN = 0x05,
1006 	UFSHCI_FLAG_F_PURGE_ENABLE = 0x06,
1007 	UFSHCI_FLAG_F_REFRESH_ENABLE = 0x07,
1008 	UFSHCI_FLAG_F_PHY_RESOURCE_REMOVAL = 0x08,
1009 	UFSHCI_FLAG_F_BUSY_RTC = 0x09,
1010 	UFSHCI_FLAG_F_PERMANENTLY_DISABLE_FW_UPDATE = 0x0b,
1011 	UFSHCI_FLAG_F_WRITE_BOOSTER_EN = 0x0e,
1012 	UFSHCI_FLAG_F_WB_BUFFER_FLUSH_EN = 0x0f,
1013 	UFSHCI_FLAG_F_WB_BUFFER_FLUSH_DURING_HIBERNATE = 0x10,
1014 	UFSHCI_FLAG_F_UNPIN_EN = 0x13,
1015 };
1016 
1017 /* UFS Spec 4.1, section 14.3 "Attributes" */
1018 enum ufshci_attributes {
1019 	UFSHCI_ATTR_B_BOOT_LUN_EN = 0x00,
1020 	UFSHCI_ATTR_B_CURRENT_POWER_MODE = 0x02,
1021 	UFSHCI_ATTR_B_ACTIVE_ICC_LEVEL = 0x03,
1022 	UFSHCI_ATTR_B_OUT_OF_ORDER_DATA_EN = 0x04,
1023 	UFSHCI_ATTR_B_BACKGROUND_OP_STATUS = 0x05,
1024 	UFSHCI_ATTR_B_PURGE_STATUS = 0x06,
1025 	UFSHCI_ATTR_B_MAX_DATA_IN_SIZE = 0x07,
1026 	UFSHCI_ATTR_B_MAX_DATA_OUT_SIZE = 0x08,
1027 	UFSHCI_ATTR_D_DYN_CAP_NEEDED = 0x09,
1028 	UFSHCI_ATTR_B_REF_CLK_FREQ = 0x0a,
1029 	UFSHCI_ATTR_B_CONFIG_DESCR_LOCK = 0x0b,
1030 	UFSHCI_ATTR_B_MAX_NUM_OF_RTT = 0x0c,
1031 	UFSHCI_ATTR_W_EXCEPTION_EVENT_CONTROL = 0x0d,
1032 	UFSHCI_ATTR_W_EXCEPTION_EVENT_STATUS = 0x0e,
1033 	UFSHCI_ATTR_D_SECONDS_PASSED = 0x0f,
1034 	UFSHCI_ATTR_W_CONTEXT_CONF = 0x10,
1035 	UFSHCI_ATTR_B_DEVICE_FFU_STATUS = 0x14,
1036 	UFSHCI_ATTR_B_PSA_STATE = 0x15,
1037 	UFSHCI_ATTR_D_PSA_DATA_SIZE = 0x16,
1038 	UFSHCI_ATTR_B_REF_CLK_GATING_WAIT_TIME = 0x17,
1039 	UFSHCI_ATTR_B_DEVICE_CASE_ROUGH_TEMPERAURE = 0x18,
1040 	UFSHCI_ATTR_B_DEVICE_TOO_HIGH_TEMP_BOUNDARY = 0x19,
1041 	UFSHCI_ATTR_B_DEVICE_TOO_LOW_TEMP_BOUNDARY = 0x1a,
1042 	UFSHCI_ATTR_B_THROTTLING_STATUS = 0x1b,
1043 	UFSHCI_ATTR_B_WB_BUFFER_FLUSH_STATUS = 0x1c,
1044 	UFSHCI_ATTR_B_AVAILABLE_WB_BUFFER_SIZE = 0x1d,
1045 	UFSHCI_ATTR_B_WB_BUFFER_LIFE_TIME_EST = 0x1e,
1046 	UFSHCI_ATTR_D_CURRENT_WB_BUFFER_SIZE = 0x1f,
1047 	UFSHCI_ATTR_B_REFRESH_STATUS = 0x2c,
1048 	UFSHCI_ATTR_B_REFRESH_FREQ = 0x2d,
1049 	UFSHCI_ATTR_B_REFRESH_UNIT = 0x2e,
1050 	UFSHCI_ATTR_B_REFRESH_METHOD = 0x2f,
1051 };
1052 
1053 /* bAvailableWriteBoosterBufferSize codes (UFS WriteBooster abailable buffer
1054  * left %) */
1055 enum ufshci_wb_available_buffer_Size {
1056 	UFSHCI_ATTR_WB_AVAILABLE_0 = 0x00,   /* 0% buffer remains  */
1057 	UFSHCI_ATTR_WB_AVAILABLE_10 = 0x01,  /* 10% buffer remains  */
1058 	UFSHCI_ATTR_WB_AVAILABLE_20 = 0x02,  /* 20% buffer remains  */
1059 	UFSHCI_ATTR_WB_AVAILABLE_30 = 0x03,  /* 30% buffer remains  */
1060 	UFSHCI_ATTR_WB_AVAILABLE_40 = 0x04,  /* 40% buffer remains  */
1061 	UFSHCI_ATTR_WB_AVAILABLE_50 = 0x05,  /* 50% buffer remains  */
1062 	UFSHCI_ATTR_WB_AVAILABLE_60 = 0x06,  /* 60% buffer remains  */
1063 	UFSHCI_ATTR_WB_AVAILABLE_70 = 0x07,  /* 70% buffer remains  */
1064 	UFSHCI_ATTR_WB_AVAILABLE_80 = 0x08,  /* 80% buffer remains  */
1065 	UFSHCI_ATTR_WB_AVAILABLE_90 = 0x09,  /* 90% buffer remains  */
1066 	UFSHCI_ATTR_WB_AVAILABLE_100 = 0x0A, /* 100% buffer remains  */
1067 };
1068 
1069 /* bWriteBoosterBufferLifeTimeEst codes (UFS WriteBooster buffer life %) */
1070 enum ufshci_wb_lifetime {
1071 	UFSHCI_ATTR_WB_LIFE_DISABLED = 0x00, /* Info not available */
1072 	UFSHCI_ATTR_WB_LIFE_0_10 = 0x01,     /*   0%–10% used  */
1073 	UFSHCI_ATTR_WB_LIFE_10_20 = 0x02,    /*  10%–20% used  */
1074 	UFSHCI_ATTR_WB_LIFE_20_30 = 0x03,    /*  20%–30% used  */
1075 	UFSHCI_ATTR_WB_LIFE_30_40 = 0x04,    /*  30%–40% used  */
1076 	UFSHCI_ATTR_WB_LIFE_40_50 = 0x05,    /*  40%–50% used  */
1077 	UFSHCI_ATTR_WB_LIFE_50_60 = 0x06,    /*  50%–60% used  */
1078 	UFSHCI_ATTR_WB_LIFE_60_70 = 0x07,    /*  60%–70% used  */
1079 	UFSHCI_ATTR_WB_LIFE_70_80 = 0x08,    /*  70%–80% used  */
1080 	UFSHCI_ATTR_WB_LIFE_80_90 = 0x09,    /*  80%–90% used  */
1081 	UFSHCI_ATTR_WB_LIFE_90_100 = 0x0A,   /* 90%–100% used  */
1082 	UFSHCI_ATTR_WB_LIFE_EXCEEDED =
1083 	    0x0B, /* Exceeded estimated life (treat as WB disabled) */
1084 };
1085 
1086 #endif /* __UFSHCI_H__ */
1087