File Index
Files and directories
Sign in
FILE

rnpgbe_mbx.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.c C
  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 **/
 17static 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 **/
 31static 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 **/
 45static 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 **/
 59static 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 **/
 72static 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 **/
 91static 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 **/
115static 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 **/
129static 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 **/
143static 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 **/
169static int mucse_read_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size)
170{
171	const int size_in_words = size / sizeof(u32);
172	struct mucse_mbx_info *mbx = &hw->mbx;
173	int err;
174
175	err = mucse_obtain_mbx_lock_pf(hw);
176	if (err)
177		return err;
178
179	for (int i = 0; i < size_in_words; i++)
180		msg[i] = mbx_data_rd32(mbx, MUCSE_MBX_FWPF_SHM + 4 * i);
181	/* Hw needs write data_reg at last */
182	mbx_data_wr32(mbx, MUCSE_MBX_FWPF_SHM, 0);
183	/* flush reqs as we have read this request data */
184	hw->mbx.fw_req = mucse_mbx_get_fwreq(mbx);
185	mucse_mbx_inc_pf_ack(hw);
186	mucse_release_mbx_lock_pf(hw, false);
187
188	return 0;
189}
190
191/**
192 * mucse_check_for_msg_pf - Check to see if the fw has sent mail
193 * @hw: pointer to the HW structure
194 *
195 * Return: 0 if the fw has set the Status bit or else -EIO
196 **/
197static int mucse_check_for_msg_pf(struct mucse_hw *hw)
198{
199	struct mucse_mbx_info *mbx = &hw->mbx;
200	u16 fw_req;
201
202	fw_req = mucse_mbx_get_fwreq(mbx);
203	/* chip's register is reset to 0 when rc send reset
204	 * mbx command. Return -EIO if in this state, others
205	 * fw == hw->mbx.fw_req means no new msg.
206	 **/
207	if (fw_req == 0 || fw_req == hw->mbx.fw_req)
208		return -EIO;
209
210	return 0;
211}
212
213/**
214 * mucse_poll_for_msg - Wait for message notification
215 * @hw: pointer to the HW structure
216 *
217 * Return: 0 on success, negative errno on failure
218 **/
219static int mucse_poll_for_msg(struct mucse_hw *hw)
220{
221	struct mucse_mbx_info *mbx = &hw->mbx;
222	int val;
223
224	return read_poll_timeout(mucse_check_for_msg_pf,
225				 val, !val, mbx->delay_us,
226				 mbx->timeout_us,
227				 false, hw);
228}
229
230/**
231 * mucse_poll_and_read_mbx - Wait for message notification and receive message
232 * @hw: pointer to the HW structure
233 * @msg: the message buffer
234 * @size: length of buffer
235 *
236 * Return: 0 if it successfully received a message notification and
237 * copied it into the receive buffer, negative errno on failure
238 **/
239int mucse_poll_and_read_mbx(struct mucse_hw *hw, u32 *msg, u16 size)
240{
241	int err;
242
243	err = mucse_poll_for_msg(hw);
244	if (err)
245		return err;
246
247	return mucse_read_mbx_pf(hw, msg, size);
248}
249
250/**
251 * mucse_mbx_get_fwack - Read fw ack from reg
252 * @mbx: pointer to the MBX structure
253 *
254 * Return: the fwack value
255 **/
256static u16 mucse_mbx_get_fwack(struct mucse_mbx_info *mbx)
257{
258	u32 val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT);
259
260	return FIELD_GET(GENMASK_U32(31, 16), val);
261}
262
263/**
264 * mucse_mbx_inc_pf_req - Increase req
265 * @hw: pointer to the HW structure
266 *
267 * mucse_mbx_inc_pf_req reads pf_req from hw, then writes
268 * new value back after increase
269 **/
270static void mucse_mbx_inc_pf_req(struct mucse_hw *hw)
271{
272	struct mucse_mbx_info *mbx = &hw->mbx;
273	u16 req;
274	u32 val;
275
276	val = mbx_data_rd32(mbx, MUCSE_MBX_PF2FW_CNT);
277	req = FIELD_GET(GENMASK_U32(15, 0), val);
278	req++;
279	val &= ~GENMASK_U32(15, 0);
280	val |= FIELD_PREP(GENMASK_U32(15, 0), req);
281	mbx_data_wr32(mbx, MUCSE_MBX_PF2FW_CNT, val);
282}
283
284/**
285 * mucse_write_mbx_pf - Place a message in the mailbox
286 * @hw: pointer to the HW structure
287 * @msg: the message buffer
288 * @size: length of buffer
289 *
290 * Return: 0 if it successfully copied message into the buffer,
291 * negative errno on failure
292 **/
293static int mucse_write_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size)
294{
295	const int size_in_words = size / sizeof(u32);
296	struct mucse_mbx_info *mbx = &hw->mbx;
297	int err;
298
299	err = mucse_obtain_mbx_lock_pf(hw);
300	if (err)
301		return err;
302
303	for (int i = 0; i < size_in_words; i++)
304		mbx_data_wr32(mbx, MUCSE_MBX_FWPF_SHM + i * 4, msg[i]);
305
306	/* flush acks as we are overwriting the message buffer */
307	hw->mbx.fw_ack = mucse_mbx_get_fwack(mbx);
308	mucse_mbx_inc_pf_req(hw);
309	mucse_release_mbx_lock_pf(hw, true);
310
311	return 0;
312}
313
314/**
315 * mucse_check_for_ack_pf - Check to see if the fw has ACKed
316 * @hw: pointer to the HW structure
317 *
318 * Return: 0 if the fw has set the Status bit or else -EIO
319 **/
320static int mucse_check_for_ack_pf(struct mucse_hw *hw)
321{
322	struct mucse_mbx_info *mbx = &hw->mbx;
323	u16 fw_ack;
324
325	fw_ack = mucse_mbx_get_fwack(mbx);
326	/* chip's register is reset to 0 when rc send reset
327	 * mbx command. Return -EIO if in this state, others
328	 * fw_ack == hw->mbx.fw_ack means no new ack.
329	 **/
330	if (fw_ack == 0 || fw_ack == hw->mbx.fw_ack)
331		return -EIO;
332
333	return 0;
334}
335
336/**
337 * mucse_poll_for_ack - Wait for message acknowledgment
338 * @hw: pointer to the HW structure
339 *
340 * Return: 0 if it successfully received a message acknowledgment,
341 * else negative errno
342 **/
343static int mucse_poll_for_ack(struct mucse_hw *hw)
344{
345	struct mucse_mbx_info *mbx = &hw->mbx;
346	int val;
347
348	return read_poll_timeout(mucse_check_for_ack_pf,
349				 val, !val, mbx->delay_us,
350				 mbx->timeout_us,
351				 false, hw);
352}
353
354/**
355 * mucse_write_and_wait_ack_mbx - Write a message to the mailbox, wait for ack
356 * @hw: pointer to the HW structure
357 * @msg: the message buffer
358 * @size: length of buffer
359 *
360 * Return: 0 if it successfully copied message into the buffer and
361 * received an ack to that message within delay * timeout_cnt period
362 **/
363int mucse_write_and_wait_ack_mbx(struct mucse_hw *hw, u32 *msg, u16 size)
364{
365	int err;
366
367	err = mucse_write_mbx_pf(hw, msg, size);
368	if (err)
369		return err;
370
371	return mucse_poll_for_ack(hw);
372}
373
374/**
375 * mucse_mbx_reset - Reset mbx info, sync info from regs
376 * @hw: pointer to the HW structure
377 *
378 * mucse_mbx_reset resets all mbx variables to default.
379 **/
380static void mucse_mbx_reset(struct mucse_hw *hw)
381{
382	struct mucse_mbx_info *mbx = &hw->mbx;
383	u32 val;
384
385	val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT);
386	hw->mbx.fw_req = FIELD_GET(GENMASK_U32(15, 0), val);
387	hw->mbx.fw_ack = FIELD_GET(GENMASK_U32(31, 16), val);
388	mbx_ctrl_wr32(mbx, MUCSE_MBX_PF2FW_CTRL(mbx), 0);
389	mbx_ctrl_wr32(mbx, MUCSE_MBX_FWPF_MASK(mbx), GENMASK_U32(31, 16));
390}
391
392/**
393 * mucse_init_mbx_params_pf - Set initial values for pf mailbox
394 * @hw: pointer to the HW structure
395 *
396 * Initializes the hw->mbx struct to correct values for pf mailbox
397 */
398void mucse_init_mbx_params_pf(struct mucse_hw *hw)
399{
400	struct mucse_mbx_info *mbx = &hw->mbx;
401
402	mbx->delay_us = 100;
403	mbx->timeout_us = 4 * USEC_PER_SEC;
404	mutex_init(&mbx->lock);
405	mucse_mbx_reset(hw);
406}
~/ Read-only file preview.