1eb5073f4SHaojian Zhuang /* 2eb5073f4SHaojian Zhuang * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3eb5073f4SHaojian Zhuang * 4eb5073f4SHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 5eb5073f4SHaojian Zhuang */ 6eb5073f4SHaojian Zhuang 7c3cf06f1SAntonio Nino Diaz #ifndef UFS_H 8c3cf06f1SAntonio Nino Diaz #define UFS_H 9eb5073f4SHaojian Zhuang 1009d40e0eSAntonio Nino Diaz #include <lib/utils_def.h> 115ac25de6Sfengbaopeng 12eb5073f4SHaojian Zhuang /* register map of UFSHCI */ 13eb5073f4SHaojian Zhuang /* Controller Capabilities */ 14eb5073f4SHaojian Zhuang #define CAP 0x00 15eb5073f4SHaojian Zhuang #define CAP_NUTRS_MASK 0x1F 16eb5073f4SHaojian Zhuang 17eb5073f4SHaojian Zhuang /* UFS Version */ 18eb5073f4SHaojian Zhuang #define VER 0x08 19eb5073f4SHaojian Zhuang /* Host Controller Identification - Product ID */ 20eb5073f4SHaojian Zhuang #define HCDDID 0x10 21eb5073f4SHaojian Zhuang /* Host Controller Identification Descriptor - Manufacturer ID */ 22eb5073f4SHaojian Zhuang #define HCPMID 0x14 23eb5073f4SHaojian Zhuang /* Auto-Hibernate Idle Timer */ 24eb5073f4SHaojian Zhuang #define AHIT 0x18 25eb5073f4SHaojian Zhuang /* Interrupt Status */ 26eb5073f4SHaojian Zhuang #define IS 0x20 27eb5073f4SHaojian Zhuang /* Interrupt Enable */ 28eb5073f4SHaojian Zhuang #define IE 0x24 29eb5073f4SHaojian Zhuang /* System Bus Fatal Error Status */ 30eb5073f4SHaojian Zhuang #define UFS_INT_SBFES (1 << 17) 31eb5073f4SHaojian Zhuang /* Host Controller Fatal Error Status */ 32eb5073f4SHaojian Zhuang #define UFS_INT_HCFES (1 << 16) 33eb5073f4SHaojian Zhuang /* UTP Error Status */ 34eb5073f4SHaojian Zhuang #define UFS_INT_UTPES (1 << 12) 35eb5073f4SHaojian Zhuang /* Device Fatal Error Status */ 36eb5073f4SHaojian Zhuang #define UFS_INT_DFES (1 << 11) 37eb5073f4SHaojian Zhuang /* UIC Command Completion Status */ 38eb5073f4SHaojian Zhuang #define UFS_INT_UCCS (1 << 10) 39eb5073f4SHaojian Zhuang /* UTP Task Management Request Completion Status */ 40eb5073f4SHaojian Zhuang #define UFS_INT_UTMRCS (1 << 9) 41eb5073f4SHaojian Zhuang /* UIC Link Startup Status */ 42eb5073f4SHaojian Zhuang #define UFS_INT_ULSS (1 << 8) 43eb5073f4SHaojian Zhuang /* UIC Link Lost Status */ 44eb5073f4SHaojian Zhuang #define UFS_INT_ULLS (1 << 7) 45eb5073f4SHaojian Zhuang /* UIC Hibernate Enter Status */ 46eb5073f4SHaojian Zhuang #define UFS_INT_UHES (1 << 6) 47eb5073f4SHaojian Zhuang /* UIC Hibernate Exit Status */ 48eb5073f4SHaojian Zhuang #define UFS_INT_UHXS (1 << 5) 49eb5073f4SHaojian Zhuang /* UIC Power Mode Status */ 50eb5073f4SHaojian Zhuang #define UFS_INT_UPMS (1 << 4) 51eb5073f4SHaojian Zhuang /* UIC Test Mode Status */ 52eb5073f4SHaojian Zhuang #define UFS_INT_UTMS (1 << 3) 53eb5073f4SHaojian Zhuang /* UIC Error */ 54eb5073f4SHaojian Zhuang #define UFS_INT_UE (1 << 2) 55eb5073f4SHaojian Zhuang /* UIC DME_ENDPOINTRESET Indication */ 56eb5073f4SHaojian Zhuang #define UFS_INT_UDEPRI (1 << 1) 57eb5073f4SHaojian Zhuang /* UTP Transfer Request Completion Status */ 58eb5073f4SHaojian Zhuang #define UFS_INT_UTRCS (1 << 0) 59eb5073f4SHaojian Zhuang 60eb5073f4SHaojian Zhuang /* Host Controller Status */ 61eb5073f4SHaojian Zhuang #define HCS 0x30 62eb5073f4SHaojian Zhuang #define HCS_UPMCRS_MASK (7 << 8) 63eb5073f4SHaojian Zhuang #define HCS_PWR_LOCAL (1 << 8) 64eb5073f4SHaojian Zhuang #define HCS_UCRDY (1 << 3) 65eb5073f4SHaojian Zhuang #define HCS_UTMRLRDY (1 << 2) 66eb5073f4SHaojian Zhuang #define HCS_UTRLRDY (1 << 1) 67eb5073f4SHaojian Zhuang #define HCS_DP (1 << 0) 68eb5073f4SHaojian Zhuang 69eb5073f4SHaojian Zhuang /* Host Controller Enable */ 70eb5073f4SHaojian Zhuang #define HCE 0x34 71eb5073f4SHaojian Zhuang #define HCE_ENABLE 1 72b3f03b20Sanans #define HCE_DISABLE 0 73eb5073f4SHaojian Zhuang 74eb5073f4SHaojian Zhuang /* Host UIC Error Code PHY Adapter Layer */ 75eb5073f4SHaojian Zhuang #define UECPA 0x38 76eb5073f4SHaojian Zhuang /* Host UIC Error Code Data Link Layer */ 77eb5073f4SHaojian Zhuang #define UECDL 0x3C 78eb5073f4SHaojian Zhuang /* Host UIC Error Code Network Layer */ 79eb5073f4SHaojian Zhuang #define UECN 0x40 80eb5073f4SHaojian Zhuang /* Host UIC Error Code Transport Layer */ 81eb5073f4SHaojian Zhuang #define UECT 0x44 82eb5073f4SHaojian Zhuang /* Host UIC Error Code */ 83eb5073f4SHaojian Zhuang #define UECDME 0x48 84eb5073f4SHaojian Zhuang /* UTP Transfer Request Interrupt Aggregation Control Register */ 85eb5073f4SHaojian Zhuang #define UTRIACR 0x4C 863e43121eSJustin Chadwell #define UTRIACR_IAEN (1U << 31) 87eb5073f4SHaojian Zhuang #define UTRIACR_IAPWEN (1 << 24) 88eb5073f4SHaojian Zhuang #define UTRIACR_IASB (1 << 20) 89eb5073f4SHaojian Zhuang #define UTRIACR_CTR (1 << 16) 90eb5073f4SHaojian Zhuang #define UTRIACR_IACTH(x) (((x) & 0x1F) << 8) 91eb5073f4SHaojian Zhuang #define UTRIACR_IATOVAL(x) ((x) & 0xFF) 92eb5073f4SHaojian Zhuang 93eb5073f4SHaojian Zhuang /* UTP Transfer Request List Base Address */ 94eb5073f4SHaojian Zhuang #define UTRLBA 0x50 95eb5073f4SHaojian Zhuang /* UTP Transfer Request List Base Address Upper 32-bits */ 96eb5073f4SHaojian Zhuang #define UTRLBAU 0x54 97eb5073f4SHaojian Zhuang /* UTP Transfer Request List Door Bell Register */ 98eb5073f4SHaojian Zhuang #define UTRLDBR 0x58 99eb5073f4SHaojian Zhuang /* UTP Transfer Request List Clear Register */ 100eb5073f4SHaojian Zhuang #define UTRLCLR 0x5C 101eb5073f4SHaojian Zhuang /* UTP Transfer Request List Run Stop Register */ 102eb5073f4SHaojian Zhuang #define UTRLRSR 0x60 103eb5073f4SHaojian Zhuang #define UTMRLBA 0x70 104eb5073f4SHaojian Zhuang #define UTMRLBAU 0x74 105eb5073f4SHaojian Zhuang #define UTMRLDBR 0x78 106eb5073f4SHaojian Zhuang #define UTMRLCLR 0x7C 107eb5073f4SHaojian Zhuang #define UTMRLRSR 0x80 108eb5073f4SHaojian Zhuang /* UIC Command */ 109eb5073f4SHaojian Zhuang #define UICCMD 0x90 110eb5073f4SHaojian Zhuang /* UIC Command Argument 1 */ 111eb5073f4SHaojian Zhuang #define UCMDARG1 0x94 112eb5073f4SHaojian Zhuang /* UIC Command Argument 2 */ 113eb5073f4SHaojian Zhuang #define UCMDARG2 0x98 114eb5073f4SHaojian Zhuang /* UIC Command Argument 3 */ 115eb5073f4SHaojian Zhuang #define UCMDARG3 0x9C 116eb5073f4SHaojian Zhuang 117eb5073f4SHaojian Zhuang #define UFS_BLOCK_SHIFT 12 /* 4KB */ 118eb5073f4SHaojian Zhuang #define UFS_BLOCK_SIZE (1 << UFS_BLOCK_SHIFT) 119eb5073f4SHaojian Zhuang #define UFS_BLOCK_MASK (UFS_BLOCK_SIZE - 1) 120eb5073f4SHaojian Zhuang #define UFS_MAX_LUNS 8 121eb5073f4SHaojian Zhuang 122eb5073f4SHaojian Zhuang /* UTP Transfer Request Descriptor */ 123eb5073f4SHaojian Zhuang /* Command Type */ 124eb5073f4SHaojian Zhuang #define CT_UFS_STORAGE 1 125eb5073f4SHaojian Zhuang #define CT_SCSI 0 126eb5073f4SHaojian Zhuang 127eb5073f4SHaojian Zhuang /* Data Direction */ 128eb5073f4SHaojian Zhuang #define DD_OUT 2 /* Device --> Host */ 129eb5073f4SHaojian Zhuang #define DD_IN 1 /* Host --> Device */ 130eb5073f4SHaojian Zhuang #define DD_NO_DATA_TRANSFER 0 131eb5073f4SHaojian Zhuang 132eb5073f4SHaojian Zhuang #define UTP_TRD_SIZE 32 133eb5073f4SHaojian Zhuang 134eb5073f4SHaojian Zhuang /* Transaction Type */ 135eb5073f4SHaojian Zhuang #define TRANS_TYPE_HD (1 << 7) /* E2ECRC */ 136eb5073f4SHaojian Zhuang #define TRANS_TYPE_DD (1 << 6) 137eb5073f4SHaojian Zhuang #define TRANS_TYPE_CODE_MASK 0x3F 138eb5073f4SHaojian Zhuang #define QUERY_RESPONSE_UPIU (0x36 << 0) 139eb5073f4SHaojian Zhuang #define READY_TO_TRANSACTION_UPIU (0x31 << 0) 140eb5073f4SHaojian Zhuang #define DATA_IN_UPIU (0x22 << 0) 141eb5073f4SHaojian Zhuang #define RESPONSE_UPIU (0x21 << 0) 142eb5073f4SHaojian Zhuang #define NOP_IN_UPIU (0x20 << 0) 143eb5073f4SHaojian Zhuang #define QUERY_REQUEST_UPIU (0x16 << 0) 144eb5073f4SHaojian Zhuang #define DATA_OUT_UPIU (0x02 << 0) 145eb5073f4SHaojian Zhuang #define CMD_UPIU (0x01 << 0) 146eb5073f4SHaojian Zhuang #define NOP_OUT_UPIU (0x00 << 0) 147eb5073f4SHaojian Zhuang 148eb5073f4SHaojian Zhuang #define OCS_SUCCESS 0x0 149eb5073f4SHaojian Zhuang #define OCS_INVALID_FUNC_ATTRIBUTE 0x1 150eb5073f4SHaojian Zhuang #define OCS_MISMATCH_REQUEST_SIZE 0x2 151eb5073f4SHaojian Zhuang #define OCS_MISMATCH_RESPONSE_SIZE 0x3 152eb5073f4SHaojian Zhuang #define OCS_PEER_COMMUNICATION_FAILURE 0x4 153eb5073f4SHaojian Zhuang #define OCS_ABORTED 0x5 154eb5073f4SHaojian Zhuang #define OCS_FATAL_ERROR 0x6 155eb5073f4SHaojian Zhuang #define OCS_MASK 0xF 156eb5073f4SHaojian Zhuang 157eb5073f4SHaojian Zhuang /* UIC Command */ 158eb5073f4SHaojian Zhuang #define DME_GET 0x01 159eb5073f4SHaojian Zhuang #define DME_SET 0x02 160eb5073f4SHaojian Zhuang #define DME_PEER_GET 0x03 161eb5073f4SHaojian Zhuang #define DME_PEER_SET 0x04 162eb5073f4SHaojian Zhuang #define DME_POWERON 0x10 163eb5073f4SHaojian Zhuang #define DME_POWEROFF 0x11 164eb5073f4SHaojian Zhuang #define DME_ENABLE 0x12 165eb5073f4SHaojian Zhuang #define DME_RESET 0x14 166eb5073f4SHaojian Zhuang #define DME_ENDPOINTRESET 0x15 167eb5073f4SHaojian Zhuang #define DME_LINKSTARTUP 0x16 168eb5073f4SHaojian Zhuang #define DME_HIBERNATE_ENTER 0x17 169eb5073f4SHaojian Zhuang #define DME_HIBERNATE_EXIT 0x18 170eb5073f4SHaojian Zhuang #define DME_TEST_MODE 0x1A 171eb5073f4SHaojian Zhuang 172eb5073f4SHaojian Zhuang #define GEN_SELECTOR_IDX(x) ((x) & 0xFFFF) 173eb5073f4SHaojian Zhuang 174eb5073f4SHaojian Zhuang #define CONFIG_RESULT_CODE_MASK 0xFF 175eb5073f4SHaojian Zhuang 176eb5073f4SHaojian Zhuang #define CDBCMD_TEST_UNIT_READY 0x00 177eb5073f4SHaojian Zhuang #define CDBCMD_READ_6 0x08 178eb5073f4SHaojian Zhuang #define CDBCMD_WRITE_6 0x0A 179eb5073f4SHaojian Zhuang #define CDBCMD_START_STOP_UNIT 0x1B 180eb5073f4SHaojian Zhuang #define CDBCMD_READ_CAPACITY_10 0x25 181eb5073f4SHaojian Zhuang #define CDBCMD_READ_10 0x28 182eb5073f4SHaojian Zhuang #define CDBCMD_WRITE_10 0x2A 183eb5073f4SHaojian Zhuang #define CDBCMD_READ_16 0x88 184eb5073f4SHaojian Zhuang #define CDBCMD_WRITE_16 0x8A 185eb5073f4SHaojian Zhuang #define CDBCMD_READ_CAPACITY_16 0x9E 186eb5073f4SHaojian Zhuang #define CDBCMD_REPORT_LUNS 0xA0 187eb5073f4SHaojian Zhuang 188eb5073f4SHaojian Zhuang #define UPIU_FLAGS_R (1 << 6) 189eb5073f4SHaojian Zhuang #define UPIU_FLAGS_W (1 << 5) 190eb5073f4SHaojian Zhuang #define UPIU_FLAGS_ATTR_MASK (3 << 0) 191eb5073f4SHaojian Zhuang #define UPIU_FLAGS_ATTR_S (0 << 0) /* Simple */ 192eb5073f4SHaojian Zhuang #define UPIU_FLAGS_ATTR_O (1 << 0) /* Ordered */ 193eb5073f4SHaojian Zhuang #define UPIU_FLAGS_ATTR_HQ (2 << 0) /* Head of Queue */ 194eb5073f4SHaojian Zhuang #define UPIU_FLAGS_ATTR_ACA (3 << 0) 195eb5073f4SHaojian Zhuang #define UPIU_FLAGS_O (1 << 6) 196eb5073f4SHaojian Zhuang #define UPIU_FLAGS_U (1 << 5) 197eb5073f4SHaojian Zhuang #define UPIU_FLAGS_D (1 << 4) 198eb5073f4SHaojian Zhuang 199eb5073f4SHaojian Zhuang #define QUERY_FUNC_STD_READ 0x01 200eb5073f4SHaojian Zhuang #define QUERY_FUNC_STD_WRITE 0x81 201eb5073f4SHaojian Zhuang 202eb5073f4SHaojian Zhuang #define QUERY_NOP 0x00 203eb5073f4SHaojian Zhuang #define QUERY_READ_DESC 0x01 204eb5073f4SHaojian Zhuang #define QUERY_WRITE_DESC 0x02 205eb5073f4SHaojian Zhuang #define QUERY_READ_ATTR 0x03 206eb5073f4SHaojian Zhuang #define QUERY_WRITE_ATTR 0x04 207eb5073f4SHaojian Zhuang #define QUERY_READ_FLAG 0x05 208eb5073f4SHaojian Zhuang #define QUERY_SET_FLAG 0x06 209eb5073f4SHaojian Zhuang #define QUERY_CLEAR_FLAG 0x07 210eb5073f4SHaojian Zhuang #define QUERY_TOGGLE_FLAG 0x08 211eb5073f4SHaojian Zhuang 212eb5073f4SHaojian Zhuang #define RW_WITHOUT_CACHE 0x18 213eb5073f4SHaojian Zhuang 214eb5073f4SHaojian Zhuang #define DESC_TYPE_DEVICE 0x00 215eb5073f4SHaojian Zhuang #define DESC_TYPE_CONFIGURATION 0x01 216eb5073f4SHaojian Zhuang #define DESC_TYPE_UNIT 0x02 217eb5073f4SHaojian Zhuang #define DESC_TYPE_INTERCONNECT 0x04 218eb5073f4SHaojian Zhuang #define DESC_TYPE_STRING 0x05 219eb5073f4SHaojian Zhuang 2205ac25de6Sfengbaopeng #define DESC_DEVICE_MAX_SIZE 0x1F 2215ac25de6Sfengbaopeng #define DEVICE_DESC_PARAM_MANF_ID 0x18 2225ac25de6Sfengbaopeng 223eb5073f4SHaojian Zhuang #define ATTR_CUR_PWR_MODE 0x02 /* bCurrentPowerMode */ 224eb5073f4SHaojian Zhuang #define ATTR_ACTIVECC 0x03 /* bActiveICCLevel */ 225eb5073f4SHaojian Zhuang 226eb5073f4SHaojian Zhuang #define DEVICE_DESCRIPTOR_LEN 0x40 227eb5073f4SHaojian Zhuang #define UNIT_DESCRIPTOR_LEN 0x23 228eb5073f4SHaojian Zhuang 229eb5073f4SHaojian Zhuang #define QUERY_RESP_SUCCESS 0x00 230eb5073f4SHaojian Zhuang #define QUERY_RESP_OPCODE 0xFE 231eb5073f4SHaojian Zhuang #define QUERY_RESP_GENERAL_FAIL 0xFF 232eb5073f4SHaojian Zhuang 233eb5073f4SHaojian Zhuang #define SENSE_KEY_NO_SENSE 0x00 234eb5073f4SHaojian Zhuang #define SENSE_KEY_RECOVERED_ERROR 0x01 235eb5073f4SHaojian Zhuang #define SENSE_KEY_NOT_READY 0x02 236eb5073f4SHaojian Zhuang #define SENSE_KEY_MEDIUM_ERROR 0x03 237eb5073f4SHaojian Zhuang #define SENSE_KEY_HARDWARE_ERROR 0x04 238eb5073f4SHaojian Zhuang #define SENSE_KEY_ILLEGAL_REQUEST 0x05 239eb5073f4SHaojian Zhuang #define SENSE_KEY_UNIT_ATTENTION 0x06 240eb5073f4SHaojian Zhuang #define SENSE_KEY_DATA_PROTECT 0x07 241eb5073f4SHaojian Zhuang #define SENSE_KEY_BLANK_CHECK 0x08 242eb5073f4SHaojian Zhuang #define SENSE_KEY_VENDOR_SPECIFIC 0x09 243eb5073f4SHaojian Zhuang #define SENSE_KEY_COPY_ABORTED 0x0A 244eb5073f4SHaojian Zhuang #define SENSE_KEY_ABORTED_COMMAND 0x0B 245eb5073f4SHaojian Zhuang #define SENSE_KEY_VOLUME_OVERFLOW 0x0D 246eb5073f4SHaojian Zhuang #define SENSE_KEY_MISCOMPARE 0x0E 247eb5073f4SHaojian Zhuang 248eb5073f4SHaojian Zhuang #define SENSE_DATA_VALID 0x70 249eb5073f4SHaojian Zhuang #define SENSE_DATA_LENGTH 18 250eb5073f4SHaojian Zhuang 251eb5073f4SHaojian Zhuang #define READ_CAPACITY_LENGTH 8 252eb5073f4SHaojian Zhuang 253eb5073f4SHaojian Zhuang #define FLAG_DEVICE_INIT 0x01 254eb5073f4SHaojian Zhuang 2555ac25de6Sfengbaopeng #define UFS_VENDOR_SKHYNIX U(0x1AD) 2565ac25de6Sfengbaopeng 2575ac25de6Sfengbaopeng #define MAX_MODEL_LEN 16 258d68d163dSJorge Troncoso 259d68d163dSJorge Troncoso /* maximum number of retries for a general UIC command */ 260d68d163dSJorge Troncoso #define UFS_UIC_COMMAND_RETRIES 3 261d68d163dSJorge Troncoso 262*28645ebdSRohit Ner /* maximum number of retries for reading UFS capacity */ 263*28645ebdSRohit Ner #define UFS_READ_CAPACITY_RETRIES 10 264*28645ebdSRohit Ner 265905635d5SJorge Troncoso /* maximum number of link-startup retries */ 266905635d5SJorge Troncoso #define DME_LINKSTARTUP_RETRIES 10 267905635d5SJorge Troncoso 26899ff1a35SJorge Troncoso #define HCE_ENABLE_OUTER_RETRIES 3 26999ff1a35SJorge Troncoso #define HCE_ENABLE_INNER_RETRIES 50 27099ff1a35SJorge Troncoso #define HCE_ENABLE_TIMEOUT_US 100 271b3f03b20Sanans #define HCE_DISABLE_TIMEOUT_US 1000 27299ff1a35SJorge Troncoso 27350593e69Sanans #define FDEVICEINIT_TIMEOUT_MS 1500 27450593e69Sanans 2755ac25de6Sfengbaopeng /** 2765ac25de6Sfengbaopeng * ufs_dev_desc - ufs device details from the device descriptor 2775ac25de6Sfengbaopeng * @wmanufacturerid: card details 2785ac25de6Sfengbaopeng * @model: card model 2795ac25de6Sfengbaopeng */ 2805ac25de6Sfengbaopeng struct ufs_dev_desc { 2815ac25de6Sfengbaopeng uint16_t wmanufacturerid; 2825ac25de6Sfengbaopeng int8_t model[MAX_MODEL_LEN + 1]; 2835ac25de6Sfengbaopeng }; 2845ac25de6Sfengbaopeng 285eb5073f4SHaojian Zhuang /* UFS Driver Flags */ 286eb5073f4SHaojian Zhuang #define UFS_FLAGS_SKIPINIT (1 << 0) 2875ac25de6Sfengbaopeng #define UFS_FLAGS_VENDOR_SKHYNIX (U(1) << 2) 288eb5073f4SHaojian Zhuang 289eb5073f4SHaojian Zhuang typedef struct sense_data { 290eb5073f4SHaojian Zhuang uint8_t resp_code : 7; 291eb5073f4SHaojian Zhuang uint8_t valid : 1; 292eb5073f4SHaojian Zhuang uint8_t reserved0; 293eb5073f4SHaojian Zhuang uint8_t sense_key : 4; 294eb5073f4SHaojian Zhuang uint8_t reserved1 : 1; 295eb5073f4SHaojian Zhuang uint8_t ili : 1; 296eb5073f4SHaojian Zhuang uint8_t eom : 1; 297eb5073f4SHaojian Zhuang uint8_t file_mark : 1; 298eb5073f4SHaojian Zhuang uint8_t info[4]; 299eb5073f4SHaojian Zhuang uint8_t asl; 300eb5073f4SHaojian Zhuang uint8_t cmd_spec_len[4]; 301eb5073f4SHaojian Zhuang uint8_t asc; 302eb5073f4SHaojian Zhuang uint8_t ascq; 303eb5073f4SHaojian Zhuang uint8_t fruc; 304eb5073f4SHaojian Zhuang uint8_t sense_key_spec0 : 7; 305eb5073f4SHaojian Zhuang uint8_t sksv : 1; 306eb5073f4SHaojian Zhuang uint8_t sense_key_spec1; 307eb5073f4SHaojian Zhuang uint8_t sense_key_spec2; 308eb5073f4SHaojian Zhuang } sense_data_t; 309eb5073f4SHaojian Zhuang 310eb5073f4SHaojian Zhuang /* UTP Transfer Request Descriptor */ 311eb5073f4SHaojian Zhuang typedef struct utrd_header { 312eb5073f4SHaojian Zhuang uint32_t reserved0 : 24; 313eb5073f4SHaojian Zhuang uint32_t i : 1; /* interrupt */ 314eb5073f4SHaojian Zhuang uint32_t dd : 2; /* data direction */ 315eb5073f4SHaojian Zhuang uint32_t reserved1 : 1; 316eb5073f4SHaojian Zhuang uint32_t ct : 4; /* command type */ 317eb5073f4SHaojian Zhuang uint32_t reserved2; 318eb5073f4SHaojian Zhuang uint32_t ocs : 8; /* Overall Command Status */ 319eb5073f4SHaojian Zhuang uint32_t reserved3 : 24; 320eb5073f4SHaojian Zhuang uint32_t reserved4; 321eb5073f4SHaojian Zhuang uint32_t ucdba; /* aligned to 128-byte */ 322eb5073f4SHaojian Zhuang uint32_t ucdbau; /* Upper 32-bits */ 323eb5073f4SHaojian Zhuang uint32_t rul : 16; /* Response UPIU Length */ 324eb5073f4SHaojian Zhuang uint32_t ruo : 16; /* Response UPIU Offset */ 325eb5073f4SHaojian Zhuang uint32_t prdtl : 16; /* PRDT Length */ 326eb5073f4SHaojian Zhuang uint32_t prdto : 16; /* PRDT Offset */ 327eb5073f4SHaojian Zhuang } utrd_header_t; /* 8 words with little endian */ 328eb5073f4SHaojian Zhuang 329eb5073f4SHaojian Zhuang /* UTP Task Management Request Descriptor */ 330eb5073f4SHaojian Zhuang typedef struct utp_utmrd { 331eb5073f4SHaojian Zhuang /* 4 words with little endian */ 332eb5073f4SHaojian Zhuang uint32_t reserved0 : 24; 333eb5073f4SHaojian Zhuang uint32_t i : 1; /* interrupt */ 334eb5073f4SHaojian Zhuang uint32_t reserved1 : 7; 335eb5073f4SHaojian Zhuang uint32_t reserved2; 336eb5073f4SHaojian Zhuang uint32_t ocs : 8; /* Overall Command Status */ 337eb5073f4SHaojian Zhuang uint32_t reserved3 : 24; 338eb5073f4SHaojian Zhuang uint32_t reserved4; 339eb5073f4SHaojian Zhuang 340eb5073f4SHaojian Zhuang /* followed by 8 words UPIU with big endian */ 341eb5073f4SHaojian Zhuang 342eb5073f4SHaojian Zhuang /* followed by 8 words Response UPIU with big endian */ 343eb5073f4SHaojian Zhuang } utp_utmrd_t; 344eb5073f4SHaojian Zhuang 345eb5073f4SHaojian Zhuang /* NOP OUT UPIU */ 346eb5073f4SHaojian Zhuang typedef struct nop_out_upiu { 347eb5073f4SHaojian Zhuang uint8_t trans_type; 348eb5073f4SHaojian Zhuang uint8_t flags; 349eb5073f4SHaojian Zhuang uint8_t reserved0; 350eb5073f4SHaojian Zhuang uint8_t task_tag; 351eb5073f4SHaojian Zhuang uint8_t reserved1; 352eb5073f4SHaojian Zhuang uint8_t reserved2; 353eb5073f4SHaojian Zhuang uint8_t reserved3; 354eb5073f4SHaojian Zhuang uint8_t reserved4; 355eb5073f4SHaojian Zhuang uint8_t total_ehs_len; 356eb5073f4SHaojian Zhuang uint8_t reserved5; 357eb5073f4SHaojian Zhuang uint16_t data_segment_len; 358eb5073f4SHaojian Zhuang uint32_t reserved6; 359eb5073f4SHaojian Zhuang uint32_t reserved7; 360eb5073f4SHaojian Zhuang uint32_t reserved8; 361eb5073f4SHaojian Zhuang uint32_t reserved9; 362eb5073f4SHaojian Zhuang uint32_t reserved10; 363eb5073f4SHaojian Zhuang uint32_t e2ecrc; 364eb5073f4SHaojian Zhuang } nop_out_upiu_t; /* 36 bytes with big endian */ 365eb5073f4SHaojian Zhuang 366eb5073f4SHaojian Zhuang /* NOP IN UPIU */ 367eb5073f4SHaojian Zhuang typedef struct nop_in_upiu { 368eb5073f4SHaojian Zhuang uint8_t trans_type; 369eb5073f4SHaojian Zhuang uint8_t flags; 370eb5073f4SHaojian Zhuang uint8_t reserved0; 371eb5073f4SHaojian Zhuang uint8_t task_tag; 372eb5073f4SHaojian Zhuang uint8_t reserved1; 373eb5073f4SHaojian Zhuang uint8_t reserved2; 374eb5073f4SHaojian Zhuang uint8_t response; 375eb5073f4SHaojian Zhuang uint8_t reserved3; 376eb5073f4SHaojian Zhuang uint8_t total_ehs_len; 377eb5073f4SHaojian Zhuang uint8_t dev_info; 378eb5073f4SHaojian Zhuang uint16_t data_segment_len; 379eb5073f4SHaojian Zhuang uint32_t reserved4; 380eb5073f4SHaojian Zhuang uint32_t reserved5; 381eb5073f4SHaojian Zhuang uint32_t reserved6; 382eb5073f4SHaojian Zhuang uint32_t reserved7; 383eb5073f4SHaojian Zhuang uint32_t reserved8; 384eb5073f4SHaojian Zhuang uint32_t e2ecrc; 385eb5073f4SHaojian Zhuang } nop_in_upiu_t; /* 36 bytes with big endian */ 386eb5073f4SHaojian Zhuang 387eb5073f4SHaojian Zhuang /* Command UPIU */ 388eb5073f4SHaojian Zhuang typedef struct cmd_upiu { 389eb5073f4SHaojian Zhuang uint8_t trans_type; 390eb5073f4SHaojian Zhuang uint8_t flags; 391eb5073f4SHaojian Zhuang uint8_t lun; 392eb5073f4SHaojian Zhuang uint8_t task_tag; 393eb5073f4SHaojian Zhuang uint8_t cmd_set_type; 394eb5073f4SHaojian Zhuang uint8_t reserved0; 395eb5073f4SHaojian Zhuang uint8_t reserved1; 396eb5073f4SHaojian Zhuang uint8_t reserved2; 397eb5073f4SHaojian Zhuang uint8_t total_ehs_len; 398eb5073f4SHaojian Zhuang uint8_t reserved3; 399eb5073f4SHaojian Zhuang uint16_t data_segment_len; 400eb5073f4SHaojian Zhuang uint32_t exp_data_trans_len; 401eb5073f4SHaojian Zhuang /* 402eb5073f4SHaojian Zhuang * A CDB has a fixed length of 16bytes or a variable length 403eb5073f4SHaojian Zhuang * of between 12 and 260 bytes 404eb5073f4SHaojian Zhuang */ 405eb5073f4SHaojian Zhuang uint8_t cdb[16]; /* little endian */ 406eb5073f4SHaojian Zhuang } cmd_upiu_t; /* 32 bytes with big endian except for cdb[] */ 407eb5073f4SHaojian Zhuang 408eb5073f4SHaojian Zhuang typedef struct query_desc { 409eb5073f4SHaojian Zhuang uint8_t opcode; 410eb5073f4SHaojian Zhuang uint8_t idn; 411eb5073f4SHaojian Zhuang uint8_t index; 412eb5073f4SHaojian Zhuang uint8_t selector; 413eb5073f4SHaojian Zhuang uint8_t reserved0[2]; 414eb5073f4SHaojian Zhuang uint16_t length; 415eb5073f4SHaojian Zhuang uint32_t reserved2[2]; 416eb5073f4SHaojian Zhuang } query_desc_t; /* 16 bytes with big endian */ 417eb5073f4SHaojian Zhuang 418eb5073f4SHaojian Zhuang typedef struct query_flag { 419eb5073f4SHaojian Zhuang uint8_t opcode; 420eb5073f4SHaojian Zhuang uint8_t idn; 421eb5073f4SHaojian Zhuang uint8_t index; 422eb5073f4SHaojian Zhuang uint8_t selector; 423eb5073f4SHaojian Zhuang uint8_t reserved0[7]; 424eb5073f4SHaojian Zhuang uint8_t value; 425eb5073f4SHaojian Zhuang uint32_t reserved8; 426eb5073f4SHaojian Zhuang } query_flag_t; /* 16 bytes with big endian */ 427eb5073f4SHaojian Zhuang 428eb5073f4SHaojian Zhuang typedef struct query_attr { 429eb5073f4SHaojian Zhuang uint8_t opcode; 430eb5073f4SHaojian Zhuang uint8_t idn; 431eb5073f4SHaojian Zhuang uint8_t index; 432eb5073f4SHaojian Zhuang uint8_t selector; 433eb5073f4SHaojian Zhuang uint8_t reserved0[4]; 434eb5073f4SHaojian Zhuang uint32_t value; /* little endian */ 435eb5073f4SHaojian Zhuang uint32_t reserved4; 436eb5073f4SHaojian Zhuang } query_attr_t; /* 16 bytes with big endian except for value */ 437eb5073f4SHaojian Zhuang 438eb5073f4SHaojian Zhuang /* Query Request UPIU */ 439eb5073f4SHaojian Zhuang typedef struct query_upiu { 440eb5073f4SHaojian Zhuang uint8_t trans_type; 441eb5073f4SHaojian Zhuang uint8_t flags; 442eb5073f4SHaojian Zhuang uint8_t reserved0; 443eb5073f4SHaojian Zhuang uint8_t task_tag; 444eb5073f4SHaojian Zhuang uint8_t reserved1; 445eb5073f4SHaojian Zhuang uint8_t query_func; 446eb5073f4SHaojian Zhuang uint8_t reserved2; 447eb5073f4SHaojian Zhuang uint8_t reserved3; 448eb5073f4SHaojian Zhuang uint8_t total_ehs_len; 449eb5073f4SHaojian Zhuang uint8_t reserved4; 450eb5073f4SHaojian Zhuang uint16_t data_segment_len; 451eb5073f4SHaojian Zhuang /* Transaction Specific Fields */ 452eb5073f4SHaojian Zhuang union { 453eb5073f4SHaojian Zhuang query_desc_t desc; 454eb5073f4SHaojian Zhuang query_flag_t flag; 455eb5073f4SHaojian Zhuang query_attr_t attr; 456eb5073f4SHaojian Zhuang } ts; 457eb5073f4SHaojian Zhuang uint32_t reserved5; 458eb5073f4SHaojian Zhuang } query_upiu_t; /* 32 bytes with big endian */ 459eb5073f4SHaojian Zhuang 460eb5073f4SHaojian Zhuang /* Query Response UPIU */ 461eb5073f4SHaojian Zhuang typedef struct query_resp_upiu { 462eb5073f4SHaojian Zhuang uint8_t trans_type; 463eb5073f4SHaojian Zhuang uint8_t flags; 464eb5073f4SHaojian Zhuang uint8_t reserved0; 465eb5073f4SHaojian Zhuang uint8_t task_tag; 466eb5073f4SHaojian Zhuang uint8_t reserved1; 467eb5073f4SHaojian Zhuang uint8_t query_func; 468eb5073f4SHaojian Zhuang uint8_t query_resp; 469eb5073f4SHaojian Zhuang uint8_t reserved2; 470eb5073f4SHaojian Zhuang uint8_t total_ehs_len; 471eb5073f4SHaojian Zhuang uint8_t dev_info; 472eb5073f4SHaojian Zhuang uint16_t data_segment_len; 473eb5073f4SHaojian Zhuang union { 474eb5073f4SHaojian Zhuang query_desc_t desc; 475eb5073f4SHaojian Zhuang query_flag_t flag; 476eb5073f4SHaojian Zhuang query_attr_t attr; 477eb5073f4SHaojian Zhuang } ts; 478eb5073f4SHaojian Zhuang uint32_t reserved3; 479eb5073f4SHaojian Zhuang } query_resp_upiu_t; /* 32 bytes with big endian */ 480eb5073f4SHaojian Zhuang 481eb5073f4SHaojian Zhuang /* Response UPIU */ 482eb5073f4SHaojian Zhuang typedef struct resp_upiu { 483eb5073f4SHaojian Zhuang uint8_t trans_type; 484eb5073f4SHaojian Zhuang uint8_t flags; 485eb5073f4SHaojian Zhuang uint8_t lun; 486eb5073f4SHaojian Zhuang uint8_t task_tag; 487eb5073f4SHaojian Zhuang uint8_t cmd_set_type; 488eb5073f4SHaojian Zhuang uint8_t reserved0; 489eb5073f4SHaojian Zhuang uint8_t reserved1; 490eb5073f4SHaojian Zhuang uint8_t status; 491eb5073f4SHaojian Zhuang uint8_t total_ehs_len; 492eb5073f4SHaojian Zhuang uint8_t dev_info; 493eb5073f4SHaojian Zhuang uint16_t data_segment_len; 494eb5073f4SHaojian Zhuang uint32_t res_trans_cnt; /* Residual Transfer Count */ 495eb5073f4SHaojian Zhuang uint32_t reserved2[4]; 496eb5073f4SHaojian Zhuang uint16_t sense_data_len; 497eb5073f4SHaojian Zhuang union { 498eb5073f4SHaojian Zhuang uint8_t sense_data[18]; 499eb5073f4SHaojian Zhuang sense_data_t sense; 500eb5073f4SHaojian Zhuang } sd; 501eb5073f4SHaojian Zhuang } resp_upiu_t; /* 52 bytes with big endian */ 502eb5073f4SHaojian Zhuang 503eb5073f4SHaojian Zhuang typedef struct cmd_info { 504eb5073f4SHaojian Zhuang uintptr_t buf; 505eb5073f4SHaojian Zhuang size_t length; 506eb5073f4SHaojian Zhuang int lba; 507eb5073f4SHaojian Zhuang uint8_t op; 508eb5073f4SHaojian Zhuang uint8_t direction; 509eb5073f4SHaojian Zhuang uint8_t lun; 510eb5073f4SHaojian Zhuang } cmd_info_t; 511eb5073f4SHaojian Zhuang 512eb5073f4SHaojian Zhuang typedef struct utp_utrd { 513eb5073f4SHaojian Zhuang uintptr_t header; /* utrd_header_t */ 514eb5073f4SHaojian Zhuang uintptr_t upiu; 515eb5073f4SHaojian Zhuang uintptr_t resp_upiu; 516eb5073f4SHaojian Zhuang uintptr_t prdt; 517eb5073f4SHaojian Zhuang size_t size_upiu; 518eb5073f4SHaojian Zhuang size_t size_resp_upiu; 519eb5073f4SHaojian Zhuang size_t size_prdt; 520eb5073f4SHaojian Zhuang int task_tag; 521eb5073f4SHaojian Zhuang } utp_utrd_t; 522eb5073f4SHaojian Zhuang 523eb5073f4SHaojian Zhuang /* Physical Region Description Table */ 524eb5073f4SHaojian Zhuang typedef struct prdt { 525eb5073f4SHaojian Zhuang uint32_t dba; /* Data Base Address */ 526eb5073f4SHaojian Zhuang uint32_t dbau; /* Data Base Address Upper 32-bits */ 527eb5073f4SHaojian Zhuang uint32_t reserved0; 528eb5073f4SHaojian Zhuang uint32_t dbc : 18; /* Data Byte Count */ 529eb5073f4SHaojian Zhuang uint32_t reserved1 : 14; 530eb5073f4SHaojian Zhuang } prdt_t; 531eb5073f4SHaojian Zhuang 532eb5073f4SHaojian Zhuang typedef struct uic_cmd { 533eb5073f4SHaojian Zhuang uint32_t op; 534eb5073f4SHaojian Zhuang uint32_t arg1; 535eb5073f4SHaojian Zhuang uint32_t arg2; 536eb5073f4SHaojian Zhuang uint32_t arg3; 537eb5073f4SHaojian Zhuang } uic_cmd_t; 538eb5073f4SHaojian Zhuang 539eb5073f4SHaojian Zhuang typedef struct ufs_params { 540eb5073f4SHaojian Zhuang uintptr_t reg_base; 541eb5073f4SHaojian Zhuang uintptr_t desc_base; 542eb5073f4SHaojian Zhuang size_t desc_size; 543eb5073f4SHaojian Zhuang unsigned long flags; 544eb5073f4SHaojian Zhuang } ufs_params_t; 545eb5073f4SHaojian Zhuang 546eb5073f4SHaojian Zhuang typedef struct ufs_ops { 547eb5073f4SHaojian Zhuang int (*phy_init)(ufs_params_t *params); 548eb5073f4SHaojian Zhuang int (*phy_set_pwr_mode)(ufs_params_t *params); 549eb5073f4SHaojian Zhuang } ufs_ops_t; 550eb5073f4SHaojian Zhuang 551eb5073f4SHaojian Zhuang int ufshc_send_uic_cmd(uintptr_t base, uic_cmd_t *cmd); 552eb5073f4SHaojian Zhuang int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val); 553eb5073f4SHaojian Zhuang int ufshc_dme_set(unsigned int attr, unsigned int idx, unsigned int val); 554eb5073f4SHaojian Zhuang 555eb5073f4SHaojian Zhuang unsigned int ufs_read_attr(int idn); 556eb5073f4SHaojian Zhuang void ufs_write_attr(int idn, unsigned int value); 557eb5073f4SHaojian Zhuang unsigned int ufs_read_flag(int idn); 558eb5073f4SHaojian Zhuang void ufs_set_flag(int idn); 559eb5073f4SHaojian Zhuang void ufs_clear_flag(int idn); 560eb5073f4SHaojian Zhuang void ufs_read_desc(int idn, int index, uintptr_t buf, size_t size); 561eb5073f4SHaojian Zhuang void ufs_write_desc(int idn, int index, uintptr_t buf, size_t size); 562eb5073f4SHaojian Zhuang size_t ufs_read_blocks(int lun, int lba, uintptr_t buf, size_t size); 563eb5073f4SHaojian Zhuang size_t ufs_write_blocks(int lun, int lba, const uintptr_t buf, size_t size); 564eb5073f4SHaojian Zhuang int ufs_init(const ufs_ops_t *ops, ufs_params_t *params); 565eb5073f4SHaojian Zhuang 566c3cf06f1SAntonio Nino Diaz #endif /* UFS_H */ 567