diff --git a/drivers/net/bnxt/hcapi/Makefile b/drivers/net/bnxt/hcapi/Makefile
new file mode 100644
index 000000000..65cddd789
--- /dev/null
+++ b/drivers/net/bnxt/hcapi/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019-2020 Broadcom Limited.
+# All rights reserved.
+
+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += hcapi/hcapi_cfa_p4.c
+
+SYMLINK-$(CONFIG_RTE_LIBRTE_BNXT_PMD)-include += hcapi/hcapi_cfa.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_BNXT_PMD)-include += hcapi/hcapi_cfa_defs.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_BNXT_PMD)-include += hcapi/hcapi_cfa_p4.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_BNXT_PMD)-include += hcapi/cfa_p40_hw.h
diff --git a/drivers/net/bnxt/hcapi/hcapi_cfa.h b/drivers/net/bnxt/hcapi/hcapi_cfa.h
new file mode 100644
index 000000000..f60af4e56
--- /dev/null
+++ b/drivers/net/bnxt/hcapi/hcapi_cfa.h
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2020 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _HCAPI_CFA_H_
+#define _HCAPI_CFA_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "hcapi_cfa_defs.h"
+
+#define SUPPORT_CFA_HW_P4  1
+
+#if SUPPORT_CFA_HW_P4 && SUPPORT_CFA_HW_P58 && SUPPORT_CFA_HW_P59
+#define SUPPORT_CFA_HW_ALL  1
+#endif
+
+/**
+ * Index used for the sram_entries field
+ */
+enum hcapi_cfa_resc_type_sram {
+	HCAPI_CFA_RESC_TYPE_SRAM_FULL_ACTION,
+	HCAPI_CFA_RESC_TYPE_SRAM_MCG,
+	HCAPI_CFA_RESC_TYPE_SRAM_ENCAP_8B,
+	HCAPI_CFA_RESC_TYPE_SRAM_ENCAP_16B,
+	HCAPI_CFA_RESC_TYPE_SRAM_ENCAP_64B,
+	HCAPI_CFA_RESC_TYPE_SRAM_SP_SMAC,
+	HCAPI_CFA_RESC_TYPE_SRAM_SP_SMAC_IPV4,
+	HCAPI_CFA_RESC_TYPE_SRAM_SP_SMAC_IPV6,
+	HCAPI_CFA_RESC_TYPE_SRAM_COUNTER_64B,
+	HCAPI_CFA_RESC_TYPE_SRAM_NAT_SPORT,
+	HCAPI_CFA_RESC_TYPE_SRAM_NAT_DPORT,
+	HCAPI_CFA_RESC_TYPE_SRAM_NAT_S_IPV4,
+	HCAPI_CFA_RESC_TYPE_SRAM_NAT_D_IPV4,
+	HCAPI_CFA_RESC_TYPE_SRAM_MAX
+};
+
+/**
+ * Index used for the hw_entries field in struct cfa_rm_db
+ */
+enum hcapi_cfa_resc_type_hw {
+	/* common HW resources for all chip variants */
+	HCAPI_CFA_RESC_TYPE_HW_L2_CTXT_TCAM,
+	HCAPI_CFA_RESC_TYPE_HW_PROF_FUNC,
+	HCAPI_CFA_RESC_TYPE_HW_PROF_TCAM,
+	HCAPI_CFA_RESC_TYPE_HW_EM_PROF_ID,
+	HCAPI_CFA_RESC_TYPE_HW_EM_REC,
+	HCAPI_CFA_RESC_TYPE_HW_WC_TCAM_PROF_ID,
+	HCAPI_CFA_RESC_TYPE_HW_WC_TCAM,
+	HCAPI_CFA_RESC_TYPE_HW_METER_PROF,
+	HCAPI_CFA_RESC_TYPE_HW_METER_INST,
+	HCAPI_CFA_RESC_TYPE_HW_MIRROR,
+	HCAPI_CFA_RESC_TYPE_HW_UPAR,
+	/* Wh+/SR specific HW resources */
+	HCAPI_CFA_RESC_TYPE_HW_SP_TCAM,
+	/* Thor, SR2 common HW resources */
+	HCAPI_CFA_RESC_TYPE_HW_FKB,
+	/* SR specific HW resources */
+	HCAPI_CFA_RESC_TYPE_HW_TBL_SCOPE,
+	HCAPI_CFA_RESC_TYPE_HW_L2_FUNC,
+	HCAPI_CFA_RESC_TYPE_HW_EPOCH0,
+	HCAPI_CFA_RESC_TYPE_HW_EPOCH1,
+	HCAPI_CFA_RESC_TYPE_HW_METADATA,
+	HCAPI_CFA_RESC_TYPE_HW_CT_STATE,
+	HCAPI_CFA_RESC_TYPE_HW_RANGE_PROF,
+	HCAPI_CFA_RESC_TYPE_HW_RANGE_ENTRY,
+	HCAPI_CFA_RESC_TYPE_HW_LAG_ENTRY,
+	HCAPI_CFA_RESC_TYPE_HW_MAX
+};
+
+struct hcapi_cfa_key_result {
+	uint64_t bucket_mem_ptr;
+	uint8_t bucket_idx;
+};
+
+/* common CFA register access macros */
+#define CFA_REG(x)		OFFSETOF(cfa_reg_t, cfa_##x)
+
+#ifndef REG_WR
+#define REG_WR(_p, x, y)  (*((uint32_t volatile *)(x)) = (y))
+#endif
+#ifndef REG_RD
+#define REG_RD(_p, x)  (*((uint32_t volatile *)(x)))
+#endif
+#define CFA_REG_RD(_p, x)	\
+	REG_RD(0, (uint32_t)(_p)->base_addr + CFA_REG(x))
+#define CFA_REG_WR(_p, x, y)	\
+	REG_WR(0, (uint32_t)(_p)->base_addr + CFA_REG(x), y)
+
+
+/* Constants used by Resource Manager Registration*/
+#define RM_CLIENT_NAME_MAX_LEN          32
+
+/**
+ *  Resource Manager Data Structures used for resource requests
+ */
+struct hcapi_cfa_resc_req_entry {
+	uint16_t min;
+	uint16_t max;
+};
+
+struct hcapi_cfa_resc_req {
+	/* Wh+/SR specific onchip Action SRAM resources */
+	/* Validity of each sram type is indicated by the
+	 * corresponding sram type bit in the sram_resc_flags. When
+	 * set to 1, the CFA sram resource type is valid and amount of
+	 * resources for this type is reserved. Each sram resource
+	 * pool is identified by the starting index and number of
+	 * resources in the pool.
+	 */
+	uint32_t sram_resc_flags;
+	struct hcapi_cfa_resc_req_entry sram_resc[HCAPI_CFA_RESC_TYPE_SRAM_MAX];
+
+	/* Validity of each resource type is indicated by the
+	 * corresponding resource type bit in the hw_resc_flags. When
+	 * set to 1, the CFA resource type is valid and amount of
+	 * resource of this type is reserved. Each resource pool is
+	 * identified by the starting index and the number of
+	 * resources in the pool.
+	 */
+	uint32_t hw_resc_flags;
+	struct hcapi_cfa_resc_req_entry hw_resc[HCAPI_CFA_RESC_TYPE_HW_MAX];
+};
+
+struct hcapi_cfa_resc_req_db {
+	struct hcapi_cfa_resc_req rx;
+	struct hcapi_cfa_resc_req tx;
+};
+
+struct hcapi_cfa_resc_entry {
+	uint16_t start;
+	uint16_t stride;
+	uint16_t tag;
+};
+
+struct hcapi_cfa_resc {
+	/* Wh+/SR specific onchip Action SRAM resources */
+	/* Validity of each sram type is indicated by the
+	 * corresponding sram type bit in the sram_resc_flags. When
+	 * set to 1, the CFA sram resource type is valid and amount of
+	 * resources for this type is reserved. Each sram resource
+	 * pool is identified by the starting index and number of
+	 * resources in the pool.
+	 */
+	uint32_t sram_resc_flags;
+	struct hcapi_cfa_resc_entry sram_resc[HCAPI_CFA_RESC_TYPE_SRAM_MAX];
+
+	/* Validity of each resource type is indicated by the
+	 * corresponding resource type bit in the hw_resc_flags. When
+	 * set to 1, the CFA resource type is valid and amount of
+	 * resource of this type is reserved. Each resource pool is
+	 * identified by the startin index and the number of resources
+	 * in the pool.
+	 */
+	uint32_t hw_resc_flags;
+	struct hcapi_cfa_resc_entry hw_resc[HCAPI_CFA_RESC_TYPE_HW_MAX];
+};
+
+struct hcapi_cfa_resc_db {
+	struct hcapi_cfa_resc rx;
+	struct hcapi_cfa_resc tx;
+};
+
+/**
+ * This is the main data structure used by the CFA Resource
+ * Manager.  This data structure holds all the state and table
+ * management information.
+ */
+typedef struct hcapi_cfa_rm_data {
+	uint32_t dummy_data;
+} hcapi_cfa_rm_data_t;
+
+/* End RM support */
+
+struct hcapi_cfa_devops;
+
+struct hcapi_cfa_devinfo {
+	uint8_t global_cfg_data[CFA_GLOBAL_CFG_DATA_SZ];
+	struct hcapi_cfa_layout_tbl layouts;
+	struct hcapi_cfa_devops *devops;
+};
+
+int hcapi_cfa_dev_bind(enum hcapi_cfa_ver hw_ver,
+		       struct hcapi_cfa_devinfo *dev_info);
+
+int hcapi_cfa_key_compile_layout(struct hcapi_cfa_key_template *key_template,
+				 struct hcapi_cfa_key_layout *key_layout);
+uint64_t hcapi_cfa_key_hash(uint64_t *key_data, uint16_t bitlen);
+int
+hcapi_cfa_action_compile_layout(struct hcapi_cfa_action_template *act_template,
+				struct hcapi_cfa_action_layout *act_layout);
+int hcapi_cfa_action_init_obj(uint64_t *act_obj,
+			      struct hcapi_cfa_action_layout *act_layout);
+int hcapi_cfa_action_compute_ptr(uint64_t *act_obj,
+				 struct hcapi_cfa_action_layout *act_layout,
+				 uint32_t base_ptr);
+
+int hcapi_cfa_action_hw_op(struct hcapi_cfa_hwop *op,
+			   uint8_t *act_tbl,
+			   struct hcapi_cfa_data *act_obj);
+int hcapi_cfa_dev_hw_op(struct hcapi_cfa_hwop *op, uint16_t tbl_id,
+			struct hcapi_cfa_data *obj_data);
+int hcapi_cfa_rm_register_client(hcapi_cfa_rm_data_t *data,
+				 const char *client_name,
+				 int *client_id);
+int hcapi_cfa_rm_unregister_client(hcapi_cfa_rm_data_t *data,
+				   int client_id);
+int hcapi_cfa_rm_query_resources(hcapi_cfa_rm_data_t *data,
+				 int client_id,
+				 uint16_t chnl_id,
+				 struct hcapi_cfa_resc_req_db *req_db);
+int hcapi_cfa_rm_query_resources_one(hcapi_cfa_rm_data_t *data,
+				     int clien_id,
+				     struct hcapi_cfa_resc_db *resc_db);
+int hcapi_cfa_rm_reserve_resources(hcapi_cfa_rm_data_t *data,
+				   int client_id,
+				   struct hcapi_cfa_resc_req_db *resc_req,
+				   struct hcapi_cfa_resc_db *resc_db);
+int hcapi_cfa_rm_release_resources(hcapi_cfa_rm_data_t *data,
+				   int client_id,
+				   struct hcapi_cfa_resc_req_db *resc_req,
+				   struct hcapi_cfa_resc_db *resc_db);
+int hcapi_cfa_rm_initialize(hcapi_cfa_rm_data_t *data);
+
+#if SUPPORT_CFA_HW_P4
+
+int hcapi_cfa_p4_dev_hw_op(struct hcapi_cfa_hwop *op, uint16_t tbl_id,
+			    struct hcapi_cfa_data *obj_data);
+int hcapi_cfa_p4_prof_l2ctxt_hwop(struct hcapi_cfa_hwop *op,
+				   struct hcapi_cfa_data *obj_data);
+int hcapi_cfa_p4_prof_l2ctxtrmp_hwop(struct hcapi_cfa_hwop *op,
+				      struct hcapi_cfa_data *obj_data);
+int hcapi_cfa_p4_prof_tcam_hwop(struct hcapi_cfa_hwop *op,
+				 struct hcapi_cfa_data *obj_data);
+int hcapi_cfa_p4_prof_tcamrmp_hwop(struct hcapi_cfa_hwop *op,
+				    struct hcapi_cfa_data *obj_data);
+int hcapi_cfa_p4_wc_tcam_hwop(struct hcapi_cfa_hwop *op,
+			       struct hcapi_cfa_data *obj_data);
+int hcapi_cfa_p4_wc_tcam_rec_hwop(struct hcapi_cfa_hwop *op,
+				   struct hcapi_cfa_data *obj_data);
+#endif /* SUPPORT_CFA_HW_P4 */
+/**
+ *  HCAPI CFA device HW operation function callback definition
+ *  This is standardized function callback hook to install different
+ *  CFA HW table programming function callback.
+ */
+
+struct hcapi_cfa_tbl_cb {
+	/**
+	 * This function callback provides the functionality to read/write
+	 * HW table entry from a HW table.
+	 *
+	 * @param[in] op
+	 *   A pointer to the Hardware operation parameter
+	 *
+	 * @param[in] obj_data
+	 *   A pointer to the HW data object for the hardware operation
+	 *
+	 * @return
+	 *   0 for SUCCESS, negative value for FAILURE
+	 */
+	int (*hwop_cb)(struct hcapi_cfa_hwop *op,
+		       struct hcapi_cfa_data *obj_data);
+};
+
+#endif  /* HCAPI_CFA_H_ */
diff --git a/drivers/net/bnxt/hcapi/hcapi_cfa_common.c b/drivers/net/bnxt/hcapi/hcapi_cfa_common.c
new file mode 100644
index 000000000..39afd4dbc
--- /dev/null
+++ b/drivers/net/bnxt/hcapi/hcapi_cfa_common.c
@@ -0,0 +1,92 @@
+/*
+ *   Copyright(c) 2019-2020 Broadcom Limited.
+ *   All rights reserved.
+ */
+
+#include "bitstring.h"
+#include "hcapi_cfa_defs.h"
+#include <errno.h>
+#include "assert.h"
+
+/* HCAPI CFA common PUT APIs */
+int hcapi_cfa_put_field(uint64_t *data_buf,
+			const struct hcapi_cfa_layout *layout,
+			uint16_t field_id, uint64_t val)
+{
+	assert(layout);
+
+	if (field_id > layout->array_sz)
+		/* Invalid field_id */
+		return -EINVAL;
+
+	if (layout->is_msb_order)
+		bs_put_msb(data_buf,
+			   layout->field_array[field_id].bitpos,
+			   layout->field_array[field_id].bitlen, val);
+	else
+		bs_put_lsb(data_buf,
+			   layout->field_array[field_id].bitpos,
+			   layout->field_array[field_id].bitlen, val);
+	return 0;
+}
+
+int hcapi_cfa_put_fields(uint64_t *obj_data,
+			 const struct hcapi_cfa_layout *layout,
+			 struct hcapi_cfa_data_obj *field_tbl,
+			 uint16_t field_tbl_sz)
+{
+	int i;
+	uint16_t bitpos;
+	uint8_t bitlen;
+	uint16_t field_id;
+
+	assert(layout);
+	assert(field_tbl);
+
+	if (layout->is_msb_order) {
+		for (i = 0; i < field_tbl_sz; i++) {
+			field_id = field_tbl[i].field_id;
+			if (field_id > layout->array_sz)
+				return -EINVAL;
+			bitpos = layout->field_array[field_id].bitpos;
+			bitlen = layout->field_array[field_id].bitlen;
+			bs_put_msb(obj_data, bitpos, bitlen,
+				   field_tbl[i].val);
+		}
+	} else {
+		for (i = 0; i < field_tbl_sz; i++) {
+			field_id = field_tbl[i].field_id;
+			if (field_id > layout->array_sz)
+				return -EINVAL;
+			bitpos = layout->field_array[field_id].bitpos;
+			bitlen = layout->field_array[field_id].bitlen;
+			bs_put_lsb(obj_data, bitpos, bitlen,
+				   field_tbl[i].val);
+		}
+	}
+	return 0;
+}
+
+/* HCAPI CFA common GET APIs */
+int hcapi_cfa_get_field(uint64_t *obj_data,
+			const struct hcapi_cfa_layout *layout,
+			uint16_t field_id,
+			uint64_t *val)
+{
+	assert(layout);
+	assert(val);
+
+	if (field_id > layout->array_sz)
+		/* Invalid field_id */
+		return -EINVAL;
+
+	if (layout->is_msb_order)
+		*val = bs_get_msb(obj_data,
+				  layout->field_array[field_id].bitpos,
+				  layout->field_array[field_id].bitlen);
+	else
+		*val = bs_get_lsb(obj_data,
+				  layout->field_array[field_id].bitpos,
+				  layout->field_array[field_id].bitlen);
+	return 0;
+}
diff --git a/drivers/net/bnxt/hcapi/hcapi_cfa_defs.h b/drivers/net/bnxt/hcapi/hcapi_cfa_defs.h
new file mode 100644
index 000000000..ea8d99d01
--- /dev/null
+++ b/drivers/net/bnxt/hcapi/hcapi_cfa_defs.h
@@ -0,0 +1,672 @@
+
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2020 Broadcom
+ * All rights reserved.
+ */
+
+/*!
+ *   \file
+ *   \brief Exported functions for CFA HW programming
+ */
+#ifndef _HCAPI_CFA_DEFS_H_
+#define _HCAPI_CFA_DEFS_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#define SUPPORT_CFA_HW_ALL 0
+#define SUPPORT_CFA_HW_P4  1
+#define SUPPORT_CFA_HW_P58 0
+#define SUPPORT_CFA_HW_P59 0
+
+#define CFA_BITS_PER_BYTE (8)
+#define __CFA_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+#define CFA_ALIGN(x, a) __CFA_ALIGN_MASK(x, (a) - 1)
+#define CFA_ALIGN_128(x) CFA_ALIGN(x, 128)
+#define CFA_ALIGN_32(x) CFA_ALIGN(x, 32)
+
+#define NUM_WORDS_ALIGN_32BIT(x)                                               \
+	(CFA_ALIGN_32(x) / (sizeof(uint32_t) * CFA_BITS_PER_BYTE))
+#define NUM_WORDS_ALIGN_128BIT(x)                                              \
+	(CFA_ALIGN_128(x) / (sizeof(uint32_t) * CFA_BITS_PER_BYTE))
+
+#define CFA_GLOBAL_CFG_DATA_SZ (100)
+
+#if SUPPORT_CFA_HW_P4 && SUPPORT_CFA_HW_P58 && SUPPORT_CFA_HW_P59
+#define SUPPORT_CFA_HW_ALL (1)
+#endif
+
+#include "hcapi_cfa_p4.h"
+#define CFA_PROF_L2CTXT_TCAM_MAX_FIELD_CNT CFA_P40_PROF_L2_CTXT_TCAM_MAX_FLD
+#define CFA_PROF_L2CTXT_REMAP_MAX_FIELD_CNT CFA_P40_PROF_L2_CTXT_RMP_DR_MAX_FLD
+#define CFA_PROF_MAX_KEY_CFG_SZ sizeof(struct cfa_p4_prof_key_cfg)
+#define CFA_KEY_MAX_FIELD_CNT 41
+#define CFA_ACT_MAX_TEMPLATE_SZ sizeof(struct cfa_p4_action_template)
+
+/**
+ * CFA HW version definition
+ */
+enum hcapi_cfa_ver {
+	HCAPI_CFA_P40 = 0, /**< CFA phase 4.0 */
+	HCAPI_CFA_P45 = 1, /**< CFA phase 4.5 */
+	HCAPI_CFA_P58 = 2, /**< CFA phase 5.8 */
+	HCAPI_CFA_P59 = 3, /**< CFA phase 5.9 */
+	HCAPI_CFA_PMAX = 4
+};
+
+/**
+ * CFA direction definition
+ */
+enum hcapi_cfa_dir {
+	HCAPI_CFA_DIR_RX = 0, /**< Receive */
+	HCAPI_CFA_DIR_TX = 1, /**< Transmit */
+	HCAPI_CFA_DIR_MAX = 2
+};
+
+/**
+ * CFA HW OPCODE definition
+ */
+enum hcapi_cfa_hwops {
+	HCAPI_CFA_HWOPS_PUT, /**< Write to HW operation */
+	HCAPI_CFA_HWOPS_GET, /**< Read from HW operation */
+	HCAPI_CFA_HWOPS_ADD, /**< For operations which require more than simple
+			      * writes to HW, this operation is used. The
+			      * distinction with this operation when compared
+			      * to the PUT ops is that this operation is used
+			      * in conjunction with the HCAPI_CFA_HWOPS_DEL
+			      * op to remove the operations issued by the
+			      * ADD OP.
+			      */
+	HCAPI_CFA_HWOPS_DEL, /**< This issues operations to clear the hardware.
+			      * This operation is used in conjunction
+			      * with the HCAPI_CFA_HWOPS_ADD op and is the
+			      * way to undo/clear the ADD op.
+			      */
+	HCAPI_CFA_HWOPS_MAX
+};
+
+/**
+ * CFA HW KEY CONTROL OPCODE definition
+ */
+enum hcapi_cfa_key_ctrlops {
+	HCAPI_CFA_KEY_CTRLOPS_INSERT, /**< insert control bits */
+	HCAPI_CFA_KEY_CTRLOPS_STRIP, /**< strip control bits */
+	HCAPI_CFA_KEY_CTRLOPS_MAX
+};
+
+/**
+ * CFA HW field structure definition
+ */
+struct hcapi_cfa_field {
+	/** [in] Starting bit position pf the HW field within a HW table
+	 *  entry.
+	 */
+	uint16_t bitpos;
+	/** [in] Number of bits for the HW field. */
+	uint8_t bitlen;
+};
+
+/**
+ * CFA HW table entry layout structure definition
+ */
+struct hcapi_cfa_layout {
+	/** [out] Bit order of layout */
+	bool is_msb_order;
+	/** [out] Size in bits of entry */
+	uint32_t total_sz_in_bits;
+	/** [out] data pointer of the HW layout fields array */
+	const struct hcapi_cfa_field *field_array;
+	/** [out] number of HW field entries in the HW layout field array */
+	uint32_t array_sz;
+};
+
+/**
+ * CFA HW data object definition
+ */
+struct hcapi_cfa_data_obj {
+	/** [in] HW field identifier. Used as an index to a HW table layout */
+	uint16_t field_id;
+	/** [in] Value of the HW field */
+	uint64_t val;
+};
+
+/**
+ * CFA HW definition
+ */
+struct hcapi_cfa_hw {
+	/** [in] HW table base address for the operation with optional device
+	 *  handle. For on-chip HW table operation, this is the either the TX
+	 *  or RX CFA HW base address. For off-chip table, this field is the
+	 *  base memory address of the off-chip table.
+	 */
+	uint64_t base_addr;
+	/** [in] Optional opaque device handle. It is generally used to access
+	 *  an GRC register space through PCIE BAR and passed to the BAR memory
+	 *  accessor routine.
+	 */
+	void *handle;
+};
+
+/**
+ * CFA HW operation definition
+ *
+ */
+struct hcapi_cfa_hwop {
+	/** [in] HW opcode */
+	enum hcapi_cfa_hwops opcode;
+	/** [in] CFA HW information used by accessor routines.
+	 */
+	struct hcapi_cfa_hw hw;
+};
+
+/**
+ * CFA HW data structure definition
+ */
+struct hcapi_cfa_data {
+	/** [in] physical offset to the HW table for the data to be
+	 *  written to.  If this is an array of registers, this is the
+	 *  index into the array of registers.  For writing keys, this
+	 *  is the byte offset into the memory wher the key should be
+	 *  written.
+	 */
+	union {
+		uint32_t index;
+		uint32_t byte_offset;
+	} u;
+	/** [in] HW data buffer pointer */
+	uint8_t *data;
+	/** [in] HW data mask buffer pointer */
+	uint8_t *data_mask;
+	/** [in] size of the HW data buffer in bytes */
+	uint16_t data_sz;
+};
+
+/*********************** Truflow start ***************************/
+enum hcapi_cfa_pg_tbl_lvl {
+	TF_PT_LVL_0,
+	TF_PT_LVL_1,
+	TF_PT_LVL_2,
+	TF_PT_LVL_MAX
+};
+
+enum hcapi_cfa_em_table_type {
+	TF_KEY0_TABLE,
+	TF_KEY1_TABLE,
+	TF_RECORD_TABLE,
+	TF_EFC_TABLE,
+	TF_MAX_TABLE
+};
+
+struct hcapi_cfa_em_page_tbl {
+	uint32_t	pg_count;
+	uint32_t	pg_size;
+	void		**pg_va_tbl;
+	uint64_t	*pg_pa_tbl;
+};
+
+struct hcapi_cfa_em_table {
+	int				type;
+	uint32_t			num_entries;
+	uint16_t			ctx_id;
+	uint32_t			entry_size;
+	int				num_lvl;
+	uint32_t			page_cnt[TF_PT_LVL_MAX];
+	uint64_t			num_data_pages;
+	void				*l0_addr;
+	uint64_t			l0_dma_addr;
+	struct hcapi_cfa_em_page_tbl    pg_tbl[TF_PT_LVL_MAX];
+};
+
+struct hcapi_cfa_em_ctx_mem_info {
+	struct hcapi_cfa_em_table		em_tables[TF_MAX_TABLE];
+};
+
+/*********************** Truflow end ****************************/
+
+/**
+ * CFA HW key table definition
+ *
+ * Applicable to EEM and off-chip EM table only.
+ */
+struct hcapi_cfa_key_tbl {
+	/** [in] For EEM, this is the KEY0 base mem pointer. For off-chip EM,
+	 *  this is the base mem pointer of the key table.
+	 */
+	uint8_t *base0;
+	/** [in] total size of the key table in bytes. For EEM, this size is
+	 *  same for both KEY0 and KEY1 table.
+	 */
+	uint32_t size;
+	/** [in] number of key buckets, applicable for newer chips */
+	uint32_t num_buckets;
+	/** [in] For EEM, this is KEY1 base mem pointer. Fo off-chip EM,
+	 *  this is the key record memory base pointer within the key table,
+	 *  applicable for newer chip
+	 */
+	uint8_t *base1;
+};
+
+/**
+ * CFA HW key buffer definition
+ */
+struct hcapi_cfa_key_obj {
+	/** [in] pointer to the key data buffer */
+	uint32_t *data;
+	/** [in] buffer len in bits */
+	uint32_t len;
+	/** [in] Pointer to the key layout */
+	struct hcapi_cfa_key_layout *layout;
+};
+
+/**
+ * CFA HW key data definition
+ */
+struct hcapi_cfa_key_data {
+	/** [in] For on-chip key table, it is the offset in unit of smallest
+	 *  key. For off-chip key table, it is the byte offset relative
+	 *  to the key record memory base.
+	 */
+	uint32_t offset;
+	/** [in] HW key data buffer pointer */
+	uint8_t *data;
+	/** [in] size of the key in bytes */
+	uint16_t size;
+};
+
+/**
+ * CFA HW key location definition
+ */
+struct hcapi_cfa_key_loc {
+	/** [out] on-chip EM bucket offset or off-chip EM bucket mem pointer */
+	uint64_t bucket_mem_ptr;
+	/** [out] index within the EM bucket */
+	uint8_t bucket_idx;
+};
+
+/**
+ * CFA HW layout table definition
+ */
+struct hcapi_cfa_layout_tbl {
+	/** [out] data pointer to an array of fix formatted layouts supported.
+	 *  The index to the array is the CFA HW table ID
+	 */
+	const struct hcapi_cfa_layout *tbl;
+	/** [out] number of fix formatted layouts in the layout array */
+	uint16_t num_layouts;
+};
+
+/**
+ * Key template consists of key fields that can be enabled/disabled
+ * individually.
+ */
+struct hcapi_cfa_key_template {
+	/** [in] key field enable field array, set 1 to the correspeonding
+	 *  field enable to make a field valid
+	 */
+	uint8_t field_en[CFA_KEY_MAX_FIELD_CNT];
+	/** [in] Identified if the key template is for TCAM. If false, the
+	 *  the key template is for EM. This field is mandantory for device that
+	 *  only support fix key formats.
+	 */
+	bool is_wc_tcam_key;
+};
+
+/**
+ * key layout consist of field array, key bitlen, key ID, and other meta data
+ * pertain to a key
+ */
+struct hcapi_cfa_key_layout {
+	/** [out] key layout data */
+	struct hcapi_cfa_layout *layout;
+	/** [out] actual key size in number of bits */
+	uint16_t bitlen;
+	/** [out] key identifier and this field is only valid for device
+	 *  that supports fix key formats
+	 */
+	uint16_t id;
+	/** [out] Indentified the key layout is WC TCAM key */
+	bool is_wc_tcam_key;
+	/** [out] total slices size, valid for WC TCAM key only. It can be
+	 *  used by the user to determine the total size of WC TCAM key slices
+	 *  in bytes.
+	 */
+	uint16_t slices_size;
+};
+
+/**
+ * key layout memory contents
+ */
+struct hcapi_cfa_key_layout_contents {
+	/** key layouts */
+	struct hcapi_cfa_key_layout key_layout;
+
+	/** layout */
+	struct hcapi_cfa_layout layout;
+
+	/** fields */
+	struct hcapi_cfa_field field_array[CFA_KEY_MAX_FIELD_CNT];
+};
+
+/**
+ * Action template consists of action fields that can be enabled/disabled
+ * individually.
+ */
+struct hcapi_cfa_action_template {
+	/** [in] CFA version for the action template */
+	enum hcapi_cfa_ver hw_ver;
+	/** [in] action field enable field array, set 1 to the correspeonding
+	 *  field enable to make a field valid
+	 */
+	uint8_t data[CFA_ACT_MAX_TEMPLATE_SZ];
+};
+
+/**
+ * action layout consist of field array, action wordlen and action format ID
+ */
+struct hcapi_cfa_action_layout {
+	/** [in] action identifier */
+	uint16_t id;
+	/** [out] action layout data */
+	struct hcapi_cfa_layout *layout;
+	/** [out] actual action record size in number of bits */
+	uint16_t wordlen;
+};
+
+/**
+ *  \defgroup CFA_HCAPI_PUT_API
+ *  HCAPI used for writing to the hardware
+ *  @{
+ */
+
+/**
+ * This API provides the functionality to program a specified value to a
+ * HW field based on the provided programming layout.
+ *
+ * @param[in,out] obj_data
+ *   A data pointer to a CFA HW key/mask data
+ *
+ * @param[in] layout
+ *   A pointer to CFA HW programming layout
+ *
+ * @param[in] field_id
+ *   ID of the HW field to be programmed
+ *
+ * @param[in] val
+ *   Value of the HW field to be programmed
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_put_field(uint64_t *data_buf,
+			const struct hcapi_cfa_layout *layout,
+			uint16_t field_id, uint64_t val);
+
+/**
+ * This API provides the functionality to program an array of field values
+ * with corresponding field IDs to a number of profiler sub-block fields
+ * based on the fixed profiler sub-block hardware programming layout.
+ *
+ * @param[in, out] obj_data
+ *   A pointer to a CFA profiler key/mask object data
+ *
+ * @param[in] layout
+ *   A pointer to CFA HW programming layout
+ *
+ * @param[in] field_tbl
+ *   A pointer to an array that consists of the object field
+ *   ID/value pairs
+ *
+ * @param[in] field_tbl_sz
+ *   Number of entries in the table
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_put_fields(uint64_t *obj_data,
+			 const struct hcapi_cfa_layout *layout,
+			 struct hcapi_cfa_data_obj *field_tbl,
+			 uint16_t field_tbl_sz);
+
+/**
+ * This API provides the functionality to write a value to a
+ * field within the bit position and bit length of a HW data
+ * object based on a provided programming layout.
+ *
+ * @param[in, out] act_obj
+ *   A pointer of the action object to be initialized
+ *
+ * @param[in] layout
+ *   A pointer of the programming layout
+ *
+ * @param field_id
+ *   [in] Identifier of the HW field
+ *
+ * @param[in] bitpos_adj
+ *   Bit position adjustment value
+ *
+ * @param[in] bitlen_adj
+ *   Bit length adjustment value
+ *
+ * @param[in] val
+ *   HW field value to be programmed
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_put_field_rel(uint64_t *obj_data,
+			    const struct hcapi_cfa_layout *layout,
+			    uint16_t field_id, int16_t bitpos_adj,
+			    int16_t bitlen_adj, uint64_t val);
+
+/*@}*/
+
+/**
+ *  \defgroup CFA_HCAPI_GET_API
+ *  HCAPI used for writing to the hardware
+ *  @{
+ */
+
+/**
+ * This API provides the functionality to get the word length of
+ * a layout object.
+ *
+ * @param[in] layout
+ *   A pointer of the HW layout
+ *
+ * @return
+ *   Word length of the layout object
+ */
+uint16_t hcapi_cfa_get_wordlen(const struct hcapi_cfa_layout *layout);
+
+/**
+ * The API provides the functionality to get bit offset and bit
+ * length information of a field from a programming layout.
+ *
+ * @param[in] layout
+ *   A pointer of the action layout
+ *
+ * @param[out] slice
+ *   A pointer to the action offset info data structure
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_get_slice(const struct hcapi_cfa_layout *layout,
+			uint16_t field_id, struct hcapi_cfa_field *slice);
+
+/**
+ * This API provides the functionality to read the value of a
+ * CFA HW field from CFA HW data object based on the hardware
+ * programming layout.
+ *
+ * @param[in] obj_data
+ *   A pointer to a CFA HW key/mask object data
+ *
+ * @param[in] layout
+ *   A pointer to CFA HW programming layout
+ *
+ * @param[in] field_id
+ *   ID of the HW field to be programmed
+ *
+ * @param[out] val
+ *   Value of the HW field
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_get_field(uint64_t *obj_data,
+			const struct hcapi_cfa_layout *layout,
+			uint16_t field_id, uint64_t *val);
+
+/**
+ * This API provides the functionality to read a number of
+ * HW fields from a CFA HW data object based on the hardware
+ * programming layout.
+ *
+ * @param[in] obj_data
+ *   A pointer to a CFA profiler key/mask object data
+ *
+ * @param[in] layout
+ *   A pointer to CFA HW programming layout
+ *
+ * @param[in, out] field_tbl
+ *   A pointer to an array that consists of the object field
+ *   ID/value pairs
+ *
+ * @param[in] field_tbl_sz
+ *   Number of entries in the table
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_get_fields(uint64_t *obj_data,
+			 const struct hcapi_cfa_layout *layout,
+			 struct hcapi_cfa_data_obj *field_tbl,
+			 uint16_t field_tbl_sz);
+
+/**
+ * Get a value to a specific location relative to a HW field
+ *
+ * This API provides the functionality to read HW field from
+ * a section of a HW data object identified by the bit position
+ * and bit length from a given programming layout in order to avoid
+ * reading the entire HW data object.
+ *
+ * @param[in] obj_data
+ *   A pointer of the data object to read from
+ *
+ * @param[in] layout
+ *   A pointer of the programming layout
+ *
+ * @param[in] field_id
+ *   Identifier of the HW field
+ *
+ * @param[in] bitpos_adj
+ *   Bit position adjustment value
+ *
+ * @param[in] bitlen_adj
+ *   Bit length adjustment value
+ *
+ * @param[out] val
+ *   Value of the HW field
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_get_field_rel(uint64_t *obj_data,
+			    const struct hcapi_cfa_layout *layout,
+			    uint16_t field_id, int16_t bitpos_adj,
+			    int16_t bitlen_adj, uint64_t *val);
+
+/**
+ * This function is used to initialize a layout_contents structure
+ *
+ * The struct hcapi_cfa_key_layout is complex as there are three
+ * layers of abstraction.  Each of those layer need to be properly
+ * initialized.
+ *
+ * @param[in] layout_contents
+ *  A pointer of the layout contents to initialize
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int
+hcapi_cfa_init_key_layout_contents(struct hcapi_cfa_key_layout_contents *cont);
+
+/**
+ * This function is used to validate a key template
+ *
+ * The struct hcapi_cfa_key_template is complex as there are three
+ * layers of abstraction.  Each of those layer need to be properly
+ * validated.
+ *
+ * @param[in] key_template
+ *  A pointer of the key template contents to validate
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int
+hcapi_cfa_is_valid_key_template(struct hcapi_cfa_key_template *key_template);
+
+/**
+ * This function is used to validate a key layout
+ *
+ * The struct hcapi_cfa_key_layout is complex as there are three
+ * layers of abstraction.  Each of those layer need to be properly
+ * validated.
+ *
+ * @param[in] key_layout
+ *  A pointer of the key layout contents to validate
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_is_valid_key_layout(struct hcapi_cfa_key_layout *key_layout);
+
+/**
+ * This function is used to hash E/EM keys
+ *
+ *
+ * @param[in] key_data
+ *  A pointer of the key
+ *
+ * @param[in] bitlen
+ *  Number of bits in the key
+ *
+ * @return
+ *   CRC32 and Lookup3 hashes of the input key
+ */
+uint64_t hcapi_cfa_key_hash(uint64_t *key_data,
+			    uint16_t bitlen);
+
+/**
+ * This function is used to execute an operation
+ *
+ *
+ * @param[in] op
+ *  Operation
+ *
+ * @param[in] key_tbl
+ *  Table
+ *
+ * @param[in] key_obj
+ *  Key data
+ *
+ * @param[in] key_key_loc
+ *
+ * @return
+ *   0 for SUCCESS, negative value for FAILURE
+ */
+int hcapi_cfa_key_hw_op(struct hcapi_cfa_hwop *op,
+			struct hcapi_cfa_key_tbl *key_tbl,
+			struct hcapi_cfa_key_data *key_obj,
+			struct hcapi_cfa_key_loc *key_loc);
+
+uint64_t hcapi_get_table_page(struct hcapi_cfa_em_table *mem,
+			      uint32_t offset);
+#endif /* HCAPI_CFA_DEFS_H_ */
diff --git a/drivers/net/bnxt/hcapi/hcapi_cfa_p4.c b/drivers/net/bnxt/hcapi/hcapi_cfa_p4.c
new file mode 100644
index 000000000..ca0b1c923
--- /dev/null
+++ b/drivers/net/bnxt/hcapi/hcapi_cfa_p4.c
@@ -0,0 +1,399 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2020 Broadcom
+ * All rights reserved.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include "lookup3.h"
+#include "rand.h"
+
+#include "hcapi_cfa_defs.h"
+
+#define HCAPI_CFA_LKUP_SEED_MEM_SIZE 512
+#define TF_EM_PAGE_SIZE (1 << 21)
+uint32_t hcapi_cfa_lkup_lkup3_init_cfg;
+uint32_t hcapi_cfa_lkup_em_seed_mem[HCAPI_CFA_LKUP_SEED_MEM_SIZE];
+bool hcapi_cfa_lkup_init;
+
+static inline uint32_t SWAP_WORDS32(uint32_t val32)
+{
+	return (((val32 & 0x0000ffff) << 16) |
+		((val32 & 0xffff0000) >> 16));
+}
+
+static void hcapi_cfa_seeds_init(void)
+{
+	int i;
+	uint32_t r;
+
+	if (hcapi_cfa_lkup_init)
+		return;
+
+	hcapi_cfa_lkup_init = true;
+
+	/* Initialize the lfsr */
+	rand_init();
+
+	/* RX and TX use the same seed values */
+	hcapi_cfa_lkup_lkup3_init_cfg = SWAP_WORDS32(rand32());
+
+	for (i = 0; i < HCAPI_CFA_LKUP_SEED_MEM_SIZE / 2; i++) {
+		r = SWAP_WORDS32(rand32());
+		hcapi_cfa_lkup_em_seed_mem[i * 2] = r;
+		r = SWAP_WORDS32(rand32());
+		hcapi_cfa_lkup_em_seed_mem[i * 2 + 1] = (r & 0x1);
+	}
+}
+
+/* CRC32i support for Key0 hash */
+#define ucrc32(ch, crc) (crc32tbl[((crc) ^ (ch)) & 0xff] ^ ((crc) >> 8))
+#define crc32(x, y) crc32i(~0, x, y)
+
+static const uint32_t crc32tbl[] = {	/* CRC polynomial 0xedb88320 */
+0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+static uint32_t hcapi_cfa_crc32i(uint32_t crc, const uint8_t *buf, size_t len)
+{
+	int l;
+
+#ifdef TF_EEM_DEBUG
+	TFP_DRV_LOG(DEBUG, "CRC2:");
+#endif
+	for (l = (len - 1); l >= 0; l--) {
+		crc = ucrc32(buf[l], crc);
+#ifdef TF_EEM_DEBUG
+		TFP_DRV_LOG(DEBUG,
+			    "%02X %08X %08X\n",
+			    (buf[l] & 0xff),
+			    crc,
+			    ~crc);
+#endif
+	}
+
+#ifdef TF_EEM_DEBUG
+	TFP_DRV_LOG(DEBUG, "\n");
+#endif
+
+	return ~crc;
+}
+
+static uint32_t hcapi_cfa_crc32_hash(uint8_t *key)
+{
+	int i;
+	uint32_t index;
+	uint32_t val1, val2;
+	uint8_t temp[4];
+	uint8_t *kptr = key;
+
+	/* Do byte-wise XOR of the 52-byte HASH key first. */
+	index = *key;
+	kptr--;
+
+	for (i = CFA_P4_EEM_KEY_MAX_SIZE - 2; i >= 0; i--) {
+		index = index ^ *kptr;
+		kptr--;
+	}
+
+	/* Get seeds */
+	val1 = hcapi_cfa_lkup_em_seed_mem[index * 2];
+	val2 = hcapi_cfa_lkup_em_seed_mem[index * 2 + 1];
+
+	temp[3] = (uint8_t)(val1 >> 24);
+	temp[2] = (uint8_t)(val1 >> 16);
+	temp[1] = (uint8_t)(val1 >> 8);
+	temp[0] = (uint8_t)(val1 & 0xff);
+	val1 = 0;
+
+	/* Start with seed */
+	if (!(val2 & 0x1))
+		val1 = hcapi_cfa_crc32i(~val1, temp, 4);
+
+	val1 = hcapi_cfa_crc32i(~val1,
+		      (key - (CFA_P4_EEM_KEY_MAX_SIZE - 1)),
+		      CFA_P4_EEM_KEY_MAX_SIZE);
+
+	/* End with seed */
+	if (val2 & 0x1)
+		val1 = hcapi_cfa_crc32i(~val1, temp, 4);
+
+	return val1;
+}
+
+static uint32_t hcapi_cfa_lookup3_hash(uint8_t *in_key)
+{
+	uint32_t val1;
+
+	val1 = hashword(((const uint32_t *)(uintptr_t *)in_key) + 1,
+			 CFA_P4_EEM_KEY_MAX_SIZE / (sizeof(uint32_t)),
+			 hcapi_cfa_lkup_lkup3_init_cfg);
+
+	return val1;
+}
+
+
+uint64_t hcapi_get_table_page(struct hcapi_cfa_em_table *mem,
+			      uint32_t offset)
+{
+	int level = 0;
+	int page = offset / TF_EM_PAGE_SIZE;
+	uint64_t addr;
+
+	if (mem == NULL)
+		return 0;
+
+	/*
+	 * Use the level according to the num_level of page table
+	 */
+	level = mem->num_lvl - 1;
+
+	addr = (uintptr_t)mem->pg_tbl[level].pg_va_tbl[page];
+
+	return addr;
+}
+
+/** Approximation of HCAPI hcapi_cfa_key_hash()
+ *
+ * Return:
+ *
+ */
+uint64_t hcapi_cfa_key_hash(uint64_t *key_data,
+			    uint16_t bitlen)
+{
+	uint32_t key0_hash;
+	uint32_t key1_hash;
+
+	/*
+	 * Init the seeds if needed
+	 */
+	if (!hcapi_cfa_lkup_init)
+		hcapi_cfa_seeds_init();
+
+	key0_hash = hcapi_cfa_crc32_hash(((uint8_t *)key_data) +
+					      (bitlen / 8) - 1);
+
+	key1_hash = hcapi_cfa_lookup3_hash((uint8_t *)key_data);
+
+	return ((uint64_t)key0_hash) << 32 | (uint64_t)key1_hash;
+}
+
+static int hcapi_cfa_key_hw_op_put(struct hcapi_cfa_hwop *op,
+				   struct hcapi_cfa_key_data *key_obj)
+{
+	int rc = 0;
+
+	memcpy((uint8_t *)(uintptr_t)op->hw.base_addr +
+	       key_obj->offset,
+	       key_obj->data,
+	       key_obj->size);
+
+	return rc;
+}
+
+static int hcapi_cfa_key_hw_op_get(struct hcapi_cfa_hwop *op,
+				   struct hcapi_cfa_key_data *key_obj)
+{
+	int rc = 0;
+
+	memcpy(key_obj->data,
+	       (uint8_t *)(uintptr_t)op->hw.base_addr +
+	       key_obj->offset,
+	       key_obj->size);
+
+	return rc;
+}
+
+static int hcapi_cfa_key_hw_op_add(struct hcapi_cfa_hwop *op,
+				   struct hcapi_cfa_key_data *key_obj)
+{
+	int rc = 0;
+	struct cfa_p4_eem_64b_entry table_entry;
+
+	/*
+	 * Is entry free?
+	 */
+	memcpy(&table_entry,
+	       (uint8_t *)(uintptr_t)op->hw.base_addr +
+	       key_obj->offset,
+	       key_obj->size);
+
+	/*
+	 * If this is entry is valid then report failure
+	 */
+	if (table_entry.hdr.word1 & (1 << CFA_P4_EEM_ENTRY_VALID_SHIFT))
+		return -1;
+
+	memcpy((uint8_t *)(uintptr_t)op->hw.base_addr +
+	       key_obj->offset,
+	       key_obj->data,
+	       key_obj->size);
+
+	return rc;
+}
+
+static int hcapi_cfa_key_hw_op_del(struct hcapi_cfa_hwop *op,
+				   struct hcapi_cfa_key_data *key_obj)
+{
+	int rc = 0;
+	struct cfa_p4_eem_64b_entry table_entry;
+
+	/*
+	 * Read entry
+	 */
+	memcpy(&table_entry,
+	       (uint8_t *)(uintptr_t)op->hw.base_addr +
+	       key_obj->offset,
+	       key_obj->size);
+
+	/*
+	 * If this is not a valid entry then report failure.
+	 */
+	if (table_entry.hdr.word1 & (1 << CFA_P4_EEM_ENTRY_VALID_SHIFT)) {
+		/*
+		 * If a key has been provided then verify the key matches
+		 * before deleting the entry.
+		 */
+		if (key_obj->data != NULL) {
+			if (memcmp(&table_entry,
+				   key_obj->data,
+				   key_obj->size) != 0)
+				return -1;
+		}
+	} else {
+		return -1;
+	}
+
+
+	/*
+	 * Delete entry
+	 */
+	memset((uint8_t *)(uintptr_t)op->hw.base_addr +
+	       key_obj->offset,
+	       0,
+	       key_obj->size);
+
+	return rc;
+}
+
+
+/** Apporiximation of hcapi_cfa_key_hw_op()
+ *
+ *
+ */
+int hcapi_cfa_key_hw_op(struct hcapi_cfa_hwop *op,
+			struct hcapi_cfa_key_tbl *key_tbl,
+			struct hcapi_cfa_key_data *key_obj,
+			struct hcapi_cfa_key_loc *key_loc)
+{
+	int rc = 0;
+
+	if (op == NULL ||
+	    key_tbl == NULL ||
+	    key_obj == NULL ||
+	    key_loc == NULL)
+		return -1;
+
+	op->hw.base_addr =
+		hcapi_get_table_page((struct hcapi_cfa_em_table *)
+				     key_tbl->base0,
+				     key_obj->offset);
+
+	if (op->hw.base_addr == 0)
+		return -1;
+
+	switch (op->opcode) {
+	case HCAPI_CFA_HWOPS_PUT: /**< Write to HW operation */
+		rc = hcapi_cfa_key_hw_op_put(op, key_obj);
+		break;
+	case HCAPI_CFA_HWOPS_GET: /**< Read from HW operation */
+		rc = hcapi_cfa_key_hw_op_get(op, key_obj);
+		break;
+	case HCAPI_CFA_HWOPS_ADD:
+		/**< For operations which require more than
+		 * simple writes to HW, this operation is used. The
+		 * distinction with this operation when compared
+		 * to the PUT ops is that this operation is used
+		 * in conjunction with the HCAPI_CFA_HWOPS_DEL
+		 * op to remove the operations issued by the
+		 * ADD OP.
+		 */
+
+		rc = hcapi_cfa_key_hw_op_add(op, key_obj);
+
+		break;
+	case HCAPI_CFA_HWOPS_DEL:
+		rc = hcapi_cfa_key_hw_op_del(op, key_obj);
+		break;
+	default:
+		rc = -1;
+		break;
+	}
+
+	return rc;
+}
diff --git a/drivers/net/bnxt/hcapi/hcapi_cfa_p4.h b/drivers/net/bnxt/hcapi/hcapi_cfa_p4.h
new file mode 100644
index 000000000..0661d6363
--- /dev/null
+++ b/drivers/net/bnxt/hcapi/hcapi_cfa_p4.h
@@ -0,0 +1,451 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2020 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _HCAPI_CFA_P4_H_
+#define _HCAPI_CFA_P4_H_
+
+#include "cfa_p40_hw.h"
+
+/** CFA phase 4 fix formatted table(layout) ID definition
+ *
+ */
+enum cfa_p4_tbl_id {
+	CFA_P4_TBL_L2CTXT_TCAM = 0,
+	CFA_P4_TBL_L2CTXT_REMAP,
+	CFA_P4_TBL_PROF_TCAM,
+	CFA_P4_TBL_PROF_TCAM_REMAP,
+	CFA_P4_TBL_WC_TCAM,
+	CFA_P4_TBL_WC_TCAM_REC,
+	CFA_P4_TBL_WC_TCAM_REMAP,
+	CFA_P4_TBL_VEB_TCAM,
+	CFA_P4_TBL_SP_TCAM,
+	CFA_P4_TBL_MAX
+};
+
+#define CFA_P4_PROF_MAX_KEYS 4
+enum cfa_p4_mac_sel_mode {
+	CFA_P4_MAC_SEL_MODE_FIRST = 0,
+	CFA_P4_MAC_SEL_MODE_LOWEST = 1,
+};
+
+struct cfa_p4_prof_key_cfg {
+	uint8_t mac_sel[CFA_P4_PROF_MAX_KEYS];
+#define CFA_P4_PROF_MAC_SEL_DMAC0 (1 << 0)
+#define CFA_P4_PROF_MAC_SEL_T_MAC0 (1 << 1)
+#define CFA_P4_PROF_MAC_SEL_OUTERMOST_MAC0 (1 << 2)
+#define CFA_P4_PROF_MAC_SEL_DMAC1 (1 << 3)
+#define CFA_P4_PROF_MAC_SEL_T_MAC1 (1 << 4)
+#define CFA_P4_PROF_MAC_OUTERMOST_MAC1 (1 << 5)
+	uint8_t pass_cnt;
+	enum cfa_p4_mac_sel_mode mode;
+};
+
+/**
+ * CFA action layout definition
+ */
+
+#define CFA_P4_ACTION_MAX_LAYOUT_SIZE 184
+
+/**
+ * Action object template structure
+ *
+ * Template structure presents data fields that are necessary to know
+ * at the beginning of Action Builder (AB) processing. Like before the
+ * AB compilation. One such example could be a template that is
+ * flexible in size (Encap Record) and the presence of these fields
+ * allows for determining the template size as well as where the
+ * fields are located in the record.
+ *
+ * The template may also present fields that are not made visible to
+ * the caller by way of the action fields.
+ *
+ * Template fields also allow for additional checking on user visible
+ * fields. One such example could be the encap pointer behavior on a
+ * CFA_P4_ACT_OBJ_TYPE_ACT or CFA_P4_ACT_OBJ_TYPE_ACT_SRAM.
+ */
+struct cfa_p4_action_template {
+	/** Action Object type
+	 *
+	 * Controls the type of the Action Template
+	 */
+	enum {
+		/** Select this type to build an Action Record Object
+		 */
+		CFA_P4_ACT_OBJ_TYPE_ACT,
+		/** Select this type to build an Action Statistics
+		 * Object
+		 */
+		CFA_P4_ACT_OBJ_TYPE_STAT,
+		/** Select this type to build a SRAM Action Record
+		 * Object.
+		 */
+		CFA_P4_ACT_OBJ_TYPE_ACT_SRAM,
+		/** Select this type to build a SRAM Action
+		 * Encapsulation Object.
+		 */
+		CFA_P4_ACT_OBJ_TYPE_ENCAP_SRAM,
+		/** Select this type to build a SRAM Action Modify
+		 * Object, with IPv4 capability.
+		 */
+		/* In case of Stingray the term Modify is used for the 'NAT
+		 * action'. Action builder is leveraged to fill in the NAT
+		 * object which then can be referenced by the action
+		 * record.
+		 */
+		CFA_P4_ACT_OBJ_TYPE_MODIFY_IPV4_SRAM,
+		/** Select this type to build a SRAM Action Source
+		 * Property Object.
+		 */
+		/* In case of Stingray this is not a 'pure' action record.
+		 * Action builder is leveraged to full in the Source Property
+		 * object which can then be referenced by the action
+		 * record.
+		 */
+		CFA_P4_ACT_OBJ_TYPE_SRC_PROP_SRAM,
+		/** Select this type to build a SRAM Action Statistics
+		 * Object
+		 */
+		CFA_P4_ACT_OBJ_TYPE_STAT_SRAM,
+	} obj_type;
+
+	/** Action Control
+	 *
+	 * Controls the internals of the Action Template
+	 *
+	 * act is valid when:
+	 * (obj_type == CFA_P4_ACT_OBJ_TYPE_ACT)
+	 */
+	/*
+	 * Stat and encap are always inline for EEM as table scope
+	 * allocation does not allow for separate Stats allocation,
+	 * but has the xx_inline flags as to be forward compatible
+	 * with Stingray 2, always treated as TRUE.
+	 */
+	struct {
+		/** Set to CFA_HCAPI_TRUE to enable statistics
+		 */
+		uint8_t stat_enable;
+		/** Set to CFA_HCAPI_TRUE to enable statistics to be inlined
+		 */
+		uint8_t stat_inline;
+
+		/** Set to CFA_HCAPI_TRUE to enable encapsulation
+		 */
+		uint8_t encap_enable;
+		/** Set to CFA_HCAPI_TRUE to enable encapsulation to be inlined
+		 */
+		uint8_t encap_inline;
+	} act;
+
+	/** Modify Setting
+	 *
+	 * Controls the type of the Modify Action the template is
+	 * describing
+	 *
+	 * modify is valid when:
+	 * (obj_type == CFA_P4_ACT_OBJ_TYPE_MODIFY_SRAM)
+	 */
+	enum {
+		/** Set to enable Modify of Source IPv4 Address
+		 */
+		CFA_P4_MR_REPLACE_SOURCE_IPV4 = 0,
+		/** Set to enable Modify of Destination IPv4 Address
+		 */
+		CFA_P4_MR_REPLACE_DEST_IPV4
+	} modify;
+
+	/** Encap Control
+	 * Controls the type of encapsulation the template is
+	 * describing
+	 *
+	 * encap is valid when:
+	 * ((obj_type == CFA_P4_ACT_OBJ_TYPE_ACT) &&
+	 *   act.encap_enable) ||
+	 * ((obj_type == CFA_P4_ACT_OBJ_TYPE_SRC_PROP_SRAM)
+	 */
+	struct {
+		/* Direction is required as Stingray Encap on RX is
+		 * limited to l2 and VTAG only.
+		 */
+		/** Receive or Transmit direction
+		 */
+		uint8_t direction;
+		/** Set to CFA_HCAPI_TRUE to enable L2 capability in the
+		 *  template
+		 */
+		uint8_t l2_enable;
+		/** vtag controls the Encap Vector - VTAG Encoding, 4 bits
+		 *
+		 * <ul>
+		 * <li> CFA_P4_ACT_ENCAP_VTAGS_PUSH_0, default, no VLAN
+		 *      Tags applied
+		 * <li> CFA_P4_ACT_ENCAP_VTAGS_PUSH_1, adds capability to
+		 *      set 1 VLAN Tag. Action Template compile adds
+		 *      the following field to the action object
+		 *      ::TF_ER_VLAN1
+		 * <li> CFA_P4_ACT_ENCAP_VTAGS_PUSH_2, adds capability to
+		 *      set 2 VLAN Tags. Action Template compile adds
+		 *      the following fields to the action object
+		 *      ::TF_ER_VLAN1 and ::TF_ER_VLAN2
+		 * </ul>
+		 */
+		enum { CFA_P4_ACT_ENCAP_VTAGS_PUSH_0 = 0,
+		       CFA_P4_ACT_ENCAP_VTAGS_PUSH_1,
+		       CFA_P4_ACT_ENCAP_VTAGS_PUSH_2 } vtag;
+
+		/*
+		 * The remaining fields are NOT supported when
+		 * direction is RX and ((obj_type ==
+		 * CFA_P4_ACT_OBJ_TYPE_ACT) && act.encap_enable).
+		 * ab_compile_layout will perform the checking and
+		 * skip remaining fields.
+		 */
+		/** L3 Encap controls the Encap Vector - L3 Encoding,
+		 *  3 bits. Defines the type of L3 Encapsulation the
+		 *  template is describing.
+		 * <ul>
+		 * <li> CFA_P4_ACT_ENCAP_L3_NONE, default, no L3
+		 *      Encapsulation processing.
+		 * <li> CFA_P4_ACT_ENCAP_L3_IPV4, enables L3 IPv4
+		 *      Encapsulation.
+		 * <li> CFA_P4_ACT_ENCAP_L3_IPV6, enables L3 IPv6
+		 *      Encapsulation.
+		 * <li> CFA_P4_ACT_ENCAP_L3_MPLS_8847, enables L3 MPLS
+		 *      8847 Encapsulation.
+		 * <li> CFA_P4_ACT_ENCAP_L3_MPLS_8848, enables L3 MPLS
+		 *      8848 Encapsulation.
+		 * </ul>
+		 */
+		enum {
+			/** Set to disable any L3 encapsulation
+			 * processing, default
+			 */
+			CFA_P4_ACT_ENCAP_L3_NONE = 0,
+			/** Set to enable L3 IPv4 encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_L3_IPV4 = 4,
+			/** Set to enable L3 IPv6 encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_L3_IPV6 = 5,
+			/** Set to enable L3 MPLS 8847 encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_L3_MPLS_8847 = 6,
+			/** Set to enable L3 MPLS 8848 encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_L3_MPLS_8848 = 7
+		} l3;
+
+#define CFA_P4_ACT_ENCAP_MAX_MPLS_LABELS 8
+		/** 1-8 labels, valid when
+		 * (l3 == CFA_P4_ACT_ENCAP_L3_MPLS_8847) ||
+		 * (l3 == CFA_P4_ACT_ENCAP_L3_MPLS_8848)
+		 *
+		 * MAX number of MPLS Labels 8.
+		 */
+		uint8_t l3_num_mpls_labels;
+
+		/** Set to CFA_HCAPI_TRUE to enable L4 capability in the
+		 * template.
+		 *
+		 * CFA_HCAPI_TRUE adds ::TF_EN_UDP_SRC_PORT and
+		 * ::TF_EN_UDP_DST_PORT to the template.
+		 */
+		uint8_t l4_enable;
+
+		/** Tunnel Encap controls the Encap Vector - Tunnel
+		 *  Encap, 3 bits. Defines the type of Tunnel
+		 *  encapsulation the template is describing
+		 * <ul>
+		 * <li> CFA_P4_ACT_ENCAP_TNL_NONE, default, no Tunnel
+		 *      Encapsulation processing.
+		 * <li> CFA_P4_ACT_ENCAP_TNL_GENERIC_FULL
+		 * <li> CFA_P4_ACT_ENCAP_TNL_VXLAN. NOTE: Expects
+		 *      l4_enable set to CFA_P4_TRUE;
+		 * <li> CFA_P4_ACT_ENCAP_TNL_NGE. NOTE: Expects l4_enable
+		 *      set to CFA_P4_TRUE;
+		 * <li> CFA_P4_ACT_ENCAP_TNL_NVGRE. NOTE: only valid if
+		 *      l4_enable set to CFA_HCAPI_FALSE.
+		 * <li> CFA_P4_ACT_ENCAP_TNL_GRE.NOTE: only valid if
+		 *      l4_enable set to CFA_HCAPI_FALSE.
+		 * <li> CFA_P4_ACT_ENCAP_TNL_GENERIC_AFTER_TL4
+		 * <li> CFA_P4_ACT_ENCAP_TNL_GENERIC_AFTER_TNL
+		 * </ul>
+		 */
+		enum {
+			/** Set to disable Tunnel header encapsulation
+			 * processing, default
+			 */
+			CFA_P4_ACT_ENCAP_TNL_NONE = 0,
+			/** Set to enable Tunnel Generic Full header
+			 * encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_TNL_GENERIC_FULL,
+			/** Set to enable VXLAN header encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_TNL_VXLAN,
+			/** Set to enable NGE (VXLAN2) header encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_TNL_NGE,
+			/** Set to enable NVGRE header encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_TNL_NVGRE,
+			/** Set to enable GRE header encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_TNL_GRE,
+			/** Set to enable Generic header after Tunnel
+			 * L4 encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_TNL_GENERIC_AFTER_TL4,
+			/** Set to enable Generic header after Tunnel
+			 * encapsulation
+			 */
+			CFA_P4_ACT_ENCAP_TNL_GENERIC_AFTER_TNL
+		} tnl;
+
+		/** Number of bytes of generic tunnel header,
+		 * valid when
+		 * (tnl == CFA_P4_ACT_ENCAP_TNL_GENERIC_FULL) ||
+		 * (tnl == CFA_P4_ACT_ENCAP_TNL_GENERIC_AFTER_TL4) ||
+		 * (tnl == CFA_P4_ACT_ENCAP_TNL_GENERIC_AFTER_TNL)
+		 */
+		uint8_t tnl_generic_size;
+		/** Number of 32b words of nge options,
+		 * valid when
+		 * (tnl == CFA_P4_ACT_ENCAP_TNL_NGE)
+		 */
+		uint8_t tnl_nge_op_len;
+		/* Currently not planned */
+		/* Custom Header */
+		/*	uint8_t custom_enable; */
+	} encap;
+};
+
+/**
+ * Enumeration of SRAM entry types, used for allocation of
+ * fixed SRAM entities. The memory model for CFA HCAPI
+ * determines if an SRAM entry type is supported.
+ */
+enum cfa_p4_action_sram_entry_type {
+	/* NOTE: Any additions to this enum must be reflected on FW
+	 * side as well.
+	 */
+
+	/** SRAM Action Record */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_ACT,
+	/** SRAM Action Encap 8 Bytes */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_ENCAP_8B,
+	/** SRAM Action Encap 16 Bytes */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_ENCAP_16B,
+	/** SRAM Action Encap 64 Bytes */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_ENCAP_64B,
+	/** SRAM Action Modify IPv4 Source */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_MODIFY_IPV4_SRC,
+	/** SRAM Action Modify IPv4 Destination */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_MODIFY_IPV4_DEST,
+	/** SRAM Action Source Properties SMAC */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_SP_SMAC,
+	/** SRAM Action Source Properties SMAC IPv4 */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_SP_SMAC_IPV4,
+	/** SRAM Action Source Properties SMAC IPv6 */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_SP_SMAC_IPV6,
+	/** SRAM Action Statistics 64 Bits */
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_STATS_64,
+	CFA_P4_ACTION_SRAM_ENTRY_TYPE_MAX
+};
+
+/**
+ * SRAM Action Record structure holding either an action index or an
+ * action ptr.
+ */
+union cfa_p4_action_sram_act_record {
+	/** SRAM Action idx specifies the offset of the SRAM
+	 * element within its SRAM Entry Type block. This
+	 * index can be written into i.e. an L2 Context. Use
+	 * this type for all SRAM Action Record types except
+	 * SRAM Full Action records. Use act_ptr instead.
+	 */
+	uint16_t act_idx;
+	/** SRAM Full Action is special in that it needs an
+	 * action record pointer. This pointer can be written
+	 * into i.e. a Wildcard TCAM entry.
+	 */
+	uint32_t act_ptr;
+};
+
+/**
+ * cfa_p4_action_param parameter definition
+ */
+struct cfa_p4_action_param {
+	/**
+	 * [in] receive or transmit direction
+	 */
+	uint8_t dir;
+	/**
+	 * [in] type of the sram allocation type
+	 */
+	enum cfa_p4_action_sram_entry_type type;
+	/**
+	 * [in] action record to set. The 'type' specified lists the
+	 *	record definition to use in the passed in record.
+	 */
+	union cfa_p4_action_sram_act_record record;
+	/**
+	 * [in] number of elements in act_data
+	 */
+	uint32_t act_size;
+	/**
+	 * [in] ptr to array of action data
+	 */
+	uint64_t *act_data;
+};
+
+/**
+ * EEM Key entry sizes
+ */
+#define CFA_P4_EEM_KEY_MAX_SIZE 52
+#define CFA_P4_EEM_KEY_RECORD_SIZE 64
+
+/**
+ * cfa_eem_entry_hdr
+ */
+struct cfa_p4_eem_entry_hdr {
+	uint32_t pointer;
+	uint32_t word1;  /*
+			  * The header is made up of two words,
+			  * this is the first word. This field has multiple
+			  * subfields, there is no suitable single name for
+			  * it so just going with word1.
+			  */
+#define CFA_P4_EEM_ENTRY_VALID_SHIFT 31
+#define CFA_P4_EEM_ENTRY_VALID_MASK 0x80000000
+#define CFA_P4_EEM_ENTRY_L1_CACHEABLE_SHIFT 30
+#define CFA_P4_EEM_ENTRY_L1_CACHEABLE_MASK 0x40000000
+#define CFA_P4_EEM_ENTRY_STRENGTH_SHIFT 28
+#define CFA_P4_EEM_ENTRY_STRENGTH_MASK 0x30000000
+#define CFA_P4_EEM_ENTRY_RESERVED_SHIFT 17
+#define CFA_P4_EEM_ENTRY_RESERVED_MASK 0x0FFE0000
+#define CFA_P4_EEM_ENTRY_KEY_SIZE_SHIFT 8
+#define CFA_P4_EEM_ENTRY_KEY_SIZE_MASK 0x0001FF00
+#define CFA_P4_EEM_ENTRY_ACT_REC_SIZE_SHIFT 3
+#define CFA_P4_EEM_ENTRY_ACT_REC_SIZE_MASK 0x000000F8
+#define CFA_P4_EEM_ENTRY_ACT_REC_INT_SHIFT 2
+#define CFA_P4_EEM_ENTRY_ACT_REC_INT_MASK 0x00000004
+#define CFA_P4_EEM_ENTRY_EXT_FLOW_CTR_SHIFT 1
+#define CFA_P4_EEM_ENTRY_EXT_FLOW_CTR_MASK 0x00000002
+#define CFA_P4_EEM_ENTRY_ACT_PTR_MSB_SHIFT 0
+#define CFA_P4_EEM_ENTRY_ACT_PTR_MSB_MASK 0x00000001
+};
+
+/**
+ *  cfa_p4_eem_key_entry
+ */
+struct cfa_p4_eem_64b_entry {
+	/** Key is 448 bits - 56 bytes */
+	uint8_t key[CFA_P4_EEM_KEY_RECORD_SIZE - sizeof(struct cfa_p4_eem_entry_hdr)];
+	/** Header is 8 bytes long */
+	struct cfa_p4_eem_entry_hdr hdr;
+};
+
+#endif /* _CFA_HW_P4_H_ */
diff --git a/drivers/net/bnxt/meson.build b/drivers/net/bnxt/meson.build
index 1f7df9d06..33e6ebd66 100644
--- a/drivers/net/bnxt/meson.build
+++ b/drivers/net/bnxt/meson.build
@@ -43,6 +43,8 @@ sources = files('bnxt_cpr.c',
 	'tf_core/tf_util.c',
 	'tf_core/tf_rm_new.c',
 
+	'hcapi/hcapi_cfa_p4.c',
+
 	'tf_ulp/bnxt_ulp.c',
 	'tf_ulp/ulp_mark_mgr.c',
 	'tf_ulp/ulp_flow_db.c',
diff --git a/drivers/net/bnxt/tf_core/tf_em.c b/drivers/net/bnxt/tf_core/tf_em.c
index 91cbc6299..38f7fe419 100644
--- a/drivers/net/bnxt/tf_core/tf_em.c
+++ b/drivers/net/bnxt/tf_core/tf_em.c
@@ -189,7 +189,7 @@ void *tf_em_get_table_page(struct tf_tbl_scope_cb *tbl_scope_cb,
 	if (dir != TF_DIR_RX && dir != TF_DIR_TX)
 		return NULL;
 
-	if (table_type < KEY0_TABLE || table_type > EFC_TABLE)
+	if (table_type < TF_KEY0_TABLE || table_type > TF_EFC_TABLE)
 		return NULL;
 
 	/*
@@ -325,7 +325,7 @@ static int tf_em_select_inject_table(struct tf_tbl_scope_cb *tbl_scope_cb,
 	key0_entry = tf_em_entry_exists(tbl_scope_cb,
 					 entry,
 					 key0_hash,
-					 KEY0_TABLE,
+					 TF_KEY0_TABLE,
 					 dir);
 
 	/*
@@ -334,23 +334,23 @@ static int tf_em_select_inject_table(struct tf_tbl_scope_cb *tbl_scope_cb,
 	key1_entry = tf_em_entry_exists(tbl_scope_cb,
 					 entry,
 					 key1_hash,
-					 KEY1_TABLE,
+					 TF_KEY1_TABLE,
 					 dir);
 
 	if (key0_entry == -EEXIST) {
-		*table = KEY0_TABLE;
+		*table = TF_KEY0_TABLE;
 		*index = key0_hash;
 		return -EEXIST;
 	} else if (key1_entry == -EEXIST) {
-		*table = KEY1_TABLE;
+		*table = TF_KEY1_TABLE;
 		*index = key1_hash;
 		return -EEXIST;
 	} else if (key0_entry == 0) {
-		*table = KEY0_TABLE;
+		*table = TF_KEY0_TABLE;
 		*index = key0_hash;
 		return 0;
 	} else if (key1_entry == 0) {
-		*table = KEY1_TABLE;
+		*table = TF_KEY1_TABLE;
 		*index = key1_hash;
 		return 0;
 	}
@@ -384,7 +384,7 @@ int tf_insert_eem_entry(struct tf_session *session,
 	int		   num_of_entry;
 
 	/* Get mask to use on hash */
-	mask = tf_em_get_key_mask(tbl_scope_cb->em_ctx_info[parms->dir].em_tables[KEY0_TABLE].num_entries);
+	mask = tf_em_get_key_mask(tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE].num_entries);
 
 	if (!mask)
 		return -EINVAL;
@@ -392,13 +392,13 @@ int tf_insert_eem_entry(struct tf_session *session,
 	num_of_entry = TF_HW_EM_KEY_MAX_SIZE + 4;
 
 	key0_hash = tf_em_lkup_get_crc32_hash(session,
-				      &parms->key[num_of_entry] - 1,
-				      parms->dir);
+					      &parms->key[num_of_entry] - 1,
+					      parms->dir);
 	key0_index = key0_hash & mask;
 
 	key1_hash =
 	   tf_em_lkup_get_lookup3_hash(session->lkup_lkup3_init_cfg[parms->dir],
-					parms->key);
+				       parms->key);
 	key1_index = key1_hash & mask;
 
 	/*
@@ -420,14 +420,14 @@ int tf_insert_eem_entry(struct tf_session *session,
 				      key1_index,
 				      &index,
 				      &table_type) == 0) {
-		if (table_type == KEY0_TABLE) {
+		if (table_type == TF_KEY0_TABLE) {
 			TF_SET_GFID(gfid,
 				    key0_index,
-				    KEY0_TABLE);
+				    TF_KEY0_TABLE);
 		} else {
 			TF_SET_GFID(gfid,
 				    key1_index,
-				    KEY1_TABLE);
+				    TF_KEY1_TABLE);
 		}
 
 		/*
diff --git a/drivers/net/bnxt/tf_core/tf_tbl.c b/drivers/net/bnxt/tf_core/tf_tbl.c
index 4e236d56c..35a7cfab5 100644
--- a/drivers/net/bnxt/tf_core/tf_tbl.c
+++ b/drivers/net/bnxt/tf_core/tf_tbl.c
@@ -285,8 +285,8 @@ tf_em_setup_page_table(struct tf_em_table *tbl)
 		tf_em_link_page_table(tp, tp_next, set_pte_last);
 	}
 
-	tbl->l0_addr = tbl->pg_tbl[PT_LVL_0].pg_va_tbl[0];
-	tbl->l0_dma_addr = tbl->pg_tbl[PT_LVL_0].pg_pa_tbl[0];
+	tbl->l0_addr = tbl->pg_tbl[TF_PT_LVL_0].pg_va_tbl[0];
+	tbl->l0_dma_addr = tbl->pg_tbl[TF_PT_LVL_0].pg_pa_tbl[0];
 }
 
 /**
@@ -317,7 +317,7 @@ tf_em_size_page_tbl_lvl(uint32_t page_size,
 			uint64_t *num_data_pages)
 {
 	uint64_t lvl_data_size = page_size;
-	int lvl = PT_LVL_0;
+	int lvl = TF_PT_LVL_0;
 	uint64_t data_size;
 
 	*num_data_pages = 0;
@@ -326,10 +326,10 @@ tf_em_size_page_tbl_lvl(uint32_t page_size,
 	while (lvl_data_size < data_size) {
 		lvl++;
 
-		if (lvl == PT_LVL_1)
+		if (lvl == TF_PT_LVL_1)
 			lvl_data_size = (uint64_t)MAX_PAGE_PTRS(page_size) *
 				page_size;
-		else if (lvl == PT_LVL_2)
+		else if (lvl == TF_PT_LVL_2)
 			lvl_data_size = (uint64_t)MAX_PAGE_PTRS(page_size) *
 				MAX_PAGE_PTRS(page_size) * page_size;
 		else
@@ -386,18 +386,18 @@ tf_em_size_page_tbls(int max_lvl,
 		     uint32_t page_size,
 		     uint32_t *page_cnt)
 {
-	if (max_lvl == PT_LVL_0) {
-		page_cnt[PT_LVL_0] = num_data_pages;
-	} else if (max_lvl == PT_LVL_1) {
-		page_cnt[PT_LVL_1] = num_data_pages;
-		page_cnt[PT_LVL_0] =
-		tf_em_page_tbl_pgcnt(page_cnt[PT_LVL_1], page_size);
-	} else if (max_lvl == PT_LVL_2) {
-		page_cnt[PT_LVL_2] = num_data_pages;
-		page_cnt[PT_LVL_1] =
-		tf_em_page_tbl_pgcnt(page_cnt[PT_LVL_2], page_size);
-		page_cnt[PT_LVL_0] =
-		tf_em_page_tbl_pgcnt(page_cnt[PT_LVL_1], page_size);
+	if (max_lvl == TF_PT_LVL_0) {
+		page_cnt[TF_PT_LVL_0] = num_data_pages;
+	} else if (max_lvl == TF_PT_LVL_1) {
+		page_cnt[TF_PT_LVL_1] = num_data_pages;
+		page_cnt[TF_PT_LVL_0] =
+		tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_1], page_size);
+	} else if (max_lvl == TF_PT_LVL_2) {
+		page_cnt[TF_PT_LVL_2] = num_data_pages;
+		page_cnt[TF_PT_LVL_1] =
+		tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_2], page_size);
+		page_cnt[TF_PT_LVL_0] =
+		tf_em_page_tbl_pgcnt(page_cnt[TF_PT_LVL_1], page_size);
 	} else {
 		return;
 	}
@@ -434,7 +434,7 @@ tf_em_size_table(struct tf_em_table *tbl)
 	/* Determine number of page table levels and the number
 	 * of data pages needed to process the given eem table.
 	 */
-	if (tbl->type == RECORD_TABLE) {
+	if (tbl->type == TF_RECORD_TABLE) {
 		/*
 		 * For action records just a memory size is provided. Work
 		 * backwards to resolve to number of entries
@@ -480,9 +480,9 @@ tf_em_size_table(struct tf_em_table *tbl)
 		    max_lvl + 1,
 		    (uint64_t)num_data_pages * TF_EM_PAGE_SIZE,
 		    num_data_pages,
-		    page_cnt[PT_LVL_0],
-		    page_cnt[PT_LVL_1],
-		    page_cnt[PT_LVL_2]);
+		    page_cnt[TF_PT_LVL_0],
+		    page_cnt[TF_PT_LVL_1],
+		    page_cnt[TF_PT_LVL_2]);
 
 	return 0;
 }
@@ -508,7 +508,7 @@ tf_em_ctx_unreg(struct tf *tfp,
 	struct tf_em_table *tbl;
 	int i;
 
-	for (i = KEY0_TABLE; i < MAX_TABLE; i++) {
+	for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
 		tbl = &ctxp->em_tables[i];
 
 		if (tbl->num_entries != 0 && tbl->entry_size != 0) {
@@ -544,7 +544,7 @@ tf_em_ctx_reg(struct tf *tfp,
 	int rc = 0;
 	int i;
 
-	for (i = KEY0_TABLE; i < MAX_TABLE; i++) {
+	for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
 		tbl = &ctxp->em_tables[i];
 
 		if (tbl->num_entries && tbl->entry_size) {
@@ -719,41 +719,41 @@ tf_em_validate_num_entries(struct tf_tbl_scope_cb *tbl_scope_cb,
 		return -EINVAL;
 	}
 	/* Rx */
-	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[KEY0_TABLE].num_entries =
+	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].num_entries =
 		parms->rx_num_flows_in_k * TF_KILOBYTE;
-	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[KEY0_TABLE].entry_size =
+	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].entry_size =
 		parms->rx_max_key_sz_in_bits / 8;
 
-	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[KEY1_TABLE].num_entries =
+	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].num_entries =
 		parms->rx_num_flows_in_k * TF_KILOBYTE;
-	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[KEY1_TABLE].entry_size =
+	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].entry_size =
 		parms->rx_max_key_sz_in_bits / 8;
 
