xref: /freebsd/sys/dev/ufshci/ufshci.h (revision 5e0d065b5b90d4f4264d8248f39f199f1a2576dc)
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 #define UFSHCI_UPIU_UNIT_NUMBER_ID_MASK 0x7f
339 #define UFSHCI_UPIU_WLUN_ID_MASK	0x80
340 	uint8_t task_tag;
341 
342 	/* dword 1 */
343 #define UFSHCI_COMMAND_SET_TYPE_SCSI 0
344 	uint8_t cmd_set_type : 4; /* [3:0] */
345 	uint8_t iid : 4;	  /* [7:4] */
346 	uint8_t ext_iid_or_function;
347 	uint8_t response;
348 	uint8_t ext_iid_or_status;
349 
350 	/* dword 2 */
351 	uint8_t ehs_length;
352 	uint8_t device_infomation;
353 	uint16_t data_segment_length; /* (Big-endian) */
354 } __packed __aligned(4);
355 
356 _Static_assert(sizeof(struct ufshci_upiu_header) == 12,
357     "ufshci_upiu_header must be 12 bytes");
358 
359 #define UFSHCI_MAX_UPIU_SIZE  512
360 #define UFSHCI_UPIU_ALIGNMENT 8 /* UPIU requires 64-bit alignment. */
361 
362 struct ufshci_upiu {
363 	/* dword 0-2 */
364 	struct ufshci_upiu_header header;
365 	/* dword 3-127 */
366 	uint8_t
367 	    reserved[UFSHCI_MAX_UPIU_SIZE - sizeof(struct ufshci_upiu_header)];
368 } __packed __aligned(8);
369 
370 _Static_assert(sizeof(struct ufshci_upiu) == 512,
371     "ufshci_upiu must be 512 bytes");
372 
373 /* UFS Spec 4.1, section 10.7.1 "COMMAND UPIU" */
374 struct ufshci_cmd_command_upiu {
375 	/* dword 0-2 */
376 	struct ufshci_upiu_header header;
377 	/* dword 3 */
378 	uint32_t expected_data_transfer_length; /* (Big-endian) */
379 
380 	/* dword 4-7 */
381 	uint8_t cdb[16];
382 
383 } __packed __aligned(4);
384 
385 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) == 32,
386     "bad size for ufshci_cmd_command_upiu");
387 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) <=
388 	UFSHCI_UTP_XFER_REQ_SIZE,
389     "bad size for ufshci_cmd_command_upiu");
390 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) % UFSHCI_UPIU_ALIGNMENT ==
391 	0,
392     "UPIU requires 64-bit alignment");
393 
394 /* UFS Spec 4.1, section 10.7.2 "RESPONSE UPIU" */
395 struct ufshci_cmd_response_upiu {
396 	/* dword 0-2 */
397 	struct ufshci_upiu_header header;
398 	/* dword 3 */
399 	uint32_t residual_transfer_count; /* (Big-endian) */
400 
401 	/* dword 4-7 */
402 	uint8_t reserved[16];
403 
404 	/* Sense Data */
405 	uint16_t sense_data_len; /* (Big-endian) */
406 	uint8_t sense_data[18];
407 
408 	/* Add padding to align the kUpiuAlignment. */
409 	uint8_t padding[4];
410 } __packed __aligned(4);
411 
412 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) == 56,
413     "bad size for ufshci_cmd_response_upiu");
414 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) <=
415 	UFSHCI_UTP_XFER_RESP_SIZE,
416     "bad size for ufshci_cmd_response_upiu");
417 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) %
418 	    UFSHCI_UPIU_ALIGNMENT ==
419 	0,
420     "UPIU requires 64-bit alignment");
421 
422 enum task_management_function {
423 	UFSHCI_TASK_MGMT_FUNCTION_ABORT_TASK = 0x01,
424 	UFSHCI_TASK_MGMT_FUNCTION_ABORT_TASK_SET = 0x02,
425 	UFSHCI_TASK_MGMT_FUNCTION_CLEAR_TASK_SET = 0x04,
426 	UFSHCI_TASK_MGMT_FUNCTION_LOGICAL_UNIT_RESET = 0x08,
427 	UFSHCI_TASK_MGMT_FUNCTION_QUERY_TASK = 0x80,
428 	UFSHCI_TASK_MGMT_FUNCTION_QUERY_TASKSET = 0x81,
429 };
430 
431 /* UFS Spec 4.1, section 10.7.6 "TASK MANAGEMENT REQUEST UPIU" */
432 struct ufshci_task_mgmt_request_upiu {
433 	/* dword 0-2 */
434 	struct ufshci_upiu_header header;
435 	/* dword 3 */
436 	uint32_t input_param1; /* (Big-endian) */
437 	/* dword 4 */
438 	uint32_t input_param2; /* (Big-endian) */
439 	/* dword 5 */
440 	uint32_t input_param3; /* (Big-endian) */
441 	/* dword 6-7 */
442 	uint8_t reserved[8];
443 } __packed __aligned(4);
444 
445 _Static_assert(sizeof(struct ufshci_task_mgmt_request_upiu) == 32,
446     "bad size for ufshci_task_mgmt_request_upiu");
447 _Static_assert(sizeof(struct ufshci_task_mgmt_request_upiu) <=
448 	UFSHCI_UTP_XFER_RESP_SIZE,
449     "bad size for ufshci_task_mgmt_request_upiu");
450 _Static_assert(sizeof(struct ufshci_task_mgmt_request_upiu) %
451 	    UFSHCI_UPIU_ALIGNMENT ==
452 	0,
453     "UPIU requires 64-bit alignment");
454 
455 enum task_management_service_response {
456 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_COMPLETE = 0x00,
457 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_NOT_SUPPORTED = 0x04,
458 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_FAILED = 0x05,
459 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_SUCCEEDED = 0x08,
460 	UFSHCI_TASK_MGMT_SERVICE_RESPONSE_INCORRECT_LUN = 0x09,
461 };
462 
463 /* UFS Spec 4.1, section 10.7.7 "TASK MANAGEMENT RESPONSE UPIU" */
464 struct ufshci_task_mgmt_response_upiu {
465 	/* dword 0-2 */
466 	struct ufshci_upiu_header header;
467 	/* dword 3 */
468 	uint32_t output_param1; /* (Big-endian) */
469 	/* dword 4 */
470 	uint32_t output_param2; /* (Big-endian) */
471 	/* dword 5-7 */
472 	uint8_t reserved[12];
473 } __packed __aligned(4);
474 
475 _Static_assert(sizeof(struct ufshci_task_mgmt_response_upiu) == 32,
476     "bad size for ufshci_task_mgmt_response_upiu");
477 _Static_assert(sizeof(struct ufshci_task_mgmt_response_upiu) <=
478 	UFSHCI_UTP_XFER_RESP_SIZE,
479     "bad size for ufshci_task_mgmt_response_upiu");
480 _Static_assert(sizeof(struct ufshci_task_mgmt_response_upiu) %
481 	    UFSHCI_UPIU_ALIGNMENT ==
482 	0,
483     "UPIU requires 64-bit alignment");
484 
485 /* UFS Spec 4.1, section 10.7.8 "QUERY REQUEST UPIU" */
486 enum ufshci_query_function {
487 	UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01,
488 	UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81,
489 };
490 
491 enum ufshci_query_opcode {
492 	UFSHCI_QUERY_OPCODE_NOP = 0,
493 	UFSHCI_QUERY_OPCODE_READ_DESCRIPTOR,
494 	UFSHCI_QUERY_OPCODE_WRITE_DESCRIPTOR,
495 	UFSHCI_QUERY_OPCODE_READ_ATTRIBUTE,
496 	UFSHCI_QUERY_OPCODE_WRITE_ATTRIBUTE,
497 	UFSHCI_QUERY_OPCODE_READ_FLAG,
498 	UFSHCI_QUERY_OPCODE_SET_FLAG,
499 	UFSHCI_QUERY_OPCODE_CLEAR_FLAG,
500 	UFSHCI_QUERY_OPCODE_TOGGLE_FLAG,
501 };
502 
503 struct ufshci_query_param {
504 	enum ufshci_query_function function;
505 	enum ufshci_query_opcode opcode;
506 	uint8_t type;
507 	uint8_t index;
508 	uint8_t selector;
509 	uint64_t value;
510 	size_t desc_size;
511 };
512 
513 struct ufshci_query_request_upiu {
514 	/* dword 0-2 */
515 	struct ufshci_upiu_header header;
516 	/* dword 3 */
517 	uint8_t opcode;
518 	uint8_t idn;
519 	uint8_t index;
520 	uint8_t selector;
521 
522 	/* dword 4-5 */
523 	union {
524 		/* The Write Attribute opcode uses 64 - bit value. */
525 		uint64_t value_64; /* (Big-endian) */
526 		struct {
527 			uint8_t reserved1[2];
528 			uint16_t length;   /* (Big-endian) */
529 			uint32_t value_32; /* (Big-endian) */
530 		};
531 	} __packed __aligned(4);
532 
533 	/* dword 6 */
534 	uint32_t reserved2;
535 
536 	/* dword 7 */
537 	uint32_t reserved3;
538 
539 	uint8_t command_data[256];
540 } __packed __aligned(4);
541 
542 _Static_assert(sizeof(struct ufshci_query_request_upiu) == 288,
543     "bad size for ufshci_query_request_upiu");
544 _Static_assert(sizeof(struct ufshci_query_request_upiu) <=
545 	UFSHCI_UTP_XFER_REQ_SIZE,
546     "bad size for ufshci_query_request_upiu");
547 _Static_assert(sizeof(struct ufshci_query_request_upiu) %
548 	    UFSHCI_UPIU_ALIGNMENT ==
549 	0,
550     "UPIU requires 64-bit alignment");
551 
552 /* UFS Spec 4.1, section 10.7.9 "QUERY RESPONSE UPIU" */
553 enum ufshci_query_response_code {
554 	UFSHCI_QUERY_RESP_CODE_SUCCESS = 0x00,
555 	UFSHCI_QUERY_RESP_CODE_PARAMETER_NOT_READABLE = 0xf6,
556 	UFSHCI_QUERY_RESP_CODE_PARAMETER_NOT_WRITEABLE = 0xf7,
557 	UFSHCI_QUERY_RESP_CODE_PARAMETER_ALREADY_WRITTEN = 0xf8,
558 	UFSHCI_QUERY_RESP_CODE_INVALID_LENGTH = 0xf9,
559 	UFSHCI_QUERY_RESP_CODE_INVALID_VALUE = 0xfa,
560 	UFSHCI_QUERY_RESP_CODE_INVALID_SELECTOR = 0xfb,
561 	UFSHCI_QUERY_RESP_CODE_INVALID_INDEX = 0xfc,
562 	UFSHCI_QUERY_RESP_CODE_INVALID_IDN = 0xfd,
563 	UFSHCI_QUERY_RESP_CODE_INVALID_OPCODE = 0xfe,
564 	UFSHCI_QUERY_RESP_CODE_GENERAL_FAILURE = 0xff,
565 };
566 
567 struct ufshci_query_response_upiu {
568 	/* dword 0-2 */
569 	struct ufshci_upiu_header header;
570 	/* dword 3 */
571 	uint8_t opcode;
572 	uint8_t idn;
573 	uint8_t index;
574 	uint8_t selector;
575 
576 	/* dword 4-5 */
577 	union {
578 		/* The Read / Write Attribute opcodes use 64 - bit value. */
579 		uint64_t value_64; /* (Big-endian) */
580 		struct {
581 			uint8_t reserved1[2];
582 			uint16_t length; /* (Big-endian) */
583 			union {
584 				uint32_t value_32; /* (Big-endian) */
585 				struct {
586 					uint8_t reserved2[3];
587 					uint8_t flag_value;
588 				};
589 			};
590 		};
591 	} __packed __aligned(4);
592 
593 	/* dword 6 */
594 	uint8_t reserved3[4];
595 
596 	/* dword 7 */
597 	uint8_t reserved4[4];
598 
599 	uint8_t command_data[256];
600 } __packed __aligned(4);
601 
602 _Static_assert(sizeof(struct ufshci_query_response_upiu) == 288,
603     "bad size for ufshci_query_response_upiu");
604 _Static_assert(sizeof(struct ufshci_query_response_upiu) <=
605 	UFSHCI_UTP_XFER_RESP_SIZE,
606     "bad size for ufshci_query_response_upiu");
607 _Static_assert(sizeof(struct ufshci_query_response_upiu) %
608 	    UFSHCI_UPIU_ALIGNMENT ==
609 	0,
610     "UPIU requires 64-bit alignment");
611 
612 /* UFS 4.1, section 10.7.11 "NOP OUT UPIU" */
613 struct ufshci_nop_out_upiu {
614 	/* dword 0-2 */
615 	struct ufshci_upiu_header header;
616 	/* dword 3-7 */
617 	uint8_t reserved[20];
618 } __packed __aligned(8);
619 _Static_assert(sizeof(struct ufshci_nop_out_upiu) == 32,
620     "ufshci_upiu_nop_out must be 32 bytes");
621 
622 /* UFS 4.1, section 10.7.12 "NOP IN UPIU" */
623 struct ufshci_nop_in_upiu {
624 	/* dword 0-2 */
625 	struct ufshci_upiu_header header;
626 	/* dword 3-7 */
627 	uint8_t reserved[20];
628 } __packed __aligned(8);
629 _Static_assert(sizeof(struct ufshci_nop_in_upiu) == 32,
630     "ufshci_upiu_nop_in must be 32 bytes");
631 
632 union ufshci_reponse_upiu {
633 	struct ufshci_upiu_header header;
634 	struct ufshci_cmd_response_upiu cmd_response_upiu;
635 	struct ufshci_query_response_upiu query_response_upiu;
636 	struct ufshci_task_mgmt_response_upiu task_mgmt_response_upiu;
637 	struct ufshci_nop_in_upiu nop_in_upiu;
638 };
639 
640 struct ufshci_completion {
641 	union ufshci_reponse_upiu response_upiu;
642 	size_t size;
643 };
644 
645 typedef void (*ufshci_cb_fn_t)(void *, const struct ufshci_completion *, bool);
646 
647 /* UFS 4.1, section 10.8.5 "Well Known Logical Unit Defined in UFS" */
648 enum ufshci_well_known_luns {
649 	UFSHCI_WLUN_REPORT_LUNS = 0x81,
650 	UFSHCI_WLUN_BOOT = 0xb0,
651 	UFSHCI_WLUN_RPMB = 0xc4,
652 	UFSHCI_WLUN_UFS_DEVICE = 0xd0,
653 };
654 
655 /*
656  * UFS Spec 4.1, section 14.1 "UFS Descriptors"
657  * All descriptors use big-endian byte ordering.
658  */
659 enum ufshci_descriptor_type {
660 	UFSHCI_DESC_TYPE_DEVICE = 0x00,
661 	UFSHCI_DESC_TYPE_CONFIGURATION = 0x01,
662 	UFSHCI_DESC_TYPE_UNIT = 0x02,
663 	UFSHCI_DESC_TYPE_INTERCONNECT = 0x04,
664 	UFSHCI_DESC_TYPE_STRING = 0x05,
665 	UFSHCI_DESC_TYPE_GEOMETRY = 0X07,
666 	UFSHCI_DESC_TYPE_POWER = 0x08,
667 	UFSHCI_DESC_TYPE_DEVICE_HEALTH = 0x09,
668 	UFSHCI_DESC_TYPE_FBO_EXTENSION_SPECIFICATION = 0x0a,
669 };
670 
671 /*
672  * UFS Spec 4.1, section 14.1.5.2 "Device Descriptor"
673  * DeviceDescriptor use big-endian byte ordering.
674  */
675 struct ufshci_device_descriptor {
676 	uint8_t bLength;
677 	uint8_t bDescriptorIDN;
678 	uint8_t bDevice;
679 	uint8_t bDeviceClass;
680 	uint8_t bDeviceSubClass;
681 	uint8_t bProtocol;
682 	uint8_t bNumberLU;
683 	uint8_t bNumberWLU;
684 	uint8_t bBootEnable;
685 	uint8_t bDescrAccessEn;
686 	uint8_t bInitPowerMode;
687 	uint8_t bHighPriorityLUN;
688 	uint8_t bSecureRemovalType;
689 	uint8_t bSecurityLU;
690 	uint8_t bBackgroundOpsTermLat;
691 	uint8_t bInitActiveICCLevel;
692 	/* 0x10 */
693 	uint16_t wSpecVersion;
694 	uint16_t wManufactureDate;
695 	uint8_t iManufacturerName;
696 	uint8_t iProductName;
697 	uint8_t iSerialNumber;
698 	uint8_t iOemID;
699 	uint16_t wManufacturerID;
700 	uint8_t bUD0BaseOffset;
701 	uint8_t bUDConfigPLength;
702 	uint8_t bDeviceRTTCap;
703 	uint16_t wPeriodicRTCUpdate;
704 	uint8_t bUfsFeaturesSupport;
705 	/* 0x20 */
706 	uint8_t bFFUTimeout;
707 	uint8_t bQueueDepth;
708 	uint16_t wDeviceVersion;
709 	uint8_t bNumSecureWPArea;
710 	uint32_t dPSAMaxDataSize;
711 	uint8_t bPSAStateTimeout;
712 	uint8_t iProductRevisionLevel;
713 	uint8_t Reserved[5];
714 	/* 0x2a */
715 	/* 0x30 */
716 	uint8_t ReservedUME[16];
717 	/* 0x40 */
718 	uint8_t ReservedHpb[3];
719 	uint8_t Reserved2[12];
720 	uint32_t dExtendedUfsFeaturesSupport;
721 	uint8_t bWriteBoosterBufferPreserveUserSpaceEn;
722 	uint8_t bWriteBoosterBufferType;
723 	uint32_t dNumSharedWriteBoosterBufferAllocUnits;
724 } __packed;
725 
726 _Static_assert(sizeof(struct ufshci_device_descriptor) == 89,
727     "bad size for ufshci_device_descriptor");
728 
729 /* Defines the bit field of dExtendedUfsFeaturesSupport. */
730 enum ufshci_desc_wb_ext_ufs_feature {
731 	UFSHCI_DESC_EXT_UFS_FEATURE_FFU = (1 << 0),
732 	UFSHCI_DESC_EXT_UFS_FEATURE_PSA = (1 << 1),
733 	UFSHCI_DESC_EXT_UFS_FEATURE_DEV_LIFE_SPAN = (1 << 2),
734 	UFSHCI_DESC_EXT_UFS_FEATURE_REFRESH_OP = (1 << 3),
735 	UFSHCI_DESC_EXT_UFS_FEATURE_TOO_HIGH_TEMP = (1 << 4),
736 	UFSHCI_DESC_EXT_UFS_FEATURE_TOO_LOW_TEMP = (1 << 5),
737 	UFSHCI_DESC_EXT_UFS_FEATURE_EXT_TEMP = (1 << 6),
738 	UFSHCI_DESC_EXT_UFS_FEATURE_HPB_SUPPORT = (1 << 7),
739 	UFSHCI_DESC_EXT_UFS_FEATURE_WRITE_BOOSTER = (1 << 8),
740 	UFSHCI_DESC_EXT_UFS_FEATURE_PERF_THROTTLING = (1 << 9),
741 	UFSHCI_DESC_EXT_UFS_FEATURE_ADVANCED_RPMB = (1 << 10),
742 	UFSHCI_DESC_EXT_UFS_FEATURE_ZONED_UFS_EXTENSION = (1 << 11),
743 	UFSHCI_DESC_EXT_UFS_FEATURE_DEV_LEVEL_EXCEPTION = (1 << 12),
744 	UFSHCI_DESC_EXT_UFS_FEATURE_HID = (1 << 13),
745 	UFSHCI_DESC_EXT_UFS_FEATURE_BARRIER = (1 << 14),
746 	UFSHCI_DESC_EXT_UFS_FEATURE_CLEAR_ERROR_HISTORY = (1 << 15),
747 	UFSHCI_DESC_EXT_UFS_FEATURE_EXT_IID = (1 << 16),
748 	UFSHCI_DESC_EXT_UFS_FEATURE_FBO = (1 << 17),
749 	UFSHCI_DESC_EXT_UFS_FEATURE_FAST_RECOVERY_MODE = (1 << 18),
750 	UFSHCI_DESC_EXT_UFS_FEATURE_RPMB_VENDOR_CMD = (1 << 19),
751 };
752 
753 /* Defines the bit field of bWriteBoosterBufferType. */
754 enum ufshci_desc_wb_buffer_type {
755 	UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED = 0x00,
756 	UFSHCI_DESC_WB_BUF_TYPE_SINGLE_SHARED = 0x01,
757 };
758 
759 /* Defines the bit field of bWriteBoosterBufferPreserveUserSpaceEn. */
760 enum ufshci_desc_user_space_config {
761 	UFSHCI_DESC_WB_BUF_USER_SPACE_REDUCTION = 0x00,
762 	UFSHCI_DESC_WB_BUF_PRESERVE_USER_SPACE = 0x01,
763 };
764 
765 /*
766  * UFS Spec 4.1, section 14.1.5.3 "Configuration Descriptor"
767  * ConfigurationDescriptor use big-endian byte ordering.
768  */
769 struct ufshci_unit_descriptor_configurable_parameters {
770 	uint8_t bLUEnable;
771 	uint8_t bBootLunID;
772 	uint8_t bLUWriteProtect;
773 	uint8_t bMemoryType;
774 	uint32_t dNumAllocUnits;
775 	uint8_t bDataReliability;
776 	uint8_t bLogicalBlockSize;
777 	uint8_t bProvisioningType;
778 	uint16_t wContextCapabilities;
779 	union {
780 		struct {
781 			uint8_t Reserved[3];
782 			uint8_t ReservedHpb[6];
783 		} __packed;
784 		uint16_t wZoneBufferAllocUnits;
785 	};
786 	uint32_t dLUNumWriteBoosterBufferAllocUnits;
787 } __packed;
788 
789 _Static_assert(sizeof(struct ufshci_unit_descriptor_configurable_parameters) ==
790 	27,
791     "bad size for ufshci_unit_descriptor_configurable_parameters");
792 
793 #define UFSHCI_CONFIGURATION_DESCEIPTOR_LU_NUM 8
794 
795 struct ufshci_configuration_descriptor {
796 	uint8_t bLength;
797 	uint8_t bDescriptorIDN;
798 	uint8_t bConfDescContinue;
799 	uint8_t bBootEnable;
800 	uint8_t bDescrAccessEn;
801 	uint8_t bInitPowerMode;
802 	uint8_t bHighPriorityLUN;
803 	uint8_t bSecureRemovalType;
804 	uint8_t bInitActiveICCLevel;
805 	uint16_t wPeriodicRTCUpdate;
806 	uint8_t Reserved;
807 	uint8_t bRPMBRegionEnable;
808 	uint8_t bRPMBRegion1Size;
809 	uint8_t bRPMBRegion2Size;
810 	uint8_t bRPMBRegion3Size;
811 	uint8_t bWriteBoosterBufferPreserveUserSpaceEn;
812 	uint8_t bWriteBoosterBufferType;
813 	uint32_t dNumSharedWriteBoosterBufferAllocUnits;
814 	/* 0x16 */
815 	struct ufshci_unit_descriptor_configurable_parameters
816 	    unit_config_params[UFSHCI_CONFIGURATION_DESCEIPTOR_LU_NUM];
817 } __packed;
818 
819 _Static_assert(sizeof(struct ufshci_configuration_descriptor) == (22 + 27 * 8),
820     "bad size for ufshci_configuration_descriptor");
821 
822 /*
823  * UFS Spec 4.1, section 14.1.5.4 "Geometry Descriptor"
824  * GeometryDescriptor use big-endian byte ordering.
825  */
826 struct ufshci_geometry_descriptor {
827 	uint8_t bLength;
828 	uint8_t bDescriptorIDN;
829 	uint8_t bMediaTechnology;
830 	uint8_t Reserved;
831 	uint64_t qTotalRawDeviceCapacity;
832 	uint8_t bMaxNumberLU;
833 	uint32_t dSegmentSize;
834 	/* 0x11 */
835 	uint8_t bAllocationUnitSize;
836 	uint8_t bMinAddrBlockSize;
837 	uint8_t bOptimalReadBlockSize;
838 	uint8_t bOptimalWriteBlockSize;
839 	uint8_t bMaxInBufferSize;
840 	uint8_t bMaxOutBufferSize;
841 	uint8_t bRPMB_ReadWriteSize;
842 	uint8_t bDynamicCapacityResourcePolicy;
843 	uint8_t bDataOrdering;
844 	uint8_t bMaxContexIDNumber;
845 	uint8_t bSysDataTagUnitSize;
846 	uint8_t bSysDataTagResSize;
847 	uint8_t bSupportedSecRTypes;
848 	uint16_t wSupportedMemoryTypes;
849 	/* 0x20 */
850 	uint32_t dSystemCodeMaxNAllocU;
851 	uint16_t wSystemCodeCapAdjFac;
852 	uint32_t dNonPersistMaxNAllocU;
853 	uint16_t wNonPersistCapAdjFac;
854 	uint32_t dEnhanced1MaxNAllocU;
855 	/* 0x30 */
856 	uint16_t wEnhanced1CapAdjFac;
857 	uint32_t dEnhanced2MaxNAllocU;
858 	uint16_t wEnhanced2CapAdjFac;
859 	uint32_t dEnhanced3MaxNAllocU;
860 	uint16_t wEnhanced3CapAdjFac;
861 	uint32_t dEnhanced4MaxNAllocU;
862 	/* 0x42 */
863 	uint16_t wEnhanced4CapAdjFac;
864 	uint32_t dOptimalLogicalBlockSize;
865 	uint8_t ReservedHpb[5];
866 	uint8_t Reserved2[2];
867 	uint32_t dWriteBoosterBufferMaxNAllocUnits;
868 	uint8_t bDeviceMaxWriteBoosterLUs;
869 	uint8_t bWriteBoosterBufferCapAdjFac;
870 	uint8_t bSupportedWriteBoosterBufferUserSpaceReductionTypes;
871 	uint8_t bSupportedWriteBoosterBufferTypes;
872 } __packed;
873 
874 _Static_assert(sizeof(struct ufshci_geometry_descriptor) == 87,
875     "bad size for ufshci_geometry_descriptor");
876 
877 /*
878  * UFS Spec 4.1, section 14.1.5.5 "Unit Descriptor"
879  * UnitDescriptor use big-endian byte ordering.
880  */
881 struct ufshci_unit_descriptor {
882 	uint8_t bLength;
883 	uint8_t bDescriptorIDN;
884 	uint8_t bUnitIndex;
885 	uint8_t bLUEnable;
886 	uint8_t bBootLunID;
887 	uint8_t bLUWriteProtect;
888 	uint8_t bLUQueueDepth;
889 	uint8_t bPSASensitive;
890 	uint8_t bMemoryType;
891 	uint8_t bDataReliability;
892 	uint8_t bLogicalBlockSize;
893 	uint64_t qLogicalBlockCount;
894 	/* 0x13 */
895 	uint32_t dEraseBlockSize;
896 	uint8_t bProvisioningType;
897 	uint64_t qPhyMemResourceCount;
898 	/* 0x20 */
899 	uint16_t wContextCapabilities;
900 	uint8_t bLargeUnitGranularity_M1;
901 	uint8_t ReservedHpb[6];
902 	uint32_t dLUNumWriteBoosterBufferAllocUnits;
903 } __packed;
904 _Static_assert(sizeof(struct ufshci_unit_descriptor) == 45,
905     "bad size for ufshci_unit_descriptor");
906 
907 enum LUWriteProtect {
908 	kNoWriteProtect = 0x00,
909 	kPowerOnWriteProtect = 0x01,
910 	kPermanentWriteProtect = 0x02,
911 };
912 
913 /*
914  * UFS Spec 4.1, section 14.1.5.6 "RPMB Unit Descriptor"
915  * RpmbUnitDescriptor use big-endian byte ordering.
916  */
917 struct ufshci_rpmb_unit_descriptor {
918 	uint8_t bLength;
919 	uint8_t bDescriptorIDN;
920 	uint8_t bUnitIndex;
921 	uint8_t bLUEnable;
922 	uint8_t bBootLunID;
923 	uint8_t bLUWriteProtect;
924 	uint8_t bLUQueueDepth;
925 	uint8_t bPSASensitive;
926 	uint8_t bMemoryType;
927 	uint8_t Reserved;
928 	uint8_t bLogicalBlockSize;
929 	uint64_t qLogicalBlockCount;
930 	/* 0x13 */
931 	uint32_t dEraseBlockSize;
932 	uint8_t bProvisioningType;
933 	uint64_t qPhyMemResourceCount;
934 	/* 0x20 */
935 	uint8_t Reserved1[3];
936 } __packed;
937 _Static_assert(sizeof(struct ufshci_rpmb_unit_descriptor) == 35,
938     "bad size for RpmbUnitDescriptor");
939 
940 /*
941  * UFS Spec 4.1, section 14.1.5.7 "Power Parameters Descriptor"
942  * PowerParametersDescriptor use big-endian byte ordering.
943  */
944 struct ufshci_power_parameters_descriptor {
945 	uint8_t bLength;
946 	uint8_t bDescriptorIDN;
947 	uint16_t wActiveICCLevelsVCC[16];
948 	uint16_t wActiveICCLevelsVCCQ[16];
949 	uint16_t wActiveICCLevelsVCCQ2[16];
950 } __packed;
951 _Static_assert(sizeof(struct ufshci_power_parameters_descriptor) == 98,
952     "bad size for PowerParametersDescriptor");
953 
954 /*
955  * UFS Spec 4.1, section 14.1.5.8 "Interconnect Descriptor"
956  * InterconnectDescriptor use big-endian byte ordering.
957  */
958 struct ufshci_interconnect_descriptor {
959 	uint8_t bLength;
960 	uint8_t bDescriptorIDN;
961 	uint16_t bcdUniproVersion;
962 	uint16_t bcdMphyVersion;
963 } __packed;
964 _Static_assert(sizeof(struct ufshci_interconnect_descriptor) == 6,
965     "bad size for InterconnectDescriptor");
966 
967 /*
968  * UFS Spec 4.1, section 14.1.5.9-13 "String Descriptor"
969  * StringDescriptor use big-endian byte ordering.
970  */
971 struct ufshci_string_descriptor {
972 	uint8_t bLength;
973 	uint8_t bDescriptorIDN;
974 	uint16_t UC[126];
975 } __packed;
976 _Static_assert(sizeof(struct ufshci_string_descriptor) == 254,
977     "bad size for StringDescriptor");
978 
979 /*
980  * UFS Spec 4.1, section 14.1.5.14 "Device Health Descriptor"
981  * DeviceHealthDescriptor use big-endian byte ordering.
982  */
983 struct ufshci_device_healthd_descriptor {
984 	uint8_t bLength;
985 	uint8_t bDescriptorIDN;
986 	uint8_t bPreEOLInfo;
987 	uint8_t bDeviceLifeTimeEstA;
988 	uint8_t bDeviceLifeTimeEstB;
989 	uint8_t VendorPropInfo[32];
990 	uint32_t dRefreshTotalCount;
991 	uint32_t dRefreshProgress;
992 } __packed;
993 _Static_assert(sizeof(struct ufshci_device_healthd_descriptor) == 45,
994     "bad size for DeviceHealthDescriptor");
995 
996 /*
997  * UFS Spec 4.1, section 14.1.5.15 "Vendor Specific Descriptor"
998  * VendorSpecificDescriptor use big-endian byte ordering.
999  */
1000 struct ufshci_vendor_specific_descriptor {
1001 	uint8_t bLength;
1002 	uint8_t bDescriptorIDN;
1003 	uint8_t DATA[254];
1004 } __packed;
1005 _Static_assert(sizeof(struct ufshci_vendor_specific_descriptor) == 256,
1006     "bad size for VendorSpecificDescriptor");
1007 
1008 /* UFS Spec 4.1, section 14.2 "Flags" */
1009 enum ufshci_flags {
1010 	UFSHCI_FLAG_F_RESERVED = 0x00,
1011 	UFSHCI_FLAG_F_DEVICE_INIT = 0x01,
1012 	UFSHCI_FLAG_F_PERMANENT_WP_EN = 0x02,
1013 	UFSHCI_FLAS_F_POWER_ON_WP_EN = 0x03,
1014 	UFSHCI_FLAG_F_BACKGROUND_OPS_EN = 0x04,
1015 	UFSHCI_FLAG_F_DEVICE_LIFE_SPAN_MODE_EN = 0x05,
1016 	UFSHCI_FLAG_F_PURGE_ENABLE = 0x06,
1017 	UFSHCI_FLAG_F_REFRESH_ENABLE = 0x07,
1018 	UFSHCI_FLAG_F_PHY_RESOURCE_REMOVAL = 0x08,
1019 	UFSHCI_FLAG_F_BUSY_RTC = 0x09,
1020 	UFSHCI_FLAG_F_PERMANENTLY_DISABLE_FW_UPDATE = 0x0b,
1021 	UFSHCI_FLAG_F_WRITE_BOOSTER_EN = 0x0e,
1022 	UFSHCI_FLAG_F_WB_BUFFER_FLUSH_EN = 0x0f,
1023 	UFSHCI_FLAG_F_WB_BUFFER_FLUSH_DURING_HIBERNATE = 0x10,
1024 	UFSHCI_FLAG_F_UNPIN_EN = 0x13,
1025 };
1026 
1027 /* UFS Spec 4.1, section 14.3 "Attributes" */
1028 enum ufshci_attributes {
1029 	UFSHCI_ATTR_B_BOOT_LUN_EN = 0x00,
1030 	UFSHCI_ATTR_B_CURRENT_POWER_MODE = 0x02,
1031 	UFSHCI_ATTR_B_ACTIVE_ICC_LEVEL = 0x03,
1032 	UFSHCI_ATTR_B_OUT_OF_ORDER_DATA_EN = 0x04,
1033 	UFSHCI_ATTR_B_BACKGROUND_OP_STATUS = 0x05,
1034 	UFSHCI_ATTR_B_PURGE_STATUS = 0x06,
1035 	UFSHCI_ATTR_B_MAX_DATA_IN_SIZE = 0x07,
1036 	UFSHCI_ATTR_B_MAX_DATA_OUT_SIZE = 0x08,
1037 	UFSHCI_ATTR_D_DYN_CAP_NEEDED = 0x09,
1038 	UFSHCI_ATTR_B_REF_CLK_FREQ = 0x0a,
1039 	UFSHCI_ATTR_B_CONFIG_DESCR_LOCK = 0x0b,
1040 	UFSHCI_ATTR_B_MAX_NUM_OF_RTT = 0x0c,
1041 	UFSHCI_ATTR_W_EXCEPTION_EVENT_CONTROL = 0x0d,
1042 	UFSHCI_ATTR_W_EXCEPTION_EVENT_STATUS = 0x0e,
1043 	UFSHCI_ATTR_D_SECONDS_PASSED = 0x0f,
1044 	UFSHCI_ATTR_W_CONTEXT_CONF = 0x10,
1045 	UFSHCI_ATTR_B_DEVICE_FFU_STATUS = 0x14,
1046 	UFSHCI_ATTR_B_PSA_STATE = 0x15,
1047 	UFSHCI_ATTR_D_PSA_DATA_SIZE = 0x16,
1048 	UFSHCI_ATTR_B_REF_CLK_GATING_WAIT_TIME = 0x17,
1049 	UFSHCI_ATTR_B_DEVICE_CASE_ROUGH_TEMPERAURE = 0x18,
1050 	UFSHCI_ATTR_B_DEVICE_TOO_HIGH_TEMP_BOUNDARY = 0x19,
1051 	UFSHCI_ATTR_B_DEVICE_TOO_LOW_TEMP_BOUNDARY = 0x1a,
1052 	UFSHCI_ATTR_B_THROTTLING_STATUS = 0x1b,
1053 	UFSHCI_ATTR_B_WB_BUFFER_FLUSH_STATUS = 0x1c,
1054 	UFSHCI_ATTR_B_AVAILABLE_WB_BUFFER_SIZE = 0x1d,
1055 	UFSHCI_ATTR_B_WB_BUFFER_LIFE_TIME_EST = 0x1e,
1056 	UFSHCI_ATTR_D_CURRENT_WB_BUFFER_SIZE = 0x1f,
1057 	UFSHCI_ATTR_B_REFRESH_STATUS = 0x2c,
1058 	UFSHCI_ATTR_B_REFRESH_FREQ = 0x2d,
1059 	UFSHCI_ATTR_B_REFRESH_UNIT = 0x2e,
1060 	UFSHCI_ATTR_B_REFRESH_METHOD = 0x2f,
1061 };
1062 
1063 /* bAvailableWriteBoosterBufferSize codes (UFS WriteBooster abailable buffer
1064  * left %) */
1065 enum ufshci_wb_available_buffer_Size {
1066 	UFSHCI_ATTR_WB_AVAILABLE_0 = 0x00,   /* 0% buffer remains  */
1067 	UFSHCI_ATTR_WB_AVAILABLE_10 = 0x01,  /* 10% buffer remains  */
1068 	UFSHCI_ATTR_WB_AVAILABLE_20 = 0x02,  /* 20% buffer remains  */
1069 	UFSHCI_ATTR_WB_AVAILABLE_30 = 0x03,  /* 30% buffer remains  */
1070 	UFSHCI_ATTR_WB_AVAILABLE_40 = 0x04,  /* 40% buffer remains  */
1071 	UFSHCI_ATTR_WB_AVAILABLE_50 = 0x05,  /* 50% buffer remains  */
1072 	UFSHCI_ATTR_WB_AVAILABLE_60 = 0x06,  /* 60% buffer remains  */
1073 	UFSHCI_ATTR_WB_AVAILABLE_70 = 0x07,  /* 70% buffer remains  */
1074 	UFSHCI_ATTR_WB_AVAILABLE_80 = 0x08,  /* 80% buffer remains  */
1075 	UFSHCI_ATTR_WB_AVAILABLE_90 = 0x09,  /* 90% buffer remains  */
1076 	UFSHCI_ATTR_WB_AVAILABLE_100 = 0x0A, /* 100% buffer remains  */
1077 };
1078 
1079 /* bWriteBoosterBufferLifeTimeEst codes (UFS WriteBooster buffer life %) */
1080 enum ufshci_wb_lifetime {
1081 	UFSHCI_ATTR_WB_LIFE_DISABLED = 0x00, /* Info not available */
1082 	UFSHCI_ATTR_WB_LIFE_0_10 = 0x01,     /*   0%–10% used  */
1083 	UFSHCI_ATTR_WB_LIFE_10_20 = 0x02,    /*  10%–20% used  */
1084 	UFSHCI_ATTR_WB_LIFE_20_30 = 0x03,    /*  20%–30% used  */
1085 	UFSHCI_ATTR_WB_LIFE_30_40 = 0x04,    /*  30%–40% used  */
1086 	UFSHCI_ATTR_WB_LIFE_40_50 = 0x05,    /*  40%–50% used  */
1087 	UFSHCI_ATTR_WB_LIFE_50_60 = 0x06,    /*  50%–60% used  */
1088 	UFSHCI_ATTR_WB_LIFE_60_70 = 0x07,    /*  60%–70% used  */
1089 	UFSHCI_ATTR_WB_LIFE_70_80 = 0x08,    /*  70%–80% used  */
1090 	UFSHCI_ATTR_WB_LIFE_80_90 = 0x09,    /*  80%–90% used  */
1091 	UFSHCI_ATTR_WB_LIFE_90_100 = 0x0A,   /* 90%–100% used  */
1092 	UFSHCI_ATTR_WB_LIFE_EXCEEDED =
1093 	    0x0B, /* Exceeded estimated life (treat as WB disabled) */
1094 };
1095 
1096 #endif /* __UFSHCI_H__ */
1097