root/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2020 - 2025 Mucse Corporation. */

#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>

#include "rnpgbe.h"
#include "rnpgbe_hw.h"
#include "rnpgbe_mbx.h"
#include "rnpgbe_mbx_fw.h"

/**
 * rnpgbe_get_permanent_mac - Get permanent mac
 * @hw: hw information structure
 * @perm_addr: pointer to store perm_addr
 *
 * rnpgbe_get_permanent_mac tries to get mac from hw
 *
 * Return: 0 on success, negative errno on failure
 **/
int rnpgbe_get_permanent_mac(struct mucse_hw *hw, u8 *perm_addr)
{
        struct device *dev = &hw->pdev->dev;
        int err;

        err = mucse_mbx_get_macaddr(hw, hw->pfvfnum, perm_addr, hw->port);
        if (err) {
                dev_err(dev, "Failed to get MAC from FW %d\n", err);
                return err;
        }

        if (!is_valid_ether_addr(perm_addr)) {
                dev_err(dev, "Failed to get valid MAC from FW\n");
                return -EINVAL;
        }

        return 0;
}

/**
 * rnpgbe_reset_hw - Do a hardware reset
 * @hw: hw information structure
 *
 * rnpgbe_reset_hw calls fw to do a hardware
 * reset, and cleans some regs to default.
 *
 * Return: 0 on success, negative errno on failure
 **/
int rnpgbe_reset_hw(struct mucse_hw *hw)
{
        mucse_hw_wr32(hw, RNPGBE_DMA_AXI_EN, 0);
        return mucse_mbx_reset_hw(hw);
}

/**
 * rnpgbe_send_notify - Echo fw status
 * @hw: hw information structure
 * @enable: true or false status
 * @mode: status mode
 *
 * Return: 0 on success, negative errno on failure
 **/
int rnpgbe_send_notify(struct mucse_hw *hw,
                       bool enable,
                       int mode)
{
        int err;
        /* Keep switch struct to support more modes in the future */
        switch (mode) {
        case mucse_fw_powerup:
                err = mucse_mbx_powerup(hw, enable);
                break;
        default:
                err = -EINVAL;
        }

        return err;
}

/**
 * rnpgbe_init_n500 - Setup n500 hw info
 * @hw: hw information structure
 *
 * rnpgbe_init_n500 initializes all private
 * structure for n500
 **/
static void rnpgbe_init_n500(struct mucse_hw *hw)
{
        struct mucse_mbx_info *mbx = &hw->mbx;

        mbx->fwpf_ctrl_base = MUCSE_N500_FWPF_CTRL_BASE;
        mbx->fwpf_shm_base = MUCSE_N500_FWPF_SHM_BASE;
}

/**
 * rnpgbe_init_n210 - Setup n210 hw info
 * @hw: hw information structure
 *
 * rnpgbe_init_n210 initializes all private
 * structure for n210
 **/
static void rnpgbe_init_n210(struct mucse_hw *hw)
{
        struct mucse_mbx_info *mbx = &hw->mbx;

        mbx->fwpf_ctrl_base = MUCSE_N210_FWPF_CTRL_BASE;
        mbx->fwpf_shm_base = MUCSE_N210_FWPF_SHM_BASE;
}

/**
 * rnpgbe_init_hw - Setup hw info according to board_type
 * @hw: hw information structure
 * @board_type: board type
 *
 * rnpgbe_init_hw initializes all hw data
 *
 * Return: 0 on success, -EINVAL on failure
 **/
int rnpgbe_init_hw(struct mucse_hw *hw, int board_type)
{
        struct mucse_mbx_info *mbx = &hw->mbx;

        hw->port = 0;

        mbx->pf2fw_mbx_ctrl = MUCSE_GBE_PFFW_MBX_CTRL_OFFSET;
        mbx->fwpf_mbx_mask = MUCSE_GBE_FWPF_MBX_MASK_OFFSET;

        switch (board_type) {
        case board_n500:
                rnpgbe_init_n500(hw);
                break;
        case board_n210:
                rnpgbe_init_n210(hw);
                break;
        default:
                return -EINVAL;
        }
        /* init_params with mbx base */
        mucse_init_mbx_params_pf(hw);

        return 0;
}