[v1,6/7] baseband/acc: introduce the new VRB2 variant

Message ID 20230919012136.2818396-7-nicolas.chautru@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Maxime Coquelin
Headers
Series VRB2 BBDEV PMD introduction |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Chautru, Nicolas Sept. 19, 2023, 1:21 a.m. UTC
  This extends the unified driver to support both the
VRB1 and VRB2 implentation of Intel vRAN Boost.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
---
 drivers/baseband/acc/acc_common.h     |   84 +-
 drivers/baseband/acc/rte_acc100_pmd.c |    4 +-
 drivers/baseband/acc/rte_vrb_pmd.c    | 1441 ++++++++++++++++++++++---
 drivers/baseband/acc/vrb1_pf_enum.h   |   17 +-
 drivers/baseband/acc/vrb2_pf_enum.h   |  124 +++
 drivers/baseband/acc/vrb2_vf_enum.h   |  121 +++
 drivers/baseband/acc/vrb_pmd.h        |  161 ++-
 7 files changed, 1789 insertions(+), 163 deletions(-)
 create mode 100644 drivers/baseband/acc/vrb2_pf_enum.h
 create mode 100644 drivers/baseband/acc/vrb2_vf_enum.h
  

Patch

diff --git a/drivers/baseband/acc/acc_common.h b/drivers/baseband/acc/acc_common.h
index 5de58dbe36..56578c43ba 100644
--- a/drivers/baseband/acc/acc_common.h
+++ b/drivers/baseband/acc/acc_common.h
@@ -18,6 +18,7 @@ 
 #define ACC_DMA_BLKID_OUT_HARQ      3
 #define ACC_DMA_BLKID_IN_HARQ       3
 #define ACC_DMA_BLKID_IN_MLD_R      3
+#define ACC_DMA_BLKID_DEWIN_IN      3
 
 /* Values used in filling in decode FCWs */
 #define ACC_FCW_TD_VER              1
@@ -103,6 +104,9 @@ 
 #define ACC_MAX_NUM_QGRPS              32
 #define ACC_RING_SIZE_GRANULARITY      64
 #define ACC_MAX_FCW_SIZE              128
+#define ACC_IQ_SIZE                    4
+
+#define ACC_FCW_FFT_BLEN_3             28
 
 /* Constants from K0 computation from 3GPP 38.212 Table 5.4.2.1-2 */
 #define ACC_N_ZC_1 66 /* N = 66 Zc for BG 1 */
@@ -132,6 +136,11 @@ 
 #define ACC_LIM_21 14 /* 0.21 */
 #define ACC_LIM_31 20 /* 0.31 */
 #define ACC_MAX_E (128 * 1024 - 2)
+#define ACC_MAX_CS 12
+
+#define ACC100_VARIANT          0
+#define VRB1_VARIANT		2
+#define VRB2_VARIANT		3
 
 /* Helper macro for logging */
 #define rte_acc_log(level, fmt, ...) \
@@ -332,6 +341,37 @@  struct __rte_packed acc_fcw_fft {
 		res:19;
 };
 
+/* FFT Frame Control Word */
+struct __rte_packed acc_fcw_fft_3 {
+	uint32_t in_frame_size:16,
+		leading_pad_size:16;
+	uint32_t out_frame_size:16,
+		leading_depad_size:16;
+	uint32_t cs_window_sel;
+	uint32_t cs_window_sel2:16,
+		cs_enable_bmap:16;
+	uint32_t num_antennas:8,
+		idft_size:8,
+		dft_size:8,
+		cs_offset:8;
+	uint32_t idft_shift:8,
+		dft_shift:8,
+		cs_multiplier:16;
+	uint32_t bypass:2,
+		fp16_in:1, /* Not supported in VRB1 */
+		fp16_out:1,
+		exp_adj:4,
+		power_shift:4,
+		power_en:1,
+		enable_dewin:1,
+		freq_resample_mode:2,
+		depad_ouput_size:16;
+	uint16_t cs_theta_0[ACC_MAX_CS];
+	uint32_t cs_theta_d[ACC_MAX_CS];
+	int8_t cs_time_offset[ACC_MAX_CS];
+};
+
+
 /* MLD-TS Frame Control Word */
 struct __rte_packed acc_fcw_mldts {
 	uint32_t fcw_version:4,
@@ -473,14 +513,14 @@  union acc_info_ring_data {
 		uint16_t valid: 1;
 	};
 	struct {
-		uint32_t aq_id_3: 6;
-		uint32_t qg_id_3: 5;
-		uint32_t vf_id_3: 6;
-		uint32_t int_nb_3: 6;
-		uint32_t msi_0_3: 1;
-		uint32_t vf2pf_3: 6;
-		uint32_t loop_3: 1;
-		uint32_t valid_3: 1;
+		uint32_t aq_id_vrb2: 6;
+		uint32_t qg_id_vrb2: 5;
+		uint32_t vf_id_vrb2: 6;
+		uint32_t int_nb_vrb2: 6;
+		uint32_t msi_0_vrb2: 1;
+		uint32_t vf2pf_vrb2: 6;
+		uint32_t loop_vrb2: 1;
+		uint32_t valid_vrb2: 1;
 	};
 } __rte_packed;
 
@@ -765,16 +805,20 @@  alloc_sw_rings_min_mem(struct rte_bbdev *dev, struct acc_device *d,
  */
 static inline uint16_t
 get_queue_id_from_ring_info(struct rte_bbdev_data *data,
-		const union acc_info_ring_data ring_data)
+		const union acc_info_ring_data ring_data, uint16_t device_variant)
 {
 	uint16_t queue_id;
+	struct acc_queue *acc_q;
+	uint16_t vf_id = (device_variant == VRB2_VARIANT) ? ring_data.vf_id_vrb2 : ring_data.vf_id;
+	uint16_t aq_id = (device_variant == VRB2_VARIANT) ? ring_data.aq_id_vrb2 : ring_data.aq_id;
+	uint16_t qg_id = (device_variant == VRB2_VARIANT) ? ring_data.qg_id_vrb2 : ring_data.qg_id;
 
 	for (queue_id = 0; queue_id < data->num_queues; ++queue_id) {
-		struct acc_queue *acc_q =
-				data->queues[queue_id].queue_private;
-		if (acc_q != NULL && acc_q->aq_id == ring_data.aq_id &&
-				acc_q->qgrp_id == ring_data.qg_id &&
-				acc_q->vf_id == ring_data.vf_id)
+		acc_q = data->queues[queue_id].queue_private;
+
+		if (acc_q != NULL && acc_q->aq_id == aq_id &&
+				acc_q->qgrp_id == qg_id &&
+				acc_q->vf_id == vf_id)
 			return queue_id;
 	}
 
@@ -1436,4 +1480,16 @@  get_num_cbs_in_tb_ldpc_enc(struct rte_bbdev_op_ldpc_enc *ldpc_enc)
 	return cbs_in_tb;
 }
 
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+static inline void
+acc_memdump(const char *string, void *buf, uint16_t bytes)
+{
+	printf("%s\n", string);
+	uint32_t *data = buf;
+	uint16_t i;
+	for (i = 0; i < bytes / 4; i++)
+		printf("0x%08X\n", data[i]);
+}
+#endif
+
 #endif /* _ACC_COMMON_H_ */
