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