1266b0663SKrzysztof Zdziarski /* SPDX-License-Identifier: BSD-3-Clause */
2266b0663SKrzysztof Zdziarski /* Copyright(c) 2007-2022 Intel Corporation */
3266b0663SKrzysztof Zdziarski #include <linux/iopoll.h>
4266b0663SKrzysztof Zdziarski #include <linux/mutex.h>
5266b0663SKrzysztof Zdziarski #include <linux/types.h>
6266b0663SKrzysztof Zdziarski #include "adf_accel_devices.h"
7266b0663SKrzysztof Zdziarski #include "adf_common_drv.h"
8266b0663SKrzysztof Zdziarski #include "adf_gen4_pfvf.h"
9266b0663SKrzysztof Zdziarski #include "adf_pfvf_utils.h"
10266b0663SKrzysztof Zdziarski #include "adf_pfvf_vf_proto.h"
11266b0663SKrzysztof Zdziarski
12266b0663SKrzysztof Zdziarski #define ADF_4XXX_PF2VM_OFFSET(i) (0x40B010 + ((i)*0x20))
13266b0663SKrzysztof Zdziarski #define ADF_4XXX_VM2PF_OFFSET(i) (0x40B014 + ((i)*0x20))
14266b0663SKrzysztof Zdziarski
15266b0663SKrzysztof Zdziarski /* VF2PF interrupt source registers */
16266b0663SKrzysztof Zdziarski #define ADF_4XXX_VM2PF_SOU 0x41A180
17266b0663SKrzysztof Zdziarski #define ADF_4XXX_VM2PF_MSK 0x41A1C0
18266b0663SKrzysztof Zdziarski #define ADF_GEN4_VF_MSK 0xFFFF
19266b0663SKrzysztof Zdziarski
20266b0663SKrzysztof Zdziarski #define ADF_PFVF_GEN4_MSGTYPE_SHIFT 2
21266b0663SKrzysztof Zdziarski #define ADF_PFVF_GEN4_MSGTYPE_MASK 0x3F
22266b0663SKrzysztof Zdziarski #define ADF_PFVF_GEN4_MSGDATA_SHIFT 8
23266b0663SKrzysztof Zdziarski #define ADF_PFVF_GEN4_MSGDATA_MASK 0xFFFFFF
24266b0663SKrzysztof Zdziarski
25266b0663SKrzysztof Zdziarski #define ADF_4XXXIOV_PF2VM_OFFSET 0x100C
26266b0663SKrzysztof Zdziarski #define ADF_4XXXIOV_VM2PF_OFFSET 0x1008
27266b0663SKrzysztof Zdziarski static const struct pfvf_csr_format csr_gen4_fmt = {
28266b0663SKrzysztof Zdziarski { ADF_PFVF_GEN4_MSGTYPE_SHIFT, ADF_PFVF_GEN4_MSGTYPE_MASK },
29266b0663SKrzysztof Zdziarski { ADF_PFVF_GEN4_MSGDATA_SHIFT, ADF_PFVF_GEN4_MSGDATA_MASK },
30266b0663SKrzysztof Zdziarski };
31266b0663SKrzysztof Zdziarski
32266b0663SKrzysztof Zdziarski static u32
adf_gen4_vf_get_pfvf_offset(u32 i)33266b0663SKrzysztof Zdziarski adf_gen4_vf_get_pfvf_offset(u32 i)
34266b0663SKrzysztof Zdziarski {
35266b0663SKrzysztof Zdziarski return ADF_4XXXIOV_PF2VM_OFFSET;
36266b0663SKrzysztof Zdziarski }
37266b0663SKrzysztof Zdziarski
38266b0663SKrzysztof Zdziarski static u32
adf_gen4_vf_get_vfpf_offset(u32 i)39266b0663SKrzysztof Zdziarski adf_gen4_vf_get_vfpf_offset(u32 i)
40266b0663SKrzysztof Zdziarski {
41266b0663SKrzysztof Zdziarski return ADF_4XXXIOV_VM2PF_OFFSET;
42266b0663SKrzysztof Zdziarski }
43266b0663SKrzysztof Zdziarski
44266b0663SKrzysztof Zdziarski static int
adf_gen4_pfvf_send(struct adf_accel_dev * accel_dev,struct pfvf_message msg,u32 pfvf_offset,struct mutex * csr_lock)45266b0663SKrzysztof Zdziarski adf_gen4_pfvf_send(struct adf_accel_dev *accel_dev,
46266b0663SKrzysztof Zdziarski struct pfvf_message msg,
47266b0663SKrzysztof Zdziarski u32 pfvf_offset,
48266b0663SKrzysztof Zdziarski struct mutex *csr_lock)
49266b0663SKrzysztof Zdziarski {
50266b0663SKrzysztof Zdziarski struct resource *pmisc_addr = adf_get_pmisc_base(accel_dev);
51266b0663SKrzysztof Zdziarski u32 csr_val;
52266b0663SKrzysztof Zdziarski int ret;
53266b0663SKrzysztof Zdziarski csr_val = adf_pfvf_csr_msg_of(accel_dev, msg, &csr_gen4_fmt);
54266b0663SKrzysztof Zdziarski if (unlikely(!csr_val))
55266b0663SKrzysztof Zdziarski return -EINVAL;
56266b0663SKrzysztof Zdziarski
57266b0663SKrzysztof Zdziarski mutex_lock(csr_lock);
58266b0663SKrzysztof Zdziarski
59266b0663SKrzysztof Zdziarski ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val | ADF_PFVF_INT);
60266b0663SKrzysztof Zdziarski
61266b0663SKrzysztof Zdziarski /* Wait for confirmation from remote that it received the message */
62266b0663SKrzysztof Zdziarski ret = read_poll_timeout(ADF_CSR_RD,
63266b0663SKrzysztof Zdziarski csr_val,
64266b0663SKrzysztof Zdziarski !(csr_val & ADF_PFVF_INT),
65266b0663SKrzysztof Zdziarski ADF_PFVF_MSG_ACK_DELAY_US,
66266b0663SKrzysztof Zdziarski ADF_PFVF_MSG_ACK_MAX_DELAY_US,
67266b0663SKrzysztof Zdziarski true,
68266b0663SKrzysztof Zdziarski pmisc_addr,
69266b0663SKrzysztof Zdziarski pfvf_offset);
70266b0663SKrzysztof Zdziarski if (ret < 0)
71266b0663SKrzysztof Zdziarski device_printf(GET_DEV(accel_dev),
72266b0663SKrzysztof Zdziarski "ACK not received from remote\n");
73266b0663SKrzysztof Zdziarski
74266b0663SKrzysztof Zdziarski mutex_unlock(csr_lock);
75266b0663SKrzysztof Zdziarski return ret;
76266b0663SKrzysztof Zdziarski }
77266b0663SKrzysztof Zdziarski
78266b0663SKrzysztof Zdziarski static int
adf_gen4_vf2pf_send(struct adf_accel_dev * accel_dev,struct pfvf_message msg,u32 pfvf_offset,struct mutex * csr_lock)79266b0663SKrzysztof Zdziarski adf_gen4_vf2pf_send(struct adf_accel_dev *accel_dev,
80266b0663SKrzysztof Zdziarski struct pfvf_message msg,
81266b0663SKrzysztof Zdziarski u32 pfvf_offset,
82266b0663SKrzysztof Zdziarski struct mutex *csr_lock)
83266b0663SKrzysztof Zdziarski {
84266b0663SKrzysztof Zdziarski return adf_gen4_pfvf_send(accel_dev, msg, pfvf_offset, csr_lock);
85266b0663SKrzysztof Zdziarski }
86266b0663SKrzysztof Zdziarski
87266b0663SKrzysztof Zdziarski static struct pfvf_message
adf_gen4_pfvf_recv(struct adf_accel_dev * accel_dev,u32 pfvf_offset,u8 compat_ver)88266b0663SKrzysztof Zdziarski adf_gen4_pfvf_recv(struct adf_accel_dev *accel_dev,
89266b0663SKrzysztof Zdziarski u32 pfvf_offset,
90266b0663SKrzysztof Zdziarski u8 compat_ver)
91266b0663SKrzysztof Zdziarski {
92266b0663SKrzysztof Zdziarski struct resource *pmisc_addr = adf_get_pmisc_base(accel_dev);
93266b0663SKrzysztof Zdziarski struct pfvf_message msg = { 0 };
94266b0663SKrzysztof Zdziarski u32 csr_val;
95266b0663SKrzysztof Zdziarski
96266b0663SKrzysztof Zdziarski /* Read message from the CSR */
97266b0663SKrzysztof Zdziarski csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset);
98266b0663SKrzysztof Zdziarski if (!(csr_val & ADF_PFVF_INT)) {
99266b0663SKrzysztof Zdziarski device_printf(GET_DEV(accel_dev),
100266b0663SKrzysztof Zdziarski "Spurious PFVF interrupt, msg 0x%.8x. Ignored\n",
101266b0663SKrzysztof Zdziarski csr_val);
102266b0663SKrzysztof Zdziarski return msg;
103266b0663SKrzysztof Zdziarski }
104266b0663SKrzysztof Zdziarski
105266b0663SKrzysztof Zdziarski /* We can now acknowledge the message reception by clearing the
106266b0663SKrzysztof Zdziarski * interrupt bit
107266b0663SKrzysztof Zdziarski */
108266b0663SKrzysztof Zdziarski ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val & ~ADF_PFVF_INT);
109266b0663SKrzysztof Zdziarski
110266b0663SKrzysztof Zdziarski /* Return the pfvf_message format */
111266b0663SKrzysztof Zdziarski return adf_pfvf_message_of(accel_dev, csr_val, &csr_gen4_fmt);
112266b0663SKrzysztof Zdziarski }
113266b0663SKrzysztof Zdziarski
114266b0663SKrzysztof Zdziarski static struct pfvf_message
adf_gen4_pf2vf_recv(struct adf_accel_dev * accel_dev,u32 pfvf_offset,u8 compat_ver)115266b0663SKrzysztof Zdziarski adf_gen4_pf2vf_recv(struct adf_accel_dev *accel_dev,
116266b0663SKrzysztof Zdziarski u32 pfvf_offset,
117266b0663SKrzysztof Zdziarski u8 compat_ver)
118266b0663SKrzysztof Zdziarski {
119266b0663SKrzysztof Zdziarski return adf_gen4_pfvf_recv(accel_dev, pfvf_offset, compat_ver);
120266b0663SKrzysztof Zdziarski }
121266b0663SKrzysztof Zdziarski
122266b0663SKrzysztof Zdziarski void
adf_gen4_init_vf_pfvf_ops(struct adf_pfvf_ops * pfvf_ops)123266b0663SKrzysztof Zdziarski adf_gen4_init_vf_pfvf_ops(struct adf_pfvf_ops *pfvf_ops)
124266b0663SKrzysztof Zdziarski {
125266b0663SKrzysztof Zdziarski pfvf_ops->enable_comms = adf_enable_vf2pf_comms;
126266b0663SKrzysztof Zdziarski pfvf_ops->get_pf2vf_offset = adf_gen4_vf_get_pfvf_offset;
127266b0663SKrzysztof Zdziarski pfvf_ops->get_vf2pf_offset = adf_gen4_vf_get_vfpf_offset;
128266b0663SKrzysztof Zdziarski pfvf_ops->send_msg = adf_gen4_vf2pf_send;
129266b0663SKrzysztof Zdziarski pfvf_ops->recv_msg = adf_gen4_pf2vf_recv;
130266b0663SKrzysztof Zdziarski }
131