diff --git a/drivers/baseband/acc/rte_acc100_pmd.c b/drivers/baseband/acc/rte_acc100_pmd.c
index 5362d39c30..7f8d05b5a9 100644
--- a/drivers/baseband/acc/rte_acc100_pmd.c
+++ b/drivers/baseband/acc/rte_acc100_pmd.c
@@ -294,7 +294,7 @@  acc100_pf_interrupt_handler(struct rte_bbdev *dev)
 		case ACC100_PF_INT_DMA_UL5G_DESC_IRQ:
 		case ACC100_PF_INT_DMA_DL5G_DESC_IRQ:
 			deq_intr_det.queue_id = get_queue_id_from_ring_info(
-					dev->data, *ring_data);
+					dev->data, *ring_data, acc100_dev->device_variant);
 			if (deq_intr_det.queue_id == UINT16_MAX) {
 				rte_bbdev_log(ERR,
 						"Couldn't find queue: aq_id: %u, qg_id: %u, vf_id: %u",
@@ -348,7 +348,7 @@  acc100_vf_interrupt_handler(struct rte_bbdev *dev)
 			 */
 			ring_data->vf_id = 0;
 			deq_intr_det.queue_id = get_queue_id_from_ring_info(
-					dev->data, *ring_data);
+					dev->data, *ring_data, acc100_dev->device_variant);
 			if (deq_intr_det.queue_id == UINT16_MAX) {
 				rte_bbdev_log(ERR,
 						"Couldn't find queue: aq_id: %u, qg_id: %u",
diff --git a/drivers/baseband/acc/rte_vrb_pmd.c b/drivers/baseband/acc/rte_vrb_pmd.c
index 0a634d62f6..36d2c8173d 100644
--- a/drivers/baseband/acc/rte_vrb_pmd.c
+++ b/drivers/baseband/acc/rte_vrb_pmd.c
@@ -37,6 +37,15 @@  vrb1_queue_offset(bool pf_device, uint8_t vf_id, uint8_t qgrp_id, uint16_t aq_id
 		return ((qgrp_id << 7) + (aq_id << 3) + VRB1_VfQmgrIngressAq);
 }
 
+static inline uint32_t
+vrb2_queue_offset(bool pf_device, uint8_t vf_id, uint8_t qgrp_id, uint16_t aq_id)
+{
+	if (pf_device)
+		return ((vf_id << 14) + (qgrp_id << 9) + (aq_id << 3) + VRB2_PfQmgrIngressAq);
+	else
+		return ((qgrp_id << 9) + (aq_id << 3) + VRB2_VfQmgrIngressAq);
+}
+
 enum {UL_4G = 0, UL_5G, DL_4G, DL_5G, FFT, MLD, NUM_ACC};
 
 /* Return the accelerator enum for a Queue Group Index. */
@@ -197,7 +206,7 @@  fetch_acc_config(struct rte_bbdev *dev)
 	struct acc_device *d = dev->data->dev_private;
 	struct rte_acc_conf *acc_conf = &d->acc_conf;
 	uint8_t acc, qg;
-	uint32_t reg_aq, reg_len0, reg_len1, reg0, reg1;
+	uint32_t reg_aq, reg_len0, reg_len1, reg_len2, reg_len3, reg0, reg1, reg2, reg3;
 	uint32_t reg_mode, idx;
 	struct rte_acc_queue_topology *q_top = NULL;
 	int qman_func_id[VRB_NUM_ACCS] = {ACC_ACCMAP_0, ACC_ACCMAP_1,
@@ -219,32 +228,81 @@  fetch_acc_config(struct rte_bbdev *dev)
 	acc_conf->num_vf_bundles = 1;
 	initQTop(acc_conf);
 
-	reg0 = acc_reg_read(d, d->reg_addr->qman_group_func);
-	reg1 = acc_reg_read(d, d->reg_addr->qman_group_func + 4);
-	for (qg = 0; qg < d->num_qgroups; qg++) {
-		reg_aq = acc_reg_read(d, d->queue_offset(d->pf_device, 0, qg, 0));
-		if (reg_aq & ACC_QUEUE_ENABLE) {
-			if (qg < ACC_NUM_QGRPS_PER_WORD)
-				idx = (reg0 >> (qg * 4)) & 0x7;
+	if (d->device_variant == VRB1_VARIANT) {
+		reg0 = acc_reg_read(d, d->reg_addr->qman_group_func);
+		reg1 = acc_reg_read(d, d->reg_addr->qman_group_func + 4);
+		for (qg = 0; qg < d->num_qgroups; qg++) {
+			reg_aq = acc_reg_read(d, d->queue_offset(d->pf_device, 0, qg, 0));
+			if (reg_aq & ACC_QUEUE_ENABLE) {
+				if (qg < ACC_NUM_QGRPS_PER_WORD)
+					idx = (reg0 >> (qg * 4)) & 0x7;
+				else
+					idx = (reg1 >> ((qg - ACC_NUM_QGRPS_PER_WORD) * 4)) & 0x7;
+				if (idx < VRB1_NUM_ACCS) {
+					acc = qman_func_id[idx];
+					updateQtop(acc, qg, acc_conf, d);
+				}
+			}
+		}
+
+		/* Check the depth of the AQs. */
+		reg_len0 = acc_reg_read(d, d->reg_addr->depth_log0_offset);
+		reg_len1 = acc_reg_read(d, d->reg_addr->depth_log1_offset);
+		for (acc = 0; acc < NUM_ACC; acc++) {
+			qtopFromAcc(&q_top, acc, acc_conf);
+			if (q_top->first_qgroup_index < ACC_NUM_QGRPS_PER_WORD)
+				q_top->aq_depth_log2 =
+						(reg_len0 >> (q_top->first_qgroup_index * 4)) & 0xF;
 			else
-				idx = (reg1 >> ((qg - ACC_NUM_QGRPS_PER_WORD) * 4)) & 0x7;
-			if (idx < VRB1_NUM_ACCS) {
-				acc = qman_func_id[idx];
-				updateQtop(acc, qg, acc_conf, d);
+				q_top->aq_depth_log2 = (reg_len1 >> ((q_top->first_qgroup_index -
+						ACC_NUM_QGRPS_PER_WORD) * 4)) & 0xF;
+		}
+	} else {
+		reg0 = acc_reg_read(d, d->reg_addr->qman_group_func);
+		reg1 = acc_reg_read(d, d->reg_addr->qman_group_func + 4);
+		reg2 = acc_reg_read(d, d->reg_addr->qman_group_func + 8);
+		reg3 = acc_reg_read(d, d->reg_addr->qman_group_func + 12);
+		/* printf("Debug Function %08x %08x %08x %08x\n", reg0, reg1, reg2, reg3);*/
+		for (qg = 0; qg < VRB2_NUM_QGRPS; qg++) {
+			reg_aq = acc_reg_read(d, vrb2_queue_offset(d->pf_device, 0, qg, 0));
+			if (reg_aq & ACC_QUEUE_ENABLE) {
+				/* printf("Qg enabled %d %x\n", qg, reg_aq);*/
+				if (qg / ACC_NUM_QGRPS_PER_WORD == 0)
+					idx = (reg0 >> ((qg % ACC_NUM_QGRPS_PER_WORD) * 4)) & 0x7;
+				else if (qg / ACC_NUM_QGRPS_PER_WORD == 1)
+					idx = (reg1 >> ((qg % ACC_NUM_QGRPS_PER_WORD) * 4)) & 0x7;
+				else if (qg / ACC_NUM_QGRPS_PER_WORD == 2)
+					idx = (reg2 >> ((qg % ACC_NUM_QGRPS_PER_WORD) * 4)) & 0x7;
+				else
+					idx = (reg3 >> ((qg % ACC_NUM_QGRPS_PER_WORD) * 4)) & 0x7;
+				if (idx < VRB_NUM_ACCS) {
+					acc = qman_func_id[idx];
+					updateQtop(acc, qg, acc_conf, d);
+				}
 			}
 		}
-	}
 
-	/* Check the depth of the AQs. */
-	reg_len0 = acc_reg_read(d, d->reg_addr->depth_log0_offset);
-	reg_len1 = acc_reg_read(d, d->reg_addr->depth_log1_offset);
-	for (acc = 0; acc < NUM_ACC; acc++) {
-		qtopFromAcc(&q_top, acc, acc_conf);
-		if (q_top->first_qgroup_index < ACC_NUM_QGRPS_PER_WORD)
-			q_top->aq_depth_log2 = (reg_len0 >> (q_top->first_qgroup_index * 4)) & 0xF;
-		else
-			q_top->aq_depth_log2 = (reg_len1 >> ((q_top->first_qgroup_index -
-					ACC_NUM_QGRPS_PER_WORD) * 4)) & 0xF;
+		/* Check the depth of the AQs. */
+		reg_len0 = acc_reg_read(d, d->reg_addr->depth_log0_offset);
+		reg_len1 = acc_reg_read(d, d->reg_addr->depth_log0_offset + 4);
+		reg_len2 = acc_reg_read(d, d->reg_addr->depth_log0_offset + 8);
+		reg_len3 = acc_reg_read(d, d->reg_addr->depth_log0_offset + 12);
+
+		for (acc = 0; acc < NUM_ACC; acc++) {
+			qtopFromAcc(&q_top, acc, acc_conf);
+			if (q_top->first_qgroup_index / ACC_NUM_QGRPS_PER_WORD == 0)
+				q_top->aq_depth_log2 = (reg_len0 >> ((q_top->first_qgroup_index %
+						ACC_NUM_QGRPS_PER_WORD) * 4)) & 0xF;
+			else if (q_top->first_qgroup_index / ACC_NUM_QGRPS_PER_WORD == 1)
+				q_top->aq_depth_log2 = (reg_len1 >> ((q_top->first_qgroup_index %
+						ACC_NUM_QGRPS_PER_WORD) * 4)) & 0xF;
+			else if (q_top->first_qgroup_index / ACC_NUM_QGRPS_PER_WORD == 2)
+				q_top->aq_depth_log2 = (reg_len2 >> ((q_top->first_qgroup_index %
+						ACC_NUM_QGRPS_PER_WORD) * 4)) & 0xF;
+			else
+				q_top->aq_depth_log2 = (reg_len3 >> ((q_top->first_qgroup_index %
+						ACC_NUM_QGRPS_PER_WORD) * 4)) & 0xF;
+		}
 	}
 
 	/* Read PF mode. */
@@ -341,18 +399,29 @@  vrb_check_ir(struct acc_device *acc_dev)
 	ring_data = acc_dev->info_ring + (acc_dev->info_ring_head & ACC_INFO_RING_MASK);
 
 	while (ring_data->valid) {
-		if ((ring_data->int_nb < ACC_PF_INT_DMA_DL_DESC_IRQ) || (
-				ring_data->int_nb > ACC_PF_INT_DMA_MLD_DESC_IRQ)) {
-			rte_bbdev_log(WARNING, "InfoRing: ITR:%d Info:0x%x",
-					ring_data->int_nb, ring_data->detailed_info);
-			/* Initialize Info Ring entry and move forward. */
-			ring_data->val = 0;
+		if (acc_dev->device_variant == VRB1_VARIANT) {
+			if ((ring_data->int_nb < ACC_PF_INT_DMA_DL_DESC_IRQ) || (
+					ring_data->int_nb > ACC_PF_INT_DMA_MLD_DESC_IRQ)) {
+				rte_bbdev_log(WARNING, "InfoRing: ITR:%d Info:0x%x",
+						ring_data->int_nb, ring_data->detailed_info);
+				/* Initialize Info Ring entry and move forward. */
+				ring_data->val = 0;
+			}
+		} else { /* VRB2_VARIANT */
+			if ((ring_data->int_nb_vrb2 < ACC_PF_INT_DMA_DL_DESC_IRQ) || (
+					ring_data->int_nb_vrb2 > ACC_PF_INT_DMA_MLD_DESC_IRQ)) {
+				rte_bbdev_log(WARNING, "InfoRing: ITR:%d Info:0x%x",
+						ring_data->int_nb_vrb2, ring_data->val);
+				/* Initialize Info Ring entry and move forward. */
+				ring_data->val = 0;
+			}
 		}
 		info_ring_head++;
 		ring_data = acc_dev->info_ring + (info_ring_head & ACC_INFO_RING_MASK);
 	}
 }
 
+
 /* Interrupt handler triggered by dev for handling specific interrupt. */
 static void
 vrb_dev_interrupt_handler(void *cb_arg)
@@ -361,16 +430,22 @@  vrb_dev_interrupt_handler(void *cb_arg)
 	struct acc_device *acc_dev = dev->data->dev_private;
 	volatile union acc_info_ring_data *ring_data;
 	struct acc_deq_intr_details deq_intr_det;
+	uint16_t vf_id, aq_id, qg_id, int_nb;
+	bool isVrb1 = (acc_dev->device_variant == VRB1_VARIANT);
 
 	ring_data = acc_dev->info_ring + (acc_dev->info_ring_head & ACC_INFO_RING_MASK);
 
 	while (ring_data->valid) {
+		vf_id = isVrb1 ? ring_data->vf_id : ring_data->vf_id_vrb2;
+		aq_id = isVrb1 ? ring_data->aq_id : ring_data->aq_id_vrb2;
+		qg_id = isVrb1 ? ring_data->qg_id : ring_data->qg_id_vrb2;
+		int_nb = isVrb1 ? ring_data->int_nb : ring_data->int_nb_vrb2;
 		if (acc_dev->pf_device) {
 			rte_bbdev_log_debug(
-					"VRB1 PF Interrupt received, Info Ring data: 0x%x -> %d",
-					ring_data->val, ring_data->int_nb);
+					"PF Interrupt received, Info Ring data: 0x%x -> %d",
+					ring_data->val, int_nb);
 
-			switch (ring_data->int_nb) {
+			switch (int_nb) {
 			case ACC_PF_INT_DMA_DL_DESC_IRQ:
 			case ACC_PF_INT_DMA_UL_DESC_IRQ:
 			case ACC_PF_INT_DMA_FFT_DESC_IRQ:
@@ -378,13 +453,11 @@  vrb_dev_interrupt_handler(void *cb_arg)
 			case ACC_PF_INT_DMA_DL5G_DESC_IRQ:
 			case ACC_PF_INT_DMA_MLD_DESC_IRQ:
 				deq_intr_det.queue_id = get_queue_id_from_ring_info(
-						dev->data, *ring_data);
+						dev->data, *ring_data, acc_dev->device_variant);
 				if (deq_intr_det.queue_id == UINT16_MAX) {
 					rte_bbdev_log(ERR,
 							"Couldn't find queue: aq_id: %u, qg_id: %u, vf_id: %u",
-							ring_data->aq_id,
-							ring_data->qg_id,
-							ring_data->vf_id);
+							aq_id, qg_id, vf_id);
 					return;
 				}
 				rte_bbdev_pmd_callback_process(dev,
@@ -396,9 +469,9 @@  vrb_dev_interrupt_handler(void *cb_arg)
 			}
 		} else {
 			rte_bbdev_log_debug(
-					"VRB1 VF Interrupt received, Info Ring data: 0x%x\n",
+					"VRB VF Interrupt received, Info Ring data: 0x%x\n",
 					ring_data->val);
-			switch (ring_data->int_nb) {
+			switch (int_nb) {
 			case ACC_VF_INT_DMA_DL_DESC_IRQ:
 			case ACC_VF_INT_DMA_UL_DESC_IRQ:
 			case ACC_VF_INT_DMA_FFT_DESC_IRQ:
@@ -406,14 +479,16 @@  vrb_dev_interrupt_handler(void *cb_arg)
 			case ACC_VF_INT_DMA_DL5G_DESC_IRQ:
 			case ACC_VF_INT_DMA_MLD_DESC_IRQ:
 				/* VFs are not aware of their vf_id - it's set to 0.  */
-				ring_data->vf_id = 0;
+				if (acc_dev->device_variant == VRB1_VARIANT)
+					ring_data->vf_id = 0;
+				else
+					ring_data->vf_id_vrb2 = 0;
 				deq_intr_det.queue_id = get_queue_id_from_ring_info(
-						dev->data, *ring_data);
+						dev->data, *ring_data, acc_dev->device_variant);
 				if (deq_intr_det.queue_id == UINT16_MAX) {
 					rte_bbdev_log(ERR,
 							"Couldn't find queue: aq_id: %u, qg_id: %u",
-							ring_data->aq_id,
-							ring_data->qg_id);
+							aq_id, qg_id);
 					return;
 				}
 				rte_bbdev_pmd_callback_process(dev,
@@ -428,8 +503,7 @@  vrb_dev_interrupt_handler(void *cb_arg)
 		/* Initialize Info Ring entry and move forward. */
 		ring_data->val = 0;
 		++acc_dev->info_ring_head;
-		ring_data = acc_dev->info_ring +
-				(acc_dev->info_ring_head & ACC_INFO_RING_MASK);
+		ring_data = acc_dev->info_ring + (acc_dev->info_ring_head & ACC_INFO_RING_MASK);
 	}
 }
 
@@ -461,7 +535,10 @@  allocate_info_ring(struct rte_bbdev *dev)
 	phys_low  = (uint32_t)(info_ring_iova);
 	acc_reg_write(d, d->reg_addr->info_ring_hi, phys_high);
 	acc_reg_write(d, d->reg_addr->info_ring_lo, phys_low);
-	acc_reg_write(d, d->reg_addr->info_ring_en, VRB1_REG_IRQ_EN_ALL);
+	if (d->device_variant == VRB1_VARIANT)
+		acc_reg_write(d, d->reg_addr->info_ring_en, VRB1_REG_IRQ_EN_ALL);
+	else
+		acc_reg_write(d, d->reg_addr->info_ring_en, VRB2_REG_IRQ_EN_ALL);
 	d->info_ring_head = (acc_reg_read(d, d->reg_addr->info_ring_ptr) &
 			0xFFF) / sizeof(union acc_info_ring_data);
 	return 0;
@@ -516,6 +593,7 @@  vrb_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
 	phys_high = (uint32_t)(d->sw_rings_iova >> 32);
 	phys_low  = (uint32_t)(d->sw_rings_iova & ~(ACC_SIZE_64MBYTE-1));
 
+
 	/* Read the populated cfg from device registers. */
 	fetch_acc_config(dev);
 
@@ -540,6 +618,10 @@  vrb_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
 	acc_reg_write(d, d->reg_addr->dma_ring_dl4g_lo, phys_low);
 	acc_reg_write(d, d->reg_addr->dma_ring_fft_hi, phys_high);
 	acc_reg_write(d, d->reg_addr->dma_ring_fft_lo, phys_low);
+	if (d->device_variant == VRB2_VARIANT) {
+		acc_reg_write(d, d->reg_addr->dma_ring_mld_hi, phys_high);
+		acc_reg_write(d, d->reg_addr->dma_ring_mld_lo, phys_low);
+	}
 	/*
 	 * Configure Ring Size to the max queue ring size
 	 * (used for wrapping purpose).
@@ -549,8 +631,7 @@  vrb_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
 
 	/* Configure tail pointer for use when SDONE enabled. */
 	if (d->tail_ptrs == NULL)
-		d->tail_ptrs = rte_zmalloc_socket(
-				dev->device->driver->name,
+		d->tail_ptrs = rte_zmalloc_socket(dev->device->driver->name,
 				VRB_MAX_QGRPS * VRB_MAX_AQS * sizeof(uint32_t),
 				RTE_CACHE_LINE_SIZE, socket_id);
 	if (d->tail_ptrs == NULL) {
@@ -574,6 +655,10 @@  vrb_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
 	acc_reg_write(d, d->reg_addr->tail_ptrs_dl4g_lo, phys_low);
 	acc_reg_write(d, d->reg_addr->tail_ptrs_fft_hi, phys_high);
 	acc_reg_write(d, d->reg_addr->tail_ptrs_fft_lo, phys_low);
+	if (d->device_variant == VRB2_VARIANT) {
+		acc_reg_write(d, d->reg_addr->tail_ptrs_mld_hi, phys_high);
+		acc_reg_write(d, d->reg_addr->tail_ptrs_mld_lo, phys_low);
+	}
 
 	ret = allocate_info_ring(dev);
 	if (ret < 0) {
@@ -671,10 +756,17 @@  vrb_intr_enable(struct rte_bbdev *dev)
 			return ret;
 		}
 
-		if (acc_dev->pf_device)
-			max_queues = VRB1_MAX_PF_MSIX;
-		else
-			max_queues = VRB1_MAX_VF_MSIX;
+		if (d->device_variant == VRB1_VARIANT) {
+			if (acc_dev->pf_device)
+				max_queues = VRB1_MAX_PF_MSIX;
+			else
+				max_queues = VRB1_MAX_VF_MSIX;
+		} else {
+			if (acc_dev->pf_device)
+				max_queues = VRB2_MAX_PF_MSIX;
+			else
+				max_queues = VRB2_MAX_VF_MSIX;
+		}
 
 		if (rte_intr_efd_enable(dev->intr_handle, max_queues)) {
 			rte_bbdev_log(ERR, "Failed to create fds for %u queues",
@@ -776,7 +868,10 @@  vrb_find_free_queue_idx(struct rte_bbdev *dev,
 			/* Mark the Queue as assigned. */
 			d->q_assigned_bit_map[group_idx] |= (1ULL << aq_idx);
 			/* Report the AQ Index. */
-			return (group_idx << VRB1_GRP_ID_SHIFT) + aq_idx;
+			if (d->device_variant == VRB1_VARIANT)
+				return (group_idx << VRB1_GRP_ID_SHIFT) + aq_idx;
+			else
+				return (group_idx << VRB2_GRP_ID_SHIFT) + aq_idx;
 		}
 	}
 	rte_bbdev_log(INFO, "Failed to find free queue on %s, priority %u",
@@ -819,6 +914,9 @@  vrb_queue_setup(struct rte_bbdev *dev, uint16_t queue_id,
 			ACC_FCW_LD_BLEN : (conf->op_type == RTE_BBDEV_OP_FFT ?
 			ACC_FCW_FFT_BLEN : ACC_FCW_MLDTS_BLEN))));
 
+	if ((q->d->device_variant == VRB2_VARIANT) && (conf->op_type == RTE_BBDEV_OP_FFT))
+		fcw_len = ACC_FCW_FFT_BLEN_3;
+
 	for (desc_idx = 0; desc_idx < d->sw_ring_max_depth; desc_idx++) {
 		desc = q->ring_addr + desc_idx;
 		desc->req.word0 = ACC_DMA_DESC_TYPE;
@@ -915,9 +1013,16 @@  vrb_queue_setup(struct rte_bbdev *dev, uint16_t queue_id,
 		}
 	}
 
-	q->qgrp_id = (q_idx >> VRB1_GRP_ID_SHIFT) & 0xF;
-	q->vf_id = (q_idx >> VRB1_VF_ID_SHIFT)  & 0x3F;
-	q->aq_id = q_idx & 0xF;
+	if (d->device_variant == VRB1_VARIANT) {
+		q->qgrp_id = (q_idx >> VRB1_GRP_ID_SHIFT) & 0xF;
+		q->vf_id = (q_idx >> VRB1_VF_ID_SHIFT)  & 0x3F;
+		q->aq_id = q_idx & 0xF;
+	} else {
+		q->qgrp_id = (q_idx >> VRB2_GRP_ID_SHIFT) & 0x1F;
+		q->vf_id = (q_idx >> VRB2_VF_ID_SHIFT)  & 0x3F;
+		q->aq_id = q_idx & 0x3F;
+	}
+
 	q->aq_depth = 0;
 	if (conf->op_type ==  RTE_BBDEV_OP_TURBO_DEC)
 		q->aq_depth = (1 << d->acc_conf.q_ul_4g.aq_depth_log2);
@@ -1150,6 +1255,127 @@  vrb_dev_info_get(struct rte_bbdev *dev, struct rte_bbdev_driver_info *dev_info)
 		RTE_BBDEV_END_OF_CAPABILITIES_LIST()
 	};
 
+	static const struct rte_bbdev_op_cap vrb2_bbdev_capabilities[] = {
+		{
+			.type = RTE_BBDEV_OP_TURBO_DEC,
+			.cap.turbo_dec = {
+				.capability_flags =
+					RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE |
+					RTE_BBDEV_TURBO_CRC_TYPE_24B |
+					RTE_BBDEV_TURBO_DEC_CRC_24B_DROP |
+					RTE_BBDEV_TURBO_EQUALIZER |
+					RTE_BBDEV_TURBO_SOFT_OUT_SATURATE |
+					RTE_BBDEV_TURBO_HALF_ITERATION_EVEN |
+					RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH |
+					RTE_BBDEV_TURBO_SOFT_OUTPUT |
+					RTE_BBDEV_TURBO_EARLY_TERMINATION |
+					RTE_BBDEV_TURBO_DEC_INTERRUPTS |
+					RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN |
+					RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT |
+					RTE_BBDEV_TURBO_MAP_DEC |
+					RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP |
+					RTE_BBDEV_TURBO_DEC_SCATTER_GATHER,
+				.max_llr_modulus = INT8_MAX,
+				.num_buffers_src =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+				.num_buffers_hard_out =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+				.num_buffers_soft_out =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+			}
+		},
+		{
+			.type = RTE_BBDEV_OP_TURBO_ENC,
+			.cap.turbo_enc = {
+				.capability_flags =
+					RTE_BBDEV_TURBO_CRC_24B_ATTACH |
+					RTE_BBDEV_TURBO_RV_INDEX_BYPASS |
+					RTE_BBDEV_TURBO_RATE_MATCH |
+					RTE_BBDEV_TURBO_ENC_INTERRUPTS |
+					RTE_BBDEV_TURBO_ENC_SCATTER_GATHER,
+				.num_buffers_src =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+			}
+		},
+		{
+			.type   = RTE_BBDEV_OP_LDPC_ENC,
+			.cap.ldpc_enc = {
+				.capability_flags =
+					RTE_BBDEV_LDPC_RATE_MATCH |
+					RTE_BBDEV_LDPC_CRC_24B_ATTACH |
+					RTE_BBDEV_LDPC_INTERLEAVER_BYPASS |
+					RTE_BBDEV_LDPC_ENC_INTERRUPTS |
+					RTE_BBDEV_LDPC_ENC_SCATTER_GATHER |
+					RTE_BBDEV_LDPC_ENC_CONCATENATION,
+				.num_buffers_src =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			}
+		},
+		{
+			.type   = RTE_BBDEV_OP_LDPC_DEC,
+			.cap.ldpc_dec = {
+			.capability_flags =
+				RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
+				RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP |
+				RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK |
+				RTE_BBDEV_LDPC_CRC_TYPE_16_CHECK |
+				RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
+				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
+				RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE |
+				RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS |
+				RTE_BBDEV_LDPC_DEC_SCATTER_GATHER |
+				RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION |
+				RTE_BBDEV_LDPC_HARQ_4BIT_COMPRESSION |
+				RTE_BBDEV_LDPC_LLR_COMPRESSION |
+				RTE_BBDEV_LDPC_SOFT_OUT_ENABLE |
+				RTE_BBDEV_LDPC_SOFT_OUT_RM_BYPASS |
+				RTE_BBDEV_LDPC_SOFT_OUT_DEINTERLEAVER_BYPASS |
+				RTE_BBDEV_LDPC_DEC_INTERRUPTS,
+			.llr_size = 8,
+			.llr_decimals = 2,
+			.num_buffers_src =
+					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			.num_buffers_hard_out =
+					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			.num_buffers_soft_out = 0,
+			}
+		},
+		{
+			.type	= RTE_BBDEV_OP_FFT,
+			.cap.fft = {
+				.capability_flags =
+						RTE_BBDEV_FFT_WINDOWING |
+						RTE_BBDEV_FFT_CS_ADJUSTMENT |
+						RTE_BBDEV_FFT_DFT_BYPASS |
+						RTE_BBDEV_FFT_IDFT_BYPASS |
+						RTE_BBDEV_FFT_FP16_INPUT |
+						RTE_BBDEV_FFT_FP16_OUTPUT |
+						RTE_BBDEV_FFT_POWER_MEAS |
+						RTE_BBDEV_FFT_WINDOWING_BYPASS,
+				.num_buffers_src =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			}
+		},
+		{
+			.type	= RTE_BBDEV_OP_MLDTS,
+			.cap.fft = {
+				.capability_flags =
+						RTE_BBDEV_MLDTS_REP,
+				.num_buffers_src =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			}
+		},
+		RTE_BBDEV_END_OF_CAPABILITIES_LIST()
+	};
+
 	static struct rte_bbdev_queue_conf default_queue_conf;
 	default_queue_conf.socket = dev->data->socket_id;
 	default_queue_conf.queue_size = ACC_MAX_QUEUE_DEPTH;
@@ -1194,7 +1420,10 @@  vrb_dev_info_get(struct rte_bbdev *dev, struct rte_bbdev_driver_info *dev_info)
 	dev_info->default_queue_conf = default_queue_conf;
 	dev_info->cpu_flag_reqs = NULL;
 	dev_info->min_alignment = 1;
-	dev_info->capabilities = vrb1_bbdev_capabilities;
+	if (d->device_variant == VRB1_VARIANT)
+		dev_info->capabilities = vrb1_bbdev_capabilities;
+	else
+		dev_info->capabilities = vrb2_bbdev_capabilities;
 	dev_info->harq_buffer_size = 0;
 
 	vrb_check_ir(d);
@@ -1243,6 +1472,9 @@  static struct rte_pci_id pci_id_vrb_pf_map[] = {
 	{
 		RTE_PCI_DEVICE(RTE_VRB1_VENDOR_ID, RTE_VRB1_PF_DEVICE_ID)
 	},
+	{
+		RTE_PCI_DEVICE(RTE_VRB2_VENDOR_ID, RTE_VRB2_PF_DEVICE_ID)
+	},
 	{.device_id = 0},
 };
 
@@ -1251,6 +1483,9 @@  static struct rte_pci_id pci_id_vrb_vf_map[] = {
 	{
 		RTE_PCI_DEVICE(RTE_VRB1_VENDOR_ID, RTE_VRB1_VF_DEVICE_ID)
 	},
+	{
+		RTE_PCI_DEVICE(RTE_VRB2_VENDOR_ID, RTE_VRB2_VF_DEVICE_ID)
+	},
 	{.device_id = 0},
 };
 
@@ -1287,6 +1522,7 @@  vrb_fcw_td_fill(const struct rte_bbdev_dec_op *op, struct acc_fcw_td *fcw)
 				fcw->ea = op->turbo_dec.cb_params.e;
 				fcw->eb = op->turbo_dec.cb_params.e;
 			}
+
 			if (op->turbo_dec.rv_index == 0)
 				fcw->k0_start_col = ACC_FCW_TD_RVIDX_0;
 			else if (op->turbo_dec.rv_index == 1)
@@ -1305,7 +1541,7 @@  vrb_fcw_td_fill(const struct rte_bbdev_dec_op *op, struct acc_fcw_td *fcw)
 		fcw->bypass_teq = 0;
 	}
 
-	fcw->code_block_mode = 1; /* FIXME */
+	fcw->code_block_mode = 1;
 	fcw->turbo_crc_type = check_bit(op->turbo_dec.op_flags,
 			RTE_BBDEV_TURBO_CRC_TYPE_24B);
 
@@ -1465,8 +1701,8 @@  vrb_dma_desc_td_fill(struct rte_bbdev_dec_op *op,
 	if (op->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
 		k = op->turbo_dec.tb_params.k_pos;
 		e = (r < op->turbo_dec.tb_params.cab)
-			? op->turbo_dec.tb_params.ea
-			: op->turbo_dec.tb_params.eb;
+				? op->turbo_dec.tb_params.ea
+				: op->turbo_dec.tb_params.eb;
 	} else {
 		k = op->turbo_dec.cb_params.k;
 		e = op->turbo_dec.cb_params.e;
@@ -1677,61 +1913,329 @@  vrb1_dma_desc_ld_fill(struct rte_bbdev_dec_op *op,
 	return 0;
 }
 
+/* Fill in a frame control word for LDPC decoding. */
 static inline void
-vrb_dma_desc_ld_update(struct rte_bbdev_dec_op *op,
-		struct acc_dma_req_desc *desc,
-		struct rte_mbuf *input, struct rte_mbuf *h_output,
-		uint32_t *in_offset, uint32_t *h_out_offset,
-		uint32_t *h_out_length,
+vrb2_fcw_ld_fill(struct rte_bbdev_dec_op *op, struct acc_fcw_ld *fcw,
 		union acc_harq_layout_data *harq_layout)
 {
-	int next_triplet = 1; /* FCW already done. */
-	desc->data_ptrs[next_triplet].address = rte_pktmbuf_iova_offset(input, *in_offset);
-	next_triplet++;
+	uint16_t harq_out_length, harq_in_length, ncb_p, k0_p, parity_offset;
+	uint32_t harq_index;
+	uint32_t l;
 
-	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
-		struct rte_bbdev_op_data hi = op->ldpc_dec.harq_combined_input;
-		desc->data_ptrs[next_triplet].address =
-				rte_pktmbuf_iova_offset(hi.data, hi.offset);
-		next_triplet++;
+	fcw->qm = op->ldpc_dec.q_m;
+	fcw->nfiller = op->ldpc_dec.n_filler;
+	fcw->BG = (op->ldpc_dec.basegraph - 1);
+	fcw->Zc = op->ldpc_dec.z_c;
+	fcw->ncb = op->ldpc_dec.n_cb;
+	fcw->k0 = get_k0(fcw->ncb, fcw->Zc, op->ldpc_dec.basegraph,
+			op->ldpc_dec.rv_index);
+	if (op->ldpc_dec.code_block_mode == RTE_BBDEV_CODE_BLOCK)
+		fcw->rm_e = op->ldpc_dec.cb_params.e;
+	else
+		fcw->rm_e = (op->ldpc_dec.tb_params.r <
+				op->ldpc_dec.tb_params.cab) ?
+						op->ldpc_dec.tb_params.ea :
+						op->ldpc_dec.tb_params.eb;
+
+	if (unlikely(check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE) &&
+			(op->ldpc_dec.harq_combined_input.length == 0))) {
+		rte_bbdev_log(WARNING, "Null HARQ input size provided");
+		/* Disable HARQ input in that case to carry forward. */
+		op->ldpc_dec.op_flags ^= RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE;
+	}
+	if (unlikely(fcw->rm_e == 0)) {
+		rte_bbdev_log(WARNING, "Null E input provided");
+		fcw->rm_e = 2;
 	}
 
-	desc->data_ptrs[next_triplet].address =
-			rte_pktmbuf_iova_offset(h_output, *h_out_offset);
-	*h_out_length = desc->data_ptrs[next_triplet].blen;
-	next_triplet++;
+	fcw->hcin_en = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE);
+	fcw->hcout_en = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
+	fcw->crc_select = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK);
+	fcw->so_en = check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_SOFT_OUT_ENABLE);
+	fcw->so_bypass_intlv = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_SOFT_OUT_DEINTERLEAVER_BYPASS);
+	fcw->so_bypass_rm = check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_SOFT_OUT_RM_BYPASS);
+	fcw->bypass_dec = 0;
+	fcw->bypass_intlv = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS);
+	if (op->ldpc_dec.q_m == 1) {
+		fcw->bypass_intlv = 1;
+		fcw->qm = 2;
+	}
+	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION)) {
+		fcw->hcin_decomp_mode = 1;
+		fcw->hcout_comp_mode = 1;
+	} else if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_HARQ_4BIT_COMPRESSION)) {
+		fcw->hcin_decomp_mode = 4;
+		fcw->hcout_comp_mode = 4;
+	} else {
+		fcw->hcin_decomp_mode = 0;
+		fcw->hcout_comp_mode = 0;
+	}
 
