bng_en-y := bnge_core.o \
            bnge_devlink.o \
-           bnge_hwrm.o
+           bnge_hwrm.o \
+           bnge_hwrm_lib.o
 
 #define DRV_NAME       "bng_en"
 #define DRV_SUMMARY    "Broadcom 800G Ethernet Linux Driver"
 
+#include <linux/etherdevice.h>
+#include "../bnxt/bnxt_hsi.h"
+
+#define DRV_VER_MAJ    1
+#define DRV_VER_MIN    15
+#define DRV_VER_UPD    1
+
 extern char bnge_driver_name[];
 
 enum board_idx {
 
 #define INVALID_HW_RING_ID      ((u16)-1)
 
+enum {
+       BNGE_FW_CAP_SHORT_CMD                           = BIT_ULL(0),
+       BNGE_FW_CAP_LLDP_AGENT                          = BIT_ULL(1),
+       BNGE_FW_CAP_DCBX_AGENT                          = BIT_ULL(2),
+       BNGE_FW_CAP_IF_CHANGE                           = BIT_ULL(3),
+       BNGE_FW_CAP_KONG_MB_CHNL                        = BIT_ULL(4),
+       BNGE_FW_CAP_ERROR_RECOVERY                      = BIT_ULL(5),
+       BNGE_FW_CAP_PKG_VER                             = BIT_ULL(6),
+       BNGE_FW_CAP_CFA_ADV_FLOW                        = BIT_ULL(7),
+       BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V2             = BIT_ULL(8),
+       BNGE_FW_CAP_PCIE_STATS_SUPPORTED                = BIT_ULL(9),
+       BNGE_FW_CAP_EXT_STATS_SUPPORTED                 = BIT_ULL(10),
+       BNGE_FW_CAP_ERR_RECOVER_RELOAD                  = BIT_ULL(11),
+       BNGE_FW_CAP_HOT_RESET                           = BIT_ULL(12),
+       BNGE_FW_CAP_RX_ALL_PKT_TS                       = BIT_ULL(13),
+       BNGE_FW_CAP_VLAN_RX_STRIP                       = BIT_ULL(14),
+       BNGE_FW_CAP_VLAN_TX_INSERT                      = BIT_ULL(15),
+       BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED              = BIT_ULL(16),
+       BNGE_FW_CAP_LIVEPATCH                           = BIT_ULL(17),
+       BNGE_FW_CAP_HOT_RESET_IF                        = BIT_ULL(18),
+       BNGE_FW_CAP_RING_MONITOR                        = BIT_ULL(19),
+       BNGE_FW_CAP_DBG_QCAPS                           = BIT_ULL(20),
+       BNGE_FW_CAP_THRESHOLD_TEMP_SUPPORTED            = BIT_ULL(21),
+       BNGE_FW_CAP_DFLT_VLAN_TPID_PCP                  = BIT_ULL(22),
+       BNGE_FW_CAP_VNIC_TUNNEL_TPA                     = BIT_ULL(23),
+       BNGE_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO          = BIT_ULL(24),
+       BNGE_FW_CAP_CFA_RFS_RING_TBL_IDX_V3             = BIT_ULL(25),
+       BNGE_FW_CAP_VNIC_RE_FLUSH                       = BIT_ULL(26),
+};
+
 struct bnge_dev {
        struct device   *dev;
        struct pci_dev  *pdev;
 
        void __iomem    *bar0;
 
+       u16             chip_num;
+       u8              chip_rev;
+
        /* HWRM members */
        u16                     hwrm_cmd_seq;
        u16                     hwrm_cmd_kong_seq;
        unsigned int            hwrm_cmd_timeout;
        unsigned int            hwrm_cmd_max_timeout;
        struct mutex            hwrm_cmd_lock;  /* serialize hwrm messages */
+
+       struct hwrm_ver_get_output      ver_resp;
+#define FW_VER_STR_LEN         32
+       char                    fw_ver_str[FW_VER_STR_LEN];
+       char                    hwrm_ver_supp[FW_VER_STR_LEN];
+       char                    nvm_cfg_ver[FW_VER_STR_LEN];
+       u64                     fw_ver_code;
+#define BNGE_FW_VER_CODE(maj, min, bld, rsv)                   \
+       ((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
+
+       unsigned long           state;
+#define BNGE_STATE_DRV_REGISTERED      0
+
+       u64                     fw_cap;
 };
 
 #endif /* _BNGE_H_ */
 
 
 #include "bnge.h"
 #include "bnge_devlink.h"
+#include "bnge_hwrm.h"
+#include "bnge_hwrm_lib.h"
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION(DRV_SUMMARY);
        pcie_print_link_status(pdev);
 }
 
+static void bnge_nvm_cfg_ver_get(struct bnge_dev *bd)
+{
+       struct hwrm_nvm_get_dev_info_output nvm_info;
+
+       if (!bnge_hwrm_nvm_dev_info(bd, &nvm_info))
+               snprintf(bd->nvm_cfg_ver, FW_VER_STR_LEN, "%d.%d.%d",
+                        nvm_info.nvm_cfg_ver_maj, nvm_info.nvm_cfg_ver_min,
+                        nvm_info.nvm_cfg_ver_upd);
+}
+
+static void bnge_fw_unregister_dev(struct bnge_dev *bd)
+{
+       bnge_hwrm_func_drv_unrgtr(bd);
+}
+
+static int bnge_fw_register_dev(struct bnge_dev *bd)
+{
+       int rc;
+
+       bd->fw_cap = 0;
+       rc = bnge_hwrm_ver_get(bd);
+       if (rc) {
+               dev_err(bd->dev, "Get Version command failed rc: %d\n", rc);
+               return rc;
+       }
+
+       bnge_nvm_cfg_ver_get(bd);
+
+       rc = bnge_hwrm_func_reset(bd);
+       if (rc) {
+               dev_err(bd->dev, "Failed to reset function rc: %d\n", rc);
+               return rc;
+       }
+
+       bnge_hwrm_fw_set_time(bd);
+
+       rc =  bnge_hwrm_func_drv_rgtr(bd);
+       if (rc) {
+               dev_err(bd->dev, "Failed to rgtr with firmware rc: %d\n", rc);
+               return rc;
+       }
+
+       return 0;
+}
+
 static void bnge_pci_disable(struct pci_dev *pdev)
 {
        pci_release_regions(pdev);
                goto err_devl_free;
        }
 
+       rc = bnge_init_hwrm_resources(bd);
+       if (rc)
+               goto err_bar_unmap;
+
+       rc = bnge_fw_register_dev(bd);
+       if (rc) {
+               dev_err(&pdev->dev, "Failed to register with firmware rc = %d\n", rc);
+               goto err_hwrm_cleanup;
+       }
+
+       bnge_devlink_register(bd);
+
        pci_save_state(pdev);
 
        return 0;
 
+err_hwrm_cleanup:
+       bnge_cleanup_hwrm_resources(bd);
+
+err_bar_unmap:
+       bnge_unmap_bars(pdev);
+
 err_devl_free:
        bnge_devlink_free(bd);
 
 {
        struct bnge_dev *bd = pci_get_drvdata(pdev);
 
+       bnge_devlink_unregister(bd);
+
+       bnge_fw_unregister_dev(bd);
+
+       bnge_cleanup_hwrm_resources(bd);
+
        bnge_unmap_bars(pdev);
 
        bnge_devlink_free(bd);
 
 
 #include "bnge.h"
 #include "bnge_devlink.h"
+#include "bnge_hwrm_lib.h"
 
 static int bnge_dl_info_put(struct bnge_dev *bd, struct devlink_info_req *req,
                            enum bnge_dl_version_type type, const char *key,
        if (!strlen(buf))
                return 0;
 
+       if (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) ||
+           !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE))
+               return 0;
+
        switch (type) {
        case BNGE_VERSION_FIXED:
                return devlink_info_version_fixed_put(req, key, buf);
        kfree(vpd_data);
 }
 
+#define HWRM_FW_VER_STR_LEN    16
+
 static int bnge_devlink_info_get(struct devlink *devlink,
                                 struct devlink_info_req *req,
                                 struct netlink_ext_ack *extack)
 {
+       struct hwrm_nvm_get_dev_info_output nvm_dev_info;
        struct bnge_dev *bd = devlink_priv(devlink);
+       struct hwrm_ver_get_output *ver_resp;
+       char mgmt_ver[FW_VER_STR_LEN];
+       char roce_ver[FW_VER_STR_LEN];
+       char ncsi_ver[FW_VER_STR_LEN];
+       char buf[32];
+
        int rc;
 
        if (bd->dsn) {
                return rc;
        }
 
+       /* More information from HWRM ver get command */
+       sprintf(buf, "%X", bd->chip_num);
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
+                             DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed to set asic id");
+               return rc;
+       }
+
+       ver_resp = &bd->ver_resp;
+       sprintf(buf, "%c%d", 'A' + ver_resp->chip_rev, ver_resp->chip_metal);
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_FIXED,
+                             DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed to set asic info");
+               return rc;
+       }
+
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+                             DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
+                             bd->nvm_cfg_ver);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed to set firmware version");
+               return rc;
+       }
+
+       buf[0] = 0;
+       strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN);
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+                             DEVLINK_INFO_VERSION_GENERIC_FW, buf);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Failed to set firmware generic version");
+               return rc;
+       }
+
+       if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
+               snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                        ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
+                        ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
+
+               snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                        ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
+                        ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
+
+               snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                        ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
+                        ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
+       } else {
+               snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                        ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
+                        ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
+
+               snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                        ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
+                        ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
+
+               snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                        ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
+                        ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
+       }
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+                             DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Failed to set firmware mgmt version");
+               return rc;
+       }
+
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+                             DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
+                             bd->hwrm_ver_supp);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Failed to set firmware mgmt api version");
+               return rc;
+       }
+
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+                             DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Failed to set ncsi firmware version");
+               return rc;
+       }
+
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_RUNNING,
+                             DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed to set roce firmware version");
+               return rc;
+       }
+
+       rc = bnge_hwrm_nvm_dev_info(bd, &nvm_dev_info);
+       if (!(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID))
+               return 0;
+
+       buf[0] = 0;
+       strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN);
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
+                             DEVLINK_INFO_VERSION_GENERIC_FW, buf);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Failed to set roce firmware version");
+               return rc;
+       }
+
+       snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor,
+                nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch);
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
+                             DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Failed to set stored firmware version");
+               return rc;
+       }
+
+       snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor,
+                nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch);
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
+                             DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
+       if (rc) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Failed to set stored ncsi firmware version");
+               return rc;
+       }
+
+       snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor,
+                nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch);
+       rc = bnge_dl_info_put(bd, req, BNGE_VERSION_STORED,
+                             DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
+       if (rc)
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Failed to set stored roce firmware version");
+
        return rc;
 }
 
 
        return bd;
 }
