xref: /freebsd/sys/dev/ufshci/ufshci.h (revision 1349a733cf2828e0040cabef89eeadc3ff00c40b)
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_overall_command_status {
164 	UFSHCI_OCS_SUCCESS = 0x0,
165 	UFSHCI_OCS_INVALID_COMMAND_TABLE_ATTRIBUTES = 0x01,
166 	UFSHCI_OCS_INVALID_PRDT_ATTRIBUTES = 0x02,
167 	UFSHCI_OCS_MISMATCH_DATA_BUFFER_SIZE = 0x03,
168 	UFSHCI_OCS_MISMATCH_RESPONSE_UPIU_SIZE = 0x04,
169 	UFSHCI_OCS_COMMUNICATION_FAILURE_WITHIN_UIC_LAYERS = 0x05,
170 	UFSHCI_OCS_ABORTED = 0x06,
171 	UFSHCI_OCS_HOST_CONTROLLER_FATAL_ERROR = 0x07,
172 	UFSHCI_OCS_DEVICE_FATAL_ERROR = 0x08,
173 	UFSHCI_OCS_INVALID_CRYPTO_CONFIGURATION = 0x09,
174 	UFSHCI_OCS_GENERAL_CRYPTO_ERROR = 0x0A,
175 	UFSHCI_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 /* UFSHCI spec 4.1, section 6.3.1 "UTP Task Management Request Descriptor" */
275 struct ufshci_utp_task_mgmt_req_desc {
276 	/* dword 0 */
277 	uint32_t reserved0 : 24; /* [23:0] */
278 	uint32_t interrupt : 1;	 /* [24] */
279 	uint32_t reserved1 : 7;	 /* [31:25] */
280 
281 	/* dword 1 */
282 	uint32_t reserved2; /* [31:0] */
283 
284 	/* dword 2 */
285 	uint8_t overall_command_status; /* [7:0] */
286 	uint8_t reserved3;		/* [15:8] */
287 	uint16_t reserved4;		/* [31:16] */
288 
289 	/* dword 3 */
290 	uint32_t reserved5; /* [31:0] */
291 
292 	/* dword 4-11 */
293 	uint8_t request_upiu[UFSHCI_UTP_TASK_MGMT_REQ_SIZE];
294 
295 	/* dword 12-19 */
296 	uint8_t response_upiu[UFSHCI_UTP_TASK_MGMT_RESP_SIZE];
297 
298 } __packed __aligned(8);
299 
300 _Static_assert(sizeof(struct ufshci_utp_task_mgmt_req_desc) == 80,
301     "ufshci_utp_task_mgmt_req_desc must be 80 bytes");
302 
303 /* UFS spec 4.1, section 10.6.2 "Basic Header Format" */
304 struct ufshci_upiu_header {
305 	/* dword 0 */
306 	union {
307 		struct {
308 			uint8_t trans_code : 6; /* [5:0] */
309 			uint8_t dd : 1;		/* [6] */
310 			uint8_t hd : 1;		/* [7] */
311 		};
312 		uint8_t trans_type;
313 	};
314 	union {
315 		struct {
316 			uint8_t task_attribute : 2;	  /* [1:0] */
317 			uint8_t cp : 1;			  /* [2] */
318 			uint8_t retransmit_indicator : 1; /* [3] */
319 #define UFSHCI_OPERATIONAL_FLAG_W 0x2
320 #define UFSHCI_OPERATIONAL_FLAG_R 0x4
321 			uint8_t operational_flags : 4; /* [7:4] */
322 		};
323 		uint8_t flags;
324 	};
325 	uint8_t lun;
326 	uint8_t task_tag;
327 
328 	/* dword 1 */
329 #define UFSHCI_COMMAND_SET_TYPE_SCSI 0
330 	uint8_t cmd_set_type : 4; /* [3:0] */
331 	uint8_t iid : 4;	  /* [7:4] */
332 	uint8_t ext_iid_or_function;
333 	uint8_t response;
334 	uint8_t ext_iid_or_status;
335 
336 	/* dword 2 */
337 	uint8_t ehs_length;
338 	uint8_t device_infomation;
339 	uint16_t data_segment_length; /* (Big-endian) */
340 } __packed __aligned(4);
341 
342 _Static_assert(sizeof(struct ufshci_upiu_header) == 12,
343     "ufshci_upiu_header must be 12 bytes");
344 
345 #define UFSHCI_MAX_UPIU_SIZE  512
346 #define UFSHCI_UPIU_ALIGNMENT 8 /* UPIU requires 64-bit alignment. */
347 
348 struct ufshci_upiu {
349 	/* dword 0-2 */
350 	struct ufshci_upiu_header header;
351 	/* dword 3-127 */
352 	uint8_t
353 	    reserved[UFSHCI_MAX_UPIU_SIZE - sizeof(struct ufshci_upiu_header)];
354 } __packed __aligned(8);
355 
356 _Static_assert(sizeof(struct ufshci_upiu) == 512,
357     "ufshci_upiu must be 512 bytes");
358 
359 struct ufshci_cmd_command_upiu {
360 	/* dword 0-2 */
361 	struct ufshci_upiu_header header;
362 	/* dword 3 */
363 	uint32_t expected_data_transfer_length; /* (Big-endian) */
364 
365 	/* dword 4-7 */
366 	uint8_t cdb[16];
367 
368 } __packed __aligned(4);
369 
370 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) == 32,
371     "bad size for ufshci_cmd_command_upiu");
372 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) <=
373 	UFSHCI_UTP_XFER_REQ_SIZE,
374     "bad size for ufshci_cmd_command_upiu");
375 _Static_assert(sizeof(struct ufshci_cmd_command_upiu) % UFSHCI_UPIU_ALIGNMENT ==
376 	0,
377     "UPIU requires 64-bit alignment");
378 
379 struct ufshci_cmd_response_upiu {
380 	/* dword 0-2 */
381 	struct ufshci_upiu_header header;
382 	/* dword 3 */
383 	uint32_t residual_transfer_count; /* (Big-endian) */
384 
385 	/* dword 4-7 */
386 	uint8_t reserved[16];
387 
388 	/* Sense Data */
389 	uint16_t sense_data_len; /* (Big-endian) */
390 	uint8_t sense_data[18];
391 
392 	/* Add padding to align the kUpiuAlignment. */
393 	uint8_t padding[4];
394 } __packed __aligned(4);
395 
396 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) == 56,
397     "bad size for ufshci_cmd_response_upiu");
398 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) <=
399 	UFSHCI_UTP_XFER_RESP_SIZE,
400     "bad size for ufshci_cmd_response_upiu");
401 _Static_assert(sizeof(struct ufshci_cmd_response_upiu) %
402 	    UFSHCI_UPIU_ALIGNMENT ==
403 	0,
404     "UPIU requires 64-bit alignment");
405 
406 /* UFS Spec 4.1, section 10.7.8 "QUERY REQUEST UPIU" */
407 enum ufshci_query_function {
408 	UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01,
409 	UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81,
410 };
411 
412 enum ufshci_query_opcode {
413 	UFSHCI_QUERY_OPCODE_NOP = 0,
414 	UFSHCI_QUERY_OPCODE_READ_DESCRIPTOR,
415 	UFSHCI_QUERY_OPCODE_WRITE_DESCRIPTOR,
416 	UFSHCI_QUERY_OPCODE_READ_ATTRIBUTE,
417 	UFSHCI_QUERY_OPCODE_WRITE_ATTRIBUTE,
418 	UFSHCI_QUERY_OPCODE_READ_FLAG,
419 	UFSHCI_QUERY_OPCODE_SET_FLAG,
420 	UFSHCI_QUERY_OPCODE_CLEAR_FLAG,
421 	UFSHCI_QUERY_OPCODE_TOGGLE_FLAG,
422 };
423 
424 struct ufshci_query_param {
425 	enum ufshci_query_function function;
426 	enum ufshci_query_opcode opcode;
427 	uint8_t type;
428 	uint8_t index;
429 	uint8_t selector;
430 	uint64_t value;
431 	size_t desc_size;
432 };
433 
434 struct ufshci_query_request_upiu {
435 	/* dword 0-2 */
436 	struct ufshci_upiu_header header;
437 	/* dword 3 */
438 	uint8_t opcode;
439 	uint8_t idn;
440 	uint8_t index;
441 	uint8_t selector;
442 
443 	/* dword 4-5 */
444 	union {
445 		/* The Write Attribute opcode uses 64 - bit value. */
446 		uint64_t value_64; /* (Big-endian) */
447 		struct {
448 			uint8_t reserved1[2];
449 			uint16_t length;   /* (Big-endian) */
450 			uint32_t value_32; /* (Big-endian) */
451 		};
452 	} __packed __aligned(4);
453 
454 	/* dword 6 */
455 	uint32_t reserved2;
456 
457 	/* dword 7 */
458 	uint32_t reserved3;
459 
460 	uint8_t command_data[256];
461 } __packed __aligned(4);
462 
463 _Static_assert(sizeof(struct ufshci_query_request_upiu) == 288,
464     "bad size for ufshci_query_request_upiu");
465 _Static_assert(sizeof(struct ufshci_query_request_upiu) <=
466 	UFSHCI_UTP_XFER_REQ_SIZE,
467     "bad size for ufshci_query_request_upiu");
468 _Static_assert(sizeof(struct ufshci_query_request_upiu) %
469 	    UFSHCI_UPIU_ALIGNMENT ==
470 	0,
471     "UPIU requires 64-bit alignment");
472 
473 /* UFS Spec 4.1, section 10.7.9 "QUERY RESPONSE UPIU" */
474 enum ufshci_query_response_code {
475 	UFSHCI_QUERY_RESP_CODE_SUCCESS = 0x00,
476 	UFSHCI_QUERY_RESP_CODE_PARAMETER_NOT_READABLE = 0xf6,
477 	UFSHCI_QUERY_RESP_CODE_PARAMETER_NOT_WRITEABLE = 0xf7,
478 	UFSHCI_QUERY_RESP_CODE_PARAMETER_ALREADY_WRITTEN = 0xf8,
479 	UFSHCI_QUERY_RESP_CODE_INVALID_LENGTH = 0xf9,
480 	UFSHCI_QUERY_RESP_CODE_INVALID_VALUE = 0xfa,
481 	UFSHCI_QUERY_RESP_CODE_INVALID_SELECTOR = 0xfb,
482 	UFSHCI_QUERY_RESP_CODE_INVALID_INDEX = 0xfc,
483 	UFSHCI_QUERY_RESP_CODE_INVALID_IDN = 0xfd,
484 	UFSHCI_QUERY_RESP_CODE_INVALID_OPCODE = 0xfe,
485 	UFSHCI_QUERY_RESP_CODE_GENERAL_FAILURE = 0xff,
486 };
487 
488 struct ufshci_query_response_upiu {
489 	/* dword 0-2 */
490 	struct ufshci_upiu_header header;
491 	/* dword 3 */
492 	uint8_t opcode;
493 	uint8_t idn;
494 	uint8_t index;
495 	uint8_t selector;
496 
497 	/* dword 4-5 */
498 	union {
499 		/* The Read / Write Attribute opcodes use 64 - bit value. */
500 		uint64_t value_64; /* (Big-endian) */
501 		struct {
502 			uint8_t reserved1[2];
503 			uint16_t length; /* (Big-endian) */
504 			union {
505 				uint32_t value_32; /* (Big-endian) */
506 				struct {
507 					uint8_t reserved2[3];
508 					uint8_t flag_value;
509 				};
510 			};
511 		};
512 	} __packed __aligned(4);
513 
514 	/* dword 6 */
515 	uint8_t reserved3[4];
516 
517 	/* dword 7 */
518 	uint8_t reserved4[4];
519 
520 	uint8_t command_data[256];
521 } __packed __aligned(4);
522 
523 _Static_assert(sizeof(struct ufshci_query_response_upiu) == 288,
524     "bad size for ufshci_query_response_upiu");
525 _Static_assert(sizeof(struct ufshci_query_response_upiu) <=
526 	UFSHCI_UTP_XFER_RESP_SIZE,
527     "bad size for ufshci_query_response_upiu");
528 _Static_assert(sizeof(struct ufshci_query_response_upiu) %
529 	    UFSHCI_UPIU_ALIGNMENT ==
530 	0,
531     "UPIU requires 64-bit alignment");
532 
533 /* UFS 4.1, section 10.7.11 "NOP OUT UPIU" */
534 struct ufshci_nop_out_upiu {
535 	/* dword 0-2 */
536 	struct ufshci_upiu_header header;
537 	/* dword 3-7 */
538 	uint8_t reserved[20];
539 } __packed __aligned(8);
540 _Static_assert(sizeof(struct ufshci_nop_out_upiu) == 32,
541     "ufshci_upiu_nop_out must be 32 bytes");
542 
543 /* UFS 4.1, section 10.7.12 "NOP IN UPIU" */
544 struct ufshci_nop_in_upiu {
545 	/* dword 0-2 */
546 	struct ufshci_upiu_header header;
547 	/* dword 3-7 */
548 	uint8_t reserved[20];
549 } __packed __aligned(8);
550 _Static_assert(sizeof(struct ufshci_nop_in_upiu) == 32,
551     "ufshci_upiu_nop_in must be 32 bytes");
552 
553 union ufshci_reponse_upiu {
554 	struct ufshci_upiu_header header;
555 	struct ufshci_cmd_response_upiu cmd_response_upiu;
556 	struct ufshci_query_response_upiu query_response_upiu;
557 	struct ufshci_nop_in_upiu nop_in_upiu;
558 };
559 
560 struct ufshci_completion {
561 	union ufshci_reponse_upiu response_upiu;
562 	size_t size;
563 };
564 
565 typedef void (*ufshci_cb_fn_t)(void *, const struct ufshci_completion *, bool);
566 
567 /*
568  * UFS Spec 4.1, section 14.1 "UFS Descriptors"
569  * All descriptors use big-endian byte ordering.
570  */
571 enum ufshci_descriptor_type {
572 	UFSHCI_DESC_TYPE_DEVICE = 0x00,
573 	UFSHCI_DESC_TYPE_CONFIGURATION = 0x01,
574 	UFSHCI_DESC_TYPE_UNIT = 0x02,
575 	UFSHCI_DESC_TYPE_INTERCONNECT = 0x04,
576 	UFSHCI_DESC_TYPE_STRING = 0x05,
577 	UFSHCI_DESC_TYPE_GEOMETRY = 0X07,
578 	UFSHCI_DESC_TYPE_POWER = 0x08,
579 	UFSHCI_DESC_TYPE_DEVICE_HEALTH = 0x09,
580 	UFSHCI_DESC_TYPE_FBO_EXTENSION_SPECIFICATION = 0x0a,
581 };
582 
583 /*
584  * UFS Spec 4.1, section 14.1.5.2 "Device Descriptor"
585  * DeviceDescriptor use big-endian byte ordering.
586  */
587 struct ufshci_device_descriptor {
588 	uint8_t bLength;
589 	uint8_t bDescriptorIDN;
590 	uint8_t bDevice;
591 	uint8_t bDeviceClass;
592 	uint8_t bDeviceSubClass;
593 	uint8_t bProtocol;
594 	uint8_t bNumberLU;
595 	uint8_t bNumberWLU;
596 	uint8_t bBootEnable;
597 	uint8_t bDescrAccessEn;
598 	uint8_t bInitPowerMode;
599 	uint8_t bHighPriorityLUN;
600 	uint8_t bSecureRemovalType;
601 	uint8_t bSecurityLU;
602 	uint8_t bBackgroundOpsTermLat;
603 	uint8_t bInitActiveICCLevel;
604 	/* 0x10 */
605 	uint16_t wSpecVersion;
606 	uint16_t wManufactureDate;
607 	uint8_t iManufacturerName;
608 	uint8_t iProductName;
609 	uint8_t iSerialNumber;
610 	uint8_t iOemID;
611 	uint16_t wManufacturerID;
612 	uint8_t bUD0BaseOffset;
613 	uint8_t bUDConfigPLength;
614 	uint8_t bDeviceRTTCap;
615 	uint16_t wPeriodicRTCUpdate;
616 	uint8_t bUfsFeaturesSupport;
617 	/* 0x20 */
618 	uint8_t bFFUTimeout;
619 	uint8_t bQueueDepth;
620 	uint16_t wDeviceVersion;
621 	uint8_t bNumSecureWPArea;
622 	uint32_t dPSAMaxDataSize;
623 	uint8_t bPSAStateTimeout;
624 	uint8_t iProductRevisionLevel;
625 	uint8_t Reserved[5];
626 	/* 0x2a */
627 	/* 0x30 */
628 	uint8_t ReservedUME[16];
629 	/* 0x40 */
630 	uint8_t ReservedHpb[3];
631 	uint8_t Reserved2[12];
632 	uint32_t dExtendedUfsFeaturesSupport;
633 	uint8_t bWriteBoosterBufferPreserveUserSpaceEn;
634 	uint8_t bWriteBoosterBufferType;
635 	uint32_t dNumSharedWriteBoosterBufferAllocUnits;
636 } __packed;
637 
638 _Static_assert(sizeof(struct ufshci_device_descriptor) == 89,
639     "bad size for ufshci_device_descriptor");
640 
641 /*
642  * UFS Spec 4.1, section 14.1.5.3 "Configuration Descriptor"
643  * ConfigurationDescriptor use big-endian byte ordering.
644  */
645 struct ufshci_unit_descriptor_configurable_parameters {
646 	uint8_t bLUEnable;
647 	uint8_t bBootLunID;
648 	uint8_t bLUWriteProtect;
649 	uint8_t bMemoryType;
650 	uint32_t dNumAllocUnits;
651 	uint8_t bDataReliability;
652 	uint8_t bLogicalBlockSize;
653 	uint8_t bProvisioningType;
654 	uint16_t wContextCapabilities;
655 	union {
656 		struct {
657 			uint8_t Reserved[3];
658 			uint8_t ReservedHpb[6];
659 		} __packed;
660 		uint16_t wZoneBufferAllocUnits;
661 	};
662 	uint32_t dLUNumWriteBoosterBufferAllocUnits;
663 } __packed;
664 
665 _Static_assert(sizeof(struct ufshci_unit_descriptor_configurable_parameters) ==
666 	27,
667     "bad size for ufshci_unit_descriptor_configurable_parameters");
668 
669 #define UFSHCI_CONFIGURATION_DESCEIPTOR_LU_NUM 8
670 
671 struct ufshci_configuration_descriptor {
672 	uint8_t bLength;
673 	uint8_t bDescriptorIDN;
674 	uint8_t bConfDescContinue;
675 	uint8_t bBootEnable;
676 	uint8_t bDescrAccessEn;
677 	uint8_t bInitPowerMode;
678 	uint8_t bHighPriorityLUN;
679 	uint8_t bSecureRemovalType;
680 	uint8_t bInitActiveICCLevel;
681 	uint16_t wPeriodicRTCUpdate;
682 	uint8_t Reserved;
683 	uint8_t bRPMBRegionEnable;
684 	uint8_t bRPMBRegion1Size;
685 	uint8_t bRPMBRegion2Size;
686 	uint8_t bRPMBRegion3Size;
687 	uint8_t bWriteBoosterBufferPreserveUserSpaceEn;
688 	uint8_t bWriteBoosterBufferType;
689 	uint32_t dNumSharedWriteBoosterBufferAllocUnits;
690 	/* 0x16 */
691 	struct ufshci_unit_descriptor_configurable_parameters
692 	    unit_config_params[UFSHCI_CONFIGURATION_DESCEIPTOR_LU_NUM];
693 } __packed;
694 
695 _Static_assert(sizeof(struct ufshci_configuration_descriptor) == (22 + 27 * 8),
696     "bad size for ufshci_configuration_descriptor");
697 
698 /*
699  * UFS Spec 4.1, section 14.1.5.4 "Geometry Descriptor"
700  * GeometryDescriptor use big-endian byte ordering.
701  */
702 struct ufshci_geometry_descriptor {
703 	uint8_t bLength;
704 	uint8_t bDescriptorIDN;
705 	uint8_t bMediaTechnology;
706 	uint8_t Reserved;
707 	uint64_t qTotalRawDeviceCapacity;
708 	uint8_t bMaxNumberLU;
709 	uint32_t dSegmentSize;
710 	/* 0x11 */
711 	uint8_t bAllocationUnitSize;
712 	uint8_t bMinAddrBlockSize;
713 	uint8_t bOptimalReadBlockSize;
714 	uint8_t bOptimalWriteBlockSize;
715 	uint8_t bMaxInBufferSize;
716 	uint8_t bMaxOutBufferSize;
717 	uint8_t bRPMB_ReadWriteSize;
718 	uint8_t bDynamicCapacityResourcePolicy;
719 	uint8_t bDataOrdering;
720 	uint8_t bMaxContexIDNumber;
721 	uint8_t bSysDataTagUnitSize;
722 	uint8_t bSysDataTagResSize;
723 	uint8_t bSupportedSecRTypes;
724 	uint16_t wSupportedMemoryTypes;
725 	/* 0x20 */
726 	uint32_t dSystemCodeMaxNAllocU;
727 	uint16_t wSystemCodeCapAdjFac;
728 	uint32_t dNonPersistMaxNAllocU;
729 	uint16_t wNonPersistCapAdjFac;
730 	uint32_t dEnhanced1MaxNAllocU;
731 	/* 0x30 */
732 	uint16_t wEnhanced1CapAdjFac;
733 	uint32_t dEnhanced2MaxNAllocU;
734 	uint16_t wEnhanced2CapAdjFac;
735 	uint32_t dEnhanced3MaxNAllocU;
736 	uint16_t wEnhanced3CapAdjFac;
737 	uint32_t dEnhanced4MaxNAllocU;
738 	/* 0x42 */
739 	uint16_t wEnhanced4CapAdjFac;
740 	uint32_t dOptimalLogicalBlockSize;
741 	uint8_t ReservedHpb[5];
742 	uint8_t Reserved2[2];
743 	uint32_t dWriteBoosterBufferMaxNAllocUnits;
744 	uint8_t bDeviceMaxWriteBoosterLUs;
745 	uint8_t bWriteBoosterBufferCapAdjFac;
746 	uint8_t bSupportedWriteBoosterBufferUserSpaceReductionTypes;
747 	uint8_t bSupportedWriteBoosterBufferTypes;
748 } __packed;
749 
750 _Static_assert(sizeof(struct ufshci_geometry_descriptor) == 87,
751     "bad size for ufshci_geometry_descriptor");
752 
753 /*
754  * UFS Spec 4.1, section 14.1.5.5 "Unit Descriptor"
755  * UnitDescriptor use big-endian byte ordering.
756  */
757 struct ufshci_unit_descriptor {
758 	uint8_t bLength;
759 	uint8_t bDescriptorIDN;
760 	uint8_t bUnitIndex;
761 	uint8_t bLUEnable;
762 	uint8_t bBootLunID;
763 	uint8_t bLUWriteProtect;
764 	uint8_t bLUQueueDepth;
765 	uint8_t bPSASensitive;
766 	uint8_t bMemoryType;
767 	uint8_t bDataReliability;
768 	uint8_t bLogicalBlockSize;
769 	uint64_t qLogicalBlockCount;
770 	/* 0x13 */
771 	uint32_t dEraseBlockSize;
772 	uint8_t bProvisioningType;
773 	uint64_t qPhyMemResourceCount;
774 	/* 0x20 */
775 	uint16_t wContextCapabilities;
776 	uint8_t bLargeUnitGranularity_M1;
777 	uint8_t ReservedHpb[6];
778 	uint32_t dLUNumWriteBoosterBufferAllocUnits;
779 } __packed;
780 _Static_assert(sizeof(struct ufshci_unit_descriptor) == 45,
781     "bad size for ufshci_unit_descriptor");
782 
783 enum LUWriteProtect {
784 	kNoWriteProtect = 0x00,
785 	kPowerOnWriteProtect = 0x01,
786 	kPermanentWriteProtect = 0x02,
787 };
788 
789 /*
790  * UFS Spec 4.1, section 14.1.5.6 "RPMB Unit Descriptor"
791  * RpmbUnitDescriptor use big-endian byte ordering.
792  */
793 struct ufshci_rpmb_unit_descriptor {
794 	uint8_t bLength;
795 	uint8_t bDescriptorIDN;
796 	uint8_t bUnitIndex;
797 	uint8_t bLUEnable;
798 	uint8_t bBootLunID;
799 	uint8_t bLUWriteProtect;
800 	uint8_t bLUQueueDepth;
801 	uint8_t bPSASensitive;
802 	uint8_t bMemoryType;
803 	uint8_t Reserved;
804 	uint8_t bLogicalBlockSize;
805 	uint64_t qLogicalBlockCount;
806 	/* 0x13 */
807 	uint32_t dEraseBlockSize;
808 	uint8_t bProvisioningType;
809 	uint64_t qPhyMemResourceCount;
810 	/* 0x20 */
811 	uint8_t Reserved1[3];
812 } __packed;
813 _Static_assert(sizeof(struct ufshci_rpmb_unit_descriptor) == 35,
814     "bad size for RpmbUnitDescriptor");
815 
816 /*
817  * UFS Spec 4.1, section 14.1.5.7 "Power Parameters Descriptor"
818  * PowerParametersDescriptor use big-endian byte ordering.
819  */
820 struct ufshci_power_parameters_descriptor {
821 	uint8_t bLength;
822 	uint8_t bDescriptorIDN;
823 	uint16_t wActiveICCLevelsVCC[16];
824 	uint16_t wActiveICCLevelsVCCQ[16];
825 	uint16_t wActiveICCLevelsVCCQ2[16];
826 } __packed;
827 _Static_assert(sizeof(struct ufshci_power_parameters_descriptor) == 98,
828     "bad size for PowerParametersDescriptor");
829 
830 /*
831  * UFS Spec 4.1, section 14.1.5.8 "Interconnect Descriptor"
832  * InterconnectDescriptor use big-endian byte ordering.
833  */
834 struct ufshci_interconnect_descriptor {
835 	uint8_t bLength;
836 	uint8_t bDescriptorIDN;
837 	uint16_t bcdUniproVersion;
838 	uint16_t bcdMphyVersion;
839 } __packed;
840 _Static_assert(sizeof(struct ufshci_interconnect_descriptor) == 6,
841     "bad size for InterconnectDescriptor");
842 
843 /*
844  * UFS Spec 4.1, section 14.1.5.9-13 "String Descriptor"
845  * StringDescriptor use big-endian byte ordering.
846  */
847 struct ufshci_string_descriptor {
848 	uint8_t bLength;
849 	uint8_t bDescriptorIDN;
850 	uint16_t UC[126];
851 } __packed;
852 _Static_assert(sizeof(struct ufshci_string_descriptor) == 254,
853     "bad size for StringDescriptor");
854 
855 /*
856  * UFS Spec 4.1, section 14.1.5.14 "Device Health Descriptor"
857  * DeviceHealthDescriptor use big-endian byte ordering.
858  */
859 struct ufshci_device_healthd_descriptor {
860 	uint8_t bLength;
861 	uint8_t bDescriptorIDN;
862 	uint8_t bPreEOLInfo;
863 	uint8_t bDeviceLifeTimeEstA;
864 	uint8_t bDeviceLifeTimeEstB;
865 	uint8_t VendorPropInfo[32];
866 	uint32_t dRefreshTotalCount;
867 	uint32_t dRefreshProgress;
868 } __packed;
869 _Static_assert(sizeof(struct ufshci_device_healthd_descriptor) == 45,
870     "bad size for DeviceHealthDescriptor");
871 
872 /*
873  * UFS Spec 4.1, section 14.1.5.15 "Vendor Specific Descriptor"
874  * VendorSpecificDescriptor use big-endian byte ordering.
875  */
876 struct ufshci_vendor_specific_descriptor {
877 	uint8_t bLength;
878 	uint8_t bDescriptorIDN;
879 	uint8_t DATA[254];
880 } __packed;
881 _Static_assert(sizeof(struct ufshci_vendor_specific_descriptor) == 256,
882     "bad size for VendorSpecificDescriptor");
883 
884 /* UFS Spec 4.1, section 14.2 "Flags" */
885 enum ufshci_flags {
886 	UFSHCI_FLAG_F_RESERVED = 0x00,
887 	UFSHCI_FLAG_F_DEVICE_INIT = 0x01,
888 	UFSHCI_FLAG_F_PERMANENT_WP_EN = 0x02,
889 	UFSHCI_FLAS_F_POWER_ON_WP_EN = 0x03,
890 	UFSHCI_FLAG_F_BACKGROUND_OPS_EN = 0x04,
891 	UFSHCI_FLAG_F_DEVICE_LIFE_SPAN_MODE_EN = 0x05,
892 	UFSHCI_FLAG_F_PURGE_ENABLE = 0x06,
893 	UFSHCI_FLAG_F_REFRESH_ENABLE = 0x07,
894 	UFSHCI_FLAG_F_PHY_RESOURCE_REMOVAL = 0x08,
895 	UFSHCI_FLAG_F_BUSY_RTC = 0x09,
896 	UFSHCI_FLAG_F_PERMANENTLY_DISABLE_FW_UPDATE = 0x0b,
897 	UFSHCI_FLAG_F_WRITE_BOOSTER_EN = 0x0e,
898 	UFSHCI_FLAG_F_WB_BUFFER_FLUSH_EN = 0x0f,
899 	UFSHCI_FLAG_F_WB_BUFFER_FLUSH_DURING_HIBERNATE = 0x10,
900 	UFSHCI_FLAG_F_UNPIN_EN = 0x13,
901 };
902 
903 /* UFS Spec 4.1, section 14.3 "Attributes" */
904 enum ufshci_attributes {
905 	UFSHCI_ATTR_B_BOOT_LUN_EN = 0x00,
906 	UFSHCI_ATTR_B_CURRENT_POWER_MODE = 0x02,
907 	UFSHCI_ATTR_B_ACTIVE_ICC_LEVEL = 0x03,
908 	UFSHCI_ATTR_B_OUT_OF_ORDER_DATA_EN = 0x04,
909 	UFSHCI_ATTR_B_BACKGROUND_OP_STATUS = 0x05,
910 	UFSHCI_ATTR_B_PURGE_STATUS = 0x06,
911 	UFSHCI_ATTR_B_MAX_DATA_IN_SIZE = 0x07,
912 	UFSHCI_ATTR_B_MAX_DATA_OUT_SIZE = 0x08,
913 	UFSHCI_ATTR_D_DYN_CAP_NEEDED = 0x09,
914 	UFSHCI_ATTR_B_REF_CLK_FREQ = 0x0a,
915 	UFSHCI_ATTR_B_CONFIG_DESCR_LOCK = 0x0b,
916 	UFSHCI_ATTR_B_MAX_NUM_OF_RTT = 0x0c,
917 	UFSHCI_ATTR_W_EXCEPTION_EVENT_CONTROL = 0x0d,
918 	UFSHCI_ATTR_W_EXCEPTION_EVENT_STATUS = 0x0e,
919 	UFSHCI_ATTR_D_SECONDS_PASSED = 0x0f,
920 	UFSHCI_ATTR_W_CONTEXT_CONF = 0x10,
921 	UFSHCI_ATTR_B_DEVICE_FFU_STATUS = 0x14,
922 	UFSHCI_ATTR_B_PSA_STATE = 0x15,
923 	UFSHCI_ATTR_D_PSA_DATA_SIZE = 0x16,
924 	UFSHCI_ATTR_B_REF_CLK_GATING_WAIT_TIME = 0x17,
925 	UFSHCI_ATTR_B_DEVICE_CASE_ROUGH_TEMPERAURE = 0x18,
926 	UFSHCI_ATTR_B_DEVICE_TOO_HIGH_TEMP_BOUNDARY = 0x19,
927 	UFSHCI_ATTR_B_DEVICE_TOO_LOW_TEMP_BOUNDARY = 0x1a,
928 	UFSHCI_ATTR_B_THROTTLING_STATUS = 0x1b,
929 	UFSHCI_ATTR_B_WB_BUFFER_FLUSH_STATUS = 0x1c,
930 	UFSHCI_ATTR_B_AVAILABLE_WB_BUFFER_SIZE = 0x1d,
931 	UFSHCI_ATTR_B_WB_BUFFER_LIFE_TIME_EST = 0x1e,
932 	UFSHCI_ATTR_D_CURRENT_WB_BUFFER_SIZE = 0x1f,
933 	UFSHCI_ATTR_B_REFRESH_STATUS = 0x2c,
934 	UFSHCI_ATTR_B_REFRESH_FREQ = 0x2d,
935 	UFSHCI_ATTR_B_REFRESH_UNIT = 0x2e,
936 	UFSHCI_ATTR_B_REFRESH_METHOD = 0x2f,
937 };
938 
939 #endif /* __UFSHCI_H__ */
940