-	if (check_bit(op->ldpc_dec.op_flags,
-				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
-		/* Adjust based on previous operation. */
-		struct rte_bbdev_dec_op *prev_op = desc->op_addr;
-		op->ldpc_dec.harq_combined_output.length =
-				prev_op->ldpc_dec.harq_combined_output.length;
-		uint32_t harq_idx = hq_index(op->ldpc_dec.harq_combined_output.offset);
-		uint32_t prev_harq_idx = hq_index(prev_op->ldpc_dec.harq_combined_output.offset);
-		harq_layout[harq_idx].val = harq_layout[prev_harq_idx].val;
-		struct rte_bbdev_op_data ho = op->ldpc_dec.harq_combined_output;
-		desc->data_ptrs[next_triplet].address =
-				rte_pktmbuf_iova_offset(ho.data, ho.offset);
-		next_triplet++;
+	fcw->llr_pack_mode = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_LLR_COMPRESSION);
+	harq_index = hq_index(op->ldpc_dec.harq_combined_output.offset);
+	if (fcw->hcin_en > 0) {
+		harq_in_length = op->ldpc_dec.harq_combined_input.length;
+		if (fcw->hcin_decomp_mode == 1)
+			harq_in_length = harq_in_length * 8 / 6;
+		else if (fcw->hcin_decomp_mode == 4)
+			harq_in_length = harq_in_length * 2;
+		harq_in_length = RTE_MIN(harq_in_length, op->ldpc_dec.n_cb
+				- op->ldpc_dec.n_filler);
+		harq_in_length = RTE_ALIGN_CEIL(harq_in_length, 64);
+		fcw->hcin_size0 = harq_in_length;
+		fcw->hcin_offset = 0;
+		fcw->hcin_size1 = 0;
+	} else {
+		fcw->hcin_size0 = 0;
+		fcw->hcin_offset = 0;
+		fcw->hcin_size1 = 0;
 	}
 
-	op->ldpc_dec.hard_output.length += *h_out_length;
-	desc->op_addr = op;
-}
+	fcw->itmax = op->ldpc_dec.iter_max;
+	fcw->so_it = op->ldpc_dec.iter_max;
+	fcw->itstop = check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE);
+	fcw->cnu_algo = ACC_ALGO_MSA;
+	fcw->synd_precoder = fcw->itstop;
 
-/* Enqueue one encode operations for device in CB mode */
-static inline int
-enqueue_enc_one_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op *op,
-		uint16_t total_enqueued_cbs)
-{
-	union acc_dma_desc *desc = NULL;
-	int ret;
-	uint32_t in_offset, out_offset, out_length, mbuf_total_left, seg_total_left;
-	struct rte_mbuf *input, *output_head, *output;
+	fcw->minsum_offset = 1;
+	fcw->dec_llrclip   = 2;
 
-	desc = acc_desc(q, total_enqueued_cbs);
-	acc_fcw_te_fill(op, &desc->req.fcw_te);
+	/*
+	 * These are all implicitly set
+	 * fcw->synd_post = 0;
+	 * fcw->dec_convllr = 0;
+	 * fcw->hcout_convllr = 0;
+	 * fcw->hcout_size1 = 0;
+	 * fcw->hcout_offset = 0;
+	 * fcw->negstop_th = 0;
+	 * fcw->negstop_it = 0;
+	 * fcw->negstop_en = 0;
+	 * fcw->gain_i = 1;
+	 * fcw->gain_h = 1;
+	 */
+	if (fcw->hcout_en > 0) {
+		parity_offset = (op->ldpc_dec.basegraph == 1 ? 20 : 8)
+			* op->ldpc_dec.z_c - op->ldpc_dec.n_filler;
+		k0_p = (fcw->k0 > parity_offset) ?
+				fcw->k0 - op->ldpc_dec.n_filler : fcw->k0;
+		ncb_p = fcw->ncb - op->ldpc_dec.n_filler;
+		l = k0_p + fcw->rm_e;
+		harq_out_length = (uint16_t) fcw->hcin_size0;
+		harq_out_length = RTE_MIN(RTE_MAX(harq_out_length, l), ncb_p);
+		harq_out_length = RTE_ALIGN_CEIL(harq_out_length, 64);
+		fcw->hcout_size0 = harq_out_length;
+		fcw->hcout_size1 = 0;
+		fcw->hcout_offset = 0;
+		harq_layout[harq_index].offset = fcw->hcout_offset;
+		harq_layout[harq_index].size0 = fcw->hcout_size0;
+	} else {
+		fcw->hcout_size0 = 0;
+		fcw->hcout_size1 = 0;
+		fcw->hcout_offset = 0;
+	}
+
+	fcw->tb_crc_select = 0;
+	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK))
+		fcw->tb_crc_select = 2;
+	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_CRC_TYPE_16_CHECK))
+		fcw->tb_crc_select = 1;
+}
+
+static inline int
+vrb2_dma_desc_ld_fill(struct rte_bbdev_dec_op *op,
+		struct acc_dma_req_desc *desc,
+		struct rte_mbuf **input, struct rte_mbuf *h_output,
+		uint32_t *in_offset, uint32_t *h_out_offset,
+		uint32_t *h_out_length, uint32_t *mbuf_total_left,
+		uint32_t *seg_total_left, struct acc_fcw_ld *fcw)
+{
+	struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
+	int next_triplet = 1; /* FCW already done. */
+	uint32_t input_length;
+	uint16_t output_length, crc24_overlap = 0;
+	uint16_t sys_cols, K, h_p_size, h_np_size;
+
+	acc_header_init(desc);
+
+	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP))
+		crc24_overlap = 24;
+
+	/* Compute some LDPC BG lengths. */
+	input_length = fcw->rm_e;
+	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_LLR_COMPRESSION))
+		input_length = (input_length * 3 + 3) / 4;
+	sys_cols = (dec->basegraph == 1) ? 22 : 10;
+	K = sys_cols * dec->z_c;
+	output_length = K - dec->n_filler - crc24_overlap;
+
+	if (unlikely((*mbuf_total_left == 0) || (*mbuf_total_left < input_length))) {
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
+				*mbuf_total_left, input_length);
+		return -1;
+	}
+
+	next_triplet = acc_dma_fill_blk_type_in(desc, input,
+			in_offset, input_length,
+			seg_total_left, next_triplet,
+			check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_DEC_SCATTER_GATHER));
+
+	if (unlikely(next_triplet < 0)) {
+		rte_bbdev_log(ERR,
+				"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+				op);
+		return -1;
+	}
+
+	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
+		if (op->ldpc_dec.harq_combined_input.data == 0) {
+			rte_bbdev_log(ERR, "HARQ input is not defined");
+			return -1;
+		}
+		h_p_size = fcw->hcin_size0 + fcw->hcin_size1;
+		if (fcw->hcin_decomp_mode == 1)
+			h_p_size = (h_p_size * 3 + 3) / 4;
+		else if (fcw->hcin_decomp_mode == 4)
+			h_p_size = h_p_size / 2;
+		if (op->ldpc_dec.harq_combined_input.data == 0) {
+			rte_bbdev_log(ERR, "HARQ input is not defined");
+			return -1;
+		}
+		acc_dma_fill_blk_type(
+				desc,
+				op->ldpc_dec.harq_combined_input.data,
+				op->ldpc_dec.harq_combined_input.offset,
+				h_p_size,
+				next_triplet,
+				ACC_DMA_BLKID_IN_HARQ);
+		next_triplet++;
+	}
+
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->m2dlen = next_triplet;
+	*mbuf_total_left -= input_length;
+
+	next_triplet = acc_dma_fill_blk_type(desc, h_output,
+			*h_out_offset, output_length >> 3, next_triplet,
+			ACC_DMA_BLKID_OUT_HARD);
+
+	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_SOFT_OUT_ENABLE)) {
+		if (op->ldpc_dec.soft_output.data == 0) {
+			rte_bbdev_log(ERR, "Soft output is not defined");
+			return -1;
+		}
+		dec->soft_output.length = fcw->rm_e;
+		acc_dma_fill_blk_type(desc, dec->soft_output.data, dec->soft_output.offset,
+				fcw->rm_e, next_triplet, ACC_DMA_BLKID_OUT_SOFT);
+		next_triplet++;
+	}
+
+	if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
+		if (op->ldpc_dec.harq_combined_output.data == 0) {
+			rte_bbdev_log(ERR, "HARQ output is not defined");
+			return -1;
+		}
+
+		/* Pruned size of the HARQ */
+		h_p_size = fcw->hcout_size0 + fcw->hcout_size1;
+		/* Non-Pruned size of the HARQ */
+		h_np_size = fcw->hcout_offset > 0 ?
+				fcw->hcout_offset + fcw->hcout_size1 :
+				h_p_size;
+		if (fcw->hcin_decomp_mode == 1) {
+			h_np_size = (h_np_size * 3 + 3) / 4;
+			h_p_size = (h_p_size * 3 + 3) / 4;
+		} else if (fcw->hcin_decomp_mode == 4) {
+			h_np_size = h_np_size / 2;
+			h_p_size = h_p_size / 2;
+		}
+		dec->harq_combined_output.length = h_np_size;
+		acc_dma_fill_blk_type(
+				desc,
+				dec->harq_combined_output.data,
+				dec->harq_combined_output.offset,
+				h_p_size,
+				next_triplet,
+				ACC_DMA_BLKID_OUT_HARQ);
+
+		next_triplet++;
+	}
+
+	*h_out_length = output_length >> 3;
+	dec->hard_output.length += *h_out_length;
+	*h_out_offset += *h_out_length;
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->d2mlen = next_triplet - desc->m2dlen;
+
+	desc->op_addr = op;
+
+	return 0;
+}
+
+static inline void
+vrb_dma_desc_ld_update(struct rte_bbdev_dec_op *op,
+		struct acc_dma_req_desc *desc,
+		struct rte_mbuf *input, struct rte_mbuf *h_output,
+		uint32_t *in_offset, uint32_t *h_out_offset,
+		uint32_t *h_out_length,
+		union acc_harq_layout_data *harq_layout)
+{
+	int next_triplet = 1; /* FCW already done. */
+	desc->data_ptrs[next_triplet].address = rte_pktmbuf_iova_offset(input, *in_offset);
+	next_triplet++;
+
+	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
+		struct rte_bbdev_op_data hi = op->ldpc_dec.harq_combined_input;
+		desc->data_ptrs[next_triplet].address =
+				rte_pktmbuf_iova_offset(hi.data, hi.offset);
+		next_triplet++;
+	}
+
+	desc->data_ptrs[next_triplet].address =
+			rte_pktmbuf_iova_offset(h_output, *h_out_offset);
+	*h_out_length = desc->data_ptrs[next_triplet].blen;
+	next_triplet++;
+
+	if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
+		/* Adjust based on previous operation. */
+		struct rte_bbdev_dec_op *prev_op = desc->op_addr;
+		op->ldpc_dec.harq_combined_output.length =
+				prev_op->ldpc_dec.harq_combined_output.length;
+		uint32_t harq_idx = hq_index(op->ldpc_dec.harq_combined_output.offset);
+		uint32_t prev_harq_idx = hq_index(prev_op->ldpc_dec.harq_combined_output.offset);
+		harq_layout[harq_idx].val = harq_layout[prev_harq_idx].val;
+		struct rte_bbdev_op_data ho = op->ldpc_dec.harq_combined_output;
+		desc->data_ptrs[next_triplet].address =
+				rte_pktmbuf_iova_offset(ho.data, ho.offset);
+		next_triplet++;
+	}
+
+	op->ldpc_dec.hard_output.length += *h_out_length;
+	desc->op_addr = op;
+}
+
+/* Enqueue one encode operations for device in CB mode */
+static inline int
+enqueue_enc_one_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op *op,
+		uint16_t total_enqueued_cbs)
+{
+	union acc_dma_desc *desc = NULL;
+	int ret;
+	uint32_t in_offset, out_offset, out_length, mbuf_total_left, seg_total_left;
+	struct rte_mbuf *input, *output_head, *output;
+
+	desc = acc_desc(q, total_enqueued_cbs);
+	acc_fcw_te_fill(op, &desc->req.fcw_te);
 
 	input = op->turbo_enc.input.data;
 	output_head = output = op->turbo_enc.output.data;
@@ -1780,6 +2284,7 @@  enqueue_ldpc_enc_n_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op **ops,
 	/** This could be done at polling. */
 	acc_header_init(&desc->req);
 	desc->req.numCBs = num;
+	desc->req.dltb = 0;
 
 	in_length_in_bytes = ops[0]->ldpc_enc.input.data->data_len;
 	out_length = (enc->cb_params.e + 7) >> 3;
@@ -1818,7 +2323,7 @@  enqueue_ldpc_enc_n_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op **ops,
 	return num;
 }
 
