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