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 32 adf_gen4_vf_get_pfvf_offset(u32 i) 33 { 34 return ADF_4XXXIOV_PF2VM_OFFSET; 35 } 36 37 static u32 38 adf_gen4_vf_get_vfpf_offset(u32 i) 39 { 40 return ADF_4XXXIOV_VM2PF_OFFSET; 41 } 42 43 static int 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 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 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 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 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