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