master
h 309 lines 7.56 KB
Raw
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/core/qdev.h"
15 #include "hw/scsi/scsi.h"
16 #include "block/ufs.h"
17 #include "scsi/constants.h"
18 #include "system/dma.h"
19
20 #define UFS_MAX_LUS 32
21 #define UFS_MAX_MCQ_QNUM 32
22 #define UFS_BLOCK_SIZE_SHIFT 12
23 #define UFS_BLOCK_SIZE (1 << UFS_BLOCK_SIZE_SHIFT)
24
25 typedef struct UfsBusClass {
26 BusClass parent_class;
27 bool (*parent_check_address)(BusState *bus, DeviceState *dev, Error **errp);
28 } UfsBusClass;
29
30 typedef struct UfsBus {
31 BusState parent_bus;
32 struct UfsHc *hc;
33 } UfsBus;
34
35 #define TYPE_UFS_BUS "ufs-bus"
36 DECLARE_OBJ_CHECKERS(UfsBus, UfsBusClass, UFS_BUS, TYPE_UFS_BUS)
37
38 typedef enum UfsRequestState {
39 UFS_REQUEST_IDLE = 0,
40 UFS_REQUEST_READY = 1,
41 UFS_REQUEST_RUNNING = 2,
42 UFS_REQUEST_COMPLETE = 3,
43 UFS_REQUEST_ERROR = 4,
44 } UfsRequestState;
45
46 typedef enum UfsReqResult {
47 UFS_REQUEST_SUCCESS = 0,
48 UFS_REQUEST_FAIL = 1,
49 UFS_REQUEST_NO_COMPLETE = 2,
50 } UfsReqResult;
51
52 #define UFS_INVALID_SLOT (-1)
53 typedef struct UfsRequest {
54 struct UfsHc *hc;
55 UfsRequestState state;
56 int slot; /* -1 when it's a MCQ request */
57
58 UtpTransferReqDesc utrd;
59 UtpUpiuReq req_upiu;
60 UtpUpiuRsp rsp_upiu;
61
62 /* for scsi command */
63 QEMUSGList *sg;
64 uint32_t data_len;
65
66 /* for MCQ */
67 struct UfsSq *sq;
68 struct UfsCqEntry cqe;
69 QTAILQ_ENTRY(UfsRequest) entry;
70 } UfsRequest;
71
72 static inline bool ufs_mcq_req(UfsRequest *req)
73 {
74 return req->sq != NULL;
75 }
76
77 struct UfsLu;
78 typedef UfsReqResult (*UfsScsiOp)(struct UfsLu *, UfsRequest *);
79
80 typedef struct UfsLu {
81 DeviceState qdev;
82 uint8_t lun;
83 UnitDescriptor unit_desc;
84 SCSIBus bus;
85 SCSIDevice *scsi_dev;
86 BlockConf conf;
87 UfsScsiOp scsi_op;
88 } UfsLu;
89
90 typedef struct UfsParams {
91 char *serial;
92 uint8_t nutrs; /* Number of UTP Transfer Request Slots */
93 uint8_t nutmrs; /* Number of UTP Task Management Request Slots */
94 bool mcq; /* Multiple Command Queue support */
95 uint8_t mcq_qcfgptr; /* MCQ Queue Configuration Pointer in MCQCAP */
96 uint8_t mcq_maxq; /* MCQ Maximum number of Queues */
97 uint32_t wb_max_size; /* WB Maximum allocation units */
98 uint32_t wb_min_size; /* WB Minimum allocation units */
99 } UfsParams;
100
101 /*
102 * MCQ Properties
103 */
104 typedef struct UfsSq {
105 struct UfsHc *u;
106 uint8_t sqid;
107 struct UfsCq *cq;
108 uint64_t addr;
109 uint16_t size; /* A number of entries (qdepth) */
110
111 QEMUBH *bh; /* Bottom half to process requests in async */
112 UfsRequest *req;
113 QTAILQ_HEAD(, UfsRequest) req_list; /* Free request list */
114 } UfsSq;
115
116 typedef struct UfsCq {
117 struct UfsHc *u;
118 uint8_t cqid;
119 uint64_t addr;
120 uint16_t size; /* A number of entries (qdepth) */
121
122 QEMUBH *bh;
123 QTAILQ_HEAD(, UfsRequest) req_list;
124 } UfsCq;
125
126 /*
127 * Extended features
128 */
129 typedef struct UfsWb {
130 uint64_t max_bytes;
131 uint64_t min_bytes;
132 uint64_t curr_bytes;
133 uint64_t used_bytes;
134 uint64_t resize_bytes;
135
136 uint64_t fifo_max_bytes;
137 uint64_t fifo_curr_bytes;
138
139 uint64_t pinned_max_bytes;
140 uint64_t non_pinned_min_bytes;
141 uint64_t pinned_curr_bytes;
142 uint64_t pinned_used_bytes;
143 uint64_t pinned_total_written_bytes;
144 } UfsWb;
145
146 typedef struct UfsHc {
147 DeviceState *dev;
148 AddressSpace *dma_as;
149 UfsBus bus;
150 MemoryRegion iomem;
151 UfsReg reg;
152 UfsMcqReg mcq_reg[UFS_MAX_MCQ_QNUM];
153 UfsMcqOpReg mcq_op_reg[UFS_MAX_MCQ_QNUM];
154 UfsParams params;
155 uint32_t reg_size;
156 UfsRequest *req_list;
157
158 UfsLu *lus[UFS_MAX_LUS];
159 UfsLu report_wlu;
160 UfsLu dev_wlu;
161 UfsLu boot_wlu;
162 UfsLu rpmb_wlu;
163 DeviceDescriptor device_desc;
164 GeometryDescriptor geometry_desc;
165 Attributes attributes;
166 Flags flags;
167
168 qemu_irq irq;
169 QEMUBH *doorbell_bh;
170 QEMUBH *complete_bh;
171
172 /* MCQ properties */
173 UfsSq *sq[UFS_MAX_MCQ_QNUM];
174 UfsCq *cq[UFS_MAX_MCQ_QNUM];
175
176 /* Extended features */
177 UfsWb wb;
178
179 uint8_t temperature;
180
181 QEMUTimer idle_timer;
182
183 uint32_t hid_fragment_count; /* Remaining fragmented 4KB units */
184 uint32_t hid_defrag_total; /* Requested units at defrag start */
185 uint32_t hid_defrag_remaining; /* Requested units left to move */
186 } UfsHc;
187
188 static inline uint32_t ufs_mcq_sq_tail(UfsHc *u, uint32_t qid)
189 {
190 return u->mcq_op_reg[qid].sq.tp;
191 }
192
193 static inline void ufs_mcq_update_sq_tail(UfsHc *u, uint32_t qid, uint32_t db)
194 {
195 u->mcq_op_reg[qid].sq.tp = db;
196 }
197
198 static inline uint32_t ufs_mcq_sq_head(UfsHc *u, uint32_t qid)
199 {
200 return u->mcq_op_reg[qid].sq.hp;
201 }
202
203 static inline void ufs_mcq_update_sq_head(UfsHc *u, uint32_t qid, uint32_t db)
204 {
205 u->mcq_op_reg[qid].sq.hp = db;
206 }
207
208 static inline bool ufs_mcq_sq_empty(UfsHc *u, uint32_t qid)
209 {
210 return ufs_mcq_sq_tail(u, qid) == ufs_mcq_sq_head(u, qid);
211 }
212
213 static inline uint32_t ufs_mcq_cq_tail(UfsHc *u, uint32_t qid)
214 {
215 return u->mcq_op_reg[qid].cq.tp;
216 }
217
218 static inline void ufs_mcq_update_cq_tail(UfsHc *u, uint32_t qid, uint32_t db)
219 {
220 u->mcq_op_reg[qid].cq.tp = db;
221 }
222
223 static inline uint32_t ufs_mcq_cq_head(UfsHc *u, uint32_t qid)
224 {
225 return u->mcq_op_reg[qid].cq.hp;
226 }
227
228 static inline void ufs_mcq_update_cq_head(UfsHc *u, uint32_t qid, uint32_t db)
229 {
230 u->mcq_op_reg[qid].cq.hp = db;
231 }
232
233 static inline bool ufs_mcq_cq_empty(UfsHc *u, uint32_t qid)
234 {
235 return ufs_mcq_cq_tail(u, qid) == ufs_mcq_cq_head(u, qid);
236 }
237
238 static inline bool ufs_mcq_cq_full(UfsHc *u, uint32_t qid)
239 {
240 uint32_t tail = ufs_mcq_cq_tail(u, qid);
241 UfsCq *cq = u->cq[qid];
242 uint16_t cq_size;
243
244 if (!cq) {
245 return false;
246 }
247
248 cq_size = cq->size;
249
250 tail = (tail + sizeof(UfsCqEntry)) % (sizeof(UfsCqEntry) * cq_size);
251 return tail == ufs_mcq_cq_head(u, qid);
252 }
253
254 static inline uint64_t ufs_unit_to_byte(UfsHc *u, uint32_t unit)
255 {
256 return (uint64_t)unit * u->geometry_desc.allocation_unit_size *
257 be32_to_cpu(u->geometry_desc.segment_size) * BDRV_SECTOR_SIZE;
258 }
259
260 static inline uint32_t ufs_byte_to_unit(UfsHc *u, uint64_t byte)
261 {
262 return byte / BDRV_SECTOR_SIZE /
263 be32_to_cpu(u->geometry_desc.segment_size) /
264 u->geometry_desc.allocation_unit_size;
265 }
266
267 static inline bool ufs_is_write_req(UfsRequest *req)
268 {
269 uint8_t cmd = req->req_upiu.sc.cdb[0];
270
271 /* UFS 4.1 Specifiaction doesn't support WRITE_12 */
272 return (cmd == WRITE_6) || (cmd == WRITE_10) || (cmd == WRITE_16);
273 }
274
275 #define TYPE_UFS_LU "ufs-lu"
276 #define UFSLU(obj) OBJECT_CHECK(UfsLu, (obj), TYPE_UFS_LU)
277
278 typedef enum UfsQueryFlagPerm {
279 UFS_QUERY_FLAG_NONE = 0x0,
280 UFS_QUERY_FLAG_READ = 0x1,
281 UFS_QUERY_FLAG_SET = 0x2,
282 UFS_QUERY_FLAG_CLEAR = 0x4,
283 UFS_QUERY_FLAG_TOGGLE = 0x8,
284 } UfsQueryFlagPerm;
285
286 typedef enum UfsQueryAttrPerm {
287 UFS_QUERY_ATTR_NONE = 0x0,
288 UFS_QUERY_ATTR_READ = 0x1,
289 UFS_QUERY_ATTR_WRITE = 0x2,
290 } UfsQueryAttrPerm;
291
292 static inline bool is_wlun(uint8_t lun)
293 {
294 return (lun == UFS_UPIU_REPORT_LUNS_WLUN ||
295 lun == UFS_UPIU_UFS_DEVICE_WLUN || lun == UFS_UPIU_BOOT_WLUN ||
296 lun == UFS_UPIU_RPMB_WLUN);
297 }
298
299 void ufs_build_upiu_header(UfsRequest *req, uint8_t trans_type, uint8_t flags,
300 uint8_t response, uint8_t scsi_status,
301 uint16_t data_segment_length);
302 void ufs_build_query_response(UfsRequest *req);
303 void ufs_complete_req(UfsRequest *req, UfsReqResult req_result);
304 void ufs_wb_update_avail_buffer(UfsHc *u);
305 void ufs_init_wlu(UfsLu *wlu, uint8_t wlun);
306 bool ufs_realize(UfsHc *u, DeviceState *dev, AddressSpace *dma_as,
307 Error **errp);
308 void ufs_unrealize(UfsHc *u);
309 #endif /* HW_UFS_UFS_H */