-	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[RECORD_TABLE].num_entries =
+	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].num_entries =
 		parms->rx_num_flows_in_k * TF_KILOBYTE;
-	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[RECORD_TABLE].entry_size =
+	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].entry_size =
 		parms->rx_max_action_entry_sz_in_bits / 8;
 
-	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[EFC_TABLE].num_entries =
+	tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EFC_TABLE].num_entries =
 		0;
 
 	/* Tx */
-	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[KEY0_TABLE].num_entries =
+	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].num_entries =
 		parms->tx_num_flows_in_k * TF_KILOBYTE;
-	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[KEY0_TABLE].entry_size =
+	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].entry_size =
 		parms->tx_max_key_sz_in_bits / 8;
 
-	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[KEY1_TABLE].num_entries =
+	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].num_entries =
 		parms->tx_num_flows_in_k * TF_KILOBYTE;
-	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[KEY1_TABLE].entry_size =
+	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].entry_size =
 		parms->tx_max_key_sz_in_bits / 8;
 
-	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[RECORD_TABLE].num_entries =
+	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].num_entries =
 		parms->tx_num_flows_in_k * TF_KILOBYTE;
-	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[RECORD_TABLE].entry_size =
+	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].entry_size =
 		parms->tx_max_action_entry_sz_in_bits / 8;
 
-	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[EFC_TABLE].num_entries =
+	tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EFC_TABLE].num_entries =
 		0;
 
 	return 0;
@@ -1572,11 +1572,11 @@ tf_alloc_eem_tbl_scope(struct tf *tfp,
 
 		em_tables = tbl_scope_cb->em_ctx_info[dir].em_tables;
 		rc = tf_msg_em_cfg(tfp,
-				   em_tables[KEY0_TABLE].num_entries,
-				   em_tables[KEY0_TABLE].ctx_id,
-				   em_tables[KEY1_TABLE].ctx_id,
-				   em_tables[RECORD_TABLE].ctx_id,
-				   em_tables[EFC_TABLE].ctx_id,
+				   em_tables[TF_KEY0_TABLE].num_entries,
+				   em_tables[TF_KEY0_TABLE].ctx_id,
+				   em_tables[TF_KEY1_TABLE].ctx_id,
+				   em_tables[TF_RECORD_TABLE].ctx_id,
+				   em_tables[TF_EFC_TABLE].ctx_id,
 				   parms->hw_flow_cache_flush_timer,
 				   dir);
 		if (rc) {
@@ -1600,9 +1600,9 @@ tf_alloc_eem_tbl_scope(struct tf *tfp,
 		 * actions related to a single table scope.
 		 */
 		rc = tf_create_tbl_pool_external(dir,
-					    tbl_scope_cb,
-					    em_tables[RECORD_TABLE].num_entries,
-					    em_tables[RECORD_TABLE].entry_size);
+				    tbl_scope_cb,
+				    em_tables[TF_RECORD_TABLE].num_entries,
+				    em_tables[TF_RECORD_TABLE].entry_size);
 		if (rc) {
 			PMD_DRV_LOG(ERR,
 				    "%d TBL: Unable to allocate idx pools %s\n",
@@ -1672,7 +1672,7 @@ tf_set_tbl_entry(struct tf *tfp,
 		base_addr = tf_em_get_table_page(tbl_scope_cb,
 						 parms->dir,
 						 offset,
-						 RECORD_TABLE);
+						 TF_RECORD_TABLE);
 		if (base_addr == NULL) {
 			PMD_DRV_LOG(ERR,
 				    "dir:%d, Base address lookup failed\n",
@@ -1972,7 +1972,7 @@ void tf_dump_dma(struct tf *tfp, uint32_t tbl_scope_id)
 	for (dir = 0; dir < TF_DIR_MAX; dir++) {
 		printf("Direction %s:\n", (dir == TF_DIR_RX ? "Rx" : "Tx"));
 
-		for (j = KEY0_TABLE; j < MAX_TABLE; j++) {
+		for (j = TF_KEY0_TABLE; j < TF_MAX_TABLE; j++) {
 			tbl = &tbl_scope_cb->em_ctx_info[dir].em_tables[j];
 			printf
 	("Table: j:%d type:%d num_entries:%d entry_size:0x%x num_lvl:%d ",
diff --git a/drivers/net/bnxt/tf_core/tf_tbl.h b/drivers/net/bnxt/tf_core/tf_tbl.h
index a8bb0edab..ee8a14665 100644
--- a/drivers/net/bnxt/tf_core/tf_tbl.h
+++ b/drivers/net/bnxt/tf_core/tf_tbl.h
@@ -14,18 +14,18 @@
 struct tf_session;
 
 enum tf_pg_tbl_lvl {
-	PT_LVL_0,
-	PT_LVL_1,
-	PT_LVL_2,
-	PT_LVL_MAX
+	TF_PT_LVL_0,
+	TF_PT_LVL_1,
+	TF_PT_LVL_2,
+	TF_PT_LVL_MAX
 };
 
 enum tf_em_table_type {
-	KEY0_TABLE,
-	KEY1_TABLE,
-	RECORD_TABLE,
-	EFC_TABLE,
-	MAX_TABLE
+	TF_KEY0_TABLE,
+	TF_KEY1_TABLE,
+	TF_RECORD_TABLE,
+	TF_EFC_TABLE,
+	TF_MAX_TABLE
 };
 
 struct tf_em_page_tbl {
@@ -41,15 +41,15 @@ struct tf_em_table {
 	uint16_t			ctx_id;
 	uint32_t			entry_size;
 	int				num_lvl;
-	uint32_t			page_cnt[PT_LVL_MAX];
+	uint32_t			page_cnt[TF_PT_LVL_MAX];
 	uint64_t			num_data_pages;
 	void				*l0_addr;
 	uint64_t			l0_dma_addr;
-	struct tf_em_page_tbl pg_tbl[PT_LVL_MAX];
+	struct tf_em_page_tbl pg_tbl[TF_PT_LVL_MAX];
 };
 
 struct tf_em_ctx_mem_info {
-	struct tf_em_table		em_tables[MAX_TABLE];
+	struct tf_em_table		em_tables[TF_MAX_TABLE];
 };
 
 /** table scope control block content */
