1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
3 */
4
5 #ifndef __ROC_MBOX_PRIV_H__
6 #define __ROC_MBOX_PRIV_H__
7
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11
12 #define SZ_64K (64ULL * 1024ULL)
13 #define SZ_1K (1ULL * 1024ULL)
14 #define MBOX_SIZE SZ_64K
15
16 /* AF/PF: PF initiated, PF/VF VF initiated */
17 #define MBOX_DOWN_RX_START 0
18 #define MBOX_DOWN_RX_SIZE (46 * SZ_1K)
19 #define MBOX_DOWN_TX_START (MBOX_DOWN_RX_START + MBOX_DOWN_RX_SIZE)
20 #define MBOX_DOWN_TX_SIZE (16 * SZ_1K)
21 /* AF/PF: AF initiated, PF/VF PF initiated */
22 #define MBOX_UP_RX_START (MBOX_DOWN_TX_START + MBOX_DOWN_TX_SIZE)
23 #define MBOX_UP_RX_SIZE SZ_1K
24 #define MBOX_UP_TX_START (MBOX_UP_RX_START + MBOX_UP_RX_SIZE)
25 #define MBOX_UP_TX_SIZE SZ_1K
26
27 #if MBOX_UP_TX_SIZE + MBOX_UP_TX_START != MBOX_SIZE
28 #error "Incorrect mailbox area sizes"
29 #endif
30
31 #define INTR_MASK(pfvfs) ((pfvfs < 64) ? (BIT_ULL(pfvfs) - 1) : (~0ull))
32
33 #define MBOX_RSP_TIMEOUT 3000 /* Time to wait for mbox response in ms */
34
35 #define MBOX_MSG_ALIGN 16 /* Align mbox msg start to 16bytes */
36
37 /* Mailbox directions */
38 #define MBOX_DIR_AFPF 0 /* AF replies to PF */
39 #define MBOX_DIR_PFAF 1 /* PF sends messages to AF */
40 #define MBOX_DIR_PFVF 2 /* PF replies to VF */
41 #define MBOX_DIR_VFPF 3 /* VF sends messages to PF */
42 #define MBOX_DIR_AFPF_UP 4 /* AF sends messages to PF */
43 #define MBOX_DIR_PFAF_UP 5 /* PF replies to AF */
44 #define MBOX_DIR_PFVF_UP 6 /* PF sends messages to VF */
45 #define MBOX_DIR_VFPF_UP 7 /* VF replies to PF */
46
47 struct mbox_dev {
48 void *mbase; /* This dev's mbox region */
49 plt_spinlock_t mbox_lock;
50 uint16_t msg_size; /* Total msg size to be sent */
51 uint16_t rsp_size; /* Total rsp size to be sure the reply is ok */
52 uint16_t num_msgs; /* No of msgs sent or waiting for response */
53 uint16_t msgs_acked; /* No of msgs for which response is received */
54 };
55
56 struct mbox {
57 uintptr_t hwbase; /* Mbox region advertised by HW */
58 uintptr_t reg_base; /* CSR base for this dev */
59 uint64_t trigger; /* Trigger mbox notification */
60 uint16_t tr_shift; /* Mbox trigger shift */
61 uint64_t rx_start; /* Offset of Rx region in mbox memory */
62 uint64_t tx_start; /* Offset of Tx region in mbox memory */
63 uint16_t rx_size; /* Size of Rx region */
64 uint16_t tx_size; /* Size of Tx region */
65 uint16_t ndevs; /* The number of peers */
66 struct mbox_dev *dev;
67 uint64_t intr_offset; /* Offset to interrupt register */
68 uint32_t rsp_tmo;
69 };
70
71 const char *mbox_id2name(uint16_t id);
72 int mbox_id2size(uint16_t id);
73 void mbox_reset(struct mbox *mbox, int devid);
74 int mbox_init(struct mbox *mbox, uintptr_t hwbase, uintptr_t reg_base,
75 int direction, int ndevsi, uint64_t intr_offset);
76 void mbox_fini(struct mbox *mbox);
77 void mbox_msg_send(struct mbox *mbox, int devid);
78 int mbox_wait_for_rsp(struct mbox *mbox, int devid);
79 int mbox_wait_for_rsp_tmo(struct mbox *mbox, int devid, uint32_t tmo);
80 int mbox_get_rsp(struct mbox *mbox, int devid, void **msg);
81 int mbox_get_rsp_tmo(struct mbox *mbox, int devid, void **msg, uint32_t tmo);
82 int mbox_get_availmem(struct mbox *mbox, int devid);
83 struct mbox_msghdr *mbox_alloc_msg_rsp(struct mbox *mbox, int devid, int size,
84 int size_rsp);
85
86 static inline struct mbox_msghdr *
mbox_alloc_msg(struct mbox * mbox,int devid,int size)87 mbox_alloc_msg(struct mbox *mbox, int devid, int size)
88 {
89 return mbox_alloc_msg_rsp(mbox, devid, size, 0);
90 }
91
92 static inline void
mbox_req_init(uint16_t mbox_id,void * msghdr)93 mbox_req_init(uint16_t mbox_id, void *msghdr)
94 {
95 struct mbox_msghdr *hdr = msghdr;
96
97 hdr->sig = MBOX_REQ_SIG;
98 hdr->ver = MBOX_VERSION;
99 hdr->id = mbox_id;
100 hdr->pcifunc = 0;
101 }
102
103 static inline void
mbox_rsp_init(uint16_t mbox_id,void * msghdr)104 mbox_rsp_init(uint16_t mbox_id, void *msghdr)
105 {
106 struct mbox_msghdr *hdr = msghdr;
107
108 hdr->sig = MBOX_RSP_SIG;
109 hdr->rc = -ETIMEDOUT;
110 hdr->id = mbox_id;
111 }
112
113 static inline bool
mbox_nonempty(struct mbox * mbox,int devid)114 mbox_nonempty(struct mbox *mbox, int devid)
115 {
116 struct mbox_dev *mdev = &mbox->dev[devid];
117 bool ret;
118
119 plt_spinlock_lock(&mdev->mbox_lock);
120 ret = mdev->num_msgs != 0;
121 plt_spinlock_unlock(&mdev->mbox_lock);
122
123 return ret;
124 }
125
126 static inline int
mbox_process(struct mbox * mbox)127 mbox_process(struct mbox *mbox)
128 {
129 mbox_msg_send(mbox, 0);
130 return mbox_get_rsp(mbox, 0, NULL);
131 }
132
133 static inline int
mbox_process_msg(struct mbox * mbox,void ** msg)134 mbox_process_msg(struct mbox *mbox, void **msg)
135 {
136 mbox_msg_send(mbox, 0);
137 return mbox_get_rsp(mbox, 0, msg);
138 }
139
140 static inline int
mbox_process_tmo(struct mbox * mbox,uint32_t tmo)141 mbox_process_tmo(struct mbox *mbox, uint32_t tmo)
142 {
143 mbox_msg_send(mbox, 0);
144 return mbox_get_rsp_tmo(mbox, 0, NULL, tmo);
145 }
146
147 static inline int
mbox_process_msg_tmo(struct mbox * mbox,void ** msg,uint32_t tmo)148 mbox_process_msg_tmo(struct mbox *mbox, void **msg, uint32_t tmo)
149 {
150 mbox_msg_send(mbox, 0);
151 return mbox_get_rsp_tmo(mbox, 0, msg, tmo);
152 }
153
154 int send_ready_msg(struct mbox *mbox, uint16_t *pf_func /* out */);
155 int reply_invalid_msg(struct mbox *mbox, int devid, uint16_t pf_func,
156 uint16_t id);
157
158 #define M(_name, _id, _fn_name, _req_type, _rsp_type) \
159 static inline struct _req_type *mbox_alloc_msg_##_fn_name( \
160 struct mbox *mbox) \
161 { \
162 struct _req_type *req; \
163 req = (struct _req_type *)mbox_alloc_msg_rsp( \
164 mbox, 0, sizeof(struct _req_type), \
165 sizeof(struct _rsp_type)); \
166 if (!req) \
167 return NULL; \
168 req->hdr.sig = MBOX_REQ_SIG; \
169 req->hdr.id = _id; \
170 plt_mbox_dbg("id=0x%x (%s)", req->hdr.id, \
171 mbox_id2name(req->hdr.id)); \
172 return req; \
173 }
174
175 MBOX_MESSAGES
176 #undef M
177
178 /* This is required for copy operations from device memory which do not work on
179 * addresses which are unaligned to 16B. This is because of specific
180 * optimizations to libc memcpy.
181 */
182 static inline volatile void *
mbox_memcpy(volatile void * d,const volatile void * s,size_t l)183 mbox_memcpy(volatile void *d, const volatile void *s, size_t l)
184 {
185 const volatile uint8_t *sb;
186 volatile uint8_t *db;
187 size_t i;
188
189 if (!d || !s)
190 return NULL;
191 db = (volatile uint8_t *)d;
192 sb = (const volatile uint8_t *)s;
193 for (i = 0; i < l; i++)
194 db[i] = sb[i];
195 return d;
196 }
197
198 /* This is required for memory operations from device memory which do not
199 * work on addresses which are unaligned to 16B. This is because of specific
200 * optimizations to libc memset.
201 */
202 static inline void
mbox_memset(volatile void * d,uint8_t val,size_t l)203 mbox_memset(volatile void *d, uint8_t val, size_t l)
204 {
205 volatile uint8_t *db;
206 size_t i = 0;
207
208 if (!d || !l)
209 return;
210 db = (volatile uint8_t *)d;
211 for (i = 0; i < l; i++)
212 db[i] = val;
213 }
214
215 #endif /* __ROC_MBOX_PRIV_H__ */
216