-/* Enqueue one encode operations for device for a partial TB
+/* Enqueue one encode operations for VRB1 device for a partial TB
  * all codes blocks have same configuration multiplexed on the same descriptor.
  */
 static inline void
@@ -2005,6 +2510,105 @@  vrb1_enqueue_ldpc_enc_one_op_tb(struct acc_queue *q, struct rte_bbdev_enc_op *op
 	return return_descs;
 }
 
+/* Fill in a frame control word for LDPC encoding. */
+static inline void
+vrb2_fcw_letb_fill(const struct rte_bbdev_enc_op *op, struct acc_fcw_le *fcw)
+{
+	fcw->qm = op->ldpc_enc.q_m;
+	fcw->nfiller = op->ldpc_enc.n_filler;
+	fcw->BG = (op->ldpc_enc.basegraph - 1);
+	fcw->Zc = op->ldpc_enc.z_c;
+	fcw->ncb = op->ldpc_enc.n_cb;
+	fcw->k0 = get_k0(fcw->ncb, fcw->Zc, op->ldpc_enc.basegraph,
+			op->ldpc_enc.rv_index);
+	fcw->rm_e = op->ldpc_enc.tb_params.ea;
+	fcw->rm_e_b = op->ldpc_enc.tb_params.eb;
+	fcw->crc_select = check_bit(op->ldpc_enc.op_flags,
+			RTE_BBDEV_LDPC_CRC_24B_ATTACH);
+	fcw->bypass_intlv = 0;
+	if (op->ldpc_enc.tb_params.c > 1) {
+		fcw->mcb_count = 0;
+		fcw->C = op->ldpc_enc.tb_params.c;
+		fcw->Cab = op->ldpc_enc.tb_params.cab;
+	} else {
+		fcw->mcb_count = 1;
+		fcw->C = 0;
+	}
+}
+
+/* Enqueue one encode operations for device in TB mode.
+ * returns the number of descs used.
+ */
+static inline int
+vrb2_enqueue_ldpc_enc_one_op_tb(struct acc_queue *q, struct rte_bbdev_enc_op *op,
+		uint16_t enq_descs)
+{
+	union acc_dma_desc *desc = NULL;
+	uint32_t in_offset, out_offset, out_length, seg_total_left;
+	struct rte_mbuf *input, *output_head, *output;
+
+	uint16_t desc_idx = ((q->sw_ring_head + enq_descs) & q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	vrb2_fcw_letb_fill(op, &desc->req.fcw_le);
+	struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
+	int next_triplet = 1; /* FCW already done */
+	uint32_t in_length_in_bytes;
+	uint16_t K, in_length_in_bits;
+
+	input = enc->input.data;
+	output_head = output = enc->output.data;
+	in_offset = enc->input.offset;
+	out_offset = enc->output.offset;
+	seg_total_left = rte_pktmbuf_data_len(enc->input.data) - in_offset;
+
+	acc_header_init(&desc->req);
+	K = (enc->basegraph == 1 ? 22 : 10) * enc->z_c;
+	in_length_in_bits = K - enc->n_filler;
+	if ((enc->op_flags & RTE_BBDEV_LDPC_CRC_24A_ATTACH) ||
+			(enc->op_flags & RTE_BBDEV_LDPC_CRC_24B_ATTACH))
+		in_length_in_bits -= 24;
+	in_length_in_bytes = (in_length_in_bits >> 3) * enc->tb_params.c;
+
+	next_triplet = acc_dma_fill_blk_type_in(&desc->req, &input, &in_offset,
+			in_length_in_bytes, &seg_total_left, next_triplet,
+			check_bit(enc->op_flags, RTE_BBDEV_LDPC_ENC_SCATTER_GATHER));
+	if (unlikely(next_triplet < 0)) {
+		rte_bbdev_log(ERR,
+				"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+				op);
+		return -1;
+	}
+	desc->req.data_ptrs[next_triplet - 1].last = 1;
+	desc->req.m2dlen = next_triplet;
+
+	/* Set output length */
+	/* Integer round up division by 8 */
+	out_length = (enc->tb_params.ea * enc->tb_params.cab +
+			enc->tb_params.eb * (enc->tb_params.c - enc->tb_params.cab)  + 7) >> 3;
+
+	next_triplet = acc_dma_fill_blk_type(&desc->req, output, out_offset,
+			out_length, next_triplet, ACC_DMA_BLKID_OUT_ENC);
+	enc->output.length = out_length;
+	out_offset += out_length;
+	desc->req.data_ptrs[next_triplet - 1].last = 1;
+	desc->req.data_ptrs[next_triplet - 1].dma_ext = 0;
+	desc->req.d2mlen = next_triplet - desc->req.m2dlen;
+	desc->req.numCBs = enc->tb_params.c;
+	if (desc->req.numCBs > 1)
+		desc->req.dltb = 1;
+	desc->req.op_addr = op;
+
+	if (out_length < ACC_MAX_E_MBUF)
+		mbuf_append(output_head, output, out_length);
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	acc_memdump("FCW", &desc->req.fcw_le, sizeof(desc->req.fcw_le));
+	acc_memdump("Req Desc.", desc, sizeof(*desc));
+#endif
+	/* One CB (one op) was successfully prepared to enqueue */
+	return 1;
+}
+
 /** Enqueue one decode operations for device in CB mode. */
 static inline int
 enqueue_dec_one_op_cb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
@@ -2017,8 +2621,10 @@  enqueue_dec_one_op_cb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
 	struct rte_mbuf *input, *h_output_head, *h_output,
 		*s_output_head, *s_output;
 
-	/* Disable explictly SO for VRB 1. */
-	op->turbo_dec.op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
+	if (q->d->device_variant == VRB1_VARIANT) {
+		/* Disable explictly SO for VRB 1. */
+		op->turbo_dec.op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
+	}
 
 	desc = acc_desc(q, total_enqueued_cbs);
 	vrb_fcw_td_fill(op, &desc->req.fcw_td);
@@ -2061,7 +2667,7 @@  enqueue_dec_one_op_cb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
 	return 1;
 }
 
-/** Enqueue one decode operations for device in CB mode */
+/** Enqueue one decode operations for device in CB mode. */
 static inline int
 vrb_enqueue_ldpc_dec_one_op_cb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
 		uint16_t total_enqueued_cbs, bool same_op)
@@ -2114,11 +2720,16 @@  vrb_enqueue_ldpc_dec_one_op_cb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
 			seg_total_left = rte_pktmbuf_data_len(input) - in_offset;
 		else
 			seg_total_left = fcw->rm_e;
-
-		ret = vrb1_dma_desc_ld_fill(op, &desc->req, &input, h_output,
-				&in_offset, &h_out_offset,
-				&h_out_length, &mbuf_total_left,
-				&seg_total_left, fcw);
+		if (q->d->device_variant == VRB1_VARIANT)
+			ret = vrb1_dma_desc_ld_fill(op, &desc->req, &input, h_output,
+					&in_offset, &h_out_offset,
+					&h_out_length, &mbuf_total_left,
+					&seg_total_left, fcw);
+		else
+			ret = vrb2_dma_desc_ld_fill(op, &desc->req, &input, h_output,
+					&in_offset, &h_out_offset,
+					&h_out_length, &mbuf_total_left,
+					&seg_total_left, fcw);
 		if (unlikely(ret < 0))
 			return ret;
 	}
@@ -2207,12 +2818,18 @@  vrb_enqueue_ldpc_dec_one_op_tb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
 		desc->req.data_ptrs[0].blen = ACC_FCW_LD_BLEN;
 		rte_memcpy(&desc->req.fcw_ld, &desc_first->req.fcw_ld, ACC_FCW_LD_BLEN);
 		desc->req.fcw_ld.tb_trailer_size = (c - r - 1) * trail_len;
-
-		ret = vrb1_dma_desc_ld_fill(op, &desc->req, &input,
-				h_output, &in_offset, &h_out_offset,
-				&h_out_length,
-				&mbuf_total_left, &seg_total_left,
-				&desc->req.fcw_ld);
+		if (q->d->device_variant == VRB1_VARIANT)
+			ret = vrb1_dma_desc_ld_fill(op, &desc->req, &input,
+					h_output, &in_offset, &h_out_offset,
+					&h_out_length,
+					&mbuf_total_left, &seg_total_left,
+					&desc->req.fcw_ld);
+		else
+			ret = vrb2_dma_desc_ld_fill(op, &desc->req, &input,
+					h_output, &in_offset, &h_out_offset,
+					&h_out_length,
+					&mbuf_total_left, &seg_total_left,
+					&desc->req.fcw_ld);
 
 		if (unlikely(ret < 0))
 			return ret;
@@ -2254,7 +2871,7 @@  vrb_enqueue_ldpc_dec_one_op_tb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
 	return current_enqueued_cbs;
 }
 
-/* Enqueue one decode operations for device in TB mode */
+/* Enqueue one decode operations for device in TB mode. */
 static inline int
 enqueue_dec_one_op_tb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
 		uint16_t total_enqueued_cbs, uint8_t cbs_in_tb)
