18f7de514SShawn Lin /* SPDX-License-Identifier: GPL-2.0+ */ 28f7de514SShawn Lin #ifndef __UFS_H 38f7de514SShawn Lin #define __UFS_H 48f7de514SShawn Lin 58f7de514SShawn Lin #include "unipro.h" 68f7de514SShawn Lin 78f7de514SShawn Lin struct udevice; 88f7de514SShawn Lin 98f7de514SShawn Lin #define UFS_CDB_SIZE 16 108f7de514SShawn Lin #define UPIU_TRANSACTION_UIC_CMD 0x1F 118f7de514SShawn Lin #define UIC_CMD_SIZE (sizeof(u32) * 4) 128f7de514SShawn Lin #define RESPONSE_UPIU_SENSE_DATA_LENGTH 18 13*7b1f08e7SYifeng Zhao 14*7b1f08e7SYifeng Zhao #ifdef CONFIG_ARCH_ROCKCHIP 15*7b1f08e7SYifeng Zhao #define UFS_MAX_LUNS 0x4 16*7b1f08e7SYifeng Zhao #else 178f7de514SShawn Lin #define UFS_MAX_LUNS 0x7F 18*7b1f08e7SYifeng Zhao #endif 198f7de514SShawn Lin 208f7de514SShawn Lin enum { 218f7de514SShawn Lin TASK_REQ_UPIU_SIZE_DWORDS = 8, 228f7de514SShawn Lin TASK_RSP_UPIU_SIZE_DWORDS = 8, 238f7de514SShawn Lin ALIGNED_UPIU_SIZE = 512, 248f7de514SShawn Lin }; 258f7de514SShawn Lin 268f7de514SShawn Lin /* UFS device power modes */ 278f7de514SShawn Lin enum ufs_dev_pwr_mode { 288f7de514SShawn Lin UFS_ACTIVE_PWR_MODE = 1, 298f7de514SShawn Lin UFS_SLEEP_PWR_MODE = 2, 308f7de514SShawn Lin UFS_POWERDOWN_PWR_MODE = 3, 318f7de514SShawn Lin }; 328f7de514SShawn Lin 338f7de514SShawn Lin enum ufs_notify_change_status { 348f7de514SShawn Lin PRE_CHANGE, 358f7de514SShawn Lin POST_CHANGE, 368f7de514SShawn Lin }; 378f7de514SShawn Lin 388f7de514SShawn Lin struct ufs_pa_layer_attr { 398f7de514SShawn Lin u32 gear_rx; 408f7de514SShawn Lin u32 gear_tx; 418f7de514SShawn Lin u32 lane_rx; 428f7de514SShawn Lin u32 lane_tx; 438f7de514SShawn Lin u32 pwr_rx; 448f7de514SShawn Lin u32 pwr_tx; 458f7de514SShawn Lin u32 hs_rate; 468f7de514SShawn Lin }; 478f7de514SShawn Lin 488f7de514SShawn Lin struct ufs_pwr_mode_info { 498f7de514SShawn Lin bool is_valid; 508f7de514SShawn Lin struct ufs_pa_layer_attr info; 518f7de514SShawn Lin }; 528f7de514SShawn Lin 538f7de514SShawn Lin enum ufs_desc_def_size { 548f7de514SShawn Lin QUERY_DESC_DEVICE_DEF_SIZE = 0x40, 558f7de514SShawn Lin QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90, 568f7de514SShawn Lin QUERY_DESC_UNIT_DEF_SIZE = 0x23, 578f7de514SShawn Lin QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, 588f7de514SShawn Lin QUERY_DESC_GEOMETRY_DEF_SIZE = 0x48, 598f7de514SShawn Lin QUERY_DESC_POWER_DEF_SIZE = 0x62, 608f7de514SShawn Lin QUERY_DESC_HEALTH_DEF_SIZE = 0x25, 618f7de514SShawn Lin }; 628f7de514SShawn Lin 638f7de514SShawn Lin struct ufs_desc_size { 648f7de514SShawn Lin int dev_desc; 658f7de514SShawn Lin int pwr_desc; 668f7de514SShawn Lin int geom_desc; 678f7de514SShawn Lin int interc_desc; 688f7de514SShawn Lin int unit_desc; 698f7de514SShawn Lin int conf_desc; 708f7de514SShawn Lin int hlth_desc; 718f7de514SShawn Lin }; 728f7de514SShawn Lin 73ec622ba8SYifeng Zhao struct ufs_device_descriptor { 74ec622ba8SYifeng Zhao uint8_t b_length; 75ec622ba8SYifeng Zhao uint8_t b_descriptor_idn; 76ec622ba8SYifeng Zhao uint8_t b_device; 77ec622ba8SYifeng Zhao uint8_t b_device_class; 78ec622ba8SYifeng Zhao uint8_t b_device_sub_class; 79ec622ba8SYifeng Zhao uint8_t b_protocol; 80ec622ba8SYifeng Zhao uint8_t b_number_lu; 81ec622ba8SYifeng Zhao uint8_t b_number_wlu; 82ec622ba8SYifeng Zhao uint8_t b_boot_enable; 83ec622ba8SYifeng Zhao uint8_t b_descr_access_en; 84ec622ba8SYifeng Zhao uint8_t b_init_power_mode; 85ec622ba8SYifeng Zhao uint8_t b_high_priority_lun; 86ec622ba8SYifeng Zhao uint8_t b_secure_removal_type; 87ec622ba8SYifeng Zhao uint8_t b_security_lu; 88ec622ba8SYifeng Zhao uint8_t b_background_ops_term_lat; 89ec622ba8SYifeng Zhao uint8_t b_init_active_icc_level; 90ec622ba8SYifeng Zhao uint16_t w_spec_version; 91ec622ba8SYifeng Zhao uint16_t w_manufacture_date; 92ec622ba8SYifeng Zhao uint8_t i_manufacturer_name; 93ec622ba8SYifeng Zhao uint8_t i_product_name; 94ec622ba8SYifeng Zhao uint8_t i_serial_number; 95ec622ba8SYifeng Zhao uint8_t i_oem_id; 96ec622ba8SYifeng Zhao uint16_t w_manufacturer_id; 97ec622ba8SYifeng Zhao uint8_t b_ud_0base_offset; 98ec622ba8SYifeng Zhao uint8_t b_ud_config_plength; 99ec622ba8SYifeng Zhao uint8_t b_device_rtt_cap; 100ec622ba8SYifeng Zhao uint16_t w_periodic_rtc_update; 101ec622ba8SYifeng Zhao uint8_t b_ufs_feature_support; 102ec622ba8SYifeng Zhao uint8_t b_ffu_timeout; 103ec622ba8SYifeng Zhao uint8_t b_queue_depth; 104ec622ba8SYifeng Zhao uint16_t w_device_version; 105ec622ba8SYifeng Zhao uint8_t b_num_secure_wp_area; 106ec622ba8SYifeng Zhao uint32_t d_psa_max_data_size; 107ec622ba8SYifeng Zhao uint8_t b_psa_state_timeout; 108ec622ba8SYifeng Zhao uint8_t i_product_revision_level; 109ec622ba8SYifeng Zhao uint8_t reserved[5]; /* 5 reserved */ 110ec622ba8SYifeng Zhao uint8_t reserved_ume[16]; /* 16 reserved */ 111ec622ba8SYifeng Zhao } __attribute__ ((packed)); 112ec622ba8SYifeng Zhao 1138f7de514SShawn Lin /* 1148f7de514SShawn Lin * Request Descriptor Definitions 1158f7de514SShawn Lin */ 1168f7de514SShawn Lin 1178f7de514SShawn Lin /* Transfer request command type */ 1188f7de514SShawn Lin enum { 1198f7de514SShawn Lin UTP_CMD_TYPE_SCSI = 0x0, 1208f7de514SShawn Lin UTP_CMD_TYPE_UFS = 0x1, 1218f7de514SShawn Lin UTP_CMD_TYPE_DEV_MANAGE = 0x2, 1228f7de514SShawn Lin }; 1238f7de514SShawn Lin 1248f7de514SShawn Lin /* UTP Transfer Request Command Offset */ 1258f7de514SShawn Lin #define UPIU_COMMAND_TYPE_OFFSET 28 1268f7de514SShawn Lin 1278f7de514SShawn Lin /* Offset of the response code in the UPIU header */ 1288f7de514SShawn Lin #define UPIU_RSP_CODE_OFFSET 8 1298f7de514SShawn Lin 1308f7de514SShawn Lin /* To accommodate UFS2.0 required Command type */ 1318f7de514SShawn Lin enum { 1328f7de514SShawn Lin UTP_CMD_TYPE_UFS_STORAGE = 0x1, 1338f7de514SShawn Lin }; 1348f7de514SShawn Lin 1358f7de514SShawn Lin enum { 1368f7de514SShawn Lin UTP_SCSI_COMMAND = 0x00000000, 1378f7de514SShawn Lin UTP_NATIVE_UFS_COMMAND = 0x10000000, 1388f7de514SShawn Lin UTP_DEVICE_MANAGEMENT_FUNCTION = 0x20000000, 1398f7de514SShawn Lin UTP_REQ_DESC_INT_CMD = 0x01000000, 1408f7de514SShawn Lin }; 1418f7de514SShawn Lin 1428f7de514SShawn Lin /* UTP Transfer Request Data Direction (DD) */ 1438f7de514SShawn Lin enum { 1448f7de514SShawn Lin UTP_NO_DATA_TRANSFER = 0x00000000, 1458f7de514SShawn Lin UTP_HOST_TO_DEVICE = 0x02000000, 1468f7de514SShawn Lin UTP_DEVICE_TO_HOST = 0x04000000, 1478f7de514SShawn Lin }; 1488f7de514SShawn Lin 1498f7de514SShawn Lin /* Overall command status values */ 1508f7de514SShawn Lin enum { 1518f7de514SShawn Lin OCS_SUCCESS = 0x0, 1528f7de514SShawn Lin OCS_INVALID_CMD_TABLE_ATTR = 0x1, 1538f7de514SShawn Lin OCS_INVALID_PRDT_ATTR = 0x2, 1548f7de514SShawn Lin OCS_MISMATCH_DATA_BUF_SIZE = 0x3, 1558f7de514SShawn Lin OCS_MISMATCH_RESP_UPIU_SIZE = 0x4, 1568f7de514SShawn Lin OCS_PEER_COMM_FAILURE = 0x5, 1578f7de514SShawn Lin OCS_ABORTED = 0x6, 1588f7de514SShawn Lin OCS_FATAL_ERROR = 0x7, 1598f7de514SShawn Lin OCS_INVALID_COMMAND_STATUS = 0x0F, 1608f7de514SShawn Lin MASK_OCS = 0x0F, 1618f7de514SShawn Lin }; 1628f7de514SShawn Lin 1638f7de514SShawn Lin /* The maximum length of the data byte count field in the PRDT is 256KB */ 1648f7de514SShawn Lin #define PRDT_DATA_BYTE_COUNT_MAX (256 * 1024) 1658f7de514SShawn Lin /* The granularity of the data byte count field in the PRDT is 32-bit */ 1668f7de514SShawn Lin #define PRDT_DATA_BYTE_COUNT_PAD 4 1678f7de514SShawn Lin 1688f7de514SShawn Lin #define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req)) 1698f7de514SShawn Lin #define QUERY_DESC_MAX_SIZE 255 1708f7de514SShawn Lin #define QUERY_DESC_MIN_SIZE 2 1718f7de514SShawn Lin #define QUERY_DESC_HDR_SIZE 2 1728f7de514SShawn Lin #define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \ 1738f7de514SShawn Lin (sizeof(struct utp_upiu_header))) 1748f7de514SShawn Lin #define RESPONSE_UPIU_SENSE_DATA_LENGTH 18 1758f7de514SShawn Lin #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\ 1768f7de514SShawn Lin cpu_to_be32((byte3 << 24) | (byte2 << 16) |\ 1778f7de514SShawn Lin (byte1 << 8) | (byte0)) 1788f7de514SShawn Lin /* 1798f7de514SShawn Lin * UFS Protocol Information Unit related definitions 1808f7de514SShawn Lin */ 1818f7de514SShawn Lin 1828f7de514SShawn Lin /* Task management functions */ 1838f7de514SShawn Lin enum { 1848f7de514SShawn Lin UFS_ABORT_TASK = 0x01, 1858f7de514SShawn Lin UFS_ABORT_TASK_SET = 0x02, 1868f7de514SShawn Lin UFS_CLEAR_TASK_SET = 0x04, 1878f7de514SShawn Lin UFS_LOGICAL_RESET = 0x08, 1888f7de514SShawn Lin UFS_QUERY_TASK = 0x80, 1898f7de514SShawn Lin UFS_QUERY_TASK_SET = 0x81, 1908f7de514SShawn Lin }; 1918f7de514SShawn Lin 1928f7de514SShawn Lin /* UTP UPIU Transaction Codes Initiator to Target */ 1938f7de514SShawn Lin enum { 1948f7de514SShawn Lin UPIU_TRANSACTION_NOP_OUT = 0x00, 1958f7de514SShawn Lin UPIU_TRANSACTION_COMMAND = 0x01, 1968f7de514SShawn Lin UPIU_TRANSACTION_DATA_OUT = 0x02, 1978f7de514SShawn Lin UPIU_TRANSACTION_TASK_REQ = 0x04, 1988f7de514SShawn Lin UPIU_TRANSACTION_QUERY_REQ = 0x16, 1998f7de514SShawn Lin }; 2008f7de514SShawn Lin 2018f7de514SShawn Lin /* UTP UPIU Transaction Codes Target to Initiator */ 2028f7de514SShawn Lin enum { 2038f7de514SShawn Lin UPIU_TRANSACTION_NOP_IN = 0x20, 2048f7de514SShawn Lin UPIU_TRANSACTION_RESPONSE = 0x21, 2058f7de514SShawn Lin UPIU_TRANSACTION_DATA_IN = 0x22, 2068f7de514SShawn Lin UPIU_TRANSACTION_TASK_RSP = 0x24, 2078f7de514SShawn Lin UPIU_TRANSACTION_READY_XFER = 0x31, 2088f7de514SShawn Lin UPIU_TRANSACTION_QUERY_RSP = 0x36, 2098f7de514SShawn Lin UPIU_TRANSACTION_REJECT_UPIU = 0x3F, 2108f7de514SShawn Lin }; 2118f7de514SShawn Lin 2128f7de514SShawn Lin /* UPIU Read/Write flags */ 2138f7de514SShawn Lin enum { 2148f7de514SShawn Lin UPIU_CMD_FLAGS_NONE = 0x00, 2158f7de514SShawn Lin UPIU_CMD_FLAGS_WRITE = 0x20, 2168f7de514SShawn Lin UPIU_CMD_FLAGS_READ = 0x40, 2178f7de514SShawn Lin }; 2188f7de514SShawn Lin 2198f7de514SShawn Lin /* UPIU Task Attributes */ 2208f7de514SShawn Lin enum { 2218f7de514SShawn Lin UPIU_TASK_ATTR_SIMPLE = 0x00, 2228f7de514SShawn Lin UPIU_TASK_ATTR_ORDERED = 0x01, 2238f7de514SShawn Lin UPIU_TASK_ATTR_HEADQ = 0x02, 2248f7de514SShawn Lin UPIU_TASK_ATTR_ACA = 0x03, 2258f7de514SShawn Lin }; 2268f7de514SShawn Lin 2278f7de514SShawn Lin /* UPIU Query request function */ 2288f7de514SShawn Lin enum { 2298f7de514SShawn Lin UPIU_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01, 2308f7de514SShawn Lin UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81, 2318f7de514SShawn Lin }; 2328f7de514SShawn Lin 2338f7de514SShawn Lin /* Offset of the response code in the UPIU header */ 2348f7de514SShawn Lin #define UPIU_RSP_CODE_OFFSET 8 2358f7de514SShawn Lin 2368f7de514SShawn Lin enum { 2378f7de514SShawn Lin MASK_SCSI_STATUS = 0xFF, 2388f7de514SShawn Lin MASK_TASK_RESPONSE = 0xFF00, 2398f7de514SShawn Lin MASK_RSP_UPIU_RESULT = 0xFFFF, 2408f7de514SShawn Lin MASK_QUERY_DATA_SEG_LEN = 0xFFFF, 2418f7de514SShawn Lin MASK_RSP_UPIU_DATA_SEG_LEN = 0xFFFF, 2428f7de514SShawn Lin MASK_RSP_EXCEPTION_EVENT = 0x10000, 2438f7de514SShawn Lin MASK_TM_SERVICE_RESP = 0xFF, 2448f7de514SShawn Lin MASK_TM_FUNC = 0xFF, 2458f7de514SShawn Lin }; 2468f7de514SShawn Lin 2478f7de514SShawn Lin /* UTP QUERY Transaction Specific Fields OpCode */ 2488f7de514SShawn Lin enum query_opcode { 2498f7de514SShawn Lin UPIU_QUERY_OPCODE_NOP = 0x0, 2508f7de514SShawn Lin UPIU_QUERY_OPCODE_READ_DESC = 0x1, 2518f7de514SShawn Lin UPIU_QUERY_OPCODE_WRITE_DESC = 0x2, 2528f7de514SShawn Lin UPIU_QUERY_OPCODE_READ_ATTR = 0x3, 2538f7de514SShawn Lin UPIU_QUERY_OPCODE_WRITE_ATTR = 0x4, 2548f7de514SShawn Lin UPIU_QUERY_OPCODE_READ_FLAG = 0x5, 2558f7de514SShawn Lin UPIU_QUERY_OPCODE_SET_FLAG = 0x6, 2568f7de514SShawn Lin UPIU_QUERY_OPCODE_CLEAR_FLAG = 0x7, 2578f7de514SShawn Lin UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8, 2588f7de514SShawn Lin }; 2598f7de514SShawn Lin 2608f7de514SShawn Lin /* Query response result code */ 2618f7de514SShawn Lin enum { 2628f7de514SShawn Lin QUERY_RESULT_SUCCESS = 0x00, 2638f7de514SShawn Lin QUERY_RESULT_NOT_READABLE = 0xF6, 2648f7de514SShawn Lin QUERY_RESULT_NOT_WRITEABLE = 0xF7, 2658f7de514SShawn Lin QUERY_RESULT_ALREADY_WRITTEN = 0xF8, 2668f7de514SShawn Lin QUERY_RESULT_INVALID_LENGTH = 0xF9, 2678f7de514SShawn Lin QUERY_RESULT_INVALID_VALUE = 0xFA, 2688f7de514SShawn Lin QUERY_RESULT_INVALID_SELECTOR = 0xFB, 2698f7de514SShawn Lin QUERY_RESULT_INVALID_INDEX = 0xFC, 2708f7de514SShawn Lin QUERY_RESULT_INVALID_IDN = 0xFD, 2718f7de514SShawn Lin QUERY_RESULT_INVALID_OPCODE = 0xFE, 2728f7de514SShawn Lin QUERY_RESULT_GENERAL_FAILURE = 0xFF, 2738f7de514SShawn Lin }; 2748f7de514SShawn Lin 2758f7de514SShawn Lin enum { 2768f7de514SShawn Lin UPIU_COMMAND_SET_TYPE_SCSI = 0x0, 2778f7de514SShawn Lin UPIU_COMMAND_SET_TYPE_UFS = 0x1, 2788f7de514SShawn Lin UPIU_COMMAND_SET_TYPE_QUERY = 0x2, 2798f7de514SShawn Lin }; 2808f7de514SShawn Lin 2818f7de514SShawn Lin /* Flag idn for Query Requests*/ 2828f7de514SShawn Lin enum flag_idn { 2838f7de514SShawn Lin QUERY_FLAG_IDN_FDEVICEINIT = 0x01, 2848f7de514SShawn Lin QUERY_FLAG_IDN_PERMANENT_WPE = 0x02, 2858f7de514SShawn Lin QUERY_FLAG_IDN_PWR_ON_WPE = 0x03, 2868f7de514SShawn Lin QUERY_FLAG_IDN_BKOPS_EN = 0x04, 2878f7de514SShawn Lin QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE = 0x05, 2888f7de514SShawn Lin QUERY_FLAG_IDN_PURGE_ENABLE = 0x06, 2898f7de514SShawn Lin QUERY_FLAG_IDN_RESERVED2 = 0x07, 2908f7de514SShawn Lin QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL = 0x08, 2918f7de514SShawn Lin QUERY_FLAG_IDN_BUSY_RTC = 0x09, 2928f7de514SShawn Lin QUERY_FLAG_IDN_RESERVED3 = 0x0A, 2938f7de514SShawn Lin QUERY_FLAG_IDN_PERMANENTLY_DISABLE_FW_UPDATE = 0x0B, 2948f7de514SShawn Lin }; 2958f7de514SShawn Lin 2968f7de514SShawn Lin /* Attribute idn for Query requests */ 2978f7de514SShawn Lin enum attr_idn { 2988f7de514SShawn Lin QUERY_ATTR_IDN_BOOT_LU_EN = 0x00, 2998f7de514SShawn Lin QUERY_ATTR_IDN_RESERVED = 0x01, 3008f7de514SShawn Lin QUERY_ATTR_IDN_POWER_MODE = 0x02, 3018f7de514SShawn Lin QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03, 3028f7de514SShawn Lin QUERY_ATTR_IDN_OOO_DATA_EN = 0x04, 3038f7de514SShawn Lin QUERY_ATTR_IDN_BKOPS_STATUS = 0x05, 3048f7de514SShawn Lin QUERY_ATTR_IDN_PURGE_STATUS = 0x06, 3058f7de514SShawn Lin QUERY_ATTR_IDN_MAX_DATA_IN = 0x07, 3068f7de514SShawn Lin QUERY_ATTR_IDN_MAX_DATA_OUT = 0x08, 3078f7de514SShawn Lin QUERY_ATTR_IDN_DYN_CAP_NEEDED = 0x09, 3088f7de514SShawn Lin QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A, 3098f7de514SShawn Lin QUERY_ATTR_IDN_CONF_DESC_LOCK = 0x0B, 3108f7de514SShawn Lin QUERY_ATTR_IDN_MAX_NUM_OF_RTT = 0x0C, 3118f7de514SShawn Lin QUERY_ATTR_IDN_EE_CONTROL = 0x0D, 3128f7de514SShawn Lin QUERY_ATTR_IDN_EE_STATUS = 0x0E, 3138f7de514SShawn Lin QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F, 3148f7de514SShawn Lin QUERY_ATTR_IDN_CNTX_CONF = 0x10, 3158f7de514SShawn Lin QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11, 3168f7de514SShawn Lin QUERY_ATTR_IDN_RESERVED2 = 0x12, 3178f7de514SShawn Lin QUERY_ATTR_IDN_RESERVED3 = 0x13, 3188f7de514SShawn Lin QUERY_ATTR_IDN_FFU_STATUS = 0x14, 3198f7de514SShawn Lin QUERY_ATTR_IDN_PSA_STATE = 0x15, 3208f7de514SShawn Lin QUERY_ATTR_IDN_PSA_DATA_SIZE = 0x16, 3218f7de514SShawn Lin }; 3228f7de514SShawn Lin 3238f7de514SShawn Lin /* Descriptor idn for Query requests */ 3248f7de514SShawn Lin enum desc_idn { 3258f7de514SShawn Lin QUERY_DESC_IDN_DEVICE = 0x0, 3268f7de514SShawn Lin QUERY_DESC_IDN_CONFIGURATION = 0x1, 3278f7de514SShawn Lin QUERY_DESC_IDN_UNIT = 0x2, 3288f7de514SShawn Lin QUERY_DESC_IDN_RFU_0 = 0x3, 3298f7de514SShawn Lin QUERY_DESC_IDN_INTERCONNECT = 0x4, 3308f7de514SShawn Lin QUERY_DESC_IDN_STRING = 0x5, 3318f7de514SShawn Lin QUERY_DESC_IDN_RFU_1 = 0x6, 3328f7de514SShawn Lin QUERY_DESC_IDN_GEOMETRY = 0x7, 3338f7de514SShawn Lin QUERY_DESC_IDN_POWER = 0x8, 3348f7de514SShawn Lin QUERY_DESC_IDN_HEALTH = 0x9, 3358f7de514SShawn Lin QUERY_DESC_IDN_MAX, 3368f7de514SShawn Lin }; 3378f7de514SShawn Lin 3388f7de514SShawn Lin enum desc_header_offset { 3398f7de514SShawn Lin QUERY_DESC_LENGTH_OFFSET = 0x00, 3408f7de514SShawn Lin QUERY_DESC_DESC_TYPE_OFFSET = 0x01, 3418f7de514SShawn Lin }; 3428f7de514SShawn Lin 3438f7de514SShawn Lin struct ufshcd_sg_entry { 3448f7de514SShawn Lin __le32 base_addr; 3458f7de514SShawn Lin __le32 upper_addr; 3468f7de514SShawn Lin __le32 reserved; 3478f7de514SShawn Lin __le32 size; 3488f7de514SShawn Lin }; 3498f7de514SShawn Lin 3508f7de514SShawn Lin #define MAX_BUFF 128 3518f7de514SShawn Lin /** 3528f7de514SShawn Lin * struct utp_transfer_cmd_desc - UFS Command Descriptor structure 3538f7de514SShawn Lin * @command_upiu: Command UPIU Frame address 3548f7de514SShawn Lin * @response_upiu: Response UPIU Frame address 3558f7de514SShawn Lin * @prd_table: Physical Region Descriptor 3568f7de514SShawn Lin */ 3578f7de514SShawn Lin struct utp_transfer_cmd_desc { 3588f7de514SShawn Lin u8 command_upiu[ALIGNED_UPIU_SIZE]; 3598f7de514SShawn Lin u8 response_upiu[ALIGNED_UPIU_SIZE]; 3608f7de514SShawn Lin struct ufshcd_sg_entry prd_table[MAX_BUFF]; 3618f7de514SShawn Lin }; 3628f7de514SShawn Lin 3638f7de514SShawn Lin /** 3648f7de514SShawn Lin * struct request_desc_header - Descriptor Header common to both UTRD and UTMRD 3658f7de514SShawn Lin * @dword0: Descriptor Header DW0 3668f7de514SShawn Lin * @dword1: Descriptor Header DW1 3678f7de514SShawn Lin * @dword2: Descriptor Header DW2 3688f7de514SShawn Lin * @dword3: Descriptor Header DW3 3698f7de514SShawn Lin */ 3708f7de514SShawn Lin struct request_desc_header { 3718f7de514SShawn Lin __le32 dword_0; 3728f7de514SShawn Lin __le32 dword_1; 3738f7de514SShawn Lin __le32 dword_2; 3748f7de514SShawn Lin __le32 dword_3; 3758f7de514SShawn Lin }; 3768f7de514SShawn Lin 3778f7de514SShawn Lin /** 3788f7de514SShawn Lin * struct utp_transfer_req_desc - UTRD structure 3798f7de514SShawn Lin * @header: UTRD header DW-0 to DW-3 3808f7de514SShawn Lin * @command_desc_base_addr_lo: UCD base address low DW-4 3818f7de514SShawn Lin * @command_desc_base_addr_hi: UCD base address high DW-5 3828f7de514SShawn Lin * @response_upiu_length: response UPIU length DW-6 3838f7de514SShawn Lin * @response_upiu_offset: response UPIU offset DW-6 3848f7de514SShawn Lin * @prd_table_length: Physical region descriptor length DW-7 3858f7de514SShawn Lin * @prd_table_offset: Physical region descriptor offset DW-7 3868f7de514SShawn Lin */ 3878f7de514SShawn Lin struct utp_transfer_req_desc { 3888f7de514SShawn Lin /* DW 0-3 */ 3898f7de514SShawn Lin struct request_desc_header header; 3908f7de514SShawn Lin 3918f7de514SShawn Lin /* DW 4-5*/ 3928f7de514SShawn Lin __le32 command_desc_base_addr_lo; 3938f7de514SShawn Lin __le32 command_desc_base_addr_hi; 3948f7de514SShawn Lin 3958f7de514SShawn Lin /* DW 6 */ 3968f7de514SShawn Lin __le16 response_upiu_length; 3978f7de514SShawn Lin __le16 response_upiu_offset; 3988f7de514SShawn Lin 3998f7de514SShawn Lin /* DW 7 */ 4008f7de514SShawn Lin __le16 prd_table_length; 4018f7de514SShawn Lin __le16 prd_table_offset; 4028f7de514SShawn Lin }; 4038f7de514SShawn Lin 4048f7de514SShawn Lin /** 4058f7de514SShawn Lin * struct utp_upiu_header - UPIU header structure 4068f7de514SShawn Lin * @dword_0: UPIU header DW-0 4078f7de514SShawn Lin * @dword_1: UPIU header DW-1 4088f7de514SShawn Lin * @dword_2: UPIU header DW-2 4098f7de514SShawn Lin */ 4108f7de514SShawn Lin struct utp_upiu_header { 4118f7de514SShawn Lin __be32 dword_0; 4128f7de514SShawn Lin __be32 dword_1; 4138f7de514SShawn Lin __be32 dword_2; 4148f7de514SShawn Lin }; 4158f7de514SShawn Lin 4168f7de514SShawn Lin /** 4178f7de514SShawn Lin * struct utp_upiu_query - upiu request buffer structure for 4188f7de514SShawn Lin * query request. 4198f7de514SShawn Lin * @opcode: command to perform B-0 4208f7de514SShawn Lin * @idn: a value that indicates the particular type of data B-1 4218f7de514SShawn Lin * @index: Index to further identify data B-2 4228f7de514SShawn Lin * @selector: Index to further identify data B-3 4238f7de514SShawn Lin * @reserved_osf: spec reserved field B-4,5 4248f7de514SShawn Lin * @length: number of descriptor bytes to read/write B-6,7 4258f7de514SShawn Lin * @value: Attribute value to be written DW-5 4268f7de514SShawn Lin * @reserved: spec reserved DW-6,7 4278f7de514SShawn Lin */ 4288f7de514SShawn Lin struct utp_upiu_query { 4298f7de514SShawn Lin __u8 opcode; 4308f7de514SShawn Lin __u8 idn; 4318f7de514SShawn Lin __u8 index; 4328f7de514SShawn Lin __u8 selector; 4338f7de514SShawn Lin __be16 reserved_osf; 4348f7de514SShawn Lin __be16 length; 4358f7de514SShawn Lin __be32 value; 4368f7de514SShawn Lin __be32 reserved[2]; 4378f7de514SShawn Lin }; 4388f7de514SShawn Lin 4398f7de514SShawn Lin /** 4408f7de514SShawn Lin * struct utp_upiu_cmd - Command UPIU structure 4418f7de514SShawn Lin * @data_transfer_len: Data Transfer Length DW-3 4428f7de514SShawn Lin * @cdb: Command Descriptor Block CDB DW-4 to DW-7 4438f7de514SShawn Lin */ 4448f7de514SShawn Lin struct utp_upiu_cmd { 4458f7de514SShawn Lin __be32 exp_data_transfer_len; 4468f7de514SShawn Lin u8 cdb[UFS_CDB_SIZE]; 4478f7de514SShawn Lin }; 4488f7de514SShawn Lin 4498f7de514SShawn Lin /* 4508f7de514SShawn Lin * UTMRD structure. 4518f7de514SShawn Lin */ 4528f7de514SShawn Lin struct utp_task_req_desc { 4538f7de514SShawn Lin /* DW 0-3 */ 4548f7de514SShawn Lin struct request_desc_header header; 4558f7de514SShawn Lin 4568f7de514SShawn Lin /* DW 4-11 - Task request UPIU structure */ 4578f7de514SShawn Lin struct utp_upiu_header req_header; 4588f7de514SShawn Lin __be32 input_param1; 4598f7de514SShawn Lin __be32 input_param2; 4608f7de514SShawn Lin __be32 input_param3; 4618f7de514SShawn Lin __be32 __reserved1[2]; 4628f7de514SShawn Lin 4638f7de514SShawn Lin /* DW 12-19 - Task Management Response UPIU structure */ 4648f7de514SShawn Lin struct utp_upiu_header rsp_header; 4658f7de514SShawn Lin __be32 output_param1; 4668f7de514SShawn Lin __be32 output_param2; 4678f7de514SShawn Lin __be32 __reserved2[3]; 4688f7de514SShawn Lin }; 4698f7de514SShawn Lin 4708f7de514SShawn Lin /** 4718f7de514SShawn Lin * struct utp_upiu_req - general upiu request structure 4728f7de514SShawn Lin * @header:UPIU header structure DW-0 to DW-2 4738f7de514SShawn Lin * @sc: fields structure for scsi command DW-3 to DW-7 4748f7de514SShawn Lin * @qr: fields structure for query request DW-3 to DW-7 4758f7de514SShawn Lin */ 4768f7de514SShawn Lin struct utp_upiu_req { 4778f7de514SShawn Lin struct utp_upiu_header header; 4788f7de514SShawn Lin union { 4798f7de514SShawn Lin struct utp_upiu_cmd sc; 4808f7de514SShawn Lin struct utp_upiu_query qr; 4818f7de514SShawn Lin struct utp_upiu_query tr; 4828f7de514SShawn Lin /* use utp_upiu_query to host the 4 dwords of uic command */ 4838f7de514SShawn Lin struct utp_upiu_query uc; 4848f7de514SShawn Lin }; 4858f7de514SShawn Lin }; 4868f7de514SShawn Lin 4878f7de514SShawn Lin /** 4888f7de514SShawn Lin * struct utp_cmd_rsp - Response UPIU structure 4898f7de514SShawn Lin * @residual_transfer_count: Residual transfer count DW-3 4908f7de514SShawn Lin * @reserved: Reserved double words DW-4 to DW-7 4918f7de514SShawn Lin * @sense_data_len: Sense data length DW-8 U16 4928f7de514SShawn Lin * @sense_data: Sense data field DW-8 to DW-12 4938f7de514SShawn Lin */ 4948f7de514SShawn Lin struct utp_cmd_rsp { 4958f7de514SShawn Lin __be32 residual_transfer_count; 4968f7de514SShawn Lin __be32 reserved[4]; 4978f7de514SShawn Lin __be16 sense_data_len; 4988f7de514SShawn Lin u8 sense_data[RESPONSE_UPIU_SENSE_DATA_LENGTH]; 4998f7de514SShawn Lin }; 5008f7de514SShawn Lin 5018f7de514SShawn Lin /** 5028f7de514SShawn Lin * struct utp_upiu_rsp - general upiu response structure 5038f7de514SShawn Lin * @header: UPIU header structure DW-0 to DW-2 5048f7de514SShawn Lin * @sr: fields structure for scsi command DW-3 to DW-12 5058f7de514SShawn Lin * @qr: fields structure for query request DW-3 to DW-7 5068f7de514SShawn Lin */ 5078f7de514SShawn Lin struct utp_upiu_rsp { 5088f7de514SShawn Lin struct utp_upiu_header header; 5098f7de514SShawn Lin union { 5108f7de514SShawn Lin struct utp_cmd_rsp sr; 5118f7de514SShawn Lin struct utp_upiu_query qr; 5128f7de514SShawn Lin }; 5138f7de514SShawn Lin }; 5148f7de514SShawn Lin 5158f7de514SShawn Lin #define MAX_MODEL_LEN 16 5168f7de514SShawn Lin /** 5178f7de514SShawn Lin * ufs_dev_desc - ufs device details from the device descriptor 5188f7de514SShawn Lin * 5198f7de514SShawn Lin * @wmanufacturerid: card details 5208f7de514SShawn Lin * @model: card model 5218f7de514SShawn Lin */ 5228f7de514SShawn Lin struct ufs_dev_desc { 5238f7de514SShawn Lin u16 wmanufacturerid; 5248f7de514SShawn Lin char model[MAX_MODEL_LEN + 1]; 5258f7de514SShawn Lin }; 5268f7de514SShawn Lin 5278f7de514SShawn Lin /* Device descriptor parameters offsets in bytes*/ 5288f7de514SShawn Lin enum device_desc_param { 5298f7de514SShawn Lin DEVICE_DESC_PARAM_LEN = 0x0, 5308f7de514SShawn Lin DEVICE_DESC_PARAM_TYPE = 0x1, 5318f7de514SShawn Lin DEVICE_DESC_PARAM_DEVICE_TYPE = 0x2, 5328f7de514SShawn Lin DEVICE_DESC_PARAM_DEVICE_CLASS = 0x3, 5338f7de514SShawn Lin DEVICE_DESC_PARAM_DEVICE_SUB_CLASS = 0x4, 5348f7de514SShawn Lin DEVICE_DESC_PARAM_PRTCL = 0x5, 5358f7de514SShawn Lin DEVICE_DESC_PARAM_NUM_LU = 0x6, 5368f7de514SShawn Lin DEVICE_DESC_PARAM_NUM_WLU = 0x7, 5378f7de514SShawn Lin DEVICE_DESC_PARAM_BOOT_ENBL = 0x8, 5388f7de514SShawn Lin DEVICE_DESC_PARAM_DESC_ACCSS_ENBL = 0x9, 5398f7de514SShawn Lin DEVICE_DESC_PARAM_INIT_PWR_MODE = 0xA, 5408f7de514SShawn Lin DEVICE_DESC_PARAM_HIGH_PR_LUN = 0xB, 5418f7de514SShawn Lin DEVICE_DESC_PARAM_SEC_RMV_TYPE = 0xC, 5428f7de514SShawn Lin DEVICE_DESC_PARAM_SEC_LU = 0xD, 5438f7de514SShawn Lin DEVICE_DESC_PARAM_BKOP_TERM_LT = 0xE, 5448f7de514SShawn Lin DEVICE_DESC_PARAM_ACTVE_ICC_LVL = 0xF, 5458f7de514SShawn Lin DEVICE_DESC_PARAM_SPEC_VER = 0x10, 5468f7de514SShawn Lin DEVICE_DESC_PARAM_MANF_DATE = 0x12, 5478f7de514SShawn Lin DEVICE_DESC_PARAM_MANF_NAME = 0x14, 5488f7de514SShawn Lin DEVICE_DESC_PARAM_PRDCT_NAME = 0x15, 5498f7de514SShawn Lin DEVICE_DESC_PARAM_SN = 0x16, 5508f7de514SShawn Lin DEVICE_DESC_PARAM_OEM_ID = 0x17, 5518f7de514SShawn Lin DEVICE_DESC_PARAM_MANF_ID = 0x18, 5528f7de514SShawn Lin DEVICE_DESC_PARAM_UD_OFFSET = 0x1A, 5538f7de514SShawn Lin DEVICE_DESC_PARAM_UD_LEN = 0x1B, 5548f7de514SShawn Lin DEVICE_DESC_PARAM_RTT_CAP = 0x1C, 5558f7de514SShawn Lin DEVICE_DESC_PARAM_FRQ_RTC = 0x1D, 5568f7de514SShawn Lin DEVICE_DESC_PARAM_UFS_FEAT = 0x1F, 5578f7de514SShawn Lin DEVICE_DESC_PARAM_FFU_TMT = 0x20, 5588f7de514SShawn Lin DEVICE_DESC_PARAM_Q_DPTH = 0x21, 5598f7de514SShawn Lin DEVICE_DESC_PARAM_DEV_VER = 0x22, 5608f7de514SShawn Lin DEVICE_DESC_PARAM_NUM_SEC_WPA = 0x24, 5618f7de514SShawn Lin DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25, 5628f7de514SShawn Lin DEVICE_DESC_PARAM_PSA_TMT = 0x29, 5638f7de514SShawn Lin DEVICE_DESC_PARAM_PRDCT_REV = 0x2A, 5648f7de514SShawn Lin }; 5658f7de514SShawn Lin 5668f7de514SShawn Lin struct ufs_hba; 5678f7de514SShawn Lin 5688f7de514SShawn Lin enum { 5698f7de514SShawn Lin UFSHCD_MAX_CHANNEL = 0, 5708f7de514SShawn Lin UFSHCD_MAX_ID = 1, 5718f7de514SShawn Lin }; 5728f7de514SShawn Lin 5738f7de514SShawn Lin enum dev_cmd_type { 5748f7de514SShawn Lin DEV_CMD_TYPE_NOP = 0x0, 5758f7de514SShawn Lin DEV_CMD_TYPE_QUERY = 0x1, 5768f7de514SShawn Lin }; 5778f7de514SShawn Lin 5788f7de514SShawn Lin /** 5798f7de514SShawn Lin * struct uic_command - UIC command structure 5808f7de514SShawn Lin * @command: UIC command 5818f7de514SShawn Lin * @argument1: UIC command argument 1 5828f7de514SShawn Lin * @argument2: UIC command argument 2 5838f7de514SShawn Lin * @argument3: UIC command argument 3 5848f7de514SShawn Lin * @cmd_active: Indicate if UIC command is outstanding 5858f7de514SShawn Lin * @result: UIC command result 5868f7de514SShawn Lin * @done: UIC command completion 5878f7de514SShawn Lin */ 5888f7de514SShawn Lin struct uic_command { 5898f7de514SShawn Lin u32 command; 5908f7de514SShawn Lin u32 argument1; 5918f7de514SShawn Lin u32 argument2; 5928f7de514SShawn Lin u32 argument3; 5938f7de514SShawn Lin int cmd_active; 5948f7de514SShawn Lin int result; 5958f7de514SShawn Lin }; 5968f7de514SShawn Lin 5978f7de514SShawn Lin /* GenSelectorIndex calculation macros for M-PHY attributes */ 5988f7de514SShawn Lin #define UIC_ARG_MPHY_TX_GEN_SEL_INDEX(lane) (lane) 5998f7de514SShawn Lin #define UIC_ARG_MPHY_RX_GEN_SEL_INDEX(lane) (PA_MAXDATALANES + (lane)) 6008f7de514SShawn Lin 6018f7de514SShawn Lin #define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\ 6028f7de514SShawn Lin ((sel) & 0xFFFF)) 6038f7de514SShawn Lin #define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0) 6048f7de514SShawn Lin #define UIC_ARG_ATTR_TYPE(t) (((t) & 0xFF) << 16) 6058f7de514SShawn Lin #define UIC_GET_ATTR_ID(v) (((v) >> 16) & 0xFFFF) 6068f7de514SShawn Lin 6078f7de514SShawn Lin /* Link Status*/ 6088f7de514SShawn Lin enum link_status { 6098f7de514SShawn Lin UFSHCD_LINK_IS_DOWN = 1, 6108f7de514SShawn Lin UFSHCD_LINK_IS_UP = 2, 6118f7de514SShawn Lin }; 6128f7de514SShawn Lin 6138f7de514SShawn Lin #define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\ 6148f7de514SShawn Lin ((sel) & 0xFFFF)) 6158f7de514SShawn Lin #define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0) 6168f7de514SShawn Lin #define UIC_ARG_ATTR_TYPE(t) (((t) & 0xFF) << 16) 6178f7de514SShawn Lin #define UIC_GET_ATTR_ID(v) (((v) >> 16) & 0xFFFF) 6188f7de514SShawn Lin 6198f7de514SShawn Lin /* UIC Commands */ 6208f7de514SShawn Lin enum uic_cmd_dme { 6218f7de514SShawn Lin UIC_CMD_DME_GET = 0x01, 6228f7de514SShawn Lin UIC_CMD_DME_SET = 0x02, 6238f7de514SShawn Lin UIC_CMD_DME_PEER_GET = 0x03, 6248f7de514SShawn Lin UIC_CMD_DME_PEER_SET = 0x04, 6258f7de514SShawn Lin UIC_CMD_DME_POWERON = 0x10, 6268f7de514SShawn Lin UIC_CMD_DME_POWEROFF = 0x11, 6278f7de514SShawn Lin UIC_CMD_DME_ENABLE = 0x12, 6288f7de514SShawn Lin UIC_CMD_DME_RESET = 0x14, 6298f7de514SShawn Lin UIC_CMD_DME_END_PT_RST = 0x15, 6308f7de514SShawn Lin UIC_CMD_DME_LINK_STARTUP = 0x16, 6318f7de514SShawn Lin UIC_CMD_DME_HIBER_ENTER = 0x17, 6328f7de514SShawn Lin UIC_CMD_DME_HIBER_EXIT = 0x18, 6338f7de514SShawn Lin UIC_CMD_DME_TEST_MODE = 0x1A, 6348f7de514SShawn Lin }; 6358f7de514SShawn Lin 6368f7de514SShawn Lin /* UIC Config result code / Generic error code */ 6378f7de514SShawn Lin enum { 6388f7de514SShawn Lin UIC_CMD_RESULT_SUCCESS = 0x00, 6398f7de514SShawn Lin UIC_CMD_RESULT_INVALID_ATTR = 0x01, 6408f7de514SShawn Lin UIC_CMD_RESULT_FAILURE = 0x01, 6418f7de514SShawn Lin UIC_CMD_RESULT_INVALID_ATTR_VALUE = 0x02, 6428f7de514SShawn Lin UIC_CMD_RESULT_READ_ONLY_ATTR = 0x03, 6438f7de514SShawn Lin UIC_CMD_RESULT_WRITE_ONLY_ATTR = 0x04, 6448f7de514SShawn Lin UIC_CMD_RESULT_BAD_INDEX = 0x05, 6458f7de514SShawn Lin UIC_CMD_RESULT_LOCKED_ATTR = 0x06, 6468f7de514SShawn Lin UIC_CMD_RESULT_BAD_TEST_FEATURE_INDEX = 0x07, 6478f7de514SShawn Lin UIC_CMD_RESULT_PEER_COMM_FAILURE = 0x08, 6488f7de514SShawn Lin UIC_CMD_RESULT_BUSY = 0x09, 6498f7de514SShawn Lin UIC_CMD_RESULT_DME_FAILURE = 0x0A, 6508f7de514SShawn Lin }; 6518f7de514SShawn Lin 6528f7de514SShawn Lin #define MASK_UIC_COMMAND_RESULT 0xFF 6538f7de514SShawn Lin 6548f7de514SShawn Lin /* Host <-> Device UniPro Link state */ 6558f7de514SShawn Lin enum uic_link_state { 6568f7de514SShawn Lin UIC_LINK_OFF_STATE = 0, /* Link powered down or disabled */ 6578f7de514SShawn Lin UIC_LINK_ACTIVE_STATE = 1, /* Link is in Fast/Slow/Sleep state */ 6588f7de514SShawn Lin UIC_LINK_HIBERN8_STATE = 2, /* Link is in Hibernate state */ 6598f7de514SShawn Lin }; 6608f7de514SShawn Lin 6618f7de514SShawn Lin /* UIC command interfaces for DME primitives */ 6628f7de514SShawn Lin #define DME_LOCAL 0 6638f7de514SShawn Lin #define DME_PEER 1 6648f7de514SShawn Lin #define ATTR_SET_NOR 0 /* NORMAL */ 6658f7de514SShawn Lin #define ATTR_SET_ST 1 /* STATIC */ 6668f7de514SShawn Lin 6678f7de514SShawn Lin int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, 6688f7de514SShawn Lin u8 attr_set, u32 mib_val, u8 peer); 6698f7de514SShawn Lin int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, 6708f7de514SShawn Lin u32 *mib_val, u8 peer); 6718f7de514SShawn Lin 6728f7de514SShawn Lin static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel, 6738f7de514SShawn Lin u32 mib_val) 6748f7de514SShawn Lin { 6758f7de514SShawn Lin return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR, 6768f7de514SShawn Lin mib_val, DME_LOCAL); 6778f7de514SShawn Lin } 6788f7de514SShawn Lin 6798f7de514SShawn Lin static inline int ufshcd_dme_get(struct ufs_hba *hba, 6808f7de514SShawn Lin u32 attr_sel, u32 *mib_val) 6818f7de514SShawn Lin { 6828f7de514SShawn Lin return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL); 6838f7de514SShawn Lin } 6848f7de514SShawn Lin 6858f7de514SShawn Lin static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, 6868f7de514SShawn Lin u32 attr_sel, u32 *mib_val) 6878f7de514SShawn Lin { 6888f7de514SShawn Lin return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER); 6898f7de514SShawn Lin } 6908f7de514SShawn Lin 6918f7de514SShawn Lin static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel, 6928f7de514SShawn Lin u32 mib_val) 6938f7de514SShawn Lin { 6948f7de514SShawn Lin return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR, 6958f7de514SShawn Lin mib_val, DME_PEER); 6968f7de514SShawn Lin } 6978f7de514SShawn Lin 6988f7de514SShawn Lin /** 6998f7de514SShawn Lin * struct ufs_query_req - parameters for building a query request 7008f7de514SShawn Lin * @query_func: UPIU header query function 7018f7de514SShawn Lin * @upiu_req: the query request data 7028f7de514SShawn Lin */ 7038f7de514SShawn Lin struct ufs_query_req { 7048f7de514SShawn Lin u8 query_func; 7058f7de514SShawn Lin struct utp_upiu_query upiu_req; 7068f7de514SShawn Lin }; 7078f7de514SShawn Lin 7088f7de514SShawn Lin /** 7098f7de514SShawn Lin * struct ufs_query_resp - UPIU QUERY 7108f7de514SShawn Lin * @response: device response code 7118f7de514SShawn Lin * @upiu_res: query response data 7128f7de514SShawn Lin */ 7138f7de514SShawn Lin struct ufs_query_res { 7148f7de514SShawn Lin u8 response; 7158f7de514SShawn Lin struct utp_upiu_query upiu_res; 7168f7de514SShawn Lin }; 7178f7de514SShawn Lin 7188f7de514SShawn Lin /** 7198f7de514SShawn Lin * struct ufs_query - holds relevant data structures for query request 7208f7de514SShawn Lin * @request: request upiu and function 7218f7de514SShawn Lin * @descriptor: buffer for sending/receiving descriptor 7228f7de514SShawn Lin * @response: response upiu and response 7238f7de514SShawn Lin */ 7248f7de514SShawn Lin struct ufs_query { 7258f7de514SShawn Lin struct ufs_query_req request; 7268f7de514SShawn Lin u8 *descriptor; 7278f7de514SShawn Lin struct ufs_query_res response; 7288f7de514SShawn Lin }; 7298f7de514SShawn Lin 7308f7de514SShawn Lin /** 7318f7de514SShawn Lin * struct ufs_dev_cmd - all assosiated fields with device management commands 7328f7de514SShawn Lin * @type: device management command type - Query, NOP OUT 7338f7de514SShawn Lin * @tag_wq: wait queue until free command slot is available 7348f7de514SShawn Lin */ 7358f7de514SShawn Lin struct ufs_dev_cmd { 7368f7de514SShawn Lin enum dev_cmd_type type; 7378f7de514SShawn Lin struct ufs_query query; 7388f7de514SShawn Lin }; 7398f7de514SShawn Lin 7408f7de514SShawn Lin struct ufs_hba_ops { 7418f7de514SShawn Lin int (*init)(struct ufs_hba *hba); 7428f7de514SShawn Lin int (*hce_enable_notify)(struct ufs_hba *hba, 7438f7de514SShawn Lin enum ufs_notify_change_status); 7448f7de514SShawn Lin int (*link_startup_notify)(struct ufs_hba *hba, 7458f7de514SShawn Lin enum ufs_notify_change_status); 7468f7de514SShawn Lin int (*phy_initialization)(struct ufs_hba *hba); 7478f7de514SShawn Lin }; 7488f7de514SShawn Lin 7498f7de514SShawn Lin struct ufs_hba { 7508f7de514SShawn Lin struct udevice *dev; 7518f7de514SShawn Lin void __iomem *mmio_base; 7528f7de514SShawn Lin struct ufs_hba_ops *ops; 7538f7de514SShawn Lin struct ufs_desc_size desc_size; 7548f7de514SShawn Lin u32 capabilities; 7558f7de514SShawn Lin u32 version; 7568f7de514SShawn Lin u32 intr_mask; 7578f7de514SShawn Lin u32 quirks; 7588f7de514SShawn Lin /* 7598f7de514SShawn Lin * If UFS host controller is having issue in processing LCC (Line 7608f7de514SShawn Lin * Control Command) coming from device then enable this quirk. 7618f7de514SShawn Lin * When this quirk is enabled, host controller driver should disable 7628f7de514SShawn Lin * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE 7638f7de514SShawn Lin * attribute of device to 0). 7648f7de514SShawn Lin */ 765ec622ba8SYifeng Zhao #define UFSHCD_QUIRK_BROKEN_LCC BIT(0) 766ec622ba8SYifeng Zhao 767ec622ba8SYifeng Zhao /* 768ec622ba8SYifeng Zhao * This quirk needs to be enabled if the host controller has 769ec622ba8SYifeng Zhao * 64-bit addressing supported capability but it doesn't work. 770ec622ba8SYifeng Zhao */ 771ec622ba8SYifeng Zhao #define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS BIT(1) 772ec622ba8SYifeng Zhao 773ec622ba8SYifeng Zhao /* 774ec622ba8SYifeng Zhao * This quirk needs to be enabled if the host controller has 775ec622ba8SYifeng Zhao * auto-hibernate capability but it's FASTAUTO only. 776ec622ba8SYifeng Zhao */ 777ec622ba8SYifeng Zhao #define UFSHCD_QUIRK_HIBERN_FASTAUTO BIT(2) 7788f7de514SShawn Lin 7798f7de514SShawn Lin /* Virtual memory reference */ 7808f7de514SShawn Lin struct utp_transfer_cmd_desc *ucdl; 7818f7de514SShawn Lin struct utp_transfer_req_desc *utrdl; 7828f7de514SShawn Lin /* TODO: Add Task Manegement Support */ 7838f7de514SShawn Lin struct utp_task_req_desc *utmrdl; 7848f7de514SShawn Lin 7858f7de514SShawn Lin struct utp_upiu_req *ucd_req_ptr; 7868f7de514SShawn Lin struct utp_upiu_rsp *ucd_rsp_ptr; 7878f7de514SShawn Lin struct ufshcd_sg_entry *ucd_prdt_ptr; 7888f7de514SShawn Lin 7898f7de514SShawn Lin /* Power Mode information */ 7908f7de514SShawn Lin enum ufs_dev_pwr_mode curr_dev_pwr_mode; 7918f7de514SShawn Lin struct ufs_pa_layer_attr pwr_info; 7928f7de514SShawn Lin struct ufs_pwr_mode_info max_pwr_info; 7938f7de514SShawn Lin 7948f7de514SShawn Lin struct ufs_dev_cmd dev_cmd; 795ec622ba8SYifeng Zhao struct ufs_device_descriptor *dev_desc; 7962c3d2faaSYifeng Zhao #if defined(CONFIG_SUPPORT_USBPLUG) 7972c3d2faaSYifeng Zhao struct ufs_configuration_descriptor *rc_desc; 7982c3d2faaSYifeng Zhao struct ufs_configuration_descriptor *wc_desc; 7992c3d2faaSYifeng Zhao struct ufs_geometry_descriptor *geo_desc; 8002c3d2faaSYifeng Zhao #endif 8018f7de514SShawn Lin }; 8028f7de514SShawn Lin 8038f7de514SShawn Lin static inline int ufshcd_ops_init(struct ufs_hba *hba) 8048f7de514SShawn Lin { 8058f7de514SShawn Lin if (hba->ops && hba->ops->init) 8068f7de514SShawn Lin return hba->ops->init(hba); 8078f7de514SShawn Lin 8088f7de514SShawn Lin return 0; 8098f7de514SShawn Lin } 8108f7de514SShawn Lin 8118f7de514SShawn Lin static inline int ufshcd_ops_hce_enable_notify(struct ufs_hba *hba, 8128f7de514SShawn Lin bool status) 8138f7de514SShawn Lin { 8148f7de514SShawn Lin if (hba->ops && hba->ops->hce_enable_notify) 8158f7de514SShawn Lin return hba->ops->hce_enable_notify(hba, status); 8168f7de514SShawn Lin 8178f7de514SShawn Lin return 0; 8188f7de514SShawn Lin } 8198f7de514SShawn Lin 8208f7de514SShawn Lin static inline int ufshcd_ops_link_startup_notify(struct ufs_hba *hba, 8218f7de514SShawn Lin bool status) 8228f7de514SShawn Lin { 8238f7de514SShawn Lin if (hba->ops && hba->ops->link_startup_notify) 8248f7de514SShawn Lin return hba->ops->link_startup_notify(hba, status); 8258f7de514SShawn Lin 8268f7de514SShawn Lin return 0; 8278f7de514SShawn Lin } 8288f7de514SShawn Lin 8298f7de514SShawn Lin /* Controller UFSHCI version */ 8308f7de514SShawn Lin enum { 8318f7de514SShawn Lin UFSHCI_VERSION_10 = 0x00010000, /* 1.0 */ 8328f7de514SShawn Lin UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */ 8338f7de514SShawn Lin UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */ 8348f7de514SShawn Lin UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */ 835ec622ba8SYifeng Zhao UFSHCI_VERSION_30 = 0x00000300, /* 3.0 */ 836ec622ba8SYifeng Zhao UFSHCI_VERSION_31 = 0x00000310, /* 3.1 */ 8378f7de514SShawn Lin }; 8388f7de514SShawn Lin 8398f7de514SShawn Lin /* Interrupt disable masks */ 8408f7de514SShawn Lin enum { 8418f7de514SShawn Lin /* Interrupt disable mask for UFSHCI v1.0 */ 8428f7de514SShawn Lin INTERRUPT_MASK_ALL_VER_10 = 0x30FFF, 8438f7de514SShawn Lin INTERRUPT_MASK_RW_VER_10 = 0x30000, 8448f7de514SShawn Lin 8458f7de514SShawn Lin /* Interrupt disable mask for UFSHCI v1.1 */ 8468f7de514SShawn Lin INTERRUPT_MASK_ALL_VER_11 = 0x31FFF, 8478f7de514SShawn Lin 8488f7de514SShawn Lin /* Interrupt disable mask for UFSHCI v2.1 */ 8498f7de514SShawn Lin INTERRUPT_MASK_ALL_VER_21 = 0x71FFF, 8508f7de514SShawn Lin }; 8518f7de514SShawn Lin 8528f7de514SShawn Lin /* UFSHCI Registers */ 8538f7de514SShawn Lin enum { 8548f7de514SShawn Lin REG_CONTROLLER_CAPABILITIES = 0x00, 8558f7de514SShawn Lin REG_UFS_VERSION = 0x08, 8568f7de514SShawn Lin REG_CONTROLLER_DEV_ID = 0x10, 8578f7de514SShawn Lin REG_CONTROLLER_PROD_ID = 0x14, 8588f7de514SShawn Lin REG_AUTO_HIBERNATE_IDLE_TIMER = 0x18, 8598f7de514SShawn Lin REG_INTERRUPT_STATUS = 0x20, 8608f7de514SShawn Lin REG_INTERRUPT_ENABLE = 0x24, 8618f7de514SShawn Lin REG_CONTROLLER_STATUS = 0x30, 8628f7de514SShawn Lin REG_CONTROLLER_ENABLE = 0x34, 8638f7de514SShawn Lin REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER = 0x38, 8648f7de514SShawn Lin REG_UIC_ERROR_CODE_DATA_LINK_LAYER = 0x3C, 8658f7de514SShawn Lin REG_UIC_ERROR_CODE_NETWORK_LAYER = 0x40, 8668f7de514SShawn Lin REG_UIC_ERROR_CODE_TRANSPORT_LAYER = 0x44, 8678f7de514SShawn Lin REG_UIC_ERROR_CODE_DME = 0x48, 8688f7de514SShawn Lin REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL = 0x4C, 8698f7de514SShawn Lin REG_UTP_TRANSFER_REQ_LIST_BASE_L = 0x50, 8708f7de514SShawn Lin REG_UTP_TRANSFER_REQ_LIST_BASE_H = 0x54, 8718f7de514SShawn Lin REG_UTP_TRANSFER_REQ_DOOR_BELL = 0x58, 8728f7de514SShawn Lin REG_UTP_TRANSFER_REQ_LIST_CLEAR = 0x5C, 8738f7de514SShawn Lin REG_UTP_TRANSFER_REQ_LIST_RUN_STOP = 0x60, 8748f7de514SShawn Lin REG_UTP_TASK_REQ_LIST_BASE_L = 0x70, 8758f7de514SShawn Lin REG_UTP_TASK_REQ_LIST_BASE_H = 0x74, 8768f7de514SShawn Lin REG_UTP_TASK_REQ_DOOR_BELL = 0x78, 8778f7de514SShawn Lin REG_UTP_TASK_REQ_LIST_CLEAR = 0x7C, 8788f7de514SShawn Lin REG_UTP_TASK_REQ_LIST_RUN_STOP = 0x80, 8798f7de514SShawn Lin REG_UIC_COMMAND = 0x90, 8808f7de514SShawn Lin REG_UIC_COMMAND_ARG_1 = 0x94, 8818f7de514SShawn Lin REG_UIC_COMMAND_ARG_2 = 0x98, 8828f7de514SShawn Lin REG_UIC_COMMAND_ARG_3 = 0x9C, 8838f7de514SShawn Lin 8848f7de514SShawn Lin UFSHCI_REG_SPACE_SIZE = 0xA0, 8858f7de514SShawn Lin 8868f7de514SShawn Lin REG_UFS_CCAP = 0x100, 8878f7de514SShawn Lin REG_UFS_CRYPTOCAP = 0x104, 8888f7de514SShawn Lin 8898f7de514SShawn Lin UFSHCI_CRYPTO_REG_SPACE_SIZE = 0x400, 8908f7de514SShawn Lin }; 8918f7de514SShawn Lin 8928f7de514SShawn Lin /* Controller capability masks */ 8938f7de514SShawn Lin enum { 8948f7de514SShawn Lin MASK_TRANSFER_REQUESTS_SLOTS = 0x0000001F, 8958f7de514SShawn Lin MASK_TASK_MANAGEMENT_REQUEST_SLOTS = 0x00070000, 8968f7de514SShawn Lin MASK_AUTO_HIBERN8_SUPPORT = 0x00800000, 8978f7de514SShawn Lin MASK_64_ADDRESSING_SUPPORT = 0x01000000, 8988f7de514SShawn Lin MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000, 8998f7de514SShawn Lin MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000, 9008f7de514SShawn Lin }; 9018f7de514SShawn Lin 9028f7de514SShawn Lin /* Interrupt Status 20h */ 9038f7de514SShawn Lin #define UTP_TRANSFER_REQ_COMPL 0x1 9048f7de514SShawn Lin #define UIC_DME_END_PT_RESET 0x2 9058f7de514SShawn Lin #define UIC_ERROR 0x4 9068f7de514SShawn Lin #define UIC_TEST_MODE 0x8 9078f7de514SShawn Lin #define UIC_POWER_MODE 0x10 9088f7de514SShawn Lin #define UIC_HIBERNATE_EXIT 0x20 9098f7de514SShawn Lin #define UIC_HIBERNATE_ENTER 0x40 9108f7de514SShawn Lin #define UIC_LINK_LOST 0x80 9118f7de514SShawn Lin #define UIC_LINK_STARTUP 0x100 9128f7de514SShawn Lin #define UTP_TASK_REQ_COMPL 0x200 9138f7de514SShawn Lin #define UIC_COMMAND_COMPL 0x400 9148f7de514SShawn Lin #define DEVICE_FATAL_ERROR 0x800 9158f7de514SShawn Lin #define CONTROLLER_FATAL_ERROR 0x10000 9168f7de514SShawn Lin #define SYSTEM_BUS_FATAL_ERROR 0x20000 9178f7de514SShawn Lin 9188f7de514SShawn Lin #define UFSHCD_UIC_PWR_MASK (UIC_HIBERNATE_ENTER |\ 9198f7de514SShawn Lin UIC_HIBERNATE_EXIT |\ 9208f7de514SShawn Lin UIC_POWER_MODE) 9218f7de514SShawn Lin 9228f7de514SShawn Lin #define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL | UIC_POWER_MODE) 9238f7de514SShawn Lin 9248f7de514SShawn Lin #define UFSHCD_ERROR_MASK (UIC_ERROR |\ 9258f7de514SShawn Lin DEVICE_FATAL_ERROR |\ 9268f7de514SShawn Lin CONTROLLER_FATAL_ERROR |\ 9278f7de514SShawn Lin SYSTEM_BUS_FATAL_ERROR) 9288f7de514SShawn Lin 9298f7de514SShawn Lin #define INT_FATAL_ERRORS (DEVICE_FATAL_ERROR |\ 9308f7de514SShawn Lin CONTROLLER_FATAL_ERROR |\ 9318f7de514SShawn Lin SYSTEM_BUS_FATAL_ERROR) 9328f7de514SShawn Lin 9338f7de514SShawn Lin /* Host Controller Enable 0x34h */ 9348f7de514SShawn Lin #define CONTROLLER_ENABLE 0x1 9358f7de514SShawn Lin #define CONTROLLER_DISABLE 0x0 9368f7de514SShawn Lin /* HCS - Host Controller Status 30h */ 9378f7de514SShawn Lin #define DEVICE_PRESENT 0x1 9388f7de514SShawn Lin #define UTP_TRANSFER_REQ_LIST_READY 0x2 9398f7de514SShawn Lin #define UTP_TASK_REQ_LIST_READY 0x4 9408f7de514SShawn Lin #define UIC_COMMAND_READY 0x8 9418f7de514SShawn Lin #define HOST_ERROR_INDICATOR 0x10 9428f7de514SShawn Lin #define DEVICE_ERROR_INDICATOR 0x20 9438f7de514SShawn Lin #define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) 9448f7de514SShawn Lin 9458f7de514SShawn Lin #define UFSHCD_STATUS_READY (UTP_TRANSFER_REQ_LIST_READY |\ 9468f7de514SShawn Lin UTP_TASK_REQ_LIST_READY |\ 9478f7de514SShawn Lin UIC_COMMAND_READY) 9488f7de514SShawn Lin 9498f7de514SShawn Lin enum { 9508f7de514SShawn Lin PWR_OK = 0x0, 9518f7de514SShawn Lin PWR_LOCAL = 0x01, 9528f7de514SShawn Lin PWR_REMOTE = 0x02, 9538f7de514SShawn Lin PWR_BUSY = 0x03, 9548f7de514SShawn Lin PWR_ERROR_CAP = 0x04, 9558f7de514SShawn Lin PWR_FATAL_ERROR = 0x05, 9568f7de514SShawn Lin }; 9578f7de514SShawn Lin 9588f7de514SShawn Lin /* UICCMD - UIC Command */ 9598f7de514SShawn Lin #define COMMAND_OPCODE_MASK 0xFF 9608f7de514SShawn Lin #define GEN_SELECTOR_INDEX_MASK 0xFFFF 9618f7de514SShawn Lin 9628f7de514SShawn Lin #define MIB_ATTRIBUTE_MASK UFS_MASK(0xFFFF, 16) 9638f7de514SShawn Lin #define RESET_LEVEL 0xFF 9648f7de514SShawn Lin 9658f7de514SShawn Lin #define ATTR_SET_TYPE_MASK UFS_MASK(0xFF, 16) 9668f7de514SShawn Lin #define CFG_RESULT_CODE_MASK 0xFF 9678f7de514SShawn Lin #define GENERIC_ERROR_CODE_MASK 0xFF 9688f7de514SShawn Lin 9698f7de514SShawn Lin #define ufshcd_writel(hba, val, reg) \ 9708f7de514SShawn Lin writel((val), (hba)->mmio_base + (reg)) 9718f7de514SShawn Lin #define ufshcd_readl(hba, reg) \ 9728f7de514SShawn Lin readl((hba)->mmio_base + (reg)) 9738f7de514SShawn Lin 9748f7de514SShawn Lin /* UTRLRSR - UTP Transfer Request Run-Stop Register 60h */ 9758f7de514SShawn Lin #define UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT 0x1 9768f7de514SShawn Lin 9778f7de514SShawn Lin /* UTMRLRSR - UTP Task Management Request Run-Stop Register 80h */ 9788f7de514SShawn Lin #define UTP_TASK_REQ_LIST_RUN_STOP_BIT 0x1 9798f7de514SShawn Lin 9808f7de514SShawn Lin int ufshcd_probe(struct udevice *dev, struct ufs_hba_ops *hba_ops); 981ec622ba8SYifeng Zhao int ufshcd_dme_reset(struct ufs_hba *hba); 982ec622ba8SYifeng Zhao int ufshcd_dme_enable(struct ufs_hba *hba); 9832c3d2faaSYifeng Zhao int ufs_create_partition_inventory(struct ufs_hba *hba); 9842c3d2faaSYifeng Zhao int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, int *desc_len); 9852c3d2faaSYifeng Zhao int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, 9862c3d2faaSYifeng Zhao int desc_index, u8 param_offset, u8 *param_read_buf, 9872c3d2faaSYifeng Zhao u8 param_size); 9882c3d2faaSYifeng Zhao int ufshcd_query_descriptor_retry(struct ufs_hba *hba, enum query_opcode opcode, 9892c3d2faaSYifeng Zhao enum desc_idn idn, u8 index, u8 selector, 9902c3d2faaSYifeng Zhao u8 *desc_buf, int *buf_len); 9918f7de514SShawn Lin #endif 992