summaryrefslogtreecommitdiffstats
path: root/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c
blob: d80d493a775689380e46410f3658d26e026ccd2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
/* Copyright(c) 2021 Intel Corporation */
#include <linux/iopoll.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include "adf_accel_devices.h"
#include "adf_common_drv.h"
#include "adf_gen4_pfvf.h"
#include "adf_pfvf_pf_proto.h"
#include "adf_pfvf_utils.h"

#define ADF_4XXX_PF2VM_OFFSET(i)	(0x40B010 + ((i) * 0x20))
#define ADF_4XXX_VM2PF_OFFSET(i)	(0x40B014 + ((i) * 0x20))

/* VF2PF interrupt source registers */
#define ADF_4XXX_VM2PF_SOU		0x41A180
#define ADF_4XXX_VM2PF_MSK		0x41A1C0

#define ADF_PFVF_GEN4_MSGTYPE_SHIFT	2
#define ADF_PFVF_GEN4_MSGTYPE_MASK	0x3F
#define ADF_PFVF_GEN4_MSGDATA_SHIFT	8
#define ADF_PFVF_GEN4_MSGDATA_MASK	0xFFFFFF

static const struct pfvf_csr_format csr_gen4_fmt = {
	{ ADF_PFVF_GEN4_MSGTYPE_SHIFT, ADF_PFVF_GEN4_MSGTYPE_MASK },
	{ ADF_PFVF_GEN4_MSGDATA_SHIFT, ADF_PFVF_GEN4_MSGDATA_MASK },
};

static u32 adf_gen4_pf_get_pf2vf_offset(u32 i)
{
	return ADF_4XXX_PF2VM_OFFSET(i);
}

static u32 adf_gen4_pf_get_vf2pf_offset(u32 i)
{
	return ADF_4XXX_VM2PF_OFFSET(i);
}

static u32 adf_gen4_get_vf2pf_sources(void __iomem *pmisc_addr)
{
	u32 sou, mask;

	sou = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_SOU);
	mask = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK);

	return sou & ~mask;
}

static void adf_gen4_enable_vf2pf_interrupts(void __iomem *pmisc_addr,
					     u32 vf_mask)
{
	unsigned int val;

	val = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK) & ~vf_mask;
	ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, val);
}

static void adf_gen4_disable_vf2pf_interrupts(void __iomem *pmisc_addr,
					      u32 vf_mask)
{
	unsigned int val;

	val = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK) | vf_mask;
	ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, val);
}

static int adf_gen4_pfvf_send(struct adf_accel_dev *accel_dev,
			      struct pfvf_message msg, u32 pfvf_offset,
			      struct mutex *csr_lock)
{
	void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
	u32 csr_val;
	int ret;

	csr_val = adf_pfvf_csr_msg_of(accel_dev, msg, &csr_gen4_fmt);
	if (unlikely(!csr_val))
		return -EINVAL;

	mutex_lock(csr_lock);

	ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val | ADF_PFVF_INT);

	/* Wait for confirmation from remote that it received the message */
	ret = read_poll_timeout(ADF_CSR_RD, csr_val, !(csr_val & ADF_PFVF_INT),
				ADF_PFVF_MSG_ACK_DELAY_US,
				ADF_PFVF_MSG_ACK_MAX_DELAY_US,
				true, pmisc_addr, pfvf_offset);
	if (ret < 0)
		dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n");

	mutex_unlock(csr_lock);
	return ret;
}

static struct pfvf_message adf_gen4_pfvf_recv(struct adf_accel_dev *accel_dev,
					      u32 pfvf_offset, u8 compat_ver)
{
	void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
	u32 csr_val;

	/* Read message from the CSR */
	csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset);

	/* We can now acknowledge the message reception by clearing the
	 * interrupt bit
	 */
	ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val & ~ADF_PFVF_INT);

	/* Return the pfvf_message format */
	return adf_pfvf_message_of(accel_dev, csr_val, &csr_gen4_fmt);
}

void adf_gen4_init_pf_pfvf_ops(struct adf_pfvf_ops *pfvf_ops)
{
	pfvf_ops->enable_comms = adf_enable_pf2vf_comms;
	pfvf_ops->get_pf2vf_offset = adf_gen4_pf_get_pf2vf_offset;
	pfvf_ops->get_vf2pf_offset = adf_gen4_pf_get_vf2pf_offset;
	pfvf_ops->get_vf2pf_sources = adf_gen4_get_vf2pf_sources;
	pfvf_ops->enable_vf2pf_interrupts = adf_gen4_enable_vf2pf_interrupts;
	pfvf_ops->disable_vf2pf_interrupts = adf_gen4_disable_vf2pf_interrupts;
	pfvf_ops->send_msg = adf_gen4_pfvf_send;
	pfvf_ops->recv_msg = adf_gen4_pfvf_recv;
}
EXPORT_SYMBOL_GPL(adf_gen4_init_pf_pfvf_ops);