diff --git a/drivers/video/tegra/host/pva/fw_config_t264.h b/drivers/video/tegra/host/pva/fw_config_t264.h
new file mode 100644
index 00000000..e105371c
--- /dev/null
+++ b/drivers/video/tegra/host/pva/fw_config_t264.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see .
+ */
+
+#ifndef FW_CONFIG_T264_H
+#define FW_CONFIG_T264_H
+/**
+ * @brief Total number of AXI data buffers for T26x.
+ */
+#define PVA_NUM_DMA_ADB_BUFFS_T26X 304U
+
+/**
+ * @brief Number of reserved AXI data buffers for T26x.
+ */
+#define PVA_NUM_RESERVED_ADB_BUFFERS_T26X 16U
+
+/**
+ * @brief Number of dynamic AXI data buffers for T26x.
+ * These exclude the reserved AXI data buffers from total available ones.
+ */
+#define PVA_NUM_DYNAMIC_ADB_BUFFS_T26X \
+ (PVA_NUM_DMA_ADB_BUFFS_T26X - PVA_NUM_RESERVED_ADB_BUFFERS_T26X)
+
+#endif
\ No newline at end of file
diff --git a/drivers/video/tegra/host/pva/nvpva_ioctl_t264.h b/drivers/video/tegra/host/pva/nvpva_ioctl_t264.h
index 4fd6ee6a..1602d72f 100644
--- a/drivers/video/tegra/host/pva/nvpva_ioctl_t264.h
+++ b/drivers/video/tegra/host/pva/nvpva_ioctl_t264.h
@@ -37,5 +37,37 @@
* R5 FW reserves one DMA channel for internal use.
*/
#define NVPVA_TASK_MAX_DMA_CHANNELS_T26X (15U)
+/* NOTE: This is a re-definition of nvpva_dma_channel that
+ * contains T26x specific changes. Once T26x is public,
+ * this definition may be merged nvpva_dma_channel.
+ *
+ * Also note that the flags1 field has the following flags:
+ * - MSB for the HW Sequencer start index field in channel registers
+ * DMA_CHANNEL_HWSEQCNTL[1].bit[0] = flags1[0].bit[0];
+ * - MSB for the HW Sequencer end index field in channel registers
+ * DMA_CHANNEL_HWSEQCNTL[2].bit[4] = flags1[0].bit[2];
+ */
+struct nvpva_dma_channel_ex {
+ uint8_t descIndex;
+ uint8_t blockHeight;
+ uint16_t adbSize;
+ uint8_t vdbSize;
+ uint16_t adbOffset;
+ uint8_t vdbOffset;
+ uint32_t outputEnableMask;
+ uint32_t padValue;
+ uint8_t reqPerGrant;
+ uint8_t prefetchEnable;
+ uint8_t chRepFactor;
+ uint8_t hwseqStart;
+ uint8_t hwseqEnd;
+ uint8_t hwseqEnable;
+ uint8_t hwseqTraversalOrder;
+ uint8_t hwseqTxSelect;
+ uint8_t hwseqTriggerDone;
+ uint8_t hwseqFrameCount;
+ uint8_t hwseqConFrameSeq;
+ uint8_t flags1;
+};
#endif /* __NVPVA_IOCTL_T264_H__ */
diff --git a/drivers/video/tegra/host/pva/pva_hwseq_t264.h b/drivers/video/tegra/host/pva/pva_hwseq_t264.h
new file mode 100644
index 00000000..0e157765
--- /dev/null
+++ b/drivers/video/tegra/host/pva/pva_hwseq_t264.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see .
+ */
+
+#ifndef PVA_HWSEQ_T264_H
+#define PVA_HWSEQ_T264_H
+
+#define PVA_HWSEQ_RAM_SIZE_T26X 2048U
+#define PVA_HWSEQ_RAM_ID_MASK_T26X 0x1FFU
+#define PVA_HWSEQ_RRA_ADDR 0xC0DAU
+#define PVA_HWSEQ_RRA_MAX_NOCR 31U
+#define PVA_HWSEQ_RRA_MAX_FRAME_COUNT 63U
+
+/** \brief Mask used to derive the MSB for HW sequencer
+ * buffer start index for a channel
+ */
+#define PVA_CH_FLAGS1_HWSEQ_START_IDX_MSB_MASK (1U)
+
+/** \brief Mask used to derive the MSB for HW sequencer
+ * buffer start index for a channel
+ */
+#define PVA_CH_FLAGS1_HWSEQ_START_IDX_MSB_SHIFT (0U)
+
+/** \brief Mask used to derive the MSB for HW sequencer
+ * buffer end index for a channel
+ */
+#define PVA_CH_FLAGS1_HWSEQ_END_IDX_MSB_MASK (1U << 2U)
+
+/** \brief Mask used to derive the MSB for HW sequencer
+ * buffer end index for a channel
+ */
+#define PVA_CH_FLAGS1_HWSEQ_END_IDX_MSB_SHIFT (2U)
+
+#define PVA_CH_FLAGS1_HWSEQ_START_IDX_MSB(flag) \
+ ((flag & PVA_CH_FLAGS1_HWSEQ_START_IDX_MSB_MASK) \
+ >> PVA_CH_FLAGS1_HWSEQ_START_IDX_MSB_SHIFT)
+
+#define PVA_CH_FLAGS1_HWSEQ_END_IDX_MSB(flag) \
+ ((flag & PVA_CH_FLAGS1_HWSEQ_END_IDX_MSB_MASK) \
+ >> PVA_CH_FLAGS1_HWSEQ_END_IDX_MSB_SHIFT)
+
+static inline bool is_rra_mode(u16 id)
+{
+ return (id == PVA_HWSEQ_RRA_ADDR);
+}
+
+static inline u32 nvpva_get_hwseq_start_idx_t26x(
+ struct nvpva_dma_channel *user_ch)
+{
+ u32 idx = ((user_ch->hwseqStart & 0xFF)
+ | (PVA_CH_FLAGS1_HWSEQ_START_IDX_MSB(user_ch->flags1) << 8U));
+
+ return (idx & (u32)PVA_HWSEQ_RAM_ID_MASK_T26X);
+}
+
+static inline u32 nvpva_get_hwseq_end_idx_t26x(
+ struct nvpva_dma_channel *user_ch)
+{
+ u32 idx = ((user_ch->hwseqEnd & 0xFF)
+ | (PVA_CH_FLAGS1_HWSEQ_END_IDX_MSB(user_ch->flags1) << 8U));
+
+ return (idx & (u32)PVA_HWSEQ_RAM_ID_MASK_T26X);
+}
+
+static int validate_rra_mode(struct pva_hw_sweq_blob_s *blob,
+ struct pva_submit_task *task,
+ struct nvpva_dma_channel *dma_ch)
+{
+ const u8 *desc_entry = NULL;
+ const u8 *column = 0U;
+ uint32_t i = 0U;
+ uint32_t num_columns = 0U;
+ u32 end = nvpva_get_hwseq_end_idx_t26x(dma_ch) * 4U;
+ u8 *blob_end = &((uint8_t *)blob)[end + 4];
+ // In each NOCR entry, 4 bytes are used for CRO
+ // and 4 bytes are used for Desc info
+ const u8 column_entry_size = 8U;
+
+ if (task->pva->version < PVA_HW_GEN3) {
+ pr_err("Selected HWSEQ mode is not supported");
+ return -EINVAL;
+ }
+
+ if (dma_ch->hwseqFrameCount > PVA_HWSEQ_RRA_MAX_FRAME_COUNT) {
+ pr_err("Invalid HWSEQ frame count");
+ return -EINVAL;
+ }
+
+ if (blob->f_header.no_cr > PVA_HWSEQ_RRA_MAX_NOCR) {
+ pr_err("Invalid HWSEQ column count");
+ return -EINVAL;
+ }
+
+ if (blob->f_header.fr != 0) {
+ pr_err("Invalid HWSEQ repetition factor");
+ return -EINVAL;
+ }
+
+ num_columns = blob->f_header.no_cr + 1U;
+ column = (u8 *)&blob->cr_header;
+ desc_entry = (u8 *)&blob->desc_header;
+
+ // Ensure there are sufficient CRO and Desc ID entries in the HWSEQ blob
+ if (((blob_end - column) / column_entry_size) < num_columns) {
+ pr_err("HWSEQ Program does not have enough columns");
+ return -EINVAL;
+ }
+
+ for (i = 0U; i < num_columns; i++) {
+ // In RRA mode, each HWSEQ column has only 1 descriptor
+ // Hence, we validate the first descriptor and ignore the second
+ // descriptor in each column
+ if ((*desc_entry == 0U) ||
+ (*desc_entry > (NVPVA_TASK_MAX_DMA_DESCRIPTOR_ID_T26X))) {
+ pr_err("Invalid Descritor ID found in HW Sequencer");
+ return -EINVAL;
+ }
+ desc_entry += column_entry_size;
+ }
+
+ return 0;
+}
+
+static inline bool hwseq_blob_validate_t26x(struct pva_hw_sweq_blob_s *blob,
+ struct pva_submit_task *task,
+ struct nvpva_dma_channel *dma_ch,
+ bool *validation_done)
+{
+ if (is_rra_mode(blob->f_header.fid)) {
+ *validation_done = true;
+ if (validate_rra_mode(blob, task, dma_ch) != 0) {
+ return false;
+ }
+ } else {
+ *validation_done = false;
+ }
+ return true;
+}
+
+static inline void nvpva_task_dma_channel_mapping_t26x(
+ struct pva_dma_ch_config_s *ch,
+ struct nvpva_dma_channel *user_ch)
+{
+ /* DMA_CHANNEL_HWSEQCNTL_CHHWSEQSTART */
+ /* Note: the MSB for HWSEQ start idx comes from bit 0 of flags1 field*/
+ ch->hwseqcntl &= ~((u32)PVA_HWSEQ_RAM_ID_MASK_T26X);
+ ch->hwseqcntl |= nvpva_get_hwseq_start_idx_t26x(user_ch);
+
+ /* DMA_CHANNEL_HWSEQCNTL_CHHWSEQEND */
+ /* Note: the MSB for HWSEQ end idx comes from bit 2 of flags1 field*/
+ ch->hwseqcntl &= (~((u32)PVA_HWSEQ_RAM_ID_MASK_T26X << 12U));
+ ch->hwseqcntl |= (nvpva_get_hwseq_end_idx_t26x(user_ch) << 12U);
+
+ /* DMA_CHANNEL_HWSEQFSCNTL_CHHWSEQFCNT*/
+ ch->hwseqfscntl |= (((uint32_t)user_ch->hwseqConFrameSeq & 0x1U) << 0U);
+
+ /* DMA_CHANNEL_HWSEQFSCNTL_CHHWSEQCFS*/
+ ch->hwseqfscntl |= (((uint32_t)user_ch->hwseqFrameCount & 0x3FU) << 16U);
+}
+
+#endif