+
+void bnge_devlink_register(struct bnge_dev *bd)
+{
+       struct devlink *devlink = priv_to_devlink(bd);
+       devlink_register(devlink);
+}
+
+void bnge_devlink_unregister(struct bnge_dev *bd)
+{
+       struct devlink *devlink = priv_to_devlink(bd);
+       devlink_unregister(devlink);
+}
 
 
 void bnge_devlink_free(struct bnge_dev *bd);
 struct bnge_dev *bnge_devlink_alloc(struct pci_dev *pdev);
+void bnge_devlink_register(struct bnge_dev *bd);
+void bnge_devlink_unregister(struct bnge_dev *bd);
 
 #endif /* _BNGE_DEVLINK_H_ */
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2025 Broadcom.
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+
+#include "bnge.h"
+#include "../bnxt/bnxt_hsi.h"
+#include "bnge_hwrm.h"
+#include "bnge_hwrm_lib.h"
+
+int bnge_hwrm_ver_get(struct bnge_dev *bd)
+{
+       u32 dev_caps_cfg, hwrm_ver, hwrm_spec_code;
+       u16 fw_maj, fw_min, fw_bld, fw_rsv;
+       struct hwrm_ver_get_output *resp;
+       struct hwrm_ver_get_input *req;
+       int rc;
+
+       rc = bnge_hwrm_req_init(bd, req, HWRM_VER_GET);
+       if (rc)
+               return rc;
+
+       bnge_hwrm_req_flags(bd, req, BNGE_HWRM_FULL_WAIT);
+       bd->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
+       req->hwrm_intf_maj = HWRM_VERSION_MAJOR;
+       req->hwrm_intf_min = HWRM_VERSION_MINOR;
+       req->hwrm_intf_upd = HWRM_VERSION_UPDATE;
+
+       resp = bnge_hwrm_req_hold(bd, req);
+       rc = bnge_hwrm_req_send(bd, req);
+       if (rc)
+               goto hwrm_ver_get_exit;
+
+       memcpy(&bd->ver_resp, resp, sizeof(struct hwrm_ver_get_output));
+
+       hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
+                        resp->hwrm_intf_min_8b << 8 |
+                        resp->hwrm_intf_upd_8b;
+       hwrm_ver = HWRM_VERSION_MAJOR << 16 | HWRM_VERSION_MINOR << 8 |
+                       HWRM_VERSION_UPDATE;
+
+       if (hwrm_spec_code > hwrm_ver)
+               snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
+                        HWRM_VERSION_MAJOR, HWRM_VERSION_MINOR,
+                        HWRM_VERSION_UPDATE);
+       else
+               snprintf(bd->hwrm_ver_supp, FW_VER_STR_LEN, "%d.%d.%d",
+                        resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b,
+                        resp->hwrm_intf_upd_8b);
+
+       fw_maj = le16_to_cpu(resp->hwrm_fw_major);
+       fw_min = le16_to_cpu(resp->hwrm_fw_minor);
+       fw_bld = le16_to_cpu(resp->hwrm_fw_build);
+       fw_rsv = le16_to_cpu(resp->hwrm_fw_patch);
+
+       bd->fw_ver_code = BNGE_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv);
+       snprintf(bd->fw_ver_str, FW_VER_STR_LEN, "%d.%d.%d.%d",
+                fw_maj, fw_min, fw_bld, fw_rsv);
+
+       if (strlen(resp->active_pkg_name)) {
+               int fw_ver_len = strlen(bd->fw_ver_str);
+
+               snprintf(bd->fw_ver_str + fw_ver_len,
+                        FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
+                        resp->active_pkg_name);
+               bd->fw_cap |= BNGE_FW_CAP_PKG_VER;
+       }
+
+       bd->hwrm_cmd_timeout = le16_to_cpu(resp->def_req_timeout);
+       if (!bd->hwrm_cmd_timeout)
+               bd->hwrm_cmd_timeout = BNGE_DFLT_HWRM_CMD_TIMEOUT;
+       bd->hwrm_cmd_max_timeout = le16_to_cpu(resp->max_req_timeout) * 1000;
+       if (!bd->hwrm_cmd_max_timeout)
+               bd->hwrm_cmd_max_timeout = BNGE_HWRM_CMD_MAX_TIMEOUT;
+       else if (bd->hwrm_cmd_max_timeout > BNGE_HWRM_CMD_MAX_TIMEOUT)
+               dev_warn(bd->dev, "Default HWRM commands max timeout increased to %d seconds\n",
+                        bd->hwrm_cmd_max_timeout / 1000);
+
+       bd->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len);
+       bd->hwrm_max_ext_req_len = le16_to_cpu(resp->max_ext_req_len);
+
+       if (bd->hwrm_max_ext_req_len < HWRM_MAX_REQ_LEN)
+               bd->hwrm_max_ext_req_len = HWRM_MAX_REQ_LEN;
+
+       bd->chip_num = le16_to_cpu(resp->chip_num);
+       bd->chip_rev = resp->chip_rev;
+
+       dev_caps_cfg = le32_to_cpu(resp->dev_caps_cfg);
+       if ((dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
+           (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
+               bd->fw_cap |= BNGE_FW_CAP_SHORT_CMD;
+
+       if (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
+               bd->fw_cap |= BNGE_FW_CAP_KONG_MB_CHNL;
+
+       if (dev_caps_cfg &
+           VER_GET_RESP_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED)
+               bd->fw_cap |= BNGE_FW_CAP_CFA_ADV_FLOW;
+
+hwrm_ver_get_exit:
+       bnge_hwrm_req_drop(bd, req);
+       return rc;
+}
+
+int
+bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
+                      struct hwrm_nvm_get_dev_info_output *nvm_info)
+{
+       struct hwrm_nvm_get_dev_info_output *resp;
+       struct hwrm_nvm_get_dev_info_input *req;
+       int rc;
+
+       rc = bnge_hwrm_req_init(bd, req, HWRM_NVM_GET_DEV_INFO);
+       if (rc)
+               return rc;
+
+       resp = bnge_hwrm_req_hold(bd, req);
+       rc = bnge_hwrm_req_send(bd, req);
+       if (!rc)
+               memcpy(nvm_info, resp, sizeof(*resp));
+       bnge_hwrm_req_drop(bd, req);
+       return rc;
+}
+
+int bnge_hwrm_func_reset(struct bnge_dev *bd)
+{
+       struct hwrm_func_reset_input *req;
+       int rc;
+
+       rc = bnge_hwrm_req_init(bd, req, HWRM_FUNC_RESET);
+       if (rc)
+               return rc;
+
+       req->enables = 0;
+       bnge_hwrm_req_timeout(bd, req, BNGE_HWRM_RESET_TIMEOUT);
+       return bnge_hwrm_req_send(bd, req);
+}
+
+int bnge_hwrm_fw_set_time(struct bnge_dev *bd)
+{
+       struct hwrm_fw_set_time_input *req;
+       struct tm tm;
+       int rc;
+
+       time64_to_tm(ktime_get_real_seconds(), 0, &tm);
+
+       rc = bnge_hwrm_req_init(bd, req, HWRM_FW_SET_TIME);
+       if (rc)
+               return rc;
+
+       req->year = cpu_to_le16(1900 + tm.tm_year);
+       req->month = 1 + tm.tm_mon;
+       req->day = tm.tm_mday;
+       req->hour = tm.tm_hour;
+       req->minute = tm.tm_min;
+       req->second = tm.tm_sec;
+       return bnge_hwrm_req_send(bd, req);
+}
+
+int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd)
+{
+       struct hwrm_func_drv_rgtr_output *resp;
+       struct hwrm_func_drv_rgtr_input *req;
+       u32 flags;
+       int rc;
+
+       rc = bnge_hwrm_req_init(bd, req, HWRM_FUNC_DRV_RGTR);
+       if (rc)
+               return rc;
+
+       req->enables = cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE |
+                                  FUNC_DRV_RGTR_REQ_ENABLES_VER |
+                                  FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
+
+       req->os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
+       flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE;
+
+       req->flags = cpu_to_le32(flags);
+       req->ver_maj_8b = DRV_VER_MAJ;
+       req->ver_min_8b = DRV_VER_MIN;
+       req->ver_upd_8b = DRV_VER_UPD;
+       req->ver_maj = cpu_to_le16(DRV_VER_MAJ);
+       req->ver_min = cpu_to_le16(DRV_VER_MIN);
+       req->ver_upd = cpu_to_le16(DRV_VER_UPD);
+
+       resp = bnge_hwrm_req_hold(bd, req);
+       rc = bnge_hwrm_req_send(bd, req);
+       if (!rc) {
+               set_bit(BNGE_STATE_DRV_REGISTERED, &bd->state);
+               if (resp->flags &
+                   cpu_to_le32(FUNC_DRV_RGTR_RESP_FLAGS_IF_CHANGE_SUPPORTED))
+                       bd->fw_cap |= BNGE_FW_CAP_IF_CHANGE;
+       }
+       bnge_hwrm_req_drop(bd, req);
+       return rc;
+}
+
+int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd)
+{
+       struct hwrm_func_drv_unrgtr_input *req;
+       int rc;
+
+       if (!test_and_clear_bit(BNGE_STATE_DRV_REGISTERED, &bd->state))
+               return 0;
+
+       rc = bnge_hwrm_req_init(bd, req, HWRM_FUNC_DRV_UNRGTR);
+       if (rc)
+               return rc;
+       return bnge_hwrm_req_send(bd, req);
+}
 
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 Broadcom */
+
+#ifndef _BNGE_HWRM_LIB_H_
+#define _BNGE_HWRM_LIB_H_
+
+int bnge_hwrm_ver_get(struct bnge_dev *bd);
+int bnge_hwrm_func_reset(struct bnge_dev *bd);
+int bnge_hwrm_fw_set_time(struct bnge_dev *bd);
+int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd);
+int bnge_hwrm_func_drv_unrgtr(struct bnge_dev *bd);
+int bnge_hwrm_vnic_qcaps(struct bnge_dev *bd);
+int bnge_hwrm_nvm_dev_info(struct bnge_dev *bd,
+                          struct hwrm_nvm_get_dev_info_output *nvm_dev_info);
+
+#endif /* _BNGE_HWRM_LIB_H_ */