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