@@ -2476,14 +3093,23 @@  vrb_enqueue_ldpc_enc_tb(struct rte_bbdev_queue_data *q_data,
 	int descs_used;
 
 	for (i = 0; i < num; ++i) {
-		cbs_in_tb = get_num_cbs_in_tb_ldpc_enc(&ops[i]->ldpc_enc);
-		/* Check if there are available space for further processing. */
-		if (unlikely((avail - cbs_in_tb < 0) || (cbs_in_tb == 0))) {
-			acc_enqueue_ring_full(q_data);
-			break;
+		if (q->d->device_variant == VRB1_VARIANT) {
+			cbs_in_tb = get_num_cbs_in_tb_ldpc_enc(&ops[i]->ldpc_enc);
+			/* Check if there are available space for further processing. */
+			if (unlikely((avail - cbs_in_tb < 0) || (cbs_in_tb == 0))) {
+				acc_enqueue_ring_full(q_data);
+				break;
+			}
+			descs_used = vrb1_enqueue_ldpc_enc_one_op_tb(q, ops[i],
+					enqueued_descs, cbs_in_tb);
+		} else {
+			if (unlikely(avail < 1)) {
+				acc_enqueue_ring_full(q_data);
+				break;
+			}
+			descs_used = vrb2_enqueue_ldpc_enc_one_op_tb(q, ops[i], enqueued_descs);
 		}
 
-		descs_used = vrb1_enqueue_ldpc_enc_one_op_tb(q, ops[i], enqueued_descs, cbs_in_tb);
 		if (descs_used < 0) {
 			acc_enqueue_invalid(q_data);
 			break;
@@ -2617,7 +3243,6 @@  vrb_enqueue_ldpc_dec_cb(struct rte_bbdev_queue_data *q_data,
 			break;
 		}
 		avail -= 1;
-
 		rte_bbdev_log(INFO, "Op %d %d %d %d %d %d %d %d %d %d %d %d\n",
 			i, ops[i]->ldpc_dec.op_flags, ops[i]->ldpc_dec.rv_index,
 			ops[i]->ldpc_dec.iter_max, ops[i]->ldpc_dec.iter_count,
@@ -2745,6 +3370,7 @@  vrb_dequeue_enc_one_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op **ref_op,
 	op->status |= ((rsp.input_err) ? (1 << RTE_BBDEV_DATA_ERROR) : 0);
 	op->status |= ((rsp.dma_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
 	op->status |= ((rsp.fcw_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+	op->status |= ((rsp.engine_hung) ? (1 << RTE_BBDEV_ENGINE_ERROR) : 0);
 
 	if (desc->req.last_desc_in_batch) {
 		(*aq_dequeued)++;
@@ -2765,7 +3391,56 @@  vrb_dequeue_enc_one_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op **ref_op,
 	return desc->req.numCBs;
 }
 
-/* Dequeue one LDPC encode operations from device in TB mode.
+
+/* Dequeue one LDPC encode operations from VRB2 device in TB mode
+ */
+static inline int
+vrb2_dequeue_ldpc_enc_one_op_tb(struct acc_queue *q, struct rte_bbdev_enc_op **ref_op,
+		uint16_t *dequeued_ops, uint32_t *aq_dequeued,
+		uint16_t *dequeued_descs)
+{
+	union acc_dma_desc *desc, atom_desc;
+	union acc_dma_rsp_desc rsp;
+	struct rte_bbdev_enc_op *op;
+	int desc_idx = ((q->sw_ring_tail + *dequeued_descs) & q->sw_ring_wrap_mask);
+
+	desc = q->ring_addr + desc_idx;
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc, __ATOMIC_RELAXED);
+
+	/* Check fdone bit */
+	if (!(atom_desc.rsp.val & ACC_FDONE))
+		return -1;
+
+	rsp.val = atom_desc.rsp.val;
+	rte_bbdev_log_debug("Resp. desc %p: %x", desc, rsp.val);
+
+	/* Dequeue */
+	op = desc->req.op_addr;
+
+	/* Clearing status, it will be set based on response */
+	op->status = 0;
+	op->status |= rsp.input_err << RTE_BBDEV_DATA_ERROR;
+	op->status |= rsp.dma_err << RTE_BBDEV_DRV_ERROR;
+	op->status |= rsp.fcw_err << RTE_BBDEV_DRV_ERROR;
+	op->status |= rsp.engine_hung << RTE_BBDEV_ENGINE_ERROR;
+
+	if (desc->req.last_desc_in_batch) {
+		(*aq_dequeued)++;
+		desc->req.last_desc_in_batch = 0;
+	}
+	desc->rsp.val = ACC_DMA_DESC_TYPE;
+	desc->rsp.add_info_0 = 0; /*Reserved bits */
+	desc->rsp.add_info_1 = 0; /*Reserved bits */
+
+	/* One op was successfully dequeued */
+	ref_op[0] = op;
+	(*dequeued_descs)++;
+	(*dequeued_ops)++;
+	return 1;
+}
+
+
+/* Dequeue one encode operations from device in TB mode.
  * That operation may cover multiple descriptors.
  */
 static inline int
@@ -2815,6 +3490,7 @@  vrb_dequeue_enc_one_op_tb(struct acc_queue *q, struct rte_bbdev_enc_op **ref_op,
 		op->status |= ((rsp.input_err) ? (1 << RTE_BBDEV_DATA_ERROR) : 0);
 		op->status |= ((rsp.dma_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
 		op->status |= ((rsp.fcw_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+		op->status |= ((rsp.engine_hung) ? (1 << RTE_BBDEV_ENGINE_ERROR) : 0);
 
 		if (desc->req.last_desc_in_batch) {
 			(*aq_dequeued)++;
@@ -2861,6 +3537,8 @@  vrb_dequeue_dec_one_op_cb(struct rte_bbdev_queue_data *q_data,
 	op->status |= ((rsp.input_err) ? (1 << RTE_BBDEV_DATA_ERROR) : 0);
 	op->status |= ((rsp.dma_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
 	op->status |= ((rsp.fcw_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+	op->status |= rsp.engine_hung << RTE_BBDEV_ENGINE_ERROR;
+
 	if (op->status != 0) {
 		/* These errors are not expected. */
 		q_data->queue_stats.dequeue_err_count++;
@@ -2914,6 +3592,7 @@  vrb_dequeue_ldpc_dec_one_op_cb(struct rte_bbdev_queue_data *q_data,
 	op->status |= rsp.input_err << RTE_BBDEV_DATA_ERROR;
 	op->status |= rsp.dma_err << RTE_BBDEV_DRV_ERROR;
 	op->status |= rsp.fcw_err << RTE_BBDEV_DRV_ERROR;
+	op->status |= rsp.engine_hung << RTE_BBDEV_ENGINE_ERROR;
 	if (op->status != 0)
 		q_data->queue_stats.dequeue_err_count++;
 
@@ -2995,6 +3674,7 @@  vrb_dequeue_dec_one_op_tb(struct acc_queue *q, struct rte_bbdev_dec_op **ref_op,
 		op->status |= ((rsp.input_err) ? (1 << RTE_BBDEV_DATA_ERROR) : 0);
 		op->status |= ((rsp.dma_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
 		op->status |= ((rsp.fcw_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+		op->status |= ((rsp.engine_hung) ? (1 << RTE_BBDEV_ENGINE_ERROR) : 0);
 
 		if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK))
 			tb_crc_check ^= desc->rsp.add_info_1;
@@ -3046,7 +3726,6 @@  vrb_dequeue_enc(struct rte_bbdev_queue_data *q_data,
 	if (avail == 0)
 		return 0;
 	op = acc_op_tail(q, 0);
-
 	cbm = op->turbo_enc.code_block_mode;
 
 	for (i = 0; i < avail; i++) {
@@ -3089,9 +3768,14 @@  vrb_dequeue_ldpc_enc(struct rte_bbdev_queue_data *q_data,
 
 	for (i = 0; i < avail; i++) {
 		if (cbm == RTE_BBDEV_TRANSPORT_BLOCK)
-			ret = vrb_dequeue_enc_one_op_tb(q, &ops[dequeued_ops],
-					&dequeued_ops, &aq_dequeued,
-					&dequeued_descs, num);
+			if (q->d->device_variant == VRB1_VARIANT)
+				ret = vrb_dequeue_enc_one_op_tb(q, &ops[dequeued_ops],
+						&dequeued_ops, &aq_dequeued,
+						&dequeued_descs, num);
+			else
+				ret = vrb2_dequeue_ldpc_enc_one_op_tb(q, &ops[dequeued_ops],
+						&dequeued_ops, &aq_dequeued,
+						&dequeued_descs);
 		else
 			ret = vrb_dequeue_enc_one_op_cb(q, &ops[dequeued_ops],
 					&dequeued_ops, &aq_dequeued,
@@ -3221,6 +3905,47 @@  vrb1_fcw_fft_fill(struct rte_bbdev_fft_op *op, struct acc_fcw_fft *fcw)
 		fcw->bypass = 0;
 }
 
+/* Fill in a frame control word for FFT processing. */
+static inline void
+vrb2_fcw_fft_fill(struct rte_bbdev_fft_op *op, struct acc_fcw_fft_3 *fcw)
+{
+	fcw->in_frame_size = op->fft.input_sequence_size;
+	fcw->leading_pad_size = op->fft.input_leading_padding;
+	fcw->out_frame_size = op->fft.output_sequence_size;
+	fcw->leading_depad_size = op->fft.output_leading_depadding;
+	fcw->cs_window_sel = op->fft.window_index[0] +
+			(op->fft.window_index[1] << 8) +
+			(op->fft.window_index[2] << 16) +
+			(op->fft.window_index[3] << 24);
+	fcw->cs_window_sel2 = op->fft.window_index[4] +
+			(op->fft.window_index[5] << 8);
+	fcw->cs_enable_bmap = op->fft.cs_bitmap;
+	fcw->num_antennas = op->fft.num_antennas_log2;
+	fcw->idft_size = op->fft.idft_log2;
+	fcw->dft_size = op->fft.dft_log2;
+	fcw->cs_offset = op->fft.cs_time_adjustment;
+	fcw->idft_shift = op->fft.idft_shift;
+	fcw->dft_shift = op->fft.dft_shift;
+	fcw->cs_multiplier = op->fft.ncs_reciprocal;
+	fcw->power_shift = op->fft.power_shift;
+	fcw->exp_adj = op->fft.fp16_exp_adjust;
+	fcw->fp16_in = check_bit(op->fft.op_flags, RTE_BBDEV_FFT_FP16_INPUT);
+	fcw->fp16_out = check_bit(op->fft.op_flags, RTE_BBDEV_FFT_FP16_OUTPUT);
+	fcw->power_en = check_bit(op->fft.op_flags, RTE_BBDEV_FFT_POWER_MEAS);
+	if (check_bit(op->fft.op_flags,
+			RTE_BBDEV_FFT_IDFT_BYPASS)) {
+		if (check_bit(op->fft.op_flags,
+				RTE_BBDEV_FFT_WINDOWING_BYPASS))
+			fcw->bypass = 2;
+		else
+			fcw->bypass = 1;
+	} else if (check_bit(op->fft.op_flags,
+			RTE_BBDEV_FFT_DFT_BYPASS))
+		fcw->bypass = 3;
+	else
+		fcw->bypass = 0;
+}
+
 static inline int
 vrb1_dma_desc_fft_fill(struct rte_bbdev_fft_op *op,
 		struct acc_dma_req_desc *desc,
@@ -3254,6 +3979,58 @@  vrb1_dma_desc_fft_fill(struct rte_bbdev_fft_op *op,
 	return 0;
 }
 
+static inline int
+vrb2_dma_desc_fft_fill(struct rte_bbdev_fft_op *op,
+		struct acc_dma_req_desc *desc,
+		struct rte_mbuf *input, struct rte_mbuf *output, struct rte_mbuf *win_input,
+		struct rte_mbuf *pwr, uint32_t *in_offset, uint32_t *out_offset,
+		uint32_t *win_offset, uint32_t *pwr_offset)
+{
+	bool pwr_en = check_bit(op->fft.op_flags, RTE_BBDEV_FFT_POWER_MEAS);
+	bool win_en = check_bit(op->fft.op_flags, RTE_BBDEV_FFT_DEWINDOWING);
+	int num_cs = 0, i, bd_idx = 1;
+
+	/* FCW already done */
+	acc_header_init(desc);
+
+	RTE_SET_USED(win_input);
+	RTE_SET_USED(win_offset);
+
+	desc->data_ptrs[bd_idx].address = rte_pktmbuf_iova_offset(input, *in_offset);
+	desc->data_ptrs[bd_idx].blen = op->fft.input_sequence_size * ACC_IQ_SIZE;
+	desc->data_ptrs[bd_idx].blkid = ACC_DMA_BLKID_IN;
+	desc->data_ptrs[bd_idx].last = 1;
+	desc->data_ptrs[bd_idx].dma_ext = 0;
+	bd_idx++;
+
+	desc->data_ptrs[bd_idx].address = rte_pktmbuf_iova_offset(output, *out_offset);
+	desc->data_ptrs[bd_idx].blen = op->fft.output_sequence_size * ACC_IQ_SIZE;
+	desc->data_ptrs[bd_idx].blkid = ACC_DMA_BLKID_OUT_HARD;
+	desc->data_ptrs[bd_idx].last = pwr_en ? 0 : 1;
+	desc->data_ptrs[bd_idx].dma_ext = 0;
+	desc->m2dlen = win_en ? 3 : 2;
+	desc->d2mlen = pwr_en ? 2 : 1;
+	desc->ib_ant_offset = op->fft.input_sequence_size;
+	desc->num_ant = op->fft.num_antennas_log2 - 3;
+
+	for (i = 0; i < RTE_BBDEV_MAX_CS; i++)
+		if (check_bit(op->fft.cs_bitmap, 1 << i))
+			num_cs++;
+	desc->num_cs = num_cs;
+
+	if (pwr_en && pwr) {
+		bd_idx++;
+		desc->data_ptrs[bd_idx].address = rte_pktmbuf_iova_offset(pwr, *pwr_offset);
+		desc->data_ptrs[bd_idx].blen = num_cs * (1 << op->fft.num_antennas_log2) * 4;
+		desc->data_ptrs[bd_idx].blkid = ACC_DMA_BLKID_OUT_SOFT;
+		desc->data_ptrs[bd_idx].last = 1;
+		desc->data_ptrs[bd_idx].dma_ext = 0;
+	}
+	desc->ob_cyc_offset = op->fft.output_sequence_size;
+	desc->ob_ant_offset = op->fft.output_sequence_size * num_cs;
+	desc->op_addr = op;
+	return 0;
+}
 
 /** Enqueue one FFT operation for device. */
 static inline int
@@ -3261,26 +4038,35 @@  vrb_enqueue_fft_one_op(struct acc_queue *q, struct rte_bbdev_fft_op *op,
 		uint16_t total_enqueued_cbs)
 {
 	union acc_dma_desc *desc;
-	struct rte_mbuf *input, *output;
-	uint32_t in_offset, out_offset;
+	struct rte_mbuf *input, *output, *pwr, *win;
+	uint32_t in_offset, out_offset, pwr_offset, win_offset;
 	struct acc_fcw_fft *fcw;
 
 	desc = acc_desc(q, total_enqueued_cbs);
 	input = op->fft.base_input.data;
 	output = op->fft.base_output.data;
+	pwr = op->fft.power_meas_output.data;
+	win = op->fft.dewindowing_input.data;
 	in_offset = op->fft.base_input.offset;
 	out_offset = op->fft.base_output.offset;
+	pwr_offset = op->fft.power_meas_output.offset;
+	win_offset = op->fft.dewindowing_input.offset;
 
 	fcw = (struct acc_fcw_fft *) (q->fcw_ring +
 			((q->sw_ring_head + total_enqueued_cbs) & q->sw_ring_wrap_mask)
 			* ACC_MAX_FCW_SIZE);
 
-	vrb1_fcw_fft_fill(op, fcw);
-	vrb1_dma_desc_fft_fill(op, &desc->req, input, output, &in_offset, &out_offset);
+	if (q->d->device_variant == VRB1_VARIANT) {
+		vrb1_fcw_fft_fill(op, fcw);
+		vrb1_dma_desc_fft_fill(op, &desc->req, input, output, &in_offset, &out_offset);
+	} else {
+		vrb2_fcw_fft_fill(op, (struct acc_fcw_fft_3 *) fcw);
+		vrb2_dma_desc_fft_fill(op, &desc->req, input, output, win, pwr,
+				&in_offset, &out_offset, &win_offset, &pwr_offset);
+	}
 #ifdef RTE_LIBRTE_BBDEV_DEBUG
-	rte_memdump(stderr, "FCW", &desc->req.fcw_fft,
-			sizeof(desc->req.fcw_fft));
-	rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+	acc_memdump("FCW", fcw, 128);
+	acc_memdump("Req Desc.", desc, 128);
 #endif
 	return 1;
 }
@@ -3353,6 +4139,7 @@  vrb_dequeue_fft_one_op(struct rte_bbdev_queue_data *q_data,
 	op->status |= rsp.input_err << RTE_BBDEV_DATA_ERROR;
 	op->status |= rsp.dma_err << RTE_BBDEV_DRV_ERROR;
 	op->status |= rsp.fcw_err << RTE_BBDEV_DRV_ERROR;
+	op->status |= rsp.engine_hung << RTE_BBDEV_ENGINE_ERROR;
 	if (op->status != 0)
 		q_data->queue_stats.dequeue_err_count++;
 
@@ -3383,6 +4170,7 @@  vrb_dequeue_fft(struct rte_bbdev_queue_data *q_data,
 	uint32_t aq_dequeued = 0;
 	int ret;
 
+
 	dequeue_num = RTE_MIN(avail, num);
 
 	for (i = 0; i < dequeue_num; ++i) {
@@ -3399,6 +4187,371 @@  vrb_dequeue_fft(struct rte_bbdev_queue_data *q_data,
 	return i;
 }
 
+/* Fill in a frame control word for MLD-TS processing. */
+static inline void
+vrb2_fcw_mldts_fill(struct rte_bbdev_mldts_op *op, struct acc_fcw_mldts *fcw)
+{
+	fcw->nrb = op->mldts.num_rbs;
+	fcw->NLayers = op->mldts.num_layers - 1;
+	fcw->Qmod0 = (op->mldts.q_m[0] >> 1) - 1;
+	fcw->Qmod1 = (op->mldts.q_m[1] >> 1) - 1;
+	fcw->Qmod2 = (op->mldts.q_m[2] >> 1) - 1;
+	fcw->Qmod3 = (op->mldts.q_m[3] >> 1) - 1;
+	/* Mark some layers as disabled */
+	if (op->mldts.num_layers == 2) {
+		fcw->Qmod2 = 3;
+		fcw->Qmod3 = 3;
+	}
+	if (op->mldts.num_layers == 3)
+		fcw->Qmod3 = 3;
+	fcw->Rrep = op->mldts.r_rep;
+	fcw->Crep = op->mldts.c_rep;
+}
+
+/* Fill in descriptor for one MLD-TS processing operation. */
+static inline int
+vrb2_dma_desc_mldts_fill(struct rte_bbdev_mldts_op *op,
+		struct acc_dma_req_desc *desc,
+		struct rte_mbuf *input_q, struct rte_mbuf *input_r,
+		struct rte_mbuf *output,
+		uint32_t *in_offset, uint32_t *out_offset)
+{
+	uint16_t qsize_per_re[VRB2_MLD_LAY_SIZE] = {8, 12, 16}; /* Layer 2 to 4. */
+	uint16_t rsize_per_re[VRB2_MLD_LAY_SIZE] = {14, 26, 42};
+	uint16_t sc_factor_per_rrep[VRB2_MLD_RREP_SIZE] = {12, 6, 4, 3, 0, 2};
+	uint16_t i, outsize_per_re = 0;
+	uint32_t sc_num, r_num, q_size, r_size, out_size;
+
+	/* Prevent out of range access. */
+	if (op->mldts.r_rep > 5)
+		op->mldts.r_rep = 5;
+	if (op->mldts.num_layers < 2)
+		op->mldts.num_layers = 2;
+	if (op->mldts.num_layers > 4)
+		op->mldts.num_layers = 4;
+	for (i = 0; i < op->mldts.num_layers; i++)
+		outsize_per_re += op->mldts.q_m[i];
+	sc_num = op->mldts.num_rbs * RTE_BBDEV_SCPERRB * (op->mldts.c_rep + 1);
+	r_num = op->mldts.num_rbs * sc_factor_per_rrep[op->mldts.r_rep];
+	q_size = qsize_per_re[op->mldts.num_layers - 2] * sc_num;
+	r_size = rsize_per_re[op->mldts.num_layers - 2] * r_num;
+	out_size =  sc_num * outsize_per_re;
+	/* printf("Sc %d R num %d Size %d %d %d\n", sc_num, r_num, q_size, r_size, out_size); */
+
+	/* FCW already done. */
+	acc_header_init(desc);
+	desc->data_ptrs[1].address = rte_pktmbuf_iova_offset(input_q, *in_offset);
+	desc->data_ptrs[1].blen = q_size;
+	desc->data_ptrs[1].blkid = ACC_DMA_BLKID_IN;
+	desc->data_ptrs[1].last = 0;
+	desc->data_ptrs[1].dma_ext = 0;
+	desc->data_ptrs[2].address = rte_pktmbuf_iova_offset(input_r, *in_offset);
+	desc->data_ptrs[2].blen = r_size;
+	desc->data_ptrs[2].blkid = ACC_DMA_BLKID_IN_MLD_R;
+	desc->data_ptrs[2].last = 1;
+	desc->data_ptrs[2].dma_ext = 0;
+	desc->data_ptrs[3].address = rte_pktmbuf_iova_offset(output, *out_offset);
+	desc->data_ptrs[3].blen = out_size;
+	desc->data_ptrs[3].blkid = ACC_DMA_BLKID_OUT_HARD;
+	desc->data_ptrs[3].last = 1;
+	desc->data_ptrs[3].dma_ext = 0;
+	desc->m2dlen = 3;
+	desc->d2mlen = 1;
+	desc->op_addr = op;
+	desc->cbs_in_tb = 1;
+
+	return 0;
+}
+
+/* Check whether the MLD operation can be processed as a single operation. */
+static inline bool
+vrb2_check_mld_r_constraint(struct rte_bbdev_mldts_op *op) {
+	uint8_t layer_idx, rrep_idx;
+	uint16_t max_rb[VRB2_MLD_LAY_SIZE][VRB2_MLD_RREP_SIZE] = {
+			{188, 275, 275, 275, 0, 275},
+			{101, 202, 275, 275, 0, 275},
+			{62, 124, 186, 248, 0, 275} };
+
+	if (op->mldts.c_rep == 0)
+		return true;
+
+	layer_idx = RTE_MIN(op->mldts.num_layers - VRB2_MLD_MIN_LAYER,
+			VRB2_MLD_MAX_LAYER - VRB2_MLD_MIN_LAYER);
+	rrep_idx = RTE_MIN(op->mldts.r_rep, VRB2_MLD_MAX_RREP);
+	rte_bbdev_log_debug("RB %d index %d %d max %d\n", op->mldts.num_rbs, layer_idx, rrep_idx,
+			max_rb[layer_idx][rrep_idx]);
+
+	return (op->mldts.num_rbs <= max_rb[layer_idx][rrep_idx]);
+}
+
+/** Enqueue MLDTS operation split accross symbols. */
+static inline int
+enqueue_mldts_split_op(struct acc_queue *q, struct rte_bbdev_mldts_op *op,
+		uint16_t total_enqueued_descs)
+{
+	uint16_t qsize_per_re[VRB2_MLD_LAY_SIZE] = {8, 12, 16}; /* Layer 2 to 4. */
+	uint16_t rsize_per_re[VRB2_MLD_LAY_SIZE] = {14, 26, 42};
+	uint16_t sc_factor_per_rrep[VRB2_MLD_RREP_SIZE] = {12, 6, 4, 3, 0, 2};
+	uint32_t i, outsize_per_re = 0, sc_num, r_num, q_size, r_size, out_size, num_syms;
+	union acc_dma_desc *desc, *first_desc;
+	uint16_t desc_idx, symb;
+	struct rte_mbuf *input_q, *input_r, *output;
+	uint32_t in_offset, out_offset;
+	struct acc_fcw_mldts *fcw;
+
+	desc_idx = ((q->sw_ring_head + total_enqueued_descs) & q->sw_ring_wrap_mask);
+	first_desc = q->ring_addr + desc_idx;
+	input_q = op->mldts.qhy_input.data;
+	input_r = op->mldts.r_input.data;
+	output = op->mldts.output.data;
+	in_offset = op->mldts.qhy_input.offset;
+	out_offset = op->mldts.output.offset;
+	num_syms = op->mldts.c_rep + 1;
+	fcw = &first_desc->req.fcw_mldts;
+	vrb2_fcw_mldts_fill(op, fcw);
+	fcw->Crep = 0; /* C rep forced to zero. */
+
+	/* Prevent out of range access. */
+	if (op->mldts.r_rep > 5)
+		op->mldts.r_rep = 5;
+	if (op->mldts.num_layers < 2)
+		op->mldts.num_layers = 2;
+	if (op->mldts.num_layers > 4)
+		op->mldts.num_layers = 4;
+
+	for (i = 0; i < op->mldts.num_layers; i++)
+		outsize_per_re += op->mldts.q_m[i];
+	sc_num = op->mldts.num_rbs * RTE_BBDEV_SCPERRB; /* C rep forced to zero. */
+	r_num = op->mldts.num_rbs * sc_factor_per_rrep[op->mldts.r_rep];
+	q_size = qsize_per_re[op->mldts.num_layers - 2] * sc_num;
+	r_size = rsize_per_re[op->mldts.num_layers - 2] * r_num;
+	out_size =  sc_num * outsize_per_re;
+
+	for (symb = 0; symb < num_syms; symb++) {
+		desc_idx = ((q->sw_ring_head + total_enqueued_descs + symb) & q->sw_ring_wrap_mask);
+		desc = q->ring_addr + desc_idx;
+		acc_header_init(&desc->req);
+		if (symb == 0)
+			desc->req.cbs_in_tb = num_syms;
+		else
+			rte_memcpy(&desc->req.fcw_mldts, fcw, ACC_FCW_MLDTS_BLEN);
+		desc->req.data_ptrs[1].address = rte_pktmbuf_iova_offset(input_q, in_offset);
+		desc->req.data_ptrs[1].blen = q_size;
+		in_offset += q_size;
+		desc->req.data_ptrs[1].blkid = ACC_DMA_BLKID_IN;
+		desc->req.data_ptrs[1].last = 0;
+		desc->req.data_ptrs[1].dma_ext = 0;
+		desc->req.data_ptrs[2].address = rte_pktmbuf_iova_offset(input_r, 0);
+		desc->req.data_ptrs[2].blen = r_size;
+		desc->req.data_ptrs[2].blkid = ACC_DMA_BLKID_IN_MLD_R;
+		desc->req.data_ptrs[2].last = 1;
+		desc->req.data_ptrs[2].dma_ext = 0;
+		desc->req.data_ptrs[3].address = rte_pktmbuf_iova_offset(output, out_offset);
+		desc->req.data_ptrs[3].blen = out_size;
+		out_offset += out_size;
+		desc->req.data_ptrs[3].blkid = ACC_DMA_BLKID_OUT_HARD;
+		desc->req.data_ptrs[3].last = 1;
+		desc->req.data_ptrs[3].dma_ext = 0;
+		desc->req.m2dlen = VRB2_MLD_M2DLEN;
+		desc->req.d2mlen = 1;
+		desc->req.op_addr = op;
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+		acc_memdump("FCW", &desc->req.fcw_mldts, sizeof(desc->req.fcw_mldts));
+		acc_memdump("Req Desc.", desc, sizeof(*desc));
+#endif
+	}
+	desc->req.sdone_enable = 0;
+
+	return num_syms;
+}
+
+/** Enqueue one MLDTS operation. */
+static inline int
+enqueue_mldts_one_op(struct acc_queue *q, struct rte_bbdev_mldts_op *op,
+		uint16_t total_enqueued_descs)
+{
+	union acc_dma_desc *desc;
+	uint16_t desc_idx;
+	struct rte_mbuf *input_q, *input_r, *output;
+	uint32_t in_offset, out_offset;
+	struct acc_fcw_mldts *fcw;
+
+	desc_idx = ((q->sw_ring_head + total_enqueued_descs) & q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	input_q = op->mldts.qhy_input.data;
+	input_r = op->mldts.r_input.data;
+	output = op->mldts.output.data;
+	in_offset = op->mldts.qhy_input.offset;
+	out_offset = op->mldts.output.offset;
+	fcw = &desc->req.fcw_mldts;
+	vrb2_fcw_mldts_fill(op, fcw);
+	vrb2_dma_desc_mldts_fill(op, &desc->req, input_q, input_r, output,
+			&in_offset, &out_offset);
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	acc_memdump("FCW", &desc->req.fcw_mldts, sizeof(desc->req.fcw_mldts));
+	acc_memdump("Req Desc.", desc, sizeof(*desc));
+#endif
+	return 1;
+}
+
+/* Enqueue MLDTS operations. */
+static uint16_t
+vrb2_enqueue_mldts(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_mldts_op **ops, uint16_t num)
+{
+	int32_t aq_avail, avail;
+	struct acc_queue *q = q_data->queue_private;
+	uint16_t i, enqueued_descs = 0, descs_in_op;
+	int ret;
+	bool as_one_op;
+
+	aq_avail = acc_aq_avail(q_data, num);
+	if (unlikely((aq_avail <= 0) || (num == 0)))
+		return 0;
+	avail = acc_ring_avail_enq(q);
+
+	for (i = 0; i < num; ++i) {
+		as_one_op = vrb2_check_mld_r_constraint(ops[i]);
+		descs_in_op = as_one_op ? 1 : ops[i]->mldts.c_rep + 1;
+
+		/* Check if there are available space for further processing. */
+		if (unlikely(avail < descs_in_op)) {
+			acc_enqueue_ring_full(q_data);
+			break;
+		}
+		avail -= descs_in_op;
+
+		if (as_one_op)
+			ret = enqueue_mldts_one_op(q, ops[i], enqueued_descs);
+		else
+			ret = enqueue_mldts_split_op(q, ops[i], enqueued_descs);
+
+		if (ret < 0) {
+			acc_enqueue_invalid(q_data);
+			break;
+		}
+
+		enqueued_descs += ret;
+	}
+
+	if (unlikely(i == 0))
+		return 0; /* Nothing to enqueue. */
+
+	acc_dma_enqueue(q, enqueued_descs, &q_data->queue_stats);
+
+	/* Update stats. */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+	return i;
+}
+
+/*
+ * Dequeue one MLDTS operation.
+ * This may have been split over multiple descriptors.
+ */
+static inline int
+dequeue_mldts_one_op(struct rte_bbdev_queue_data *q_data,
+		struct acc_queue *q, struct rte_bbdev_mldts_op **ref_op,
+		uint16_t dequeued_ops, uint32_t *aq_dequeued)
+{
+	union acc_dma_desc *desc, atom_desc, *last_desc;
+	union acc_dma_rsp_desc rsp;
+	struct rte_bbdev_mldts_op *op;
+	uint8_t descs_in_op, i;
+
+	desc = acc_desc_tail(q, dequeued_ops);
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc, __ATOMIC_RELAXED);
+
+	/* Check fdone bit. */
+	if (!(atom_desc.rsp.val & ACC_FDONE))
+		return -1;
+
+	descs_in_op = desc->req.cbs_in_tb;
+	if (descs_in_op > 1) {
+		/* Get last CB. */
+		last_desc = q->ring_addr + ((q->sw_ring_tail + dequeued_ops + descs_in_op - 1)
+				& q->sw_ring_wrap_mask);
+		/* Check if last op is ready to dequeue by checking fdone bit. If not exit. */
+		atom_desc.atom_hdr = __atomic_load_n((uint64_t *)last_desc, __ATOMIC_RELAXED);
+		if (!(atom_desc.rsp.val & ACC_FDONE))
+			return -1;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+		acc_memdump("Last Resp", &last_desc->rsp.val, sizeof(desc->rsp.val));
+#endif
+		/* Check each operation iteratively using fdone. */
+		for (i = 1; i < descs_in_op - 1; i++) {
+			last_desc = q->ring_addr + ((q->sw_ring_tail + dequeued_ops + i)
+					& q->sw_ring_wrap_mask);
+			atom_desc.atom_hdr = __atomic_load_n((uint64_t *)last_desc,
+					__ATOMIC_RELAXED);
+			if (!(atom_desc.rsp.val & ACC_FDONE))
+				return -1;
+		}
+	}
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	acc_memdump("Resp", &desc->rsp.val, sizeof(desc->rsp.val));
+#endif
+	/* Dequeue. */
+	op = desc->req.op_addr;
+
+	/* Clearing status, it will be set based on response. */
+	op->status = 0;
+
+	for (i = 0; i < descs_in_op; i++) {
+		desc = q->ring_addr + ((q->sw_ring_tail + dequeued_ops + i) & q->sw_ring_wrap_mask);
+		atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc, __ATOMIC_RELAXED);
+		rsp.val = atom_desc.rsp.val;
+		op->status |= rsp.input_err << RTE_BBDEV_DATA_ERROR;
+		op->status |= rsp.dma_err << RTE_BBDEV_DRV_ERROR;
+		op->status |= rsp.fcw_err << RTE_BBDEV_DRV_ERROR;
+		op->status |= rsp.engine_hung << RTE_BBDEV_ENGINE_ERROR;
+	}
+
+	if (op->status != 0)
+		q_data->queue_stats.dequeue_err_count++;
+	if (op->status & (1 << RTE_BBDEV_DRV_ERROR))
+		vrb_check_ir(q->d);
+
+	/* Check if this is the last desc in batch (Atomic Queue). */
+	if (desc->req.last_desc_in_batch) {
+		(*aq_dequeued)++;
+		desc->req.last_desc_in_batch = 0;
+	}
+	desc->rsp.val = ACC_DMA_DESC_TYPE;
+	desc->rsp.add_info_0 = 0;
+	*ref_op = op;
+
+	return descs_in_op;
+}
+
+/* Dequeue MLDTS operations from VRB2 device. */
+static uint16_t
+vrb2_dequeue_mldts(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_mldts_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	uint16_t dequeue_num, i, dequeued_cbs = 0;
+	uint32_t avail = acc_ring_avail_deq(q);
+	uint32_t aq_dequeued = 0;
+	int ret;
+
+	dequeue_num = RTE_MIN(avail, num);
+
+	for (i = 0; i < dequeue_num; ++i) {
+		ret = dequeue_mldts_one_op(q_data, q, &ops[i], dequeued_cbs, &aq_dequeued);
+		if (ret <= 0)
+			break;
+		dequeued_cbs += ret;
+	}
+
+	q->aq_dequeued += aq_dequeued;
+	q->sw_ring_tail += dequeued_cbs;
+	/* Update enqueue stats. */
+	q_data->queue_stats.dequeued_count += i;
+	return i;
+}
+
 /* Initialization Function */
 static void
 vrb_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
@@ -3417,6 +4570,8 @@  vrb_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
 	dev->dequeue_ldpc_dec_ops = vrb_dequeue_ldpc_dec;
 	dev->enqueue_fft_ops = vrb_enqueue_fft;
 	dev->dequeue_fft_ops = vrb_dequeue_fft;
+	dev->enqueue_mldts_ops = vrb2_enqueue_mldts;
+	dev->dequeue_mldts_ops = vrb2_dequeue_mldts;
 
 	d->pf_device = !strcmp(drv->driver.name, RTE_STR(VRB_PF_DRIVER_NAME));
 	d->mmio_base = pci_dev->mem_resource[0].addr;
@@ -3433,6 +4588,16 @@  vrb_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
 			d->reg_addr = &vrb1_pf_reg_addr;
 		else
 			d->reg_addr = &vrb1_vf_reg_addr;
+	} else {
+		d->device_variant = VRB2_VARIANT;
+		d->queue_offset = vrb2_queue_offset;
+		d->fcw_ld_fill = vrb2_fcw_ld_fill;
+		d->num_qgroups = VRB2_NUM_QGRPS;
+		d->num_aqs = VRB2_NUM_AQS;
+		if (d->pf_device)
+			d->reg_addr = &vrb2_pf_reg_addr;
+		else
+			d->reg_addr = &vrb2_vf_reg_addr;
 	}
 
 	rte_bbdev_log_debug("Init device %s [%s] @ vaddr %p paddr %#"PRIx64"",
diff --git a/drivers/baseband/acc/vrb1_pf_enum.h b/drivers/baseband/acc/vrb1_pf_enum.h
index 82a36685e9..6dc359800f 100644
--- a/drivers/baseband/acc/vrb1_pf_enum.h
+++ b/drivers/baseband/acc/vrb1_pf_enum.h
@@ -98,11 +98,18 @@  enum {
 	ACC_PF_INT_DMA_UL5G_DESC_IRQ = 8,
 	ACC_PF_INT_DMA_DL5G_DESC_IRQ = 9,
 	ACC_PF_INT_DMA_MLD_DESC_IRQ = 10,
-	ACC_PF_INT_ARAM_ECC_1BIT_ERR = 11,
-	ACC_PF_INT_PARITY_ERR = 12,
-	ACC_PF_INT_QMGR_ERR = 13,
-	ACC_PF_INT_INT_REQ_OVERFLOW = 14,
-	ACC_PF_INT_APB_TIMEOUT = 15,
+	ACC_PF_INT_ARAM_ACCESS_ERR = 11,
+	ACC_PF_INT_ARAM_ECC_1BIT_ERR = 12,
+	ACC_PF_INT_PARITY_ERR = 13,
+	ACC_PF_INT_QMGR_OVERFLOW = 14,
+	ACC_PF_INT_QMGR_ERR = 15,
+	ACC_PF_INT_ATS_ERR = 22,
+	ACC_PF_INT_ARAM_FUUL = 23,
+	ACC_PF_INT_EXTRA_READ = 24,
+	ACC_PF_INT_COMPLETION_TIMEOUT = 25,
+	ACC_PF_INT_CORE_HANG = 26,
+	ACC_PF_INT_DMA_HANG = 28,
+	ACC_PF_INT_DS_HANG = 27,
 };
 
 #endif /* VRB1_PF_ENUM_H */
diff --git a/drivers/baseband/acc/vrb2_pf_enum.h b/drivers/baseband/acc/vrb2_pf_enum.h
new file mode 100644
index 0000000000..e2801e2d7d
--- /dev/null
+++ b/drivers/baseband/acc/vrb2_pf_enum.h
@@ -0,0 +1,124 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#ifndef VRB2_PF_ENUM_H
+#define VRB2_PF_ENUM_H
+
+/*
+ * VRB2 Register mapping on PF BAR0
+ * This is automatically generated from RDL, format may change with new RDL
+ * Release.
+ * Variable names are as is
+ */
+enum {
+	VRB2_PfQmgrEgressQueuesTemplate             = 0x0007FC00,
+	VRB2_PfQmgrIngressAq                        = 0x00100000,
+	VRB2_PfQmgrSoftReset                        = 0x00A00034,
+	VRB2_PfQmgrAramAllocEn	              = 0x00A000a0,
+	VRB2_PfQmgrAramAllocSetupN0                 = 0x00A000b0,
+	VRB2_PfQmgrAramAllocSetupN1                 = 0x00A000b4,
+	VRB2_PfQmgrAramAllocSetupN2                 = 0x00A000b8,
+	VRB2_PfQmgrAramAllocSetupN3                 = 0x00A000bc,
+	VRB2_PfQmgrDepthLog2Grp                     = 0x00A00200,
+	VRB2_PfQmgrTholdGrp                         = 0x00A00300,
+	VRB2_PfQmgrGrpTmplateReg0Indx               = 0x00A00600,
+	VRB2_PfQmgrGrpTmplateReg1Indx               = 0x00A00700,
+	VRB2_PfQmgrGrpTmplateReg2Indx               = 0x00A00800,
+	VRB2_PfQmgrGrpTmplateReg3Indx               = 0x00A00900,
+	VRB2_PfQmgrGrpTmplateReg4Indx               = 0x00A00A00,
+	VRB2_PfQmgrGrpTmplateReg5Indx               = 0x00A00B00,
+	VRB2_PfQmgrGrpTmplateReg6Indx               = 0x00A00C00,
+	VRB2_PfQmgrGrpTmplateReg7Indx               = 0x00A00D00,
+	VRB2_PfQmgrGrpTmplateEnRegIndx              = 0x00A00E00,
+	VRB2_PfQmgrArbQDepthGrp                     = 0x00A02F00,
+	VRB2_PfQmgrGrpFunction0                     = 0x00A02F80,
+	VRB2_PfQmgrGrpPriority                      = 0x00A02FC0,
+	VRB2_PfQmgrVfBaseAddr                       = 0x00A08000,
+	VRB2_PfQmgrAqEnableVf                       = 0x00A10000,
+	VRB2_PfQmgrRingSizeVf                       = 0x00A20010,
+	VRB2_PfQmgrGrpDepthLog20Vf                  = 0x00A20020,
+	VRB2_PfQmgrGrpDepthLog21Vf                  = 0x00A20024,
+	VRB2_PfFabricM2iBufferReg                   = 0x00B30000,
+	VRB2_PfFecUl5gIbDebug0Reg                   = 0x00B401FC,
+	VRB2_PfFftConfig0                           = 0x00B58004,
+	VRB2_PfFftParityMask8                       = 0x00B5803C,
+	VRB2_PfDmaConfig0Reg                        = 0x00B80000,
+	VRB2_PfDmaConfig1Reg                        = 0x00B80004,
+	VRB2_PfDmaQmgrAddrReg                       = 0x00B80008,
+	VRB2_PfDmaAxcacheReg                        = 0x00B80010,
+	VRB2_PfDmaAxiControl                        = 0x00B8002C,
+	VRB2_PfDmaQmanen                            = 0x00B80040,
+	VRB2_PfDmaQmanenSelect                      = 0x00B80044,
+	VRB2_PfDmaCfgRrespBresp                     = 0x00B80814,
+	VRB2_PfDmaDescriptorSignature               = 0x00B80868,
+	VRB2_PfDmaErrorDetectionEn                  = 0x00B80870,
+	VRB2_PfDmaFec5GulDescBaseLoRegVf            = 0x00B88020,
+	VRB2_PfDmaFec5GulDescBaseHiRegVf            = 0x00B88024,
+	VRB2_PfDmaFec5GulRespPtrLoRegVf             = 0x00B88028,
+	VRB2_PfDmaFec5GulRespPtrHiRegVf             = 0x00B8802C,
+	VRB2_PfDmaFec5GdlDescBaseLoRegVf            = 0x00B88040,
+	VRB2_PfDmaFec5GdlDescBaseHiRegVf            = 0x00B88044,
+	VRB2_PfDmaFec5GdlRespPtrLoRegVf             = 0x00B88048,
+	VRB2_PfDmaFec5GdlRespPtrHiRegVf             = 0x00B8804C,
+	VRB2_PfDmaFec4GulDescBaseLoRegVf            = 0x00B88060,
+	VRB2_PfDmaFec4GulDescBaseHiRegVf            = 0x00B88064,
+	VRB2_PfDmaFec4GulRespPtrLoRegVf             = 0x00B88068,
+	VRB2_PfDmaFec4GulRespPtrHiRegVf             = 0x00B8806C,
+	VRB2_PfDmaFec4GdlDescBaseLoRegVf            = 0x00B88080,
+	VRB2_PfDmaFec4GdlDescBaseHiRegVf            = 0x00B88084,
+	VRB2_PfDmaFec4GdlRespPtrLoRegVf             = 0x00B88088,
+	VRB2_PfDmaFec4GdlRespPtrHiRegVf             = 0x00B8808C,
+	VRB2_PfDmaFftDescBaseLoRegVf                = 0x00B880A0,
+	VRB2_PfDmaFftDescBaseHiRegVf                = 0x00B880A4,
+	VRB2_PfDmaFftRespPtrLoRegVf                 = 0x00B880A8,
+	VRB2_PfDmaFftRespPtrHiRegVf                 = 0x00B880AC,
+	VRB2_PfDmaMldDescBaseLoRegVf                = 0x00B880C0,
+	VRB2_PfDmaMldDescBaseHiRegVf                = 0x00B880C4,
+	VRB2_PfQosmonAEvalOverflow0                 = 0x00B90008,
+	VRB2_PfPermonACntrlRegVf                    = 0x00B98000,
+	VRB2_PfQosmonBEvalOverflow0                 = 0x00BA0008,
+	VRB2_PfPermonBCntrlRegVf                    = 0x00BA8000,
+	VRB2_PfPermonCCntrlRegVf                    = 0x00BB8000,
+	VRB2_PfHiInfoRingBaseLoRegPf                = 0x00C84014,
+	VRB2_PfHiInfoRingBaseHiRegPf                = 0x00C84018,
+	VRB2_PfHiInfoRingPointerRegPf               = 0x00C8401C,
+	VRB2_PfHiInfoRingIntWrEnRegPf               = 0x00C84020,
+	VRB2_PfHiBlockTransmitOnErrorEn             = 0x00C84038,
+	VRB2_PfHiCfgMsiIntWrEnRegPf                 = 0x00C84040,
+	VRB2_PfHiMsixVectorMapperPf                 = 0x00C84060,
+	VRB2_PfHiPfMode                             = 0x00C84108,
+	VRB2_PfHiClkGateHystReg                     = 0x00C8410C,
+	VRB2_PfHiMsiDropEnableReg                   = 0x00C84114,
+	VRB2_PfHiSectionPowerGatingReq              = 0x00C84128,
+	VRB2_PfHiSectionPowerGatingAck              = 0x00C8412C,
+};
+
+/* TIP PF Interrupt numbers */
+enum {
+	VRB2_PF_INT_QMGR_AQ_OVERFLOW = 0,
+	VRB2_PF_INT_DOORBELL_VF_2_PF = 1,
+	VRB2_PF_INT_ILLEGAL_FORMAT = 2,
+	VRB2_PF_INT_QMGR_DISABLED_ACCESS = 3,
+	VRB2_PF_INT_QMGR_AQ_OVERTHRESHOLD = 4,
+	VRB2_PF_INT_DMA_DL_DESC_IRQ = 5,
+	VRB2_PF_INT_DMA_UL_DESC_IRQ = 6,
+	VRB2_PF_INT_DMA_FFT_DESC_IRQ = 7,
+	VRB2_PF_INT_DMA_UL5G_DESC_IRQ = 8,
+	VRB2_PF_INT_DMA_DL5G_DESC_IRQ = 9,
+	VRB2_PF_INT_DMA_MLD_DESC_IRQ = 10,
+	VRB2_PF_INT_ARAM_ACCESS_ERR = 11,
+	VRB2_PF_INT_ARAM_ECC_1BIT_ERR = 12,
+	VRB2_PF_INT_PARITY_ERR = 13,
+	VRB2_PF_INT_QMGR_OVERFLOW = 14,
+	VRB2_PF_INT_QMGR_ERR = 15,
+	VRB2_PF_INT_ATS_ERR = 22,
+	VRB2_PF_INT_ARAM_FUUL = 23,
+	VRB2_PF_INT_EXTRA_READ = 24,
+	VRB2_PF_INT_COMPLETION_TIMEOUT = 25,
+	VRB2_PF_INT_CORE_HANG = 26,
+	VRB2_PF_INT_DMA_HANG = 28,
+	VRB2_PF_INT_DS_HANG = 27,
+};
+
+#endif /* VRB2_PF_ENUM_H */
diff --git a/drivers/baseband/acc/vrb2_vf_enum.h b/drivers/baseband/acc/vrb2_vf_enum.h
new file mode 100644
index 0000000000..69debc9116
--- /dev/null
+++ b/drivers/baseband/acc/vrb2_vf_enum.h
@@ -0,0 +1,121 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#ifndef VRB2_VF_ENUM_H
+#define VRB2_VF_ENUM_H
+
+/*
+ * VRB2 Register mapping on VF BAR0
+ * This is automatically generated from RDL, format may change with new RDL
+ */
+enum {
+	VRB2_VfHiVfToPfDbellVf           = 0x00000000,
+	VRB2_VfHiPfToVfDbellVf           = 0x00000008,
+	VRB2_VfHiInfoRingBaseLoVf        = 0x00000010,
+	VRB2_VfHiInfoRingBaseHiVf        = 0x00000014,
+	VRB2_VfHiInfoRingPointerVf       = 0x00000018,
+	VRB2_VfHiInfoRingIntWrEnVf       = 0x00000020,
+	VRB2_VfHiInfoRingPf2VfWrEnVf     = 0x00000024,
+	VRB2_VfHiMsixVectorMapperVf      = 0x00000060,
+	VRB2_VfHiDeviceStatus            = 0x00000068,
+	VRB2_VfHiInterruptSrc            = 0x00000070,
+	VRB2_VfDmaFec5GulDescBaseLoRegVf = 0x00000120,
+	VRB2_VfDmaFec5GulDescBaseHiRegVf = 0x00000124,
+	VRB2_VfDmaFec5GulRespPtrLoRegVf  = 0x00000128,
+	VRB2_VfDmaFec5GulRespPtrHiRegVf  = 0x0000012C,
+	VRB2_VfDmaFec5GdlDescBaseLoRegVf = 0x00000140,
+	VRB2_VfDmaFec5GdlDescBaseHiRegVf = 0x00000144,
+	VRB2_VfDmaFec5GdlRespPtrLoRegVf  = 0x00000148,
+	VRB2_VfDmaFec5GdlRespPtrHiRegVf  = 0x0000014C,
+	VRB2_VfDmaFec4GulDescBaseLoRegVf = 0x00000160,
+	VRB2_VfDmaFec4GulDescBaseHiRegVf = 0x00000164,
+	VRB2_VfDmaFec4GulRespPtrLoRegVf  = 0x00000168,
+	VRB2_VfDmaFec4GulRespPtrHiRegVf  = 0x0000016C,
+	VRB2_VfDmaFec4GdlDescBaseLoRegVf = 0x00000180,
+	VRB2_VfDmaFec4GdlDescBaseHiRegVf = 0x00000184,
+	VRB2_VfDmaFec4GdlRespPtrLoRegVf  = 0x00000188,
+	VRB2_VfDmaFec4GdlRespPtrHiRegVf  = 0x0000018C,
+	VRB2_VfDmaFftDescBaseLoRegVf     = 0x000001A0,
+	VRB2_VfDmaFftDescBaseHiRegVf     = 0x000001A4,
+	VRB2_VfDmaFftRespPtrLoRegVf      = 0x000001A8,
+	VRB2_VfDmaFftRespPtrHiRegVf      = 0x000001AC,
+	VRB2_VfDmaMldDescBaseLoRegVf     = 0x000001C0,
+	VRB2_VfDmaMldDescBaseHiRegVf     = 0x000001C4,
+	VRB2_VfDmaMldRespPtrLoRegVf      = 0x000001C8,
+	VRB2_VfDmaMldRespPtrHiRegVf      = 0x000001CC,
+	VRB2_VfPmACntrlRegVf             = 0x00000200,
+	VRB2_VfPmACountVf                = 0x00000208,
+	VRB2_VfPmAKCntLoVf               = 0x00000210,
+	VRB2_VfPmAKCntHiVf               = 0x00000214,
+	VRB2_VfPmADeltaCntLoVf           = 0x00000220,
+	VRB2_VfPmADeltaCntHiVf           = 0x00000224,
+	VRB2_VfPmBCntrlRegVf             = 0x00000240,
+	VRB2_VfPmBCountVf                = 0x00000248,
+	VRB2_VfPmBKCntLoVf               = 0x00000250,
+	VRB2_VfPmBKCntHiVf               = 0x00000254,
+	VRB2_VfPmBDeltaCntLoVf           = 0x00000260,
+	VRB2_VfPmBDeltaCntHiVf           = 0x00000264,
+	VRB2_VfPmCCntrlRegVf             = 0x00000280,
+	VRB2_VfPmCCountVf                = 0x00000288,
+	VRB2_VfPmCKCntLoVf               = 0x00000290,
+	VRB2_VfPmCKCntHiVf               = 0x00000294,
+	VRB2_VfPmCDeltaCntLoVf           = 0x000002A0,
+	VRB2_VfPmCDeltaCntHiVf           = 0x000002A4,
+	VRB2_VfPmDCntrlRegVf             = 0x000002C0,
+	VRB2_VfPmDCountVf                = 0x000002C8,
+	VRB2_VfPmDKCntLoVf               = 0x000002D0,
+	VRB2_VfPmDKCntHiVf               = 0x000002D4,
+	VRB2_VfPmDDeltaCntLoVf           = 0x000002E0,
+	VRB2_VfPmDDeltaCntHiVf           = 0x000002E4,
+	VRB2_VfPmECntrlRegVf             = 0x00000300,
+	VRB2_VfPmECountVf                = 0x00000308,
+	VRB2_VfPmEKCntLoVf               = 0x00000310,
+	VRB2_VfPmEKCntHiVf               = 0x00000314,
+	VRB2_VfPmEDeltaCntLoVf           = 0x00000320,
+	VRB2_VfPmEDeltaCntHiVf           = 0x00000324,
+	VRB2_VfPmFCntrlRegVf             = 0x00000340,
+	VRB2_VfPmFCountVf                = 0x00000348,
+	VRB2_VfPmFKCntLoVf               = 0x00000350,
+	VRB2_VfPmFKCntHiVf               = 0x00000354,
+	VRB2_VfPmFDeltaCntLoVf           = 0x00000360,
+	VRB2_VfPmFDeltaCntHiVf           = 0x00000364,
+	VRB2_VfQmgrAqReset0              = 0x00000600,
+	VRB2_VfQmgrAqReset1              = 0x00000604,
+	VRB2_VfQmgrAqReset2              = 0x00000608,
+	VRB2_VfQmgrAqReset3              = 0x0000060C,
+	VRB2_VfQmgrRingSizeVf            = 0x00000610,
+	VRB2_VfQmgrGrpDepthLog20Vf       = 0x00000620,
+	VRB2_VfQmgrGrpDepthLog21Vf       = 0x00000624,
+	VRB2_VfQmgrGrpDepthLog22Vf       = 0x00000628,
+	VRB2_VfQmgrGrpDepthLog23Vf       = 0x0000062C,
+	VRB2_VfQmgrGrpFunction0Vf        = 0x00000630,
+	VRB2_VfQmgrGrpFunction1Vf        = 0x00000634,
+	VRB2_VfQmgrAramUsageN0           = 0x00000640,
+	VRB2_VfQmgrAramUsageN1           = 0x00000644,
+	VRB2_VfQmgrAramUsageN2           = 0x00000648,
+	VRB2_VfQmgrAramUsageN3           = 0x0000064C,
+	VRB2_VfHiMSIXBaseLoRegVf         = 0x00001000,
+	VRB2_VfHiMSIXBaseHiRegVf         = 0x00001004,
+	VRB2_VfHiMSIXBaseDataRegVf       = 0x00001008,
+	VRB2_VfHiMSIXBaseMaskRegVf       = 0x0000100C,
+	VRB2_VfHiMSIXPBABaseLoRegVf      = 0x00003000,
+	VRB2_VfQmgrIngressAq             = 0x00004000,
+};
+
+/* TIP VF Interrupt numbers */
+enum {
+	VRB2_VF_INT_QMGR_AQ_OVERFLOW = 0,
+	VRB2_VF_INT_DOORBELL_PF_2_VF = 1,
+	VRB2_VF_INT_ILLEGAL_FORMAT = 2,
+	VRB2_VF_INT_QMGR_DISABLED_ACCESS = 3,
+	VRB2_VF_INT_QMGR_AQ_OVERTHRESHOLD = 4,
+	VRB2_VF_INT_DMA_DL_DESC_IRQ = 5,
+	VRB2_VF_INT_DMA_UL_DESC_IRQ = 6,
+	VRB2_VF_INT_DMA_FFT_DESC_IRQ = 7,
+	VRB2_VF_INT_DMA_UL5G_DESC_IRQ = 8,
+	VRB2_VF_INT_DMA_DL5G_DESC_IRQ = 9,
+	VRB2_VF_INT_DMA_MLD_DESC_IRQ = 10,
+};
+
+#endif /* VRB2_VF_ENUM_H */
diff --git a/drivers/baseband/acc/vrb_pmd.h b/drivers/baseband/acc/vrb_pmd.h
index 1cabc0b7f4..def8ceaf93 100644
--- a/drivers/baseband/acc/vrb_pmd.h
+++ b/drivers/baseband/acc/vrb_pmd.h
@@ -8,6 +8,8 @@ 
 #include "acc_common.h"
 #include "vrb1_pf_enum.h"
 #include "vrb1_vf_enum.h"
+#include "vrb2_pf_enum.h"
+#include "vrb2_vf_enum.h"
 #include "vrb_cfg.h"
 
 /* Helper macro for logging */
@@ -31,12 +33,13 @@ 
 #define RTE_VRB1_VENDOR_ID           (0x8086)
 #define RTE_VRB1_PF_DEVICE_ID        (0x57C0)
 #define RTE_VRB1_VF_DEVICE_ID        (0x57C1)
-
-#define VRB1_VARIANT               2
+#define RTE_VRB2_VENDOR_ID           (0x8086)
+#define RTE_VRB2_PF_DEVICE_ID        (0x57C2)
+#define RTE_VRB2_VF_DEVICE_ID        (0x57C3)
 
 #define VRB_NUM_ACCS                 6
 #define VRB_MAX_QGRPS                32
-#define VRB_MAX_AQS                  32
+#define VRB_MAX_AQS                  64
 
 #define ACC_STATUS_WAIT      10
 #define ACC_STATUS_TO        100
@@ -61,7 +64,6 @@ 
 #define VRB1_SIG_DL_4G_LAST 23
 #define VRB1_SIG_FFT        24
 #define VRB1_SIG_FFT_LAST   24
-
 #define VRB1_NUM_ACCS       5
 
 /* VRB1 Configuration */
@@ -90,6 +92,69 @@ 
 #define VRB1_MAX_PF_MSIX            (256+32)
 #define VRB1_MAX_VF_MSIX            (256+7)
 
+/* VRB2 specific flags */
+
+#define VRB2_NUM_VFS        64
+#define VRB2_NUM_QGRPS      32
+#define VRB2_NUM_AQS        64
+#define VRB2_GRP_ID_SHIFT    12 /* Queue Index Hierarchy */
+#define VRB2_VF_ID_SHIFT     6  /* Queue Index Hierarchy */
+#define VRB2_WORDS_IN_ARAM_SIZE (512 * 1024 / 4)
+#define VRB2_NUM_ACCS        6
+#define VRB2_AQ_REG_NUM      4
+
+/* VRB2 Mapping of signals for the available engines */
+#define VRB2_SIG_UL_5G       0
+#define VRB2_SIG_UL_5G_LAST  5
+#define VRB2_SIG_DL_5G       9
+#define VRB2_SIG_DL_5G_LAST 11
+#define VRB2_SIG_UL_4G      12
+#define VRB2_SIG_UL_4G_LAST 16
+#define VRB2_SIG_DL_4G      21
+#define VRB2_SIG_DL_4G_LAST 23
+#define VRB2_SIG_FFT        24
+#define VRB2_SIG_FFT_LAST   26
+#define VRB2_SIG_MLD        30
+#define VRB2_SIG_MLD_LAST   31
+#define VRB2_FFT_NUM        3
+
+#define VRB2_FCW_MLDTS_BLEN 32
+#define VRB2_MLD_MIN_LAYER   2
+#define VRB2_MLD_MAX_LAYER   4
+#define VRB2_MLD_MAX_RREP    5
+#define VRB2_MLD_LAY_SIZE    3
+#define VRB2_MLD_RREP_SIZE   6
+#define VRB2_MLD_M2DLEN      3
+
+#define VRB2_MAX_PF_MSIX      (256+32)
+#define VRB2_MAX_VF_MSIX      (64+7)
+#define VRB2_REG_IRQ_EN_ALL   0xFFFFFFFF  /* Enable all interrupts */
+#define VRB2_FABRIC_MODE      0x8000103
+#define VRB2_CFG_DMA_ERROR    0x7DF
+#define VRB2_CFG_AXI_CACHE    0x11
+#define VRB2_CFG_QMGR_HI_P    0x0F0F
+#define VRB2_RESET_HARD       0x1FF
+#define VRB2_ENGINES_MAX      9
+#define VRB2_GPEX_AXIMAP_NUM  17
+#define VRB2_CLOCK_GATING_EN  0x30000
+#define VRB2_FFT_CFG_0        0x2001
+#define VRB2_FFT_ECC          0x60
+#define VRB2_FFT_RAM_EN       0x80008000
+#define VRB2_FFT_RAM_DIS      0x0
+#define VRB2_FFT_RAM_SIZE     512
+#define VRB2_CLK_EN           0x00010A01
+#define VRB2_CLK_DIS          0x01F10A01
+#define VRB2_PG_MASK_0        0x1F
+#define VRB2_PG_MASK_1        0xF
+#define VRB2_PG_MASK_2        0x1
+#define VRB2_PG_MASK_3        0x0
+#define VRB2_PG_MASK_FFT      1
+#define VRB2_PG_MASK_4GUL     4
+#define VRB2_PG_MASK_5GUL     8
+#define VRB2_PF_PM_REG_OFFSET 0x10000
+#define VRB2_VF_PM_REG_OFFSET 0x40
+#define VRB2_PM_START         0x2
+
 struct acc_registry_addr {
 	unsigned int dma_ring_dl5g_hi;
 	unsigned int dma_ring_dl5g_lo;
@@ -218,4 +283,92 @@  static const struct acc_registry_addr vrb1_vf_reg_addr = {
 	.pf2vf_doorbell = VRB1_VfHiPfToVfDbellVf,
 };
 
+
+/* Structure holding registry addresses for PF */
+static const struct acc_registry_addr vrb2_pf_reg_addr = {
+	.dma_ring_dl5g_hi =  VRB2_PfDmaFec5GdlDescBaseHiRegVf,
+	.dma_ring_dl5g_lo =  VRB2_PfDmaFec5GdlDescBaseLoRegVf,
+	.dma_ring_ul5g_hi =  VRB2_PfDmaFec5GulDescBaseHiRegVf,
+	.dma_ring_ul5g_lo =  VRB2_PfDmaFec5GulDescBaseLoRegVf,
+	.dma_ring_dl4g_hi =  VRB2_PfDmaFec4GdlDescBaseHiRegVf,
+	.dma_ring_dl4g_lo =  VRB2_PfDmaFec4GdlDescBaseLoRegVf,
+	.dma_ring_ul4g_hi =  VRB2_PfDmaFec4GulDescBaseHiRegVf,
+	.dma_ring_ul4g_lo =  VRB2_PfDmaFec4GulDescBaseLoRegVf,
+	.dma_ring_fft_hi =   VRB2_PfDmaFftDescBaseHiRegVf,
+	.dma_ring_fft_lo =   VRB2_PfDmaFftDescBaseLoRegVf,
+	.dma_ring_mld_hi =   VRB2_PfDmaMldDescBaseHiRegVf,
+	.dma_ring_mld_lo =   VRB2_PfDmaMldDescBaseLoRegVf,
+	.ring_size =         VRB2_PfQmgrRingSizeVf,
+	.info_ring_hi =      VRB2_PfHiInfoRingBaseHiRegPf,
+	.info_ring_lo =      VRB2_PfHiInfoRingBaseLoRegPf,
+	.info_ring_en =      VRB2_PfHiInfoRingIntWrEnRegPf,
+	.info_ring_ptr =     VRB2_PfHiInfoRingPointerRegPf,
+	.tail_ptrs_dl5g_hi = VRB2_PfDmaFec5GdlRespPtrHiRegVf,
+	.tail_ptrs_dl5g_lo = VRB2_PfDmaFec5GdlRespPtrLoRegVf,
+	.tail_ptrs_ul5g_hi = VRB2_PfDmaFec5GulRespPtrHiRegVf,
+	.tail_ptrs_ul5g_lo = VRB2_PfDmaFec5GulRespPtrLoRegVf,
+	.tail_ptrs_dl4g_hi = VRB2_PfDmaFec4GdlRespPtrHiRegVf,
+	.tail_ptrs_dl4g_lo = VRB2_PfDmaFec4GdlRespPtrLoRegVf,
+	.tail_ptrs_ul4g_hi = VRB2_PfDmaFec4GulRespPtrHiRegVf,
+	.tail_ptrs_ul4g_lo = VRB2_PfDmaFec4GulRespPtrLoRegVf,
+	.tail_ptrs_fft_hi =  VRB2_PfDmaFftRespPtrHiRegVf,
+	.tail_ptrs_fft_lo =  VRB2_PfDmaFftRespPtrLoRegVf,
+	.tail_ptrs_mld_hi =  VRB2_PfDmaFftRespPtrHiRegVf,
+	.tail_ptrs_mld_lo =  VRB2_PfDmaFftRespPtrLoRegVf,
+	.depth_log0_offset = VRB2_PfQmgrGrpDepthLog20Vf,
+	.depth_log1_offset = VRB2_PfQmgrGrpDepthLog21Vf,
+	.qman_group_func =   VRB2_PfQmgrGrpFunction0,
+	.hi_mode =           VRB2_PfHiMsixVectorMapperPf,
+	.pf_mode =           VRB2_PfHiPfMode,
+	.pmon_ctrl_a =       VRB2_PfPermonACntrlRegVf,
+	.pmon_ctrl_b =       VRB2_PfPermonBCntrlRegVf,
+	.pmon_ctrl_c =       VRB2_PfPermonCCntrlRegVf,
+	.vf2pf_doorbell =    0,
+	.pf2vf_doorbell =    0,
+};
+
+/* Structure holding registry addresses for VF */
+static const struct acc_registry_addr vrb2_vf_reg_addr = {
+	.dma_ring_dl5g_hi =  VRB2_VfDmaFec5GdlDescBaseHiRegVf,
+	.dma_ring_dl5g_lo =  VRB2_VfDmaFec5GdlDescBaseLoRegVf,
+	.dma_ring_ul5g_hi =  VRB2_VfDmaFec5GulDescBaseHiRegVf,
+	.dma_ring_ul5g_lo =  VRB2_VfDmaFec5GulDescBaseLoRegVf,
+	.dma_ring_dl4g_hi =  VRB2_VfDmaFec4GdlDescBaseHiRegVf,
+	.dma_ring_dl4g_lo =  VRB2_VfDmaFec4GdlDescBaseLoRegVf,
+	.dma_ring_ul4g_hi =  VRB2_VfDmaFec4GulDescBaseHiRegVf,
+	.dma_ring_ul4g_lo =  VRB2_VfDmaFec4GulDescBaseLoRegVf,
+	.dma_ring_fft_hi =   VRB2_VfDmaFftDescBaseHiRegVf,
+	.dma_ring_fft_lo =   VRB2_VfDmaFftDescBaseLoRegVf,
+	.dma_ring_mld_hi =   VRB2_VfDmaMldDescBaseHiRegVf,
+	.dma_ring_mld_lo =   VRB2_VfDmaMldDescBaseLoRegVf,
+	.ring_size =         VRB2_VfQmgrRingSizeVf,
+	.info_ring_hi =      VRB2_VfHiInfoRingBaseHiVf,
+	.info_ring_lo =      VRB2_VfHiInfoRingBaseLoVf,
+	.info_ring_en =      VRB2_VfHiInfoRingIntWrEnVf,
+	.info_ring_ptr =     VRB2_VfHiInfoRingPointerVf,
+	.tail_ptrs_dl5g_hi = VRB2_VfDmaFec5GdlRespPtrHiRegVf,
+	.tail_ptrs_dl5g_lo = VRB2_VfDmaFec5GdlRespPtrLoRegVf,
+	.tail_ptrs_ul5g_hi = VRB2_VfDmaFec5GulRespPtrHiRegVf,
+	.tail_ptrs_ul5g_lo = VRB2_VfDmaFec5GulRespPtrLoRegVf,
+	.tail_ptrs_dl4g_hi = VRB2_VfDmaFec4GdlRespPtrHiRegVf,
+	.tail_ptrs_dl4g_lo = VRB2_VfDmaFec4GdlRespPtrLoRegVf,
+	.tail_ptrs_ul4g_hi = VRB2_VfDmaFec4GulRespPtrHiRegVf,
+	.tail_ptrs_ul4g_lo = VRB2_VfDmaFec4GulRespPtrLoRegVf,
+	.tail_ptrs_fft_hi =  VRB2_VfDmaFftRespPtrHiRegVf,
+	.tail_ptrs_fft_lo =  VRB2_VfDmaFftRespPtrLoRegVf,
+	.tail_ptrs_mld_hi =  VRB2_VfDmaMldRespPtrHiRegVf,
+	.tail_ptrs_mld_lo =  VRB2_VfDmaMldRespPtrLoRegVf,
+	.depth_log0_offset = VRB2_VfQmgrGrpDepthLog20Vf,
+	.depth_log1_offset = VRB2_VfQmgrGrpDepthLog21Vf,
+	.qman_group_func =   VRB2_VfQmgrGrpFunction0Vf,
+	.hi_mode =           VRB2_VfHiMsixVectorMapperVf,
+	.pf_mode =           0,
+	.pmon_ctrl_a =       VRB2_VfPmACntrlRegVf,
+	.pmon_ctrl_b =       VRB2_VfPmBCntrlRegVf,
+	.pmon_ctrl_c =       VRB2_VfPmCCntrlRegVf,
+	.vf2pf_doorbell =    VRB2_VfHiVfToPfDbellVf,
+	.pf2vf_doorbell =    VRB2_VfHiPfToVfDbellVf,
+};
+
+
 #endif /* _VRB_PMD_H_ */