xref: /freebsd/sys/dev/qat/qat_common/adf_gen4_pfvf.c (revision ded037e65e5239671b1292ec987a2e0894b217b5)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2025 Intel Corporation */
3 #include <linux/iopoll.h>
4 #include <linux/types.h>
5 #include "adf_accel_devices.h"
6 #include "adf_common_drv.h"
7 #include "adf_gen4_pfvf.h"
8 #include "adf_pfvf_utils.h"
9 #include "adf_pfvf_vf_proto.h"
10 
11 #define ADF_4XXX_PF2VM_OFFSET(i) (0x40B010 + ((i)*0x20))
12 #define ADF_4XXX_VM2PF_OFFSET(i) (0x40B014 + ((i)*0x20))
13 
14 /* VF2PF interrupt source registers */
15 #define ADF_4XXX_VM2PF_SOU 0x41A180
16 #define ADF_4XXX_VM2PF_MSK 0x41A1C0
17 #define ADF_GEN4_VF_MSK 0xFFFF
18 
19 #define ADF_PFVF_GEN4_MSGTYPE_SHIFT 2
20 #define ADF_PFVF_GEN4_MSGTYPE_MASK 0x3F
21 #define ADF_PFVF_GEN4_MSGDATA_SHIFT 8
22 #define ADF_PFVF_GEN4_MSGDATA_MASK 0xFFFFFF
23 
24 #define ADF_4XXXIOV_PF2VM_OFFSET 0x100C
25 #define ADF_4XXXIOV_VM2PF_OFFSET 0x1008
26 static const struct pfvf_csr_format csr_gen4_fmt = {
27 	{ ADF_PFVF_GEN4_MSGTYPE_SHIFT, ADF_PFVF_GEN4_MSGTYPE_MASK },
28 	{ ADF_PFVF_GEN4_MSGDATA_SHIFT, ADF_PFVF_GEN4_MSGDATA_MASK },
29 };
30 
31 static u32
adf_gen4_vf_get_pfvf_offset(u32 i)32 adf_gen4_vf_get_pfvf_offset(u32 i)
33 {
34 	return ADF_4XXXIOV_PF2VM_OFFSET;
35 }
36 
37 static u32
adf_gen4_vf_get_vfpf_offset(u32 i)38 adf_gen4_vf_get_vfpf_offset(u32 i)
39 {
40 	return ADF_4XXXIOV_VM2PF_OFFSET;
41 }
42 
43 static int
adf_gen4_pfvf_send(struct adf_accel_dev * accel_dev,struct pfvf_message msg,u32 pfvf_offset,struct mutex * csr_lock)44 adf_gen4_pfvf_send(struct adf_accel_dev *accel_dev,
45 		   struct pfvf_message msg,
46 		   u32 pfvf_offset,
47 		   struct mutex *csr_lock)
48 {
49 	struct resource *pmisc_addr = adf_get_pmisc_base(accel_dev);
50 	u32 csr_val;
51 	int ret;
52 	csr_val = adf_pfvf_csr_msg_of(accel_dev, msg, &csr_gen4_fmt);
53 	if (unlikely(!csr_val))
54 		return -EINVAL;
55 
56 	mutex_lock(csr_lock);
57 
58 	ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val | ADF_PFVF_INT);
59 
60 	/* Wait for confirmation from remote that it received the message */
61 	ret = read_poll_timeout(ADF_CSR_RD,
62 				csr_val,
63 				!(csr_val & ADF_PFVF_INT),
64 				ADF_PFVF_MSG_ACK_DELAY_US,
65 				ADF_PFVF_MSG_ACK_MAX_DELAY_US,
66 				true,
67 				pmisc_addr,
68 				pfvf_offset);
69 	if (ret < 0)
70 		device_printf(GET_DEV(accel_dev),
71 			      "ACK not received from remote\n");
72 
73 	mutex_unlock(csr_lock);
74 	return ret;
75 }
76 
77 static int
adf_gen4_vf2pf_send(struct adf_accel_dev * accel_dev,struct pfvf_message msg,u32 pfvf_offset,struct mutex * csr_lock)78 adf_gen4_vf2pf_send(struct adf_accel_dev *accel_dev,
79 		    struct pfvf_message msg,
80 		    u32 pfvf_offset,
81 		    struct mutex *csr_lock)
82 {
83 	return adf_gen4_pfvf_send(accel_dev, msg, pfvf_offset, csr_lock);
84 }
85 
86 static struct pfvf_message
adf_gen4_pfvf_recv(struct adf_accel_dev * accel_dev,u32 pfvf_offset,u8 compat_ver)87 adf_gen4_pfvf_recv(struct adf_accel_dev *accel_dev,
88 		   u32 pfvf_offset,
89 		   u8 compat_ver)
90 {
91 	struct resource *pmisc_addr = adf_get_pmisc_base(accel_dev);
92 	struct pfvf_message msg = { 0 };
93 	u32 csr_val;
94 
95 	/* Read message from the CSR */
96 	csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset);
97 	if (!(csr_val & ADF_PFVF_INT)) {
98 		device_printf(GET_DEV(accel_dev),
99 			      "Spurious PFVF interrupt, msg 0x%.8x. Ignored\n",
100 			      csr_val);
101 		return msg;
102 	}
103 
104 	/* We can now acknowledge the message reception by clearing the
105 	 * interrupt bit
106 	 */
107 	ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val & ~ADF_PFVF_INT);
108 
109 	/* Return the pfvf_message format */
110 	return adf_pfvf_message_of(accel_dev, csr_val, &csr_gen4_fmt);
111 }
112 
113 static struct pfvf_message
adf_gen4_pf2vf_recv(struct adf_accel_dev * accel_dev,u32 pfvf_offset,u8 compat_ver)114 adf_gen4_pf2vf_recv(struct adf_accel_dev *accel_dev,
115 		    u32 pfvf_offset,
116 		    u8 compat_ver)
117 {
118 	return adf_gen4_pfvf_recv(accel_dev, pfvf_offset, compat_ver);
119 }
120 
121 void
adf_gen4_init_vf_pfvf_ops(struct adf_pfvf_ops * pfvf_ops)122 adf_gen4_init_vf_pfvf_ops(struct adf_pfvf_ops *pfvf_ops)
123 {
124 	pfvf_ops->enable_comms = adf_enable_vf2pf_comms;
125 	pfvf_ops->get_pf2vf_offset = adf_gen4_vf_get_pfvf_offset;
126 	pfvf_ops->get_vf2pf_offset = adf_gen4_vf_get_vfpf_offset;
127 	pfvf_ops->send_msg = adf_gen4_vf2pf_send;
128 	pfvf_ops->recv_msg = adf_gen4_pf2vf_recv;
129 }
130