FILE
rnpgbe_mbx.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx.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.