1*19d8e8c7SSrujana Challa // SPDX-License-Identifier: GPL-2.0-only
2*19d8e8c7SSrujana Challa /* Copyright (C) 2020 Marvell. */
3*19d8e8c7SSrujana Challa 
4*19d8e8c7SSrujana Challa #include "otx2_cpt_common.h"
5*19d8e8c7SSrujana Challa #include "otx2_cptvf.h"
6*19d8e8c7SSrujana Challa #include <rvu_reg.h>
7*19d8e8c7SSrujana Challa 
8*19d8e8c7SSrujana Challa irqreturn_t otx2_cptvf_pfvf_mbox_intr(int __always_unused irq, void *arg)
9*19d8e8c7SSrujana Challa {
10*19d8e8c7SSrujana Challa 	struct otx2_cptvf_dev *cptvf = arg;
11*19d8e8c7SSrujana Challa 	u64 intr;
12*19d8e8c7SSrujana Challa 
13*19d8e8c7SSrujana Challa 	/* Read the interrupt bits */
14*19d8e8c7SSrujana Challa 	intr = otx2_cpt_read64(cptvf->reg_base, BLKADDR_RVUM, 0,
15*19d8e8c7SSrujana Challa 			       OTX2_RVU_VF_INT);
16*19d8e8c7SSrujana Challa 
17*19d8e8c7SSrujana Challa 	if (intr & 0x1ULL) {
18*19d8e8c7SSrujana Challa 		/* Schedule work queue function to process the MBOX request */
19*19d8e8c7SSrujana Challa 		queue_work(cptvf->pfvf_mbox_wq, &cptvf->pfvf_mbox_work);
20*19d8e8c7SSrujana Challa 		/* Clear and ack the interrupt */
21*19d8e8c7SSrujana Challa 		otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0,
22*19d8e8c7SSrujana Challa 				 OTX2_RVU_VF_INT, 0x1ULL);
23*19d8e8c7SSrujana Challa 	}
24*19d8e8c7SSrujana Challa 	return IRQ_HANDLED;
25*19d8e8c7SSrujana Challa }
26*19d8e8c7SSrujana Challa 
27*19d8e8c7SSrujana Challa static void process_pfvf_mbox_mbox_msg(struct otx2_cptvf_dev *cptvf,
28*19d8e8c7SSrujana Challa 				       struct mbox_msghdr *msg)
29*19d8e8c7SSrujana Challa {
30*19d8e8c7SSrujana Challa 	struct otx2_cptlfs_info *lfs = &cptvf->lfs;
31*19d8e8c7SSrujana Challa 	struct cpt_rd_wr_reg_msg *rsp_reg;
32*19d8e8c7SSrujana Challa 	struct msix_offset_rsp *rsp_msix;
33*19d8e8c7SSrujana Challa 	int i;
34*19d8e8c7SSrujana Challa 
35*19d8e8c7SSrujana Challa 	if (msg->id >= MBOX_MSG_MAX) {
36*19d8e8c7SSrujana Challa 		dev_err(&cptvf->pdev->dev,
37*19d8e8c7SSrujana Challa 			"MBOX msg with unknown ID %d\n", msg->id);
38*19d8e8c7SSrujana Challa 		return;
39*19d8e8c7SSrujana Challa 	}
40*19d8e8c7SSrujana Challa 	if (msg->sig != OTX2_MBOX_RSP_SIG) {
41*19d8e8c7SSrujana Challa 		dev_err(&cptvf->pdev->dev,
42*19d8e8c7SSrujana Challa 			"MBOX msg with wrong signature %x, ID %d\n",
43*19d8e8c7SSrujana Challa 			msg->sig, msg->id);
44*19d8e8c7SSrujana Challa 		return;
45*19d8e8c7SSrujana Challa 	}
46*19d8e8c7SSrujana Challa 	switch (msg->id) {
47*19d8e8c7SSrujana Challa 	case MBOX_MSG_READY:
48*19d8e8c7SSrujana Challa 		cptvf->vf_id = ((msg->pcifunc >> RVU_PFVF_FUNC_SHIFT)
49*19d8e8c7SSrujana Challa 				& RVU_PFVF_FUNC_MASK) - 1;
50*19d8e8c7SSrujana Challa 		break;
51*19d8e8c7SSrujana Challa 	case MBOX_MSG_ATTACH_RESOURCES:
52*19d8e8c7SSrujana Challa 		/* Check if resources were successfully attached */
53*19d8e8c7SSrujana Challa 		if (!msg->rc)
54*19d8e8c7SSrujana Challa 			lfs->are_lfs_attached = 1;
55*19d8e8c7SSrujana Challa 		break;
56*19d8e8c7SSrujana Challa 	case MBOX_MSG_DETACH_RESOURCES:
57*19d8e8c7SSrujana Challa 		/* Check if resources were successfully detached */
58*19d8e8c7SSrujana Challa 		if (!msg->rc)
59*19d8e8c7SSrujana Challa 			lfs->are_lfs_attached = 0;
60*19d8e8c7SSrujana Challa 		break;
61*19d8e8c7SSrujana Challa 	case MBOX_MSG_MSIX_OFFSET:
62*19d8e8c7SSrujana Challa 		rsp_msix = (struct msix_offset_rsp *) msg;
63*19d8e8c7SSrujana Challa 		for (i = 0; i < rsp_msix->cptlfs; i++)
64*19d8e8c7SSrujana Challa 			lfs->lf[i].msix_offset = rsp_msix->cptlf_msixoff[i];
65*19d8e8c7SSrujana Challa 		break;
66*19d8e8c7SSrujana Challa 	case MBOX_MSG_CPT_RD_WR_REGISTER:
67*19d8e8c7SSrujana Challa 		rsp_reg = (struct cpt_rd_wr_reg_msg *) msg;
68*19d8e8c7SSrujana Challa 		if (msg->rc) {
69*19d8e8c7SSrujana Challa 			dev_err(&cptvf->pdev->dev,
70*19d8e8c7SSrujana Challa 				"Reg %llx rd/wr(%d) failed %d\n",
71*19d8e8c7SSrujana Challa 				rsp_reg->reg_offset, rsp_reg->is_write,
72*19d8e8c7SSrujana Challa 				msg->rc);
73*19d8e8c7SSrujana Challa 			return;
74*19d8e8c7SSrujana Challa 		}
75*19d8e8c7SSrujana Challa 		if (!rsp_reg->is_write)
76*19d8e8c7SSrujana Challa 			*rsp_reg->ret_val = rsp_reg->val;
77*19d8e8c7SSrujana Challa 		break;
78*19d8e8c7SSrujana Challa 	default:
79*19d8e8c7SSrujana Challa 		dev_err(&cptvf->pdev->dev, "Unsupported msg %d received.\n",
80*19d8e8c7SSrujana Challa 			msg->id);
81*19d8e8c7SSrujana Challa 		break;
82*19d8e8c7SSrujana Challa 	}
83*19d8e8c7SSrujana Challa }
84*19d8e8c7SSrujana Challa 
85*19d8e8c7SSrujana Challa void otx2_cptvf_pfvf_mbox_handler(struct work_struct *work)
86*19d8e8c7SSrujana Challa {
87*19d8e8c7SSrujana Challa 	struct otx2_cptvf_dev *cptvf;
88*19d8e8c7SSrujana Challa 	struct otx2_mbox *pfvf_mbox;
89*19d8e8c7SSrujana Challa 	struct otx2_mbox_dev *mdev;
90*19d8e8c7SSrujana Challa 	struct mbox_hdr *rsp_hdr;
91*19d8e8c7SSrujana Challa 	struct mbox_msghdr *msg;
92*19d8e8c7SSrujana Challa 	int offset, i;
93*19d8e8c7SSrujana Challa 
94*19d8e8c7SSrujana Challa 	/* sync with mbox memory region */
95*19d8e8c7SSrujana Challa 	smp_rmb();
96*19d8e8c7SSrujana Challa 
97*19d8e8c7SSrujana Challa 	cptvf = container_of(work, struct otx2_cptvf_dev, pfvf_mbox_work);
98*19d8e8c7SSrujana Challa 	pfvf_mbox = &cptvf->pfvf_mbox;
99*19d8e8c7SSrujana Challa 	mdev = &pfvf_mbox->dev[0];
100*19d8e8c7SSrujana Challa 	rsp_hdr = (struct mbox_hdr *)(mdev->mbase + pfvf_mbox->rx_start);
101*19d8e8c7SSrujana Challa 	if (rsp_hdr->num_msgs == 0)
102*19d8e8c7SSrujana Challa 		return;
103*19d8e8c7SSrujana Challa 	offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
104*19d8e8c7SSrujana Challa 
105*19d8e8c7SSrujana Challa 	for (i = 0; i < rsp_hdr->num_msgs; i++) {
106*19d8e8c7SSrujana Challa 		msg = (struct mbox_msghdr *)(mdev->mbase + pfvf_mbox->rx_start +
107*19d8e8c7SSrujana Challa 					     offset);
108*19d8e8c7SSrujana Challa 		process_pfvf_mbox_mbox_msg(cptvf, msg);
109*19d8e8c7SSrujana Challa 		offset = msg->next_msgoff;
110*19d8e8c7SSrujana Challa 		mdev->msgs_acked++;
111*19d8e8c7SSrujana Challa 	}
112*19d8e8c7SSrujana Challa 	otx2_mbox_reset(pfvf_mbox, 0);
113*19d8e8c7SSrujana Challa }
114