1c7f9abceSXiaoxu Zeng // SPDX-License-Identifier: BSD-2-Clause
2c7f9abceSXiaoxu Zeng /*
3c7f9abceSXiaoxu Zeng * Copyright 2022-2023 HiSilicon Limited.
4c7f9abceSXiaoxu Zeng * Kunpeng hardware accelerator queue management module.
5c7f9abceSXiaoxu Zeng */
6c7f9abceSXiaoxu Zeng #include "hisi_qm.h"
7c7f9abceSXiaoxu Zeng
8c7f9abceSXiaoxu Zeng #define QM_FVT_CFG_RDY_BIT 0x1
9c7f9abceSXiaoxu Zeng /* Doorbell */
10c7f9abceSXiaoxu Zeng #define QM_DOORBELL_SQ_CQ_BASE 0x1000
11c7f9abceSXiaoxu Zeng #define QM_DB_CMD_SHIFT 12
12c7f9abceSXiaoxu Zeng #define QM_DB_RAND_DATA_SHIFT 16
13c7f9abceSXiaoxu Zeng #define QM_DB_INDEX_SHIFT 32
14c7f9abceSXiaoxu Zeng #define QM_DB_PRIORITY_SHIFT 48
15c7f9abceSXiaoxu Zeng #define QM_DB_RAND_DATA 0x5a
16c7f9abceSXiaoxu Zeng #define QM_DOORBELL_CMD_SQ 0
17c7f9abceSXiaoxu Zeng #define QM_DOORBELL_CMD_CQ 1
18c7f9abceSXiaoxu Zeng /* Mailbox */
19c7f9abceSXiaoxu Zeng #define QM_MAILBOX_BASE 0x300
20c7f9abceSXiaoxu Zeng #define QM_MAILBOX_DATA_ADDR_L 0x304
21c7f9abceSXiaoxu Zeng #define QM_MAILBOX_DATA_ADDR_H 0x308
22c7f9abceSXiaoxu Zeng #define QM_MB_BUSY_SHIFT 13
23c7f9abceSXiaoxu Zeng #define QM_MB_BUSY_BIT BIT32(QM_MB_BUSY_SHIFT)
24c7f9abceSXiaoxu Zeng #define QM_MB_OP_SHIFT 14
25c7f9abceSXiaoxu Zeng #define QM_MB_OP_WR 0
26c7f9abceSXiaoxu Zeng #define QM_MB_OP_RD 1
276374dbceSZexi Yu #define QM_MB_STATUS_MASK GENMASK_32(12, 9)
286374dbceSZexi Yu #define QM_MB_WAIT_READY_CNT 10
296374dbceSZexi Yu #define QM_MB_WAIT_MAX_CNT 21000
306374dbceSZexi Yu #define QM_MB_WAIT_PERIOD 200
31c7f9abceSXiaoxu Zeng /* XQC_VFT */
32c7f9abceSXiaoxu Zeng #define QM_VFT_CFG_OP_ENABLE 0x100054
33c7f9abceSXiaoxu Zeng #define QM_VFT_CFG_OP_WR 0x100058
34c7f9abceSXiaoxu Zeng #define QM_VFT_CFG_TYPE 0x10005c
35c7f9abceSXiaoxu Zeng #define QM_VFT_CFG_ADDRESS 0x100060
36c7f9abceSXiaoxu Zeng #define QM_VFT_CFG_DATA_L 0x100064
37c7f9abceSXiaoxu Zeng #define QM_VFT_CFG_DATA_H 0x100068
38c7f9abceSXiaoxu Zeng #define QM_VFT_CFG_RDY 0x10006c
39c7f9abceSXiaoxu Zeng #define QM_SQC_VFT 0
40c7f9abceSXiaoxu Zeng #define QM_CQC_VFT 1
41c7f9abceSXiaoxu Zeng #define QM_SQC_VFT_START_SQN_SHIFT 28
42c7f9abceSXiaoxu Zeng #define QM_SQC_VFT_VALID BIT64(44)
43c7f9abceSXiaoxu Zeng #define QM_SQC_VFT_SQ_NUM_SHIFT 45
44c7f9abceSXiaoxu Zeng #define QM_CQC_VFT_VALID BIT(28)
45c7f9abceSXiaoxu Zeng #define QM_VFT_WRITE 0
46c7f9abceSXiaoxu Zeng #define QM_VFT_READ 1
47c7f9abceSXiaoxu Zeng #define QM_SQC_VFT_BASE_MASK 0x3ff
48c7f9abceSXiaoxu Zeng #define QM_SQC_VFT_NUM_MASK 0x3ff
49c7f9abceSXiaoxu Zeng /* QM INIT */
50c7f9abceSXiaoxu Zeng #define QM_MEM_START_INIT 0x100040
51c7f9abceSXiaoxu Zeng #define QM_MEM_INIT_DONE 0x100044
52c7f9abceSXiaoxu Zeng #define QM_VF_AEQ_INT_MASK 0x4
53c7f9abceSXiaoxu Zeng #define QM_VF_AEQ_INT_MASK_EN 0x1
54c7f9abceSXiaoxu Zeng #define QM_VF_EQ_INT_MASK 0xc
55c7f9abceSXiaoxu Zeng #define QM_VF_EQ_INT_MASK_EN 0x1
56c7f9abceSXiaoxu Zeng #define QM_ARUSER_M_CFG_1 0x100088
57c7f9abceSXiaoxu Zeng #define QM_ARUSER_M_CFG_ENABLE 0x100090
58c7f9abceSXiaoxu Zeng #define QM_AWUSER_M_CFG_1 0x100098
59c7f9abceSXiaoxu Zeng #define QM_AWUSER_M_CFG_ENABLE 0x1000a0
60c7f9abceSXiaoxu Zeng #define QM_AXUSER_CFG 0x40001070
61c7f9abceSXiaoxu Zeng #define AXUSER_M_CFG_ENABLE 0x7ffffc
62c7f9abceSXiaoxu Zeng #define QM_AXI_M_CFG 0x1000ac
63c7f9abceSXiaoxu Zeng #define AXI_M_CFG 0xffff
64c7f9abceSXiaoxu Zeng #define QM_PEH_AXUSER_CFG 0x1000cc
65c7f9abceSXiaoxu Zeng #define PEH_AXUSER_CFG 0x400801
66c7f9abceSXiaoxu Zeng #define QM_CACHE_CTL 0x100050
67c7f9abceSXiaoxu Zeng #define QM_CACHE_CFG 0x4893
688122e61dSZexi Yu #define QM_CACHE_WB_START 0x204
698122e61dSZexi Yu #define QM_CACHE_WB_DONE 0x208
70e5dba603SZexi Yu #define QM_PM_CTRL0 0x100148
71e5dba603SZexi Yu #define QM_IDLE_DISABLE BIT(9)
72e5dba603SZexi Yu #define QM_DB_TIMEOUT_CFG 0x100074
73e5dba603SZexi Yu #define QM_DB_TIMEOUT_SET 0x1fffff
74c7f9abceSXiaoxu Zeng /* XQC shift */
75c7f9abceSXiaoxu Zeng #define QM_SQ_SQE_SIZE_SHIFT 12
76c7f9abceSXiaoxu Zeng #define QM_SQ_ORDER_SHIFT 4
77c7f9abceSXiaoxu Zeng #define QM_SQ_TYPE_SHIFT 8
78c7f9abceSXiaoxu Zeng #define QM_CQE_SIZE 4
79c7f9abceSXiaoxu Zeng #define QM_CQ_CQE_SIZE_SHIFT 12
80c7f9abceSXiaoxu Zeng /* CQE */
81c7f9abceSXiaoxu Zeng #define QM_CQE_PHASE(cqe) (((cqe)->w7) & QM_FVT_CFG_RDY_BIT)
82c7f9abceSXiaoxu Zeng
83c7f9abceSXiaoxu Zeng enum qm_mailbox_common_cmd {
84c7f9abceSXiaoxu Zeng QM_MB_CMD_SQC = 0x0,
85c7f9abceSXiaoxu Zeng QM_MB_CMD_CQC,
86c7f9abceSXiaoxu Zeng QM_MB_CMD_EQC,
87c7f9abceSXiaoxu Zeng QM_MB_CMD_AEQC,
88c7f9abceSXiaoxu Zeng QM_MB_CMD_SQC_BT,
89c7f9abceSXiaoxu Zeng QM_MB_CMD_CQC_BT,
90c7f9abceSXiaoxu Zeng QM_MB_CMD_SQC_VFT,
91c7f9abceSXiaoxu Zeng };
92c7f9abceSXiaoxu Zeng
93c7f9abceSXiaoxu Zeng enum qm_mailbox_cmd_v3 {
94c7f9abceSXiaoxu Zeng QM_MB_CM_CLOSE_QM = 0x7,
95c7f9abceSXiaoxu Zeng QM_MB_CMD_CLOSE_QP,
96c7f9abceSXiaoxu Zeng QM_MB_CMD_FLUSH_QM,
97c7f9abceSXiaoxu Zeng QM_MB_CMD_FLUSH_QP,
98c7f9abceSXiaoxu Zeng QM_MB_CMD_SRC = 0xc,
99c7f9abceSXiaoxu Zeng QM_MB_CMD_DST,
100c7f9abceSXiaoxu Zeng QM_MB_CMD_STOP_QM,
101c7f9abceSXiaoxu Zeng };
102c7f9abceSXiaoxu Zeng
103c7f9abceSXiaoxu Zeng struct qm_mailbox {
104c7f9abceSXiaoxu Zeng union {
105c7f9abceSXiaoxu Zeng struct {
106c7f9abceSXiaoxu Zeng uint16_t w0;
107c7f9abceSXiaoxu Zeng uint16_t queue;
108c7f9abceSXiaoxu Zeng uint32_t base_l;
109c7f9abceSXiaoxu Zeng uint32_t base_h;
110c7f9abceSXiaoxu Zeng uint32_t token;
111c7f9abceSXiaoxu Zeng };
112c7f9abceSXiaoxu Zeng uint64_t x[2];
113c7f9abceSXiaoxu Zeng };
114c7f9abceSXiaoxu Zeng };
115c7f9abceSXiaoxu Zeng
116c7f9abceSXiaoxu Zeng struct qm_dfx_registers {
117c7f9abceSXiaoxu Zeng const char *reg_name;
118c7f9abceSXiaoxu Zeng uint32_t reg_offset;
119c7f9abceSXiaoxu Zeng };
120c7f9abceSXiaoxu Zeng
121c7f9abceSXiaoxu Zeng static const struct qm_dfx_registers qm_dfx_regs[] = {
122c7f9abceSXiaoxu Zeng { .reg_name = "QM_ECC_1BIT_CNT ", .reg_offset = 0x104000 },
123c7f9abceSXiaoxu Zeng { .reg_name = "QM_ECC_MBIT_CNT ", .reg_offset = 0x104008 },
124c7f9abceSXiaoxu Zeng { .reg_name = "QM_DFX_MB_CNT ", .reg_offset = 0x104018 },
125c7f9abceSXiaoxu Zeng { .reg_name = "QM_DFX_DB_CNT ", .reg_offset = 0x104028 },
126c7f9abceSXiaoxu Zeng { .reg_name = "QM_DFX_SQE_CNT ", .reg_offset = 0x104038 },
127c7f9abceSXiaoxu Zeng { .reg_name = "QM_DFX_CQE_CNT ", .reg_offset = 0x104048 },
128c7f9abceSXiaoxu Zeng { .reg_name = "QM_DFX_SEND_SQE_TO_ACC_CNT", .reg_offset = 0x104050 },
129c7f9abceSXiaoxu Zeng { .reg_name = "QM_DFX_WB_SQE_FROM_ACC_CNT", .reg_offset = 0x104058 },
130c7f9abceSXiaoxu Zeng { .reg_name = "QM_DFX_ACC_FINISH_CNT ", .reg_offset = 0x104060 },
131c7f9abceSXiaoxu Zeng { .reg_name = "QM_DFX_CQE_ERR_CNT ", .reg_offset = 0x1040b4 },
132c7f9abceSXiaoxu Zeng { }
133c7f9abceSXiaoxu Zeng };
134c7f9abceSXiaoxu Zeng
hisi_qm_get_version(struct hisi_qm * qm)135c7f9abceSXiaoxu Zeng void hisi_qm_get_version(struct hisi_qm *qm)
136c7f9abceSXiaoxu Zeng {
137c7f9abceSXiaoxu Zeng qm->version = io_read32(qm->io_base + HISI_QM_REVISON_ID_BASE) &
138c7f9abceSXiaoxu Zeng HISI_QM_REVISON_ID_MASK;
139c7f9abceSXiaoxu Zeng }
140c7f9abceSXiaoxu Zeng
qm_db(struct hisi_qm * qm,uint16_t qn,uint8_t cmd,uint16_t index,uint8_t priority)141c7f9abceSXiaoxu Zeng static void qm_db(struct hisi_qm *qm, uint16_t qn, uint8_t cmd, uint16_t index,
142c7f9abceSXiaoxu Zeng uint8_t priority)
143c7f9abceSXiaoxu Zeng {
144c7f9abceSXiaoxu Zeng uint64_t doorbell = 0;
145c7f9abceSXiaoxu Zeng
146c7f9abceSXiaoxu Zeng doorbell = qn | SHIFT_U64(cmd, QM_DB_CMD_SHIFT) |
147c7f9abceSXiaoxu Zeng SHIFT_U64(QM_DB_RAND_DATA, QM_DB_RAND_DATA_SHIFT) |
148c7f9abceSXiaoxu Zeng SHIFT_U64(index, QM_DB_INDEX_SHIFT) |
149c7f9abceSXiaoxu Zeng SHIFT_U64(priority, QM_DB_PRIORITY_SHIFT);
150c7f9abceSXiaoxu Zeng
151c7f9abceSXiaoxu Zeng io_write64(qm->io_base + QM_DOORBELL_SQ_CQ_BASE, doorbell);
152c7f9abceSXiaoxu Zeng }
153c7f9abceSXiaoxu Zeng
qm_mb_write(struct hisi_qm * qm,struct qm_mailbox * mb)154c7f9abceSXiaoxu Zeng static void qm_mb_write(struct hisi_qm *qm, struct qm_mailbox *mb)
155c7f9abceSXiaoxu Zeng {
156c7f9abceSXiaoxu Zeng vaddr_t dst = qm->io_base + QM_MAILBOX_BASE;
157c7f9abceSXiaoxu Zeng
1586374dbceSZexi Yu write_64bit_pair(dst, mb->x[1], mb->x[0]);
1596374dbceSZexi Yu dsb_osh();
160c7f9abceSXiaoxu Zeng }
161c7f9abceSXiaoxu Zeng
qm_mb_read(struct hisi_qm * qm,struct qm_mailbox * mb)1626374dbceSZexi Yu static void qm_mb_read(struct hisi_qm *qm, struct qm_mailbox *mb)
1636374dbceSZexi Yu {
1646374dbceSZexi Yu vaddr_t mb_base = qm->io_base + QM_MAILBOX_BASE;
1656374dbceSZexi Yu
1666374dbceSZexi Yu read_64bit_pair(mb_base, mb->x + 1, mb->x);
1676374dbceSZexi Yu dsb_osh();
1686374dbceSZexi Yu }
1696374dbceSZexi Yu
qm_wait_mb_ready(struct hisi_qm * qm)1706374dbceSZexi Yu static enum hisi_drv_status qm_wait_mb_ready(struct hisi_qm *qm)
171c7f9abceSXiaoxu Zeng {
172c7f9abceSXiaoxu Zeng struct qm_mailbox mb = { };
1736374dbceSZexi Yu uint32_t timeout = 0;
174c7f9abceSXiaoxu Zeng
1756374dbceSZexi Yu timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_READY_CNT);
1766374dbceSZexi Yu while (!timeout_elapsed(timeout)) {
1776374dbceSZexi Yu /* 128 bits should be read from hardware at one time*/
1786374dbceSZexi Yu qm_mb_read(qm, &mb);
1796374dbceSZexi Yu if (!(mb.w0 & QM_MB_BUSY_BIT))
1806374dbceSZexi Yu return HISI_QM_DRVCRYPT_NO_ERR;
1816374dbceSZexi Yu }
182c7f9abceSXiaoxu Zeng
1836374dbceSZexi Yu EMSG("QM mailbox is busy to start!");
1846374dbceSZexi Yu
185c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_EBUSY;
186c7f9abceSXiaoxu Zeng }
187c7f9abceSXiaoxu Zeng
qm_wait_mb_finish(struct hisi_qm * qm,struct qm_mailbox * mb)1886374dbceSZexi Yu static enum hisi_drv_status qm_wait_mb_finish(struct hisi_qm *qm,
1896374dbceSZexi Yu struct qm_mailbox *mb)
1906374dbceSZexi Yu {
1916374dbceSZexi Yu uint32_t timeout = 0;
192c7f9abceSXiaoxu Zeng
1936374dbceSZexi Yu timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_MAX_CNT);
1946374dbceSZexi Yu while (!timeout_elapsed(timeout)) {
1956374dbceSZexi Yu qm_mb_read(qm, mb);
1966374dbceSZexi Yu if (!(mb->w0 & QM_MB_BUSY_BIT)) {
1976374dbceSZexi Yu if (mb->w0 & QM_MB_STATUS_MASK) {
1986374dbceSZexi Yu EMSG("QM mailbox operation failed!");
1996374dbceSZexi Yu return HISI_QM_DRVCRYPT_EIO;
2006374dbceSZexi Yu } else {
2016374dbceSZexi Yu return HISI_QM_DRVCRYPT_NO_ERR;
202c7f9abceSXiaoxu Zeng }
2036374dbceSZexi Yu }
2046374dbceSZexi Yu }
2056374dbceSZexi Yu
2066374dbceSZexi Yu return HISI_QM_DRVCRYPT_ETMOUT;
2076374dbceSZexi Yu }
2086374dbceSZexi Yu
qm_mb_init(struct qm_mailbox * mb,uint8_t cmd,uint64_t base,uint16_t qnum,uint8_t op)2096374dbceSZexi Yu static void qm_mb_init(struct qm_mailbox *mb, uint8_t cmd, uint64_t base,
2106374dbceSZexi Yu uint16_t qnum, uint8_t op)
2116374dbceSZexi Yu {
2126374dbceSZexi Yu mb->w0 = cmd | SHIFT_U32(op, QM_MB_OP_SHIFT) | QM_MB_BUSY_BIT;
2136374dbceSZexi Yu mb->queue = qnum;
2146374dbceSZexi Yu reg_pair_from_64(base, &mb->base_h, &mb->base_l);
2156374dbceSZexi Yu mb->token = 0;
2166374dbceSZexi Yu }
2176374dbceSZexi Yu
qm_mb_nolock(struct hisi_qm * qm,struct qm_mailbox * mb)2186374dbceSZexi Yu static enum hisi_drv_status qm_mb_nolock(struct hisi_qm *qm,
2196374dbceSZexi Yu struct qm_mailbox *mb)
2206374dbceSZexi Yu {
2216374dbceSZexi Yu if (qm_wait_mb_ready(qm))
2226374dbceSZexi Yu return HISI_QM_DRVCRYPT_EBUSY;
2236374dbceSZexi Yu
2246374dbceSZexi Yu qm_mb_write(qm, mb);
2256374dbceSZexi Yu
2266374dbceSZexi Yu return qm_wait_mb_finish(qm, mb);
2276374dbceSZexi Yu }
2286374dbceSZexi Yu
hisi_qm_mb_write(struct hisi_qm * qm,uint8_t cmd,uintptr_t dma_addr,uint16_t qnum)2296374dbceSZexi Yu static enum hisi_drv_status hisi_qm_mb_write(struct hisi_qm *qm, uint8_t cmd,
2306374dbceSZexi Yu uintptr_t dma_addr, uint16_t qnum)
2316374dbceSZexi Yu {
2326374dbceSZexi Yu enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
2336374dbceSZexi Yu struct qm_mailbox mb = { };
2346374dbceSZexi Yu
2356374dbceSZexi Yu qm_mb_init(&mb, cmd, dma_addr, qnum, QM_MB_OP_WR);
2366374dbceSZexi Yu mutex_lock(&qm->mailbox_lock);
2376374dbceSZexi Yu ret = qm_mb_nolock(qm, &mb);
2386374dbceSZexi Yu mutex_unlock(&qm->mailbox_lock);
2396374dbceSZexi Yu
2406374dbceSZexi Yu return ret;
2416374dbceSZexi Yu }
2426374dbceSZexi Yu
hisi_qm_mb_read(struct hisi_qm * qm,uint64_t * base,uint8_t cmd,uint16_t qnum)2436374dbceSZexi Yu static enum hisi_drv_status hisi_qm_mb_read(struct hisi_qm *qm, uint64_t *base,
2446374dbceSZexi Yu uint8_t cmd, uint16_t qnum)
2456374dbceSZexi Yu {
2466374dbceSZexi Yu enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
2476374dbceSZexi Yu struct qm_mailbox mb = { };
2486374dbceSZexi Yu
2496374dbceSZexi Yu qm_mb_init(&mb, cmd, 0, qnum, QM_MB_OP_RD);
2506374dbceSZexi Yu mutex_lock(&qm->mailbox_lock);
2516374dbceSZexi Yu ret = qm_mb_nolock(qm, &mb);
2526374dbceSZexi Yu mutex_unlock(&qm->mailbox_lock);
2536374dbceSZexi Yu if (ret)
2546374dbceSZexi Yu return ret;
2556374dbceSZexi Yu
2566374dbceSZexi Yu reg_pair_from_64(*base, &mb.base_h, &mb.base_l);
257c7f9abceSXiaoxu Zeng
258c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
259c7f9abceSXiaoxu Zeng }
260c7f9abceSXiaoxu Zeng
qm_cfg_vft_data(struct hisi_qm * qm,uint8_t vft_type,uint32_t base,uint32_t number)261c7f9abceSXiaoxu Zeng static void qm_cfg_vft_data(struct hisi_qm *qm, uint8_t vft_type,
262c7f9abceSXiaoxu Zeng uint32_t base, uint32_t number)
263c7f9abceSXiaoxu Zeng {
264c7f9abceSXiaoxu Zeng uint32_t data_h = 0;
265c7f9abceSXiaoxu Zeng uint32_t data_l = 0;
266c7f9abceSXiaoxu Zeng uint64_t data = 0;
267c7f9abceSXiaoxu Zeng
268c7f9abceSXiaoxu Zeng switch (vft_type) {
269c7f9abceSXiaoxu Zeng case QM_SQC_VFT:
270c7f9abceSXiaoxu Zeng data = SHIFT_U64(base, QM_SQC_VFT_START_SQN_SHIFT) |
271c7f9abceSXiaoxu Zeng QM_SQC_VFT_VALID |
272c7f9abceSXiaoxu Zeng SHIFT_U64((number - 1), QM_SQC_VFT_SQ_NUM_SHIFT);
273c7f9abceSXiaoxu Zeng break;
274c7f9abceSXiaoxu Zeng case QM_CQC_VFT:
275c7f9abceSXiaoxu Zeng data = QM_CQC_VFT_VALID;
276c7f9abceSXiaoxu Zeng break;
277c7f9abceSXiaoxu Zeng default:
278c7f9abceSXiaoxu Zeng panic("Invalid vft type");
279c7f9abceSXiaoxu Zeng }
280c7f9abceSXiaoxu Zeng
281c7f9abceSXiaoxu Zeng reg_pair_from_64(data, &data_h, &data_l);
282c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VFT_CFG_DATA_L, data_l);
283c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VFT_CFG_DATA_H, data_h);
284c7f9abceSXiaoxu Zeng }
285c7f9abceSXiaoxu Zeng
qm_set_vft_common(struct hisi_qm * qm,uint8_t vft_type,uint32_t function,uint32_t base,uint32_t num)286c7f9abceSXiaoxu Zeng static enum hisi_drv_status qm_set_vft_common(struct hisi_qm *qm,
287c7f9abceSXiaoxu Zeng uint8_t vft_type,
288c7f9abceSXiaoxu Zeng uint32_t function,
289c7f9abceSXiaoxu Zeng uint32_t base,
290c7f9abceSXiaoxu Zeng uint32_t num)
291c7f9abceSXiaoxu Zeng {
292c7f9abceSXiaoxu Zeng uint32_t val = 0;
293c7f9abceSXiaoxu Zeng
294c7f9abceSXiaoxu Zeng if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val,
295c7f9abceSXiaoxu Zeng val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD,
296c7f9abceSXiaoxu Zeng POLL_TIMEOUT)) {
297c7f9abceSXiaoxu Zeng EMSG("QM VFT is not ready");
298c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_EBUSY;
299c7f9abceSXiaoxu Zeng }
300c7f9abceSXiaoxu Zeng
301c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VFT_CFG_OP_WR, QM_VFT_WRITE);
302c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VFT_CFG_TYPE, vft_type);
303c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VFT_CFG_ADDRESS, function);
304c7f9abceSXiaoxu Zeng qm_cfg_vft_data(qm, vft_type, base, num);
305c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VFT_CFG_RDY, 0x0);
306c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VFT_CFG_OP_ENABLE, QM_FVT_CFG_RDY_BIT);
307c7f9abceSXiaoxu Zeng
308c7f9abceSXiaoxu Zeng if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val,
309c7f9abceSXiaoxu Zeng val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD,
310c7f9abceSXiaoxu Zeng POLL_TIMEOUT)) {
311c7f9abceSXiaoxu Zeng EMSG("QM VFT is not ready");
312c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_EBUSY;
313c7f9abceSXiaoxu Zeng }
314c7f9abceSXiaoxu Zeng
315c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
316c7f9abceSXiaoxu Zeng }
317c7f9abceSXiaoxu Zeng
qm_set_xqc_vft(struct hisi_qm * qm,uint32_t function,uint32_t base,uint32_t num)318c7f9abceSXiaoxu Zeng static enum hisi_drv_status qm_set_xqc_vft(struct hisi_qm *qm,
319c7f9abceSXiaoxu Zeng uint32_t function,
320c7f9abceSXiaoxu Zeng uint32_t base, uint32_t num)
321c7f9abceSXiaoxu Zeng {
322c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
323c7f9abceSXiaoxu Zeng int i = 0;
324c7f9abceSXiaoxu Zeng
325c7f9abceSXiaoxu Zeng for (i = QM_SQC_VFT; i <= QM_CQC_VFT; i++) {
326c7f9abceSXiaoxu Zeng ret = qm_set_vft_common(qm, i, function, base, num);
327c7f9abceSXiaoxu Zeng if (ret) {
328c7f9abceSXiaoxu Zeng EMSG("QM set type %d fail", i);
329c7f9abceSXiaoxu Zeng return ret;
330c7f9abceSXiaoxu Zeng }
331c7f9abceSXiaoxu Zeng }
332c7f9abceSXiaoxu Zeng
333c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
334c7f9abceSXiaoxu Zeng }
335c7f9abceSXiaoxu Zeng
qm_get_vft(struct hisi_qm * qm,uint32_t * base,uint32_t * num)336c7f9abceSXiaoxu Zeng static enum hisi_drv_status qm_get_vft(struct hisi_qm *qm, uint32_t *base,
337c7f9abceSXiaoxu Zeng uint32_t *num)
338c7f9abceSXiaoxu Zeng {
339c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
340c7f9abceSXiaoxu Zeng uint64_t sqc_vft = 0;
341c7f9abceSXiaoxu Zeng
3426374dbceSZexi Yu ret = hisi_qm_mb_read(qm, &sqc_vft, QM_MB_CMD_SQC_VFT, 0);
343c7f9abceSXiaoxu Zeng if (ret)
344c7f9abceSXiaoxu Zeng return ret;
345c7f9abceSXiaoxu Zeng
346c7f9abceSXiaoxu Zeng *base = (sqc_vft >> QM_SQC_VFT_START_SQN_SHIFT) & QM_SQC_VFT_BASE_MASK;
347c7f9abceSXiaoxu Zeng *num = ((sqc_vft >> QM_SQC_VFT_SQ_NUM_SHIFT) & QM_SQC_VFT_NUM_MASK) + 1;
348c7f9abceSXiaoxu Zeng
349c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
350c7f9abceSXiaoxu Zeng }
351c7f9abceSXiaoxu Zeng
qp_free(struct hisi_qm * qm,uint32_t id)352c7f9abceSXiaoxu Zeng static void qp_free(struct hisi_qm *qm, uint32_t id)
353c7f9abceSXiaoxu Zeng {
354c7f9abceSXiaoxu Zeng struct hisi_qp *qp = &qm->qp_array[id];
355c7f9abceSXiaoxu Zeng
356c7f9abceSXiaoxu Zeng free(qp->sqe);
357c7f9abceSXiaoxu Zeng free(qp->cqe);
358c7f9abceSXiaoxu Zeng }
359c7f9abceSXiaoxu Zeng
qp_alloc(struct hisi_qm * qm,uint32_t id)360c7f9abceSXiaoxu Zeng static enum hisi_drv_status qp_alloc(struct hisi_qm *qm, uint32_t id)
361c7f9abceSXiaoxu Zeng {
362c7f9abceSXiaoxu Zeng size_t sq_size = qm->sqe_size * HISI_QM_Q_DEPTH;
363c7f9abceSXiaoxu Zeng size_t cq_size = sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH;
364c7f9abceSXiaoxu Zeng struct hisi_qp *qp = &qm->qp_array[id];
365c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
366c7f9abceSXiaoxu Zeng
367c7f9abceSXiaoxu Zeng qp->sqe = memalign(HISI_QM_ALIGN128, sq_size);
368c7f9abceSXiaoxu Zeng if (!qp->sqe) {
369c7f9abceSXiaoxu Zeng EMSG("Fail to malloc sq[%"PRIu32"]", id);
370c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_ENOMEM;
371c7f9abceSXiaoxu Zeng }
372c7f9abceSXiaoxu Zeng qp->sqe_dma = virt_to_phys(qp->sqe);
373c7f9abceSXiaoxu Zeng qp->cqe = memalign(HISI_QM_ALIGN32, cq_size);
374c7f9abceSXiaoxu Zeng if (!qp->cqe) {
375c7f9abceSXiaoxu Zeng EMSG("Fail to malloc cq[%"PRIu32"]", id);
376c7f9abceSXiaoxu Zeng ret = HISI_QM_DRVCRYPT_ENOMEM;
377c7f9abceSXiaoxu Zeng goto free_sqe;
378c7f9abceSXiaoxu Zeng }
379c7f9abceSXiaoxu Zeng qp->cqe_dma = virt_to_phys(qp->cqe);
380c7f9abceSXiaoxu Zeng
381c7f9abceSXiaoxu Zeng qp->qp_id = id;
382c7f9abceSXiaoxu Zeng qp->qm = qm;
383c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
384c7f9abceSXiaoxu Zeng
385c7f9abceSXiaoxu Zeng free_sqe:
386c7f9abceSXiaoxu Zeng free(qp->sqe);
387c7f9abceSXiaoxu Zeng return ret;
388c7f9abceSXiaoxu Zeng }
389c7f9abceSXiaoxu Zeng
hisi_qm_free_xqc(struct qm_xqc * xqc)390bcc9201fSZexi Yu static void hisi_qm_free_xqc(struct qm_xqc *xqc)
391bcc9201fSZexi Yu {
392bcc9201fSZexi Yu free(xqc->cqc);
393bcc9201fSZexi Yu free(xqc->sqc);
394bcc9201fSZexi Yu }
395bcc9201fSZexi Yu
qm_free(struct hisi_qm * qm)396c7f9abceSXiaoxu Zeng static void qm_free(struct hisi_qm *qm)
397c7f9abceSXiaoxu Zeng {
398c7f9abceSXiaoxu Zeng unsigned int i = 0;
399c7f9abceSXiaoxu Zeng
400c7f9abceSXiaoxu Zeng for (i = 0; i < qm->qp_num; i++)
401c7f9abceSXiaoxu Zeng qp_free(qm, i);
402c7f9abceSXiaoxu Zeng
403c7f9abceSXiaoxu Zeng free(qm->qp_array);
404bcc9201fSZexi Yu hisi_qm_free_xqc(&qm->xqc);
405bcc9201fSZexi Yu hisi_qm_free_xqc(&qm->cfg_xqc);
406bcc9201fSZexi Yu }
407bcc9201fSZexi Yu
hisi_qm_alloc_xqc(struct qm_xqc * xqc,uint32_t qp_num)408bcc9201fSZexi Yu static enum hisi_drv_status hisi_qm_alloc_xqc(struct qm_xqc *xqc,
409bcc9201fSZexi Yu uint32_t qp_num)
410bcc9201fSZexi Yu {
411bcc9201fSZexi Yu enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
412bcc9201fSZexi Yu size_t sqc_size = 0;
413bcc9201fSZexi Yu size_t cqc_size = 0;
414bcc9201fSZexi Yu
415bcc9201fSZexi Yu sqc_size = sizeof(struct qm_sqc) * qp_num;
416bcc9201fSZexi Yu cqc_size = sizeof(struct qm_cqc) * qp_num;
417bcc9201fSZexi Yu
418bcc9201fSZexi Yu xqc->sqc = memalign(HISI_QM_ALIGN32, sqc_size);
419bcc9201fSZexi Yu if (!xqc->sqc) {
420bcc9201fSZexi Yu EMSG("Fail to malloc sqc");
421bcc9201fSZexi Yu return HISI_QM_DRVCRYPT_ENOMEM;
422bcc9201fSZexi Yu }
423bcc9201fSZexi Yu memset(xqc->sqc, 0, sqc_size);
424bcc9201fSZexi Yu xqc->sqc_dma = virt_to_phys(xqc->sqc);
425bcc9201fSZexi Yu
426bcc9201fSZexi Yu xqc->cqc = memalign(HISI_QM_ALIGN32, cqc_size);
427bcc9201fSZexi Yu if (!xqc->cqc) {
428bcc9201fSZexi Yu EMSG("Fail to malloc cqc");
429bcc9201fSZexi Yu ret = HISI_QM_DRVCRYPT_ENOMEM;
430bcc9201fSZexi Yu goto free_sqc;
431bcc9201fSZexi Yu }
432bcc9201fSZexi Yu memset(xqc->cqc, 0, cqc_size);
433bcc9201fSZexi Yu xqc->cqc_dma = virt_to_phys(xqc->cqc);
434bcc9201fSZexi Yu
435bcc9201fSZexi Yu return HISI_QM_DRVCRYPT_NO_ERR;
436bcc9201fSZexi Yu
437bcc9201fSZexi Yu free(xqc->cqc);
438bcc9201fSZexi Yu free_sqc:
439bcc9201fSZexi Yu free(xqc->sqc);
440bcc9201fSZexi Yu return ret;
441c7f9abceSXiaoxu Zeng }
442c7f9abceSXiaoxu Zeng
qm_alloc(struct hisi_qm * qm)443c7f9abceSXiaoxu Zeng static enum hisi_drv_status qm_alloc(struct hisi_qm *qm)
444c7f9abceSXiaoxu Zeng {
445c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
446bcc9201fSZexi Yu int32_t j;
447bcc9201fSZexi Yu uint32_t i;
448c7f9abceSXiaoxu Zeng
449bcc9201fSZexi Yu ret = hisi_qm_alloc_xqc(&qm->xqc, qm->qp_num);
450bcc9201fSZexi Yu if (ret)
451bcc9201fSZexi Yu return ret;
452c7f9abceSXiaoxu Zeng
453bcc9201fSZexi Yu ret = hisi_qm_alloc_xqc(&qm->cfg_xqc, 1);
454bcc9201fSZexi Yu if (ret)
455bcc9201fSZexi Yu goto free_xqc;
456c7f9abceSXiaoxu Zeng
457c7f9abceSXiaoxu Zeng qm->qp_array = calloc(qm->qp_num, sizeof(struct hisi_qp));
458c7f9abceSXiaoxu Zeng if (!qm->qp_array) {
459c7f9abceSXiaoxu Zeng EMSG("Fail to malloc qp_array");
460c7f9abceSXiaoxu Zeng ret = HISI_QM_DRVCRYPT_ENOMEM;
461bcc9201fSZexi Yu goto free_cfg_xqc;
462c7f9abceSXiaoxu Zeng }
463c7f9abceSXiaoxu Zeng
464c7f9abceSXiaoxu Zeng for (i = 0; i < qm->qp_num; i++) {
465c7f9abceSXiaoxu Zeng ret = qp_alloc(qm, i);
466c7f9abceSXiaoxu Zeng if (ret)
467c7f9abceSXiaoxu Zeng goto free_qp_mem;
468c7f9abceSXiaoxu Zeng }
469c7f9abceSXiaoxu Zeng
470c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
471c7f9abceSXiaoxu Zeng
472c7f9abceSXiaoxu Zeng free_qp_mem:
473c7f9abceSXiaoxu Zeng for (j = (int)i - 1; j >= 0; j--)
474c7f9abceSXiaoxu Zeng qp_free(qm, j);
475c7f9abceSXiaoxu Zeng free(qm->qp_array);
476bcc9201fSZexi Yu free_cfg_xqc:
477bcc9201fSZexi Yu hisi_qm_free_xqc(&qm->cfg_xqc);
478bcc9201fSZexi Yu free_xqc:
479bcc9201fSZexi Yu hisi_qm_free_xqc(&qm->xqc);
480c7f9abceSXiaoxu Zeng return ret;
481c7f9abceSXiaoxu Zeng }
482c7f9abceSXiaoxu Zeng
hisi_qm_init(struct hisi_qm * qm)483c7f9abceSXiaoxu Zeng enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm)
484c7f9abceSXiaoxu Zeng {
485c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
486c7f9abceSXiaoxu Zeng
487c7f9abceSXiaoxu Zeng if (qm->fun_type == HISI_QM_HW_VF) {
488c7f9abceSXiaoxu Zeng ret = qm_get_vft(qm, &qm->qp_base, &qm->qp_num);
489c7f9abceSXiaoxu Zeng if (ret) {
490c7f9abceSXiaoxu Zeng EMSG("Fail to get function vft config");
491c7f9abceSXiaoxu Zeng return ret;
492c7f9abceSXiaoxu Zeng }
493c7f9abceSXiaoxu Zeng }
494c7f9abceSXiaoxu Zeng
495c7f9abceSXiaoxu Zeng if (!qm->qp_num || !qm->sqe_size) {
496c7f9abceSXiaoxu Zeng EMSG("Invalid QM parameters");
497c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_EINVAL;
498c7f9abceSXiaoxu Zeng }
499c7f9abceSXiaoxu Zeng
500c7f9abceSXiaoxu Zeng ret = qm_alloc(qm);
501c7f9abceSXiaoxu Zeng if (ret)
502c7f9abceSXiaoxu Zeng return ret;
503c7f9abceSXiaoxu Zeng
504c7f9abceSXiaoxu Zeng qm->qp_in_used = 0;
505c7f9abceSXiaoxu Zeng qm->qp_idx = 0;
506c7f9abceSXiaoxu Zeng mutex_init(&qm->qp_lock);
5076374dbceSZexi Yu mutex_init(&qm->mailbox_lock);
508c7f9abceSXiaoxu Zeng
509c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
510c7f9abceSXiaoxu Zeng }
511c7f9abceSXiaoxu Zeng
qm_cache_writeback(struct hisi_qm * qm)512c7f9abceSXiaoxu Zeng static void qm_cache_writeback(struct hisi_qm *qm)
513c7f9abceSXiaoxu Zeng {
514c7f9abceSXiaoxu Zeng uint32_t val = 0;
515c7f9abceSXiaoxu Zeng
516c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_CACHE_WB_START, QM_FVT_CFG_RDY_BIT);
517c7f9abceSXiaoxu Zeng
518c7f9abceSXiaoxu Zeng if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_CACHE_WB_DONE, val,
519c7f9abceSXiaoxu Zeng val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD,
520c7f9abceSXiaoxu Zeng POLL_TIMEOUT))
521c7f9abceSXiaoxu Zeng panic("QM writeback sqc cache fail");
522c7f9abceSXiaoxu Zeng }
523c7f9abceSXiaoxu Zeng
hisi_qm_uninit(struct hisi_qm * qm)524c7f9abceSXiaoxu Zeng void hisi_qm_uninit(struct hisi_qm *qm)
525c7f9abceSXiaoxu Zeng {
526c7f9abceSXiaoxu Zeng qm_cache_writeback(qm);
527c7f9abceSXiaoxu Zeng qm_free(qm);
528c7f9abceSXiaoxu Zeng mutex_destroy(&qm->qp_lock);
5296374dbceSZexi Yu mutex_destroy(&qm->mailbox_lock);
530c7f9abceSXiaoxu Zeng }
531c7f9abceSXiaoxu Zeng
qm_hw_mem_reset(struct hisi_qm * qm)532c7f9abceSXiaoxu Zeng static enum hisi_drv_status qm_hw_mem_reset(struct hisi_qm *qm)
533c7f9abceSXiaoxu Zeng {
534c7f9abceSXiaoxu Zeng uint32_t val = 0;
535c7f9abceSXiaoxu Zeng
536c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_MEM_START_INIT, QM_FVT_CFG_RDY_BIT);
537c7f9abceSXiaoxu Zeng
538c7f9abceSXiaoxu Zeng if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_MEM_INIT_DONE, val,
539c7f9abceSXiaoxu Zeng val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD,
540c7f9abceSXiaoxu Zeng POLL_TIMEOUT))
541c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_EBUSY;
542c7f9abceSXiaoxu Zeng
543c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
544c7f9abceSXiaoxu Zeng }
545c7f9abceSXiaoxu Zeng
qm_func_vft_cfg(struct hisi_qm * qm)546c7f9abceSXiaoxu Zeng static enum hisi_drv_status qm_func_vft_cfg(struct hisi_qm *qm)
547c7f9abceSXiaoxu Zeng {
548c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
549c7f9abceSXiaoxu Zeng uint32_t q_base = qm->qp_num;
550c7f9abceSXiaoxu Zeng uint32_t act_q_num = 0;
551c7f9abceSXiaoxu Zeng unsigned int i = 0;
552c7f9abceSXiaoxu Zeng unsigned int j = 0;
553c7f9abceSXiaoxu Zeng
554c7f9abceSXiaoxu Zeng if (!qm->vfs_num)
555c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
556c7f9abceSXiaoxu Zeng
557c7f9abceSXiaoxu Zeng if (qm->vfs_num > HISI_QM_MAX_VFS_NUM) {
558c7f9abceSXiaoxu Zeng EMSG("Invalid QM vfs_num");
559c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_EINVAL;
560c7f9abceSXiaoxu Zeng }
561c7f9abceSXiaoxu Zeng
562c7f9abceSXiaoxu Zeng for (i = 1; i <= qm->vfs_num; i++) {
563c7f9abceSXiaoxu Zeng act_q_num = HISI_QM_VF_Q_NUM;
564c7f9abceSXiaoxu Zeng ret = qm_set_xqc_vft(qm, i, q_base, act_q_num);
565c7f9abceSXiaoxu Zeng if (ret) {
566c7f9abceSXiaoxu Zeng for (j = 1; j < i; j++)
567c7f9abceSXiaoxu Zeng (void)qm_set_xqc_vft(qm, j, 0, 0);
568c7f9abceSXiaoxu Zeng return ret;
569c7f9abceSXiaoxu Zeng }
570c7f9abceSXiaoxu Zeng q_base += act_q_num;
571c7f9abceSXiaoxu Zeng }
572c7f9abceSXiaoxu Zeng
573c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
574c7f9abceSXiaoxu Zeng }
575c7f9abceSXiaoxu Zeng
hisi_qm_start(struct hisi_qm * qm)576c7f9abceSXiaoxu Zeng enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm)
577c7f9abceSXiaoxu Zeng {
578c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
579c7f9abceSXiaoxu Zeng
580c7f9abceSXiaoxu Zeng if (qm->fun_type == HISI_QM_HW_PF) {
581c7f9abceSXiaoxu Zeng ret = qm_hw_mem_reset(qm);
582c7f9abceSXiaoxu Zeng if (ret) {
583c7f9abceSXiaoxu Zeng EMSG("Fail to reset QM hardware mem");
584c7f9abceSXiaoxu Zeng return ret;
585c7f9abceSXiaoxu Zeng }
586c7f9abceSXiaoxu Zeng
587c7f9abceSXiaoxu Zeng ret = qm_set_xqc_vft(qm, 0, qm->qp_base, qm->qp_num);
588c7f9abceSXiaoxu Zeng if (ret) {
589c7f9abceSXiaoxu Zeng EMSG("Fail to set PF xqc_vft");
590c7f9abceSXiaoxu Zeng return ret;
591c7f9abceSXiaoxu Zeng }
592c7f9abceSXiaoxu Zeng
593c7f9abceSXiaoxu Zeng ret = qm_func_vft_cfg(qm);
594c7f9abceSXiaoxu Zeng if (ret) {
595c7f9abceSXiaoxu Zeng EMSG("Fail to set VF xqc_vft");
596c7f9abceSXiaoxu Zeng return ret;
597c7f9abceSXiaoxu Zeng }
598c7f9abceSXiaoxu Zeng }
599c7f9abceSXiaoxu Zeng
600bcc9201fSZexi Yu ret = hisi_qm_mb_write(qm, QM_MB_CMD_SQC_BT, qm->xqc.sqc_dma, 0);
601c7f9abceSXiaoxu Zeng if (ret) {
602c7f9abceSXiaoxu Zeng EMSG("Fail to set sqc_bt");
603c7f9abceSXiaoxu Zeng return ret;
604c7f9abceSXiaoxu Zeng }
605c7f9abceSXiaoxu Zeng
606bcc9201fSZexi Yu ret = hisi_qm_mb_write(qm, QM_MB_CMD_CQC_BT, qm->xqc.cqc_dma, 0);
607c7f9abceSXiaoxu Zeng if (ret) {
608c7f9abceSXiaoxu Zeng EMSG("Fail to set cqc_bt");
609c7f9abceSXiaoxu Zeng return ret;
610c7f9abceSXiaoxu Zeng }
611c7f9abceSXiaoxu Zeng
612c7f9abceSXiaoxu Zeng /* Security mode does not support msi */
613c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VF_AEQ_INT_MASK, QM_VF_AEQ_INT_MASK_EN);
614c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_VF_EQ_INT_MASK, QM_VF_EQ_INT_MASK_EN);
615c7f9abceSXiaoxu Zeng
616c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
617c7f9abceSXiaoxu Zeng }
618c7f9abceSXiaoxu Zeng
qm_disable_clock_gate(struct hisi_qm * qm)619e5dba603SZexi Yu static void qm_disable_clock_gate(struct hisi_qm *qm)
620e5dba603SZexi Yu
621e5dba603SZexi Yu {
622e5dba603SZexi Yu if (qm->version == HISI_QM_HW_V2)
623e5dba603SZexi Yu return;
624e5dba603SZexi Yu
625e5dba603SZexi Yu io_setbits32(qm->io_base + QM_PM_CTRL0, QM_IDLE_DISABLE);
626e5dba603SZexi Yu }
627e5dba603SZexi Yu
hisi_qm_dev_init(struct hisi_qm * qm)628c7f9abceSXiaoxu Zeng void hisi_qm_dev_init(struct hisi_qm *qm)
629c7f9abceSXiaoxu Zeng {
630c7f9abceSXiaoxu Zeng if (qm->fun_type == HISI_QM_HW_VF)
631c7f9abceSXiaoxu Zeng return;
632c7f9abceSXiaoxu Zeng
633e5dba603SZexi Yu qm_disable_clock_gate(qm);
634e5dba603SZexi Yu
635c7f9abceSXiaoxu Zeng /* QM user domain */
636c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_ARUSER_M_CFG_1, QM_AXUSER_CFG);
637c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_ARUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE);
638c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_AWUSER_M_CFG_1, QM_AXUSER_CFG);
639c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_AWUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE);
640c7f9abceSXiaoxu Zeng /* QM cache */
641c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_AXI_M_CFG, AXI_M_CFG);
642c7f9abceSXiaoxu Zeng
643c7f9abceSXiaoxu Zeng if (qm->version == HISI_QM_HW_V2) {
644c7f9abceSXiaoxu Zeng /* Disable FLR triggered by BME(bus master enable) */
645c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_PEH_AXUSER_CFG, PEH_AXUSER_CFG);
646c7f9abceSXiaoxu Zeng /* Set sec sqc and cqc cache wb threshold 4 */
647c7f9abceSXiaoxu Zeng io_write32(qm->io_base + QM_CACHE_CTL, QM_CACHE_CFG);
648c7f9abceSXiaoxu Zeng }
649c7f9abceSXiaoxu Zeng /* Disable QM ras */
650c7f9abceSXiaoxu Zeng io_write32(qm->io_base + HISI_QM_ABNML_INT_MASK,
651c7f9abceSXiaoxu Zeng HISI_QM_ABNML_INT_MASK_CFG);
652e5dba603SZexi Yu /* Set doorbell timeout to QM_DB_TIMEOUT_SET ns */
653e5dba603SZexi Yu io_write32(qm->io_base + QM_DB_TIMEOUT_CFG, QM_DB_TIMEOUT_SET);
654c7f9abceSXiaoxu Zeng }
655c7f9abceSXiaoxu Zeng
qm_sqc_cfg(struct hisi_qp * qp)656c7f9abceSXiaoxu Zeng static enum hisi_drv_status qm_sqc_cfg(struct hisi_qp *qp)
657c7f9abceSXiaoxu Zeng {
658c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
659c7f9abceSXiaoxu Zeng struct hisi_qm *qm = qp->qm;
660bcc9201fSZexi Yu struct qm_sqc *sqc = qm->cfg_xqc.sqc;
661bcc9201fSZexi Yu struct qm_mailbox mb = { };
662c7f9abceSXiaoxu Zeng
663bcc9201fSZexi Yu mutex_lock(&qm->mailbox_lock);
664c7f9abceSXiaoxu Zeng memset(sqc, 0, sizeof(struct qm_sqc));
665c7f9abceSXiaoxu Zeng reg_pair_from_64(qp->sqe_dma, &sqc->base_h, &sqc->base_l);
666c7f9abceSXiaoxu Zeng sqc->dw3 = (HISI_QM_Q_DEPTH - 1) |
667c7f9abceSXiaoxu Zeng SHIFT_U32(qm->sqe_log2_size, QM_SQ_SQE_SIZE_SHIFT);
668c7f9abceSXiaoxu Zeng sqc->rand_data = QM_DB_RAND_DATA;
669c7f9abceSXiaoxu Zeng sqc->cq_num = qp->qp_id;
670c7f9abceSXiaoxu Zeng sqc->w13 = BIT32(QM_SQ_ORDER_SHIFT) |
671c7f9abceSXiaoxu Zeng SHIFT_U32(qp->sq_type, QM_SQ_TYPE_SHIFT);
672c7f9abceSXiaoxu Zeng
673bcc9201fSZexi Yu qm_mb_init(&mb, QM_MB_CMD_SQC, qm->cfg_xqc.sqc_dma, qp->qp_id,
674bcc9201fSZexi Yu QM_MB_OP_WR);
675bcc9201fSZexi Yu ret = qm_mb_nolock(qm, &mb);
676bcc9201fSZexi Yu mutex_unlock(&qm->mailbox_lock);
677c7f9abceSXiaoxu Zeng
678c7f9abceSXiaoxu Zeng return ret;
679c7f9abceSXiaoxu Zeng }
680c7f9abceSXiaoxu Zeng
qm_cqc_cfg(struct hisi_qp * qp)681c7f9abceSXiaoxu Zeng static enum hisi_drv_status qm_cqc_cfg(struct hisi_qp *qp)
682c7f9abceSXiaoxu Zeng {
683c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
684c7f9abceSXiaoxu Zeng struct hisi_qm *qm = qp->qm;
685bcc9201fSZexi Yu struct qm_cqc *cqc = qm->cfg_xqc.cqc;
686bcc9201fSZexi Yu struct qm_mailbox mb = { };
687c7f9abceSXiaoxu Zeng
688bcc9201fSZexi Yu mutex_lock(&qm->mailbox_lock);
689c7f9abceSXiaoxu Zeng memset(cqc, 0, sizeof(struct qm_cqc));
690c7f9abceSXiaoxu Zeng reg_pair_from_64(qp->cqe_dma, &cqc->base_h, &cqc->base_l);
691c7f9abceSXiaoxu Zeng cqc->dw3 = (HISI_QM_Q_DEPTH - 1) |
692c7f9abceSXiaoxu Zeng SHIFT_U32(QM_CQE_SIZE, QM_CQ_CQE_SIZE_SHIFT);
693c7f9abceSXiaoxu Zeng cqc->rand_data = QM_DB_RAND_DATA;
694c7f9abceSXiaoxu Zeng cqc->dw6 = PHASE_DEFAULT_VAL;
695c7f9abceSXiaoxu Zeng
696bcc9201fSZexi Yu qm_mb_init(&mb, QM_MB_CMD_CQC, qm->cfg_xqc.cqc_dma, qp->qp_id,
697bcc9201fSZexi Yu QM_MB_OP_WR);
698bcc9201fSZexi Yu ret = qm_mb_nolock(qm, &mb);
699bcc9201fSZexi Yu mutex_unlock(&qm->mailbox_lock);
700c7f9abceSXiaoxu Zeng
701c7f9abceSXiaoxu Zeng return ret;
702c7f9abceSXiaoxu Zeng }
703c7f9abceSXiaoxu Zeng
hisi_qm_create_qp(struct hisi_qm * qm,uint8_t sq_type)704c7f9abceSXiaoxu Zeng struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type)
705c7f9abceSXiaoxu Zeng {
706c7f9abceSXiaoxu Zeng struct hisi_qp *qp = NULL;
707c50da435SZexi Yu int cur_idx = 0;
708c50da435SZexi Yu uint32_t i = 0;
709c7f9abceSXiaoxu Zeng
710c7f9abceSXiaoxu Zeng mutex_lock(&qm->qp_lock);
711c7f9abceSXiaoxu Zeng if (qm->qp_in_used == qm->qp_num) {
712c7f9abceSXiaoxu Zeng EMSG("All %"PRIu32" queues of QM are busy", qm->qp_num);
713c7f9abceSXiaoxu Zeng goto err_proc;
714c7f9abceSXiaoxu Zeng }
715c7f9abceSXiaoxu Zeng
716c50da435SZexi Yu for (i = 0; i < qm->qp_num; i++) {
717c50da435SZexi Yu cur_idx = (qm->qp_idx + i) % qm->qp_num;
718c50da435SZexi Yu if (!qm->qp_array[cur_idx].used) {
719c50da435SZexi Yu qm->qp_array[cur_idx].used = true;
720c50da435SZexi Yu qm->qp_idx = cur_idx + 1;
721c50da435SZexi Yu break;
722c50da435SZexi Yu }
723c50da435SZexi Yu }
724c7f9abceSXiaoxu Zeng
725c50da435SZexi Yu qp = qm->qp_array + cur_idx;
726c7f9abceSXiaoxu Zeng memset(qp->cqe, 0, sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH);
727c7f9abceSXiaoxu Zeng qp->sq_type = sq_type;
728c7f9abceSXiaoxu Zeng qp->sq_tail = 0;
729c7f9abceSXiaoxu Zeng qp->cq_head = 0;
730c7f9abceSXiaoxu Zeng qp->cqc_phase = true;
731c7f9abceSXiaoxu Zeng
732c7f9abceSXiaoxu Zeng if (qm_sqc_cfg(qp)) {
733c7f9abceSXiaoxu Zeng EMSG("Fail to set qp[%"PRIu32"] sqc", qp->qp_id);
734*09c44b0dSZexi Yu goto err_qp_release;
735c7f9abceSXiaoxu Zeng }
736c7f9abceSXiaoxu Zeng
737c7f9abceSXiaoxu Zeng if (qm_cqc_cfg(qp)) {
738c7f9abceSXiaoxu Zeng EMSG("Fail to set qp[%"PRIu32"] cqc", qp->qp_id);
739*09c44b0dSZexi Yu goto err_qp_release;
740c7f9abceSXiaoxu Zeng }
741c7f9abceSXiaoxu Zeng
742c7f9abceSXiaoxu Zeng qm->qp_in_used++;
743c7f9abceSXiaoxu Zeng mutex_unlock(&qm->qp_lock);
744c7f9abceSXiaoxu Zeng return qp;
745c7f9abceSXiaoxu Zeng
746*09c44b0dSZexi Yu err_qp_release:
747*09c44b0dSZexi Yu qp->used = false;
748c7f9abceSXiaoxu Zeng err_proc:
749c7f9abceSXiaoxu Zeng qp->sq_type = 0;
750c7f9abceSXiaoxu Zeng qp->cqc_phase = false;
751c7f9abceSXiaoxu Zeng mutex_unlock(&qm->qp_lock);
752c7f9abceSXiaoxu Zeng return NULL;
753c7f9abceSXiaoxu Zeng }
754c7f9abceSXiaoxu Zeng
hisi_qm_release_qp(struct hisi_qp * qp)755c7f9abceSXiaoxu Zeng void hisi_qm_release_qp(struct hisi_qp *qp)
756c7f9abceSXiaoxu Zeng {
757c7f9abceSXiaoxu Zeng struct hisi_qm *qm = NULL;
758c7f9abceSXiaoxu Zeng
759c7f9abceSXiaoxu Zeng if (!qp) {
760c7f9abceSXiaoxu Zeng EMSG("QP is NULL");
761c7f9abceSXiaoxu Zeng return;
762c7f9abceSXiaoxu Zeng }
763c7f9abceSXiaoxu Zeng
764c7f9abceSXiaoxu Zeng qm = qp->qm;
765c7f9abceSXiaoxu Zeng mutex_lock(&qm->qp_lock);
766c7f9abceSXiaoxu Zeng qm->qp_in_used--;
767c50da435SZexi Yu qp->used = false;
768c7f9abceSXiaoxu Zeng mutex_unlock(&qm->qp_lock);
769c7f9abceSXiaoxu Zeng }
770c7f9abceSXiaoxu Zeng
qm_sq_tail_update(struct hisi_qp * qp)771c7f9abceSXiaoxu Zeng static void qm_sq_tail_update(struct hisi_qp *qp)
772c7f9abceSXiaoxu Zeng {
773c7f9abceSXiaoxu Zeng if (qp->sq_tail == HISI_QM_Q_DEPTH - 1)
774c7f9abceSXiaoxu Zeng qp->sq_tail = 0;
775c7f9abceSXiaoxu Zeng else
776c7f9abceSXiaoxu Zeng qp->sq_tail++;
777c7f9abceSXiaoxu Zeng }
778c7f9abceSXiaoxu Zeng
779c7f9abceSXiaoxu Zeng /*
780c7f9abceSXiaoxu Zeng * One task thread will just bind to one hardware queue, and
781c7f9abceSXiaoxu Zeng * hardware does not support msi. So we have no lock here.
782c7f9abceSXiaoxu Zeng */
hisi_qp_send(struct hisi_qp * qp,void * msg)783c7f9abceSXiaoxu Zeng enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg)
784c7f9abceSXiaoxu Zeng {
785c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
786c7f9abceSXiaoxu Zeng struct hisi_qm *qm = NULL;
787c7f9abceSXiaoxu Zeng void *sqe = NULL;
788c7f9abceSXiaoxu Zeng
789c7f9abceSXiaoxu Zeng if (!qp) {
790c7f9abceSXiaoxu Zeng EMSG("QP is NULL");
791c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_EINVAL;
792c7f9abceSXiaoxu Zeng }
793c7f9abceSXiaoxu Zeng
794c7f9abceSXiaoxu Zeng qm = qp->qm;
795c7f9abceSXiaoxu Zeng ret = qm->dev_status_check(qm);
796c7f9abceSXiaoxu Zeng if (ret)
797c7f9abceSXiaoxu Zeng return ret;
798c7f9abceSXiaoxu Zeng
799c7f9abceSXiaoxu Zeng sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * qp->sq_tail);
800c7f9abceSXiaoxu Zeng memset(sqe, 0, qm->sqe_size);
801c7f9abceSXiaoxu Zeng
802c7f9abceSXiaoxu Zeng ret = qp->fill_sqe(sqe, msg);
803c7f9abceSXiaoxu Zeng if (ret) {
804c7f9abceSXiaoxu Zeng EMSG("Fail to fill sqe");
805c7f9abceSXiaoxu Zeng return ret;
806c7f9abceSXiaoxu Zeng }
807c7f9abceSXiaoxu Zeng
808c7f9abceSXiaoxu Zeng qm_sq_tail_update(qp);
809c7f9abceSXiaoxu Zeng
810c7f9abceSXiaoxu Zeng dsb();
811c7f9abceSXiaoxu Zeng qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_SQ, qp->sq_tail, 0);
812c7f9abceSXiaoxu Zeng
813c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
814c7f9abceSXiaoxu Zeng }
815c7f9abceSXiaoxu Zeng
qm_cq_head_update(struct hisi_qp * qp)816c7f9abceSXiaoxu Zeng static void qm_cq_head_update(struct hisi_qp *qp)
817c7f9abceSXiaoxu Zeng {
818c7f9abceSXiaoxu Zeng if (qp->cq_head == HISI_QM_Q_DEPTH - 1) {
819c7f9abceSXiaoxu Zeng qp->cqc_phase = !qp->cqc_phase;
820c7f9abceSXiaoxu Zeng qp->cq_head = 0;
821c7f9abceSXiaoxu Zeng } else {
822c7f9abceSXiaoxu Zeng qp->cq_head++;
823c7f9abceSXiaoxu Zeng }
824c7f9abceSXiaoxu Zeng }
825c7f9abceSXiaoxu Zeng
hisi_qp_recv(struct hisi_qp * qp,void * msg)826c7f9abceSXiaoxu Zeng static enum hisi_drv_status hisi_qp_recv(struct hisi_qp *qp, void *msg)
827c7f9abceSXiaoxu Zeng {
828c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
829c7f9abceSXiaoxu Zeng struct hisi_qm *qm = qp->qm;
830c7f9abceSXiaoxu Zeng struct qm_cqe *cqe = NULL;
831c7f9abceSXiaoxu Zeng void *sqe = NULL;
832c7f9abceSXiaoxu Zeng
833c7f9abceSXiaoxu Zeng ret = qm->dev_status_check(qm);
834c7f9abceSXiaoxu Zeng if (ret)
835c7f9abceSXiaoxu Zeng return ret;
836c7f9abceSXiaoxu Zeng
837c7f9abceSXiaoxu Zeng cqe = qp->cqe + qp->cq_head;
838c7f9abceSXiaoxu Zeng if (QM_CQE_PHASE(cqe) == qp->cqc_phase) {
839c7f9abceSXiaoxu Zeng dsb_osh();
840c7f9abceSXiaoxu Zeng sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * cqe->sq_head);
841c7f9abceSXiaoxu Zeng ret = qp->parse_sqe(sqe, msg);
842c7f9abceSXiaoxu Zeng qm_cq_head_update(qp);
843c7f9abceSXiaoxu Zeng qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, qp->cq_head, 0);
844c7f9abceSXiaoxu Zeng if (ret) {
845c7f9abceSXiaoxu Zeng EMSG("Fail to parse sqe");
846c7f9abceSXiaoxu Zeng return ret;
847c7f9abceSXiaoxu Zeng }
848c7f9abceSXiaoxu Zeng } else {
849c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_NO_ERR;
850c7f9abceSXiaoxu Zeng }
851c7f9abceSXiaoxu Zeng
852c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_RECV_DONE;
853c7f9abceSXiaoxu Zeng }
854c7f9abceSXiaoxu Zeng
qm_dfx_dump(struct hisi_qm * qm)855c7f9abceSXiaoxu Zeng static void qm_dfx_dump(struct hisi_qm *qm)
856c7f9abceSXiaoxu Zeng {
857c7f9abceSXiaoxu Zeng const struct qm_dfx_registers *regs = qm_dfx_regs;
858c7f9abceSXiaoxu Zeng __maybe_unused uint32_t val = 0;
859c7f9abceSXiaoxu Zeng
860c7f9abceSXiaoxu Zeng if (qm->fun_type == HISI_QM_HW_VF)
861c7f9abceSXiaoxu Zeng return;
862c7f9abceSXiaoxu Zeng
863c7f9abceSXiaoxu Zeng while (regs->reg_name) {
864c7f9abceSXiaoxu Zeng val = io_read32(qm->io_base + regs->reg_offset);
865c7f9abceSXiaoxu Zeng EMSG("%s= 0x%" PRIx32, regs->reg_name, val);
866c7f9abceSXiaoxu Zeng regs++;
867c7f9abceSXiaoxu Zeng }
868c7f9abceSXiaoxu Zeng }
869c7f9abceSXiaoxu Zeng
hisi_qp_recv_sync(struct hisi_qp * qp,void * msg)870c7f9abceSXiaoxu Zeng enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg)
871c7f9abceSXiaoxu Zeng {
872c7f9abceSXiaoxu Zeng enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
8736374dbceSZexi Yu uint32_t timeout = 0;
874c7f9abceSXiaoxu Zeng
875*09c44b0dSZexi Yu if (!qp || !qp->qm || !msg) {
876*09c44b0dSZexi Yu EMSG("Invalid qp recv sync parameters");
877c7f9abceSXiaoxu Zeng return HISI_QM_DRVCRYPT_EINVAL;
878c7f9abceSXiaoxu Zeng }
879c7f9abceSXiaoxu Zeng
8806374dbceSZexi Yu timeout = timeout_init_us(QM_SINGLE_WAIT_TIME *
8816374dbceSZexi Yu HISI_QM_RECV_SYNC_TIMEOUT);
8826374dbceSZexi Yu while (!timeout_elapsed(timeout)) {
883c7f9abceSXiaoxu Zeng ret = hisi_qp_recv(qp, msg);
8846374dbceSZexi Yu if (ret) {
8856374dbceSZexi Yu if (ret != HISI_QM_DRVCRYPT_RECV_DONE) {
886c7f9abceSXiaoxu Zeng EMSG("QM recv task error");
887c7f9abceSXiaoxu Zeng qm_dfx_dump(qp->qm);
888c7f9abceSXiaoxu Zeng return ret;
8896374dbceSZexi Yu } else {
8906374dbceSZexi Yu return HISI_QM_DRVCRYPT_NO_ERR;
891c7f9abceSXiaoxu Zeng }
892c7f9abceSXiaoxu Zeng }
893c7f9abceSXiaoxu Zeng }
8946374dbceSZexi Yu
8956374dbceSZexi Yu EMSG("QM recv task timeout");
8966374dbceSZexi Yu qm_dfx_dump(qp->qm);
8976374dbceSZexi Yu return HISI_QM_DRVCRYPT_ETMOUT;
8986374dbceSZexi Yu }
899