xref: /openbmc/qemu/hw/ufs/ufs.h (revision 096434fea13acd19f4ead00cdf9babea8dc7e61e)
1bc4e68d3SJeuk Kim /*
2bc4e68d3SJeuk Kim  * QEMU UFS
3bc4e68d3SJeuk Kim  *
4bc4e68d3SJeuk Kim  * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
5bc4e68d3SJeuk Kim  *
6bc4e68d3SJeuk Kim  * Written by Jeuk Kim <jeuk20.kim@samsung.com>
7bc4e68d3SJeuk Kim  *
8bc4e68d3SJeuk Kim  * SPDX-License-Identifier: GPL-2.0-or-later
9bc4e68d3SJeuk Kim  */
10bc4e68d3SJeuk Kim 
11bc4e68d3SJeuk Kim #ifndef HW_UFS_UFS_H
12bc4e68d3SJeuk Kim #define HW_UFS_UFS_H
13bc4e68d3SJeuk Kim 
14bc4e68d3SJeuk Kim #include "hw/pci/pci_device.h"
15bc4e68d3SJeuk Kim #include "hw/scsi/scsi.h"
16bc4e68d3SJeuk Kim #include "block/ufs.h"
17bc4e68d3SJeuk Kim 
18bc4e68d3SJeuk Kim #define UFS_MAX_LUS 32
19*096434feSJeuk Kim #define UFS_BLOCK_SIZE_SHIFT 12
20*096434feSJeuk Kim #define UFS_BLOCK_SIZE (1 << UFS_BLOCK_SIZE_SHIFT)
21bc4e68d3SJeuk Kim 
222a8b36a4SJeuk Kim typedef struct UfsBusClass {
232a8b36a4SJeuk Kim     BusClass parent_class;
242a8b36a4SJeuk Kim     bool (*parent_check_address)(BusState *bus, DeviceState *dev, Error **errp);
252a8b36a4SJeuk Kim } UfsBusClass;
262a8b36a4SJeuk Kim 
272a8b36a4SJeuk Kim typedef struct UfsBus {
28*096434feSJeuk Kim     BusState parent_bus;
292a8b36a4SJeuk Kim } UfsBus;
302a8b36a4SJeuk Kim 
312a8b36a4SJeuk Kim #define TYPE_UFS_BUS "ufs-bus"
322a8b36a4SJeuk Kim DECLARE_OBJ_CHECKERS(UfsBus, UfsBusClass, UFS_BUS, TYPE_UFS_BUS)
332a8b36a4SJeuk Kim 
34329f1662SJeuk Kim typedef enum UfsRequestState {
35329f1662SJeuk Kim     UFS_REQUEST_IDLE = 0,
36329f1662SJeuk Kim     UFS_REQUEST_READY = 1,
37329f1662SJeuk Kim     UFS_REQUEST_RUNNING = 2,
38329f1662SJeuk Kim     UFS_REQUEST_COMPLETE = 3,
39329f1662SJeuk Kim     UFS_REQUEST_ERROR = 4,
40329f1662SJeuk Kim } UfsRequestState;
41329f1662SJeuk Kim 
42329f1662SJeuk Kim typedef enum UfsReqResult {
43329f1662SJeuk Kim     UFS_REQUEST_SUCCESS = 0,
44329f1662SJeuk Kim     UFS_REQUEST_FAIL = 1,
452a8b36a4SJeuk Kim     UFS_REQUEST_NO_COMPLETE = 2,
46329f1662SJeuk Kim } UfsReqResult;
47329f1662SJeuk Kim 
48329f1662SJeuk Kim typedef struct UfsRequest {
49329f1662SJeuk Kim     struct UfsHc *hc;
50329f1662SJeuk Kim     UfsRequestState state;
51329f1662SJeuk Kim     int slot;
52329f1662SJeuk Kim 
53329f1662SJeuk Kim     UtpTransferReqDesc utrd;
54329f1662SJeuk Kim     UtpUpiuReq req_upiu;
55329f1662SJeuk Kim     UtpUpiuRsp rsp_upiu;
56329f1662SJeuk Kim 
57329f1662SJeuk Kim     /* for scsi command */
58329f1662SJeuk Kim     QEMUSGList *sg;
59*096434feSJeuk Kim     uint32_t data_len;
60329f1662SJeuk Kim } UfsRequest;
61329f1662SJeuk Kim 
62*096434feSJeuk Kim struct UfsLu;
63*096434feSJeuk Kim typedef UfsReqResult (*UfsScsiOp)(struct UfsLu *, UfsRequest *);
64*096434feSJeuk Kim 
652a8b36a4SJeuk Kim typedef struct UfsLu {
66*096434feSJeuk Kim     DeviceState qdev;
672a8b36a4SJeuk Kim     uint8_t lun;
682a8b36a4SJeuk Kim     UnitDescriptor unit_desc;
69*096434feSJeuk Kim     SCSIBus bus;
70*096434feSJeuk Kim     SCSIDevice *scsi_dev;
71*096434feSJeuk Kim     BlockConf conf;
72*096434feSJeuk Kim     UfsScsiOp scsi_op;
732a8b36a4SJeuk Kim } UfsLu;
742a8b36a4SJeuk Kim 
75bc4e68d3SJeuk Kim typedef struct UfsParams {
76bc4e68d3SJeuk Kim     char *serial;
77bc4e68d3SJeuk Kim     uint8_t nutrs; /* Number of UTP Transfer Request Slots */
78bc4e68d3SJeuk Kim     uint8_t nutmrs; /* Number of UTP Task Management Request Slots */
79bc4e68d3SJeuk Kim } UfsParams;
80bc4e68d3SJeuk Kim 
81bc4e68d3SJeuk Kim typedef struct UfsHc {
82bc4e68d3SJeuk Kim     PCIDevice parent_obj;
832a8b36a4SJeuk Kim     UfsBus bus;
84bc4e68d3SJeuk Kim     MemoryRegion iomem;
85bc4e68d3SJeuk Kim     UfsReg reg;
86bc4e68d3SJeuk Kim     UfsParams params;
87bc4e68d3SJeuk Kim     uint32_t reg_size;
88329f1662SJeuk Kim     UfsRequest *req_list;
89329f1662SJeuk Kim 
902a8b36a4SJeuk Kim     UfsLu *lus[UFS_MAX_LUS];
91*096434feSJeuk Kim     UfsLu report_wlu;
92*096434feSJeuk Kim     UfsLu dev_wlu;
93*096434feSJeuk Kim     UfsLu boot_wlu;
94*096434feSJeuk Kim     UfsLu rpmb_wlu;
95329f1662SJeuk Kim     DeviceDescriptor device_desc;
96329f1662SJeuk Kim     GeometryDescriptor geometry_desc;
97329f1662SJeuk Kim     Attributes attributes;
98329f1662SJeuk Kim     Flags flags;
99bc4e68d3SJeuk Kim 
100bc4e68d3SJeuk Kim     qemu_irq irq;
101bc4e68d3SJeuk Kim     QEMUBH *doorbell_bh;
102bc4e68d3SJeuk Kim     QEMUBH *complete_bh;
103bc4e68d3SJeuk Kim } UfsHc;
104bc4e68d3SJeuk Kim 
105bc4e68d3SJeuk Kim #define TYPE_UFS "ufs"
106bc4e68d3SJeuk Kim #define UFS(obj) OBJECT_CHECK(UfsHc, (obj), TYPE_UFS)
107bc4e68d3SJeuk Kim 
1082a8b36a4SJeuk Kim #define TYPE_UFS_LU "ufs-lu"
1092a8b36a4SJeuk Kim #define UFSLU(obj) OBJECT_CHECK(UfsLu, (obj), TYPE_UFS_LU)
1102a8b36a4SJeuk Kim 
111329f1662SJeuk Kim typedef enum UfsQueryFlagPerm {
112329f1662SJeuk Kim     UFS_QUERY_FLAG_NONE = 0x0,
113329f1662SJeuk Kim     UFS_QUERY_FLAG_READ = 0x1,
114329f1662SJeuk Kim     UFS_QUERY_FLAG_SET = 0x2,
115329f1662SJeuk Kim     UFS_QUERY_FLAG_CLEAR = 0x4,
116329f1662SJeuk Kim     UFS_QUERY_FLAG_TOGGLE = 0x8,
117329f1662SJeuk Kim } UfsQueryFlagPerm;
118329f1662SJeuk Kim 
119329f1662SJeuk Kim typedef enum UfsQueryAttrPerm {
120329f1662SJeuk Kim     UFS_QUERY_ATTR_NONE = 0x0,
121329f1662SJeuk Kim     UFS_QUERY_ATTR_READ = 0x1,
122329f1662SJeuk Kim     UFS_QUERY_ATTR_WRITE = 0x2,
123329f1662SJeuk Kim } UfsQueryAttrPerm;
124329f1662SJeuk Kim 
1252a8b36a4SJeuk Kim static inline bool is_wlun(uint8_t lun)
1262a8b36a4SJeuk Kim {
1272a8b36a4SJeuk Kim     return (lun == UFS_UPIU_REPORT_LUNS_WLUN ||
1282a8b36a4SJeuk Kim             lun == UFS_UPIU_UFS_DEVICE_WLUN || lun == UFS_UPIU_BOOT_WLUN ||
1292a8b36a4SJeuk Kim             lun == UFS_UPIU_RPMB_WLUN);
1302a8b36a4SJeuk Kim }
1312a8b36a4SJeuk Kim 
132*096434feSJeuk Kim void ufs_build_upiu_header(UfsRequest *req, uint8_t trans_type, uint8_t flags,
133*096434feSJeuk Kim                            uint8_t response, uint8_t scsi_status,
134*096434feSJeuk Kim                            uint16_t data_segment_length);
135*096434feSJeuk Kim void ufs_complete_req(UfsRequest *req, UfsReqResult req_result);
136*096434feSJeuk Kim void ufs_init_wlu(UfsLu *wlu, uint8_t wlun);
137bc4e68d3SJeuk Kim #endif /* HW_UFS_UFS_H */
138