xref: /openbmc/linux/drivers/crypto/marvell/octeontx/otx_cptpf_mbox.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
1d9110b0bSSrujanaChalla // SPDX-License-Identifier: GPL-2.0
2d9110b0bSSrujanaChalla /* Marvell OcteonTX CPT driver
3d9110b0bSSrujanaChalla  *
4d9110b0bSSrujanaChalla  * Copyright (C) 2019 Marvell International Ltd.
5d9110b0bSSrujanaChalla  *
6d9110b0bSSrujanaChalla  * This program is free software; you can redistribute it and/or modify
7d9110b0bSSrujanaChalla  * it under the terms of the GNU General Public License version 2 as
8d9110b0bSSrujanaChalla  * published by the Free Software Foundation.
9d9110b0bSSrujanaChalla  */
10d9110b0bSSrujanaChalla 
11d9110b0bSSrujanaChalla #include "otx_cpt_common.h"
12d9110b0bSSrujanaChalla #include "otx_cptpf.h"
13d9110b0bSSrujanaChalla 
get_mbox_opcode_str(int msg_opcode)14d9110b0bSSrujanaChalla static char *get_mbox_opcode_str(int msg_opcode)
15d9110b0bSSrujanaChalla {
16d9110b0bSSrujanaChalla 	char *str = "Unknown";
17d9110b0bSSrujanaChalla 
18d9110b0bSSrujanaChalla 	switch (msg_opcode) {
19d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_VF_UP:
20d9110b0bSSrujanaChalla 		str = "UP";
21d9110b0bSSrujanaChalla 		break;
22d9110b0bSSrujanaChalla 
23d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_VF_DOWN:
24d9110b0bSSrujanaChalla 		str = "DOWN";
25d9110b0bSSrujanaChalla 		break;
26d9110b0bSSrujanaChalla 
27d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_READY:
28d9110b0bSSrujanaChalla 		str = "READY";
29d9110b0bSSrujanaChalla 		break;
30d9110b0bSSrujanaChalla 
31d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_QLEN:
32d9110b0bSSrujanaChalla 		str = "QLEN";
33d9110b0bSSrujanaChalla 		break;
34d9110b0bSSrujanaChalla 
35d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_QBIND_GRP:
36d9110b0bSSrujanaChalla 		str = "QBIND_GRP";
37d9110b0bSSrujanaChalla 		break;
38d9110b0bSSrujanaChalla 
39d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_VQ_PRIORITY:
40d9110b0bSSrujanaChalla 		str = "VQ_PRIORITY";
41d9110b0bSSrujanaChalla 		break;
42d9110b0bSSrujanaChalla 
43d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_PF_TYPE:
44d9110b0bSSrujanaChalla 		str = "PF_TYPE";
45d9110b0bSSrujanaChalla 		break;
46d9110b0bSSrujanaChalla 
47d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_ACK:
48d9110b0bSSrujanaChalla 		str = "ACK";
49d9110b0bSSrujanaChalla 		break;
50d9110b0bSSrujanaChalla 
51d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_NACK:
52d9110b0bSSrujanaChalla 		str = "NACK";
53d9110b0bSSrujanaChalla 		break;
54d9110b0bSSrujanaChalla 	}
55d9110b0bSSrujanaChalla 
56d9110b0bSSrujanaChalla 	return str;
57d9110b0bSSrujanaChalla }
58d9110b0bSSrujanaChalla 
dump_mbox_msg(struct otx_cpt_mbox * mbox_msg,int vf_id)59d9110b0bSSrujanaChalla static void dump_mbox_msg(struct otx_cpt_mbox *mbox_msg, int vf_id)
60d9110b0bSSrujanaChalla {
61d9110b0bSSrujanaChalla 	char raw_data_str[OTX_CPT_MAX_MBOX_DATA_STR_SIZE];
62d9110b0bSSrujanaChalla 
63d9110b0bSSrujanaChalla 	hex_dump_to_buffer(mbox_msg, sizeof(struct otx_cpt_mbox), 16, 8,
64d9110b0bSSrujanaChalla 			   raw_data_str, OTX_CPT_MAX_MBOX_DATA_STR_SIZE, false);
65d9110b0bSSrujanaChalla 	if (vf_id >= 0)
66*0a8f5989SChristophe JAILLET 		pr_debug("MBOX opcode %s received from VF%d raw_data %s\n",
67d9110b0bSSrujanaChalla 			 get_mbox_opcode_str(mbox_msg->msg), vf_id,
68d9110b0bSSrujanaChalla 			 raw_data_str);
69d9110b0bSSrujanaChalla 	else
70*0a8f5989SChristophe JAILLET 		pr_debug("MBOX opcode %s received from PF raw_data %s\n",
71d9110b0bSSrujanaChalla 			 get_mbox_opcode_str(mbox_msg->msg), raw_data_str);
72d9110b0bSSrujanaChalla }
73d9110b0bSSrujanaChalla 
otx_cpt_send_msg_to_vf(struct otx_cpt_device * cpt,int vf,struct otx_cpt_mbox * mbx)74d9110b0bSSrujanaChalla static void otx_cpt_send_msg_to_vf(struct otx_cpt_device *cpt, int vf,
75d9110b0bSSrujanaChalla 				   struct otx_cpt_mbox *mbx)
76d9110b0bSSrujanaChalla {
77d9110b0bSSrujanaChalla 	/* Writing mbox(0) causes interrupt */
78d9110b0bSSrujanaChalla 	writeq(mbx->data, cpt->reg_base + OTX_CPT_PF_VFX_MBOXX(vf, 1));
79d9110b0bSSrujanaChalla 	writeq(mbx->msg, cpt->reg_base + OTX_CPT_PF_VFX_MBOXX(vf, 0));
80d9110b0bSSrujanaChalla }
81d9110b0bSSrujanaChalla 
82d9110b0bSSrujanaChalla /*
83d9110b0bSSrujanaChalla  * ACKs VF's mailbox message
84d9110b0bSSrujanaChalla  * @vf: VF to which ACK to be sent
85d9110b0bSSrujanaChalla  */
otx_cpt_mbox_send_ack(struct otx_cpt_device * cpt,int vf,struct otx_cpt_mbox * mbx)86d9110b0bSSrujanaChalla static void otx_cpt_mbox_send_ack(struct otx_cpt_device *cpt, int vf,
87d9110b0bSSrujanaChalla 			      struct otx_cpt_mbox *mbx)
88d9110b0bSSrujanaChalla {
89d9110b0bSSrujanaChalla 	mbx->data = 0ull;
90d9110b0bSSrujanaChalla 	mbx->msg = OTX_CPT_MSG_ACK;
91d9110b0bSSrujanaChalla 	otx_cpt_send_msg_to_vf(cpt, vf, mbx);
92d9110b0bSSrujanaChalla }
93d9110b0bSSrujanaChalla 
94d9110b0bSSrujanaChalla /* NACKs VF's mailbox message that PF is not able to complete the action */
otx_cptpf_mbox_send_nack(struct otx_cpt_device * cpt,int vf,struct otx_cpt_mbox * mbx)95d9110b0bSSrujanaChalla static void otx_cptpf_mbox_send_nack(struct otx_cpt_device *cpt, int vf,
96d9110b0bSSrujanaChalla 				     struct otx_cpt_mbox *mbx)
97d9110b0bSSrujanaChalla {
98d9110b0bSSrujanaChalla 	mbx->data = 0ull;
99d9110b0bSSrujanaChalla 	mbx->msg = OTX_CPT_MSG_NACK;
100d9110b0bSSrujanaChalla 	otx_cpt_send_msg_to_vf(cpt, vf, mbx);
101d9110b0bSSrujanaChalla }
102d9110b0bSSrujanaChalla 
otx_cpt_clear_mbox_intr(struct otx_cpt_device * cpt,u32 vf)103d9110b0bSSrujanaChalla static void otx_cpt_clear_mbox_intr(struct otx_cpt_device *cpt, u32 vf)
104d9110b0bSSrujanaChalla {
105d9110b0bSSrujanaChalla 	/* W1C for the VF */
106d9110b0bSSrujanaChalla 	writeq(1ull << vf, cpt->reg_base + OTX_CPT_PF_MBOX_INTX(0));
107d9110b0bSSrujanaChalla }
108d9110b0bSSrujanaChalla 
109d9110b0bSSrujanaChalla /*
110d9110b0bSSrujanaChalla  * Configure QLEN/Chunk sizes for VF
111d9110b0bSSrujanaChalla  */
otx_cpt_cfg_qlen_for_vf(struct otx_cpt_device * cpt,int vf,u32 size)112d9110b0bSSrujanaChalla static void otx_cpt_cfg_qlen_for_vf(struct otx_cpt_device *cpt, int vf,
113d9110b0bSSrujanaChalla 				    u32 size)
114d9110b0bSSrujanaChalla {
115d9110b0bSSrujanaChalla 	union otx_cptx_pf_qx_ctl pf_qx_ctl;
116d9110b0bSSrujanaChalla 
117d9110b0bSSrujanaChalla 	pf_qx_ctl.u = readq(cpt->reg_base + OTX_CPT_PF_QX_CTL(vf));
118d9110b0bSSrujanaChalla 	pf_qx_ctl.s.size = size;
119d9110b0bSSrujanaChalla 	pf_qx_ctl.s.cont_err = true;
120d9110b0bSSrujanaChalla 	writeq(pf_qx_ctl.u, cpt->reg_base + OTX_CPT_PF_QX_CTL(vf));
121d9110b0bSSrujanaChalla }
122d9110b0bSSrujanaChalla 
123d9110b0bSSrujanaChalla /*
124d9110b0bSSrujanaChalla  * Configure VQ priority
125d9110b0bSSrujanaChalla  */
otx_cpt_cfg_vq_priority(struct otx_cpt_device * cpt,int vf,u32 pri)126d9110b0bSSrujanaChalla static void otx_cpt_cfg_vq_priority(struct otx_cpt_device *cpt, int vf, u32 pri)
127d9110b0bSSrujanaChalla {
128d9110b0bSSrujanaChalla 	union otx_cptx_pf_qx_ctl pf_qx_ctl;
129d9110b0bSSrujanaChalla 
130d9110b0bSSrujanaChalla 	pf_qx_ctl.u = readq(cpt->reg_base + OTX_CPT_PF_QX_CTL(vf));
131d9110b0bSSrujanaChalla 	pf_qx_ctl.s.pri = pri;
132d9110b0bSSrujanaChalla 	writeq(pf_qx_ctl.u, cpt->reg_base + OTX_CPT_PF_QX_CTL(vf));
133d9110b0bSSrujanaChalla }
134d9110b0bSSrujanaChalla 
otx_cpt_bind_vq_to_grp(struct otx_cpt_device * cpt,u8 q,u8 grp)135d9110b0bSSrujanaChalla static int otx_cpt_bind_vq_to_grp(struct otx_cpt_device *cpt, u8 q, u8 grp)
136d9110b0bSSrujanaChalla {
137d9110b0bSSrujanaChalla 	struct device *dev = &cpt->pdev->dev;
138d9110b0bSSrujanaChalla 	struct otx_cpt_eng_grp_info *eng_grp;
139d9110b0bSSrujanaChalla 	union otx_cptx_pf_qx_ctl pf_qx_ctl;
140d9110b0bSSrujanaChalla 	struct otx_cpt_ucode *ucode;
141d9110b0bSSrujanaChalla 
142d9110b0bSSrujanaChalla 	if (q >= cpt->max_vfs) {
143*0a8f5989SChristophe JAILLET 		dev_err(dev, "Requested queue %d is > than maximum avail %d\n",
144d9110b0bSSrujanaChalla 			q, cpt->max_vfs);
145d9110b0bSSrujanaChalla 		return -EINVAL;
146d9110b0bSSrujanaChalla 	}
147d9110b0bSSrujanaChalla 
148d9110b0bSSrujanaChalla 	if (grp >= OTX_CPT_MAX_ENGINE_GROUPS) {
149*0a8f5989SChristophe JAILLET 		dev_err(dev, "Requested group %d is > than maximum avail %d\n",
150d9110b0bSSrujanaChalla 			grp, OTX_CPT_MAX_ENGINE_GROUPS);
151d9110b0bSSrujanaChalla 		return -EINVAL;
152d9110b0bSSrujanaChalla 	}
153d9110b0bSSrujanaChalla 
154d9110b0bSSrujanaChalla 	eng_grp = &cpt->eng_grps.grp[grp];
155d9110b0bSSrujanaChalla 	if (!eng_grp->is_enabled) {
156*0a8f5989SChristophe JAILLET 		dev_err(dev, "Requested engine group %d is disabled\n", grp);
157d9110b0bSSrujanaChalla 		return -EINVAL;
158d9110b0bSSrujanaChalla 	}
159d9110b0bSSrujanaChalla 
160d9110b0bSSrujanaChalla 	pf_qx_ctl.u = readq(cpt->reg_base + OTX_CPT_PF_QX_CTL(q));
161d9110b0bSSrujanaChalla 	pf_qx_ctl.s.grp = grp;
162d9110b0bSSrujanaChalla 	writeq(pf_qx_ctl.u, cpt->reg_base + OTX_CPT_PF_QX_CTL(q));
163d9110b0bSSrujanaChalla 
164d9110b0bSSrujanaChalla 	if (eng_grp->mirror.is_ena)
165d9110b0bSSrujanaChalla 		ucode = &eng_grp->g->grp[eng_grp->mirror.idx].ucode[0];
166d9110b0bSSrujanaChalla 	else
167d9110b0bSSrujanaChalla 		ucode = &eng_grp->ucode[0];
168d9110b0bSSrujanaChalla 
169d9110b0bSSrujanaChalla 	if (otx_cpt_uc_supports_eng_type(ucode, OTX_CPT_SE_TYPES))
170d9110b0bSSrujanaChalla 		return OTX_CPT_SE_TYPES;
171d9110b0bSSrujanaChalla 	else if (otx_cpt_uc_supports_eng_type(ucode, OTX_CPT_AE_TYPES))
172d9110b0bSSrujanaChalla 		return OTX_CPT_AE_TYPES;
173d9110b0bSSrujanaChalla 	else
174d9110b0bSSrujanaChalla 		return BAD_OTX_CPTVF_TYPE;
175d9110b0bSSrujanaChalla }
176d9110b0bSSrujanaChalla 
177d9110b0bSSrujanaChalla /* Interrupt handler to handle mailbox messages from VFs */
otx_cpt_handle_mbox_intr(struct otx_cpt_device * cpt,int vf)178d9110b0bSSrujanaChalla static void otx_cpt_handle_mbox_intr(struct otx_cpt_device *cpt, int vf)
179d9110b0bSSrujanaChalla {
180d9110b0bSSrujanaChalla 	int vftype = 0;
181d9110b0bSSrujanaChalla 	struct otx_cpt_mbox mbx = {};
182d9110b0bSSrujanaChalla 	struct device *dev = &cpt->pdev->dev;
183d9110b0bSSrujanaChalla 	/*
184d9110b0bSSrujanaChalla 	 * MBOX[0] contains msg
185d9110b0bSSrujanaChalla 	 * MBOX[1] contains data
186d9110b0bSSrujanaChalla 	 */
187d9110b0bSSrujanaChalla 	mbx.msg  = readq(cpt->reg_base + OTX_CPT_PF_VFX_MBOXX(vf, 0));
188d9110b0bSSrujanaChalla 	mbx.data = readq(cpt->reg_base + OTX_CPT_PF_VFX_MBOXX(vf, 1));
189d9110b0bSSrujanaChalla 
190d9110b0bSSrujanaChalla 	dump_mbox_msg(&mbx, vf);
191d9110b0bSSrujanaChalla 
192d9110b0bSSrujanaChalla 	switch (mbx.msg) {
193d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_VF_UP:
194d9110b0bSSrujanaChalla 		mbx.msg  = OTX_CPT_MSG_VF_UP;
195d9110b0bSSrujanaChalla 		mbx.data = cpt->vfs_enabled;
196d9110b0bSSrujanaChalla 		otx_cpt_send_msg_to_vf(cpt, vf, &mbx);
197d9110b0bSSrujanaChalla 		break;
198d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_READY:
199d9110b0bSSrujanaChalla 		mbx.msg  = OTX_CPT_MSG_READY;
200d9110b0bSSrujanaChalla 		mbx.data = vf;
201d9110b0bSSrujanaChalla 		otx_cpt_send_msg_to_vf(cpt, vf, &mbx);
202d9110b0bSSrujanaChalla 		break;
203d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_VF_DOWN:
204d9110b0bSSrujanaChalla 		/* First msg in VF teardown sequence */
205d9110b0bSSrujanaChalla 		otx_cpt_mbox_send_ack(cpt, vf, &mbx);
206d9110b0bSSrujanaChalla 		break;
207d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_QLEN:
208d9110b0bSSrujanaChalla 		otx_cpt_cfg_qlen_for_vf(cpt, vf, mbx.data);
209d9110b0bSSrujanaChalla 		otx_cpt_mbox_send_ack(cpt, vf, &mbx);
210d9110b0bSSrujanaChalla 		break;
211d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_QBIND_GRP:
212d9110b0bSSrujanaChalla 		vftype = otx_cpt_bind_vq_to_grp(cpt, vf, (u8)mbx.data);
213d9110b0bSSrujanaChalla 		if ((vftype != OTX_CPT_AE_TYPES) &&
214d9110b0bSSrujanaChalla 		    (vftype != OTX_CPT_SE_TYPES)) {
215*0a8f5989SChristophe JAILLET 			dev_err(dev, "VF%d binding to eng group %llu failed\n",
216d9110b0bSSrujanaChalla 				vf, mbx.data);
217d9110b0bSSrujanaChalla 			otx_cptpf_mbox_send_nack(cpt, vf, &mbx);
218d9110b0bSSrujanaChalla 		} else {
219d9110b0bSSrujanaChalla 			mbx.msg = OTX_CPT_MSG_QBIND_GRP;
220d9110b0bSSrujanaChalla 			mbx.data = vftype;
221d9110b0bSSrujanaChalla 			otx_cpt_send_msg_to_vf(cpt, vf, &mbx);
222d9110b0bSSrujanaChalla 		}
223d9110b0bSSrujanaChalla 		break;
224d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_PF_TYPE:
225d9110b0bSSrujanaChalla 		mbx.msg = OTX_CPT_MSG_PF_TYPE;
226d9110b0bSSrujanaChalla 		mbx.data = cpt->pf_type;
227d9110b0bSSrujanaChalla 		otx_cpt_send_msg_to_vf(cpt, vf, &mbx);
228d9110b0bSSrujanaChalla 		break;
229d9110b0bSSrujanaChalla 	case OTX_CPT_MSG_VQ_PRIORITY:
230d9110b0bSSrujanaChalla 		otx_cpt_cfg_vq_priority(cpt, vf, mbx.data);
231d9110b0bSSrujanaChalla 		otx_cpt_mbox_send_ack(cpt, vf, &mbx);
232d9110b0bSSrujanaChalla 		break;
233d9110b0bSSrujanaChalla 	default:
234d9110b0bSSrujanaChalla 		dev_err(&cpt->pdev->dev, "Invalid msg from VF%d, msg 0x%llx\n",
235d9110b0bSSrujanaChalla 			vf, mbx.msg);
236d9110b0bSSrujanaChalla 		break;
237d9110b0bSSrujanaChalla 	}
238d9110b0bSSrujanaChalla }
239d9110b0bSSrujanaChalla 
otx_cpt_mbox_intr_handler(struct otx_cpt_device * cpt,int mbx)240d9110b0bSSrujanaChalla void otx_cpt_mbox_intr_handler (struct otx_cpt_device *cpt, int mbx)
241d9110b0bSSrujanaChalla {
242d9110b0bSSrujanaChalla 	u64 intr;
243d9110b0bSSrujanaChalla 	u8  vf;
244d9110b0bSSrujanaChalla 
245d9110b0bSSrujanaChalla 	intr = readq(cpt->reg_base + OTX_CPT_PF_MBOX_INTX(0));
246d9110b0bSSrujanaChalla 	pr_debug("PF interrupt mbox%d mask 0x%llx\n", mbx, intr);
247d9110b0bSSrujanaChalla 	for (vf = 0; vf < cpt->max_vfs; vf++) {
248d9110b0bSSrujanaChalla 		if (intr & (1ULL << vf)) {
249d9110b0bSSrujanaChalla 			otx_cpt_handle_mbox_intr(cpt, vf);
250d9110b0bSSrujanaChalla 			otx_cpt_clear_mbox_intr(cpt, vf);
251d9110b0bSSrujanaChalla 		}
252d9110b0bSSrujanaChalla 	}
253d9110b0bSSrujanaChalla }
254