xref: /linux/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c (revision fab183d632628381b466a41479489541ac0e29a0)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2022 - 2025 Mucse Corporation. */
3 
4 #include <linux/errno.h>
5 #include <linux/bitfield.h>
6 #include <linux/iopoll.h>
7 
8 #include "rnpgbe_mbx.h"
9 
10 /**
11  * mbx_data_rd32 - Reads reg with base mbx->fwpf_shm_base
12  * @mbx: pointer to the MBX structure
13  * @reg: register offset
14  *
15  * Return: register value
16  **/
mbx_data_rd32(struct mucse_mbx_info * mbx,u32 reg)17 static u32 mbx_data_rd32(struct mucse_mbx_info *mbx, u32 reg)
18 {
19 	struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx);
20 
21 	return readl(hw->hw_addr + mbx->fwpf_shm_base + reg);
22 }
23 
24 /**
25  * mbx_data_wr32 - Writes value to reg with base mbx->fwpf_shm_base
26  * @mbx: pointer to the MBX structure
27  * @reg: register offset
28  * @value: value to be written
29  *
30  **/
mbx_data_wr32(struct mucse_mbx_info * mbx,u32 reg,u32 value)31 static void mbx_data_wr32(struct mucse_mbx_info *mbx, u32 reg, u32 value)
32 {
33 	struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx);
34 
35 	writel(value, hw->hw_addr + mbx->fwpf_shm_base + reg);
36 }
37 
38 /**
39  * mbx_ctrl_rd32 - Reads reg with base mbx->fwpf_ctrl_base
40  * @mbx: pointer to the MBX structure
41  * @reg: register offset
42  *
43  * Return: register value
44  **/
mbx_ctrl_rd32(struct mucse_mbx_info * mbx,u32 reg)45 static u32 mbx_ctrl_rd32(struct mucse_mbx_info *mbx, u32 reg)
46 {
47 	struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx);
48 
49 	return readl(hw->hw_addr + mbx->fwpf_ctrl_base + reg);
50 }
51 
52 /**
53  * mbx_ctrl_wr32 - Writes value to reg with base mbx->fwpf_ctrl_base
54  * @mbx: pointer to the MBX structure
55  * @reg: register offset
56  * @value: value to be written
57  *
58  **/
mbx_ctrl_wr32(struct mucse_mbx_info * mbx,u32 reg,u32 value)59 static void mbx_ctrl_wr32(struct mucse_mbx_info *mbx, u32 reg, u32 value)
60 {
61 	struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx);
62 
63 	writel(value, hw->hw_addr + mbx->fwpf_ctrl_base + reg);
64 }
65 
66 /**
67  * mucse_mbx_get_lock_pf - Write ctrl and read back lock status
68  * @hw: pointer to the HW structure
69  *
70  * Return: register value after write
71  **/
mucse_mbx_get_lock_pf(struct mucse_hw * hw)72 static u32 mucse_mbx_get_lock_pf(struct mucse_hw *hw)
73 {
74 	struct mucse_mbx_info *mbx = &hw->mbx;
75 	u32 reg = MUCSE_MBX_PF2FW_CTRL(mbx);
76 
77 	mbx_ctrl_wr32(mbx, reg, MUCSE_MBX_PFU);
78 
79 	return mbx_ctrl_rd32(mbx, reg);
80 }
81 
82 /**
83  * mucse_obtain_mbx_lock_pf - Obtain mailbox lock
84  * @hw: pointer to the HW structure
85  *
86  * Pair with mucse_release_mbx_lock_pf()
87  * This function maybe used in an irq handler.
88  *
89  * Return: 0 on success, negative errno on failure
90  **/
mucse_obtain_mbx_lock_pf(struct mucse_hw * hw)91 static int mucse_obtain_mbx_lock_pf(struct mucse_hw *hw)
92 {
93 	struct mucse_mbx_info *mbx = &hw->mbx;
94 	u32 val;
95 
96 	return read_poll_timeout_atomic(mucse_mbx_get_lock_pf,
97 					val, val & MUCSE_MBX_PFU,
98 					mbx->delay_us,
99 					mbx->timeout_us,
100 					false, hw);
101 }
102 
103 /**
104  * mucse_release_mbx_lock_pf - Release mailbox lock
105  * @hw: pointer to the HW structure
106  * @req: send a request or not
107  *
108  * Pair with mucse_obtain_mbx_lock_pf():
109  * - Releases the mailbox lock by clearing MUCSE_MBX_PFU bit
110  * - Simultaneously sends the request by setting MUCSE_MBX_REQ bit
111  *   if req is true
112  * (Both bits are in the same mailbox control register,
113  * so operations are combined)
114  **/
mucse_release_mbx_lock_pf(struct mucse_hw * hw,bool req)115 static void mucse_release_mbx_lock_pf(struct mucse_hw *hw, bool req)
116 {
117 	struct mucse_mbx_info *mbx = &hw->mbx;
118 	u32 reg = MUCSE_MBX_PF2FW_CTRL(mbx);
119 
120 	mbx_ctrl_wr32(mbx, reg, req ? MUCSE_MBX_REQ : 0);
121 }
122 
123 /**
124  * mucse_mbx_get_fwreq - Read fw req from reg
125  * @mbx: pointer to the mbx structure
126  *
127  * Return: the fwreq value
128  **/
mucse_mbx_get_fwreq(struct mucse_mbx_info * mbx)129 static u16 mucse_mbx_get_fwreq(struct mucse_mbx_info *mbx)
130 {
131 	u32 val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT);
132 
133 	return FIELD_GET(GENMASK_U32(15, 0), val);
134 }
135 
136 /**
137  * mucse_mbx_inc_pf_ack - Increase ack
138  * @hw: pointer to the HW structure
139  *
140  * mucse_mbx_inc_pf_ack reads pf_ack from hw, then writes
141  * new value back after increase
142  **/
mucse_mbx_inc_pf_ack(struct mucse_hw * hw)143 static void mucse_mbx_inc_pf_ack(struct mucse_hw *hw)
144 {
145 	struct mucse_mbx_info *mbx = &hw->mbx;
146 	u16 ack;
147 	u32 val;
148 
149 	val = mbx_data_rd32(mbx, MUCSE_MBX_PF2FW_CNT);
150 	ack = FIELD_GET(GENMASK_U32(31, 16), val);
151 	ack++;
152 	val &= ~GENMASK_U32(31, 16);
153 	val |= FIELD_PREP(GENMASK_U32(31, 16), ack);
154 	mbx_data_wr32(mbx, MUCSE_MBX_PF2FW_CNT, val);
155 }
156 
157 /**
158  * mucse_read_mbx_pf - Read a message from the mailbox
159  * @hw: pointer to the HW structure
160  * @msg: the message buffer
161  * @size: length of buffer
162  *
163  * mucse_read_mbx_pf copies a message from the mbx buffer to the caller's
164  * memory buffer. The presumption is that the caller knows that there was
165  * a message due to a fw request so no polling for message is needed.
166  *
167  * Return: 0 on success, negative errno on failure
168  **/
mucse_read_mbx_pf(struct mucse_hw * hw,__le32 * msg,u16 size)169 static int mucse_read_mbx_pf(struct mucse_hw *hw, __le32 *msg, u16 size)
170 {
171 	const int size_in_words = size / sizeof(__le32);
172 	struct mucse_mbx_info *mbx = &hw->mbx;
173 	int off = MUCSE_MBX_FWPF_SHM;
174 	int err;
175 
176 	err = mucse_obtain_mbx_lock_pf(hw);
177 	if (err)
178 		return err;
179 
180 	/* memcpy_fromio() is unsuitable: the mailbox uses 32-bit MMIO
181 	 * registers, not byte-addressable RAM. readl() guarantees
182 	 * the required 32-bit access width.
183 	 */
184 	for (int i = 0; i < size_in_words; i++)
185 		msg[i] = cpu_to_le32(mbx_data_rd32(mbx, off + 4 * i));
186 	/* Hw needs write data_reg at last */
187 	mbx_data_wr32(mbx, MUCSE_MBX_FWPF_SHM, 0);
188 	/* flush reqs as we have read this request data */
189 	hw->mbx.fw_req = mucse_mbx_get_fwreq(mbx);
190 	mucse_mbx_inc_pf_ack(hw);
191 	mucse_release_mbx_lock_pf(hw, false);
192 
193 	return 0;
194 }
195 
196 /**
197  * mucse_check_for_msg_pf - Check to see if the fw has sent mail
198  * @hw: pointer to the HW structure
199  *
200  * Return: 0 if the fw has set the Status bit or else -EIO
201  **/
mucse_check_for_msg_pf(struct mucse_hw * hw)202 static int mucse_check_for_msg_pf(struct mucse_hw *hw)
203 {
204 	struct mucse_mbx_info *mbx = &hw->mbx;
205 	u16 fw_req;
206 
207 	fw_req = mucse_mbx_get_fwreq(mbx);
208 	/* chip's register is reset to 0 when rc send reset
209 	 * mbx command. Return -EIO if in this state, others
210 	 * fw == hw->mbx.fw_req means no new msg.
211 	 **/
212 	if (fw_req == 0 || fw_req == hw->mbx.fw_req)
213 		return -EIO;
214 
215 	return 0;
216 }
217 
218 /**
219  * mucse_poll_for_msg - Wait for message notification
220  * @hw: pointer to the HW structure
221  *
222  * Return: 0 on success, negative errno on failure
223  **/
mucse_poll_for_msg(struct mucse_hw * hw)224 static int mucse_poll_for_msg(struct mucse_hw *hw)
225 {
226 	struct mucse_mbx_info *mbx = &hw->mbx;
227 	int val;
228 
229 	return read_poll_timeout(mucse_check_for_msg_pf,
230 				 val, !val, mbx->delay_us,
231 				 mbx->timeout_us,
232 				 false, hw);
233 }
234 
235 /**
236  * mucse_poll_and_read_mbx - Wait for message notification and receive message
237  * @hw: pointer to the HW structure
238  * @msg: the message buffer
239  * @size: length of buffer
240  *
241  * Return: 0 if it successfully received a message notification and
242  * copied it into the receive buffer, negative errno on failure
243  **/
mucse_poll_and_read_mbx(struct mucse_hw * hw,__le32 * msg,u16 size)244 int mucse_poll_and_read_mbx(struct mucse_hw *hw, __le32 *msg, u16 size)
245 {
246 	int err;
247 
248 	err = mucse_poll_for_msg(hw);
249 	if (err)
250 		return err;
251 
252 	return mucse_read_mbx_pf(hw, msg, size);
253 }
254 
255 /**
256  * mucse_mbx_get_fwack - Read fw ack from reg
257  * @mbx: pointer to the MBX structure
258  *
259  * Return: the fwack value
260  **/
mucse_mbx_get_fwack(struct mucse_mbx_info * mbx)261 static u16 mucse_mbx_get_fwack(struct mucse_mbx_info *mbx)
262 {
263 	u32 val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT);
264 
265 	return FIELD_GET(GENMASK_U32(31, 16), val);
266 }
267 
268 /**
269  * mucse_mbx_inc_pf_req - Increase req
270  * @hw: pointer to the HW structure
271  *
272  * mucse_mbx_inc_pf_req reads pf_req from hw, then writes
273  * new value back after increase
274  **/
mucse_mbx_inc_pf_req(struct mucse_hw * hw)275 static void mucse_mbx_inc_pf_req(struct mucse_hw *hw)
276 {
277 	struct mucse_mbx_info *mbx = &hw->mbx;
278 	u16 req;
279 	u32 val;
280 
281 	val = mbx_data_rd32(mbx, MUCSE_MBX_PF2FW_CNT);
282 	req = FIELD_GET(GENMASK_U32(15, 0), val);
283 	req++;
284 	val &= ~GENMASK_U32(15, 0);
285 	val |= FIELD_PREP(GENMASK_U32(15, 0), req);
286 	mbx_data_wr32(mbx, MUCSE_MBX_PF2FW_CNT, val);
287 }
288 
289 /**
290  * mucse_write_mbx_pf - Place a message in the mailbox
291  * @hw: pointer to the HW structure
292  * @msg: the message buffer
293  * @size: length of buffer
294  *
295  * Return: 0 if it successfully copied message into the buffer,
296  * negative errno on failure
297  **/
mucse_write_mbx_pf(struct mucse_hw * hw,const __le32 * msg,u16 size)298 static int mucse_write_mbx_pf(struct mucse_hw *hw, const __le32 *msg, u16 size)
299 {
300 	const int size_in_words = size / sizeof(__le32);
301 	struct mucse_mbx_info *mbx = &hw->mbx;
302 	int err;
303 
304 	err = mucse_obtain_mbx_lock_pf(hw);
305 	if (err)
306 		return err;
307 
308 	/* memcpy_toio() would decompose into arbitrary-width accesses;
309 	 * the mailbox requires 32-bit MMIO writes via writel().
310 	 */
311 	for (int i = 0; i < size_in_words; i++)
312 		mbx_data_wr32(mbx, MUCSE_MBX_FWPF_SHM + i * 4,
313 			      le32_to_cpu(msg[i]));
314 
315 	/* flush acks as we are overwriting the message buffer */
316 	hw->mbx.fw_ack = mucse_mbx_get_fwack(mbx);
317 	mucse_mbx_inc_pf_req(hw);
318 	mucse_release_mbx_lock_pf(hw, true);
319 
320 	return 0;
321 }
322 
323 /**
324  * mucse_check_for_ack_pf - Check to see if the fw has ACKed
325  * @hw: pointer to the HW structure
326  *
327  * Return: 0 if the fw has set the Status bit or else -EIO
328  **/
mucse_check_for_ack_pf(struct mucse_hw * hw)329 static int mucse_check_for_ack_pf(struct mucse_hw *hw)
330 {
331 	struct mucse_mbx_info *mbx = &hw->mbx;
332 	u16 fw_ack;
333 
334 	fw_ack = mucse_mbx_get_fwack(mbx);
335 	/* chip's register is reset to 0 when rc send reset
336 	 * mbx command. Return -EIO if in this state, others
337 	 * fw_ack == hw->mbx.fw_ack means no new ack.
338 	 **/
339 	if (fw_ack == 0 || fw_ack == hw->mbx.fw_ack)
340 		return -EIO;
341 
342 	return 0;
343 }
344 
345 /**
346  * mucse_poll_for_ack - Wait for message acknowledgment
347  * @hw: pointer to the HW structure
348  *
349  * Return: 0 if it successfully received a message acknowledgment,
350  * else negative errno
351  **/
mucse_poll_for_ack(struct mucse_hw * hw)352 static int mucse_poll_for_ack(struct mucse_hw *hw)
353 {
354 	struct mucse_mbx_info *mbx = &hw->mbx;
355 	int val;
356 
357 	return read_poll_timeout(mucse_check_for_ack_pf,
358 				 val, !val, mbx->delay_us,
359 				 mbx->timeout_us,
360 				 false, hw);
361 }
362 
363 /**
364  * mucse_write_and_wait_ack_mbx - Write a message to the mailbox, wait for ack
365  * @hw: pointer to the HW structure
366  * @msg: the message buffer
367  * @size: length of buffer
368  *
369  * Return: 0 if it successfully copied message into the buffer and
370  * received an ack to that message within delay * timeout_cnt period
371  **/
mucse_write_and_wait_ack_mbx(struct mucse_hw * hw,const __le32 * msg,u16 size)372 int mucse_write_and_wait_ack_mbx(struct mucse_hw *hw, const __le32 *msg,
373 				 u16 size)
374 {
375 	int err;
376 
377 	err = mucse_write_mbx_pf(hw, msg, size);
378 	if (err)
379 		return err;
380 
381 	return mucse_poll_for_ack(hw);
382 }
383 
384 /**
385  * mucse_mbx_reset - Reset mbx info, sync info from regs
386  * @hw: pointer to the HW structure
387  *
388  * mucse_mbx_reset resets all mbx variables to default.
389  **/
mucse_mbx_reset(struct mucse_hw * hw)390 static void mucse_mbx_reset(struct mucse_hw *hw)
391 {
392 	struct mucse_mbx_info *mbx = &hw->mbx;
393 	u32 val;
394 
395 	val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT);
396 	hw->mbx.fw_req = FIELD_GET(GENMASK_U32(15, 0), val);
397 	hw->mbx.fw_ack = FIELD_GET(GENMASK_U32(31, 16), val);
398 	mbx_ctrl_wr32(mbx, MUCSE_MBX_PF2FW_CTRL(mbx), 0);
399 	mbx_ctrl_wr32(mbx, MUCSE_MBX_FWPF_MASK(mbx), GENMASK_U32(31, 16));
400 }
401 
402 /**
403  * mucse_init_mbx_params_pf - Set initial values for pf mailbox
404  * @hw: pointer to the HW structure
405  *
406  * Initializes the hw->mbx struct to correct values for pf mailbox
407  */
mucse_init_mbx_params_pf(struct mucse_hw * hw)408 void mucse_init_mbx_params_pf(struct mucse_hw *hw)
409 {
410 	struct mucse_mbx_info *mbx = &hw->mbx;
411 
412 	mbx->delay_us = 100;
413 	mbx->timeout_us = 4 * USEC_PER_SEC;
414 	mutex_init(&mbx->lock);
415 	mucse_mbx_reset(hw);
416 }
417