1 /* 2 * QEMU UFS 3 * 4 * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. 5 * 6 * Written by Jeuk Kim <jeuk20.kim@samsung.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 11 #ifndef HW_UFS_UFS_H 12 #define HW_UFS_UFS_H 13 14 #include "hw/pci/pci_device.h" 15 #include "hw/scsi/scsi.h" 16 #include "block/ufs.h" 17 18 #define UFS_MAX_LUS 32 19 #define UFS_MAX_MCQ_QNUM 32 20 #define UFS_BLOCK_SIZE_SHIFT 12 21 #define UFS_BLOCK_SIZE (1 << UFS_BLOCK_SIZE_SHIFT) 22 23 typedef struct UfsBusClass { 24 BusClass parent_class; 25 bool (*parent_check_address)(BusState *bus, DeviceState *dev, Error **errp); 26 } UfsBusClass; 27 28 typedef struct UfsBus { 29 BusState parent_bus; 30 } UfsBus; 31 32 #define TYPE_UFS_BUS "ufs-bus" 33 DECLARE_OBJ_CHECKERS(UfsBus, UfsBusClass, UFS_BUS, TYPE_UFS_BUS) 34 35 typedef enum UfsRequestState { 36 UFS_REQUEST_IDLE = 0, 37 UFS_REQUEST_READY = 1, 38 UFS_REQUEST_RUNNING = 2, 39 UFS_REQUEST_COMPLETE = 3, 40 UFS_REQUEST_ERROR = 4, 41 } UfsRequestState; 42 43 typedef enum UfsReqResult { 44 UFS_REQUEST_SUCCESS = 0, 45 UFS_REQUEST_FAIL = 1, 46 UFS_REQUEST_NO_COMPLETE = 2, 47 } UfsReqResult; 48 49 #define UFS_INVALID_SLOT (-1) 50 typedef struct UfsRequest { 51 struct UfsHc *hc; 52 UfsRequestState state; 53 int slot; /* -1 when it's a MCQ request */ 54 55 UtpTransferReqDesc utrd; 56 UtpUpiuReq req_upiu; 57 UtpUpiuRsp rsp_upiu; 58 59 /* for scsi command */ 60 QEMUSGList *sg; 61 uint32_t data_len; 62 63 /* for MCQ */ 64 struct UfsSq *sq; 65 struct UfsCqEntry cqe; 66 QTAILQ_ENTRY(UfsRequest) entry; 67 } UfsRequest; 68 69 static inline bool ufs_mcq_req(UfsRequest *req) 70 { 71 return req->sq != NULL; 72 } 73 74 struct UfsLu; 75 typedef UfsReqResult (*UfsScsiOp)(struct UfsLu *, UfsRequest *); 76 77 typedef struct UfsLu { 78 DeviceState qdev; 79 uint8_t lun; 80 UnitDescriptor unit_desc; 81 SCSIBus bus; 82 SCSIDevice *scsi_dev; 83 BlockConf conf; 84 UfsScsiOp scsi_op; 85 } UfsLu; 86 87 typedef struct UfsParams { 88 char *serial; 89 uint8_t nutrs; /* Number of UTP Transfer Request Slots */ 90 uint8_t nutmrs; /* Number of UTP Task Management Request Slots */ 91 bool mcq; /* Multiple Command Queue support */ 92 uint8_t mcq_qcfgptr; /* MCQ Queue Configuration Pointer in MCQCAP */ 93 uint8_t mcq_maxq; /* MCQ Maximum number of Queues */ 94 } UfsParams; 95 96 /* 97 * MCQ Properties 98 */ 99 typedef struct UfsSq { 100 struct UfsHc *u; 101 uint8_t sqid; 102 struct UfsCq *cq; 103 uint64_t addr; 104 uint16_t size; /* A number of entries (qdepth) */ 105 106 QEMUBH *bh; /* Bottom half to process requests in async */ 107 UfsRequest *req; 108 QTAILQ_HEAD(, UfsRequest) req_list; /* Free request list */ 109 } UfsSq; 110 111 typedef struct UfsCq { 112 struct UfsHc *u; 113 uint8_t cqid; 114 uint64_t addr; 115 uint16_t size; /* A number of entries (qdepth) */ 116 117 QEMUBH *bh; 118 QTAILQ_HEAD(, UfsRequest) req_list; 119 } UfsCq; 120 121 typedef struct UfsHc { 122 PCIDevice parent_obj; 123 UfsBus bus; 124 MemoryRegion iomem; 125 UfsReg reg; 126 UfsMcqReg mcq_reg[UFS_MAX_MCQ_QNUM]; 127 UfsMcqOpReg mcq_op_reg[UFS_MAX_MCQ_QNUM]; 128 UfsParams params; 129 uint32_t reg_size; 130 UfsRequest *req_list; 131 132 UfsLu *lus[UFS_MAX_LUS]; 133 UfsLu report_wlu; 134 UfsLu dev_wlu; 135 UfsLu boot_wlu; 136 UfsLu rpmb_wlu; 137 DeviceDescriptor device_desc; 138 GeometryDescriptor geometry_desc; 139 Attributes attributes; 140 Flags flags; 141 142 qemu_irq irq; 143 QEMUBH *doorbell_bh; 144 QEMUBH *complete_bh; 145 146 /* MCQ properties */ 147 UfsSq *sq[UFS_MAX_MCQ_QNUM]; 148 UfsCq *cq[UFS_MAX_MCQ_QNUM]; 149 } UfsHc; 150 151 static inline uint32_t ufs_mcq_sq_tail(UfsHc *u, uint32_t qid) 152 { 153 return u->mcq_op_reg[qid].sq.tp; 154 } 155 156 static inline void ufs_mcq_update_sq_tail(UfsHc *u, uint32_t qid, uint32_t db) 157 { 158 u->mcq_op_reg[qid].sq.tp = db; 159 } 160 161 static inline uint32_t ufs_mcq_sq_head(UfsHc *u, uint32_t qid) 162 { 163 return u->mcq_op_reg[qid].sq.hp; 164 } 165 166 static inline void ufs_mcq_update_sq_head(UfsHc *u, uint32_t qid, uint32_t db) 167 { 168 u->mcq_op_reg[qid].sq.hp = db; 169 } 170 171 static inline bool ufs_mcq_sq_empty(UfsHc *u, uint32_t qid) 172 { 173 return ufs_mcq_sq_tail(u, qid) == ufs_mcq_sq_head(u, qid); 174 } 175 176 static inline uint32_t ufs_mcq_cq_tail(UfsHc *u, uint32_t qid) 177 { 178 return u->mcq_op_reg[qid].cq.tp; 179 } 180 181 static inline void ufs_mcq_update_cq_tail(UfsHc *u, uint32_t qid, uint32_t db) 182 { 183 u->mcq_op_reg[qid].cq.tp = db; 184 } 185 186 static inline uint32_t ufs_mcq_cq_head(UfsHc *u, uint32_t qid) 187 { 188 return u->mcq_op_reg[qid].cq.hp; 189 } 190 191 static inline void ufs_mcq_update_cq_head(UfsHc *u, uint32_t qid, uint32_t db) 192 { 193 u->mcq_op_reg[qid].cq.hp = db; 194 } 195 196 static inline bool ufs_mcq_cq_empty(UfsHc *u, uint32_t qid) 197 { 198 return ufs_mcq_cq_tail(u, qid) == ufs_mcq_cq_head(u, qid); 199 } 200 201 #define TYPE_UFS "ufs" 202 #define UFS(obj) OBJECT_CHECK(UfsHc, (obj), TYPE_UFS) 203 204 #define TYPE_UFS_LU "ufs-lu" 205 #define UFSLU(obj) OBJECT_CHECK(UfsLu, (obj), TYPE_UFS_LU) 206 207 typedef enum UfsQueryFlagPerm { 208 UFS_QUERY_FLAG_NONE = 0x0, 209 UFS_QUERY_FLAG_READ = 0x1, 210 UFS_QUERY_FLAG_SET = 0x2, 211 UFS_QUERY_FLAG_CLEAR = 0x4, 212 UFS_QUERY_FLAG_TOGGLE = 0x8, 213 } UfsQueryFlagPerm; 214 215 typedef enum UfsQueryAttrPerm { 216 UFS_QUERY_ATTR_NONE = 0x0, 217 UFS_QUERY_ATTR_READ = 0x1, 218 UFS_QUERY_ATTR_WRITE = 0x2, 219 } UfsQueryAttrPerm; 220 221 static inline bool is_wlun(uint8_t lun) 222 { 223 return (lun == UFS_UPIU_REPORT_LUNS_WLUN || 224 lun == UFS_UPIU_UFS_DEVICE_WLUN || lun == UFS_UPIU_BOOT_WLUN || 225 lun == UFS_UPIU_RPMB_WLUN); 226 } 227 228 void ufs_build_upiu_header(UfsRequest *req, uint8_t trans_type, uint8_t flags, 229 uint8_t response, uint8_t scsi_status, 230 uint16_t data_segment_length); 231 void ufs_complete_req(UfsRequest *req, UfsReqResult req_result); 232 void ufs_init_wlu(UfsLu *wlu, uint8_t wlun); 233 #endif /* HW_UFS_UFS_H */ 234