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