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