diff --git a/drivers/staging/media/ipu7/ipu7-boot.c b/drivers/staging/media/ipu7/ipu7-boot.c
new file mode 100644
index 000000000000..8e58d00566b4
--- /dev/null
+++ b/drivers/staging/media/ipu7/ipu7-boot.c
@@ -0,0 +1,431 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 - 2025 Intel Corporation
+ */
+
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/iopoll.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "abi/ipu7_fw_boot_abi.h"
+
+#include "ipu7.h"
+#include "ipu7-boot.h"
+#include "ipu7-bus.h"
+#include "ipu7-buttress-regs.h"
+#include "ipu7-dma.h"
+#include "ipu7-platform-regs.h"
+#include "ipu7-syscom.h"
+
+#define IPU_FW_START_STOP_TIMEOUT		2000
+#define IPU_BOOT_CELL_RESET_TIMEOUT		(2 * USEC_PER_SEC)
+#define BOOT_STATE_IS_CRITICAL(s)	IA_GOFO_FW_BOOT_STATE_IS_CRITICAL(s)
+#define BOOT_STATE_IS_READY(s)		((s) == IA_GOFO_FW_BOOT_STATE_READY)
+#define BOOT_STATE_IS_INACTIVE(s)	((s) == IA_GOFO_FW_BOOT_STATE_INACTIVE)
+
+struct ipu7_boot_context {
+	u32 base;
+	u32 dmem_address;
+	u32 status_ctrl_reg;
+	u32 fw_start_address_reg;
+	u32 fw_code_base_reg;
+};
+
+static const struct ipu7_boot_context contexts[IPU_SUBSYS_NUM] = {
+	{
+		/* ISYS */
+		.dmem_address = IPU_ISYS_DMEM_OFFSET,
+		.status_ctrl_reg = BUTTRESS_REG_DRV_IS_UCX_CONTROL_STATUS,
+		.fw_start_address_reg = BUTTRESS_REG_DRV_IS_UCX_START_ADDR,
+		.fw_code_base_reg = IS_UC_CTRL_BASE
+	},
+	{
+		/* PSYS */
+		.dmem_address = IPU_PSYS_DMEM_OFFSET,
+		.status_ctrl_reg = BUTTRESS_REG_DRV_PS_UCX_CONTROL_STATUS,
+		.fw_start_address_reg = BUTTRESS_REG_DRV_PS_UCX_START_ADDR,
+		.fw_code_base_reg = PS_UC_CTRL_BASE
+	}
+};
+
+static u32 get_fw_boot_reg_addr(const struct ipu7_bus_device *adev,
+				enum ia_gofo_buttress_reg_id reg)
+{
+	u32 base = (adev->subsys == IPU_IS) ? 0U : (u32)IA_GOFO_FW_BOOT_ID_MAX;
+
+	return BUTTRESS_FW_BOOT_PARAMS_ENTRY(base + (u32)reg);
+}
+
+static void write_fw_boot_param(const struct ipu7_bus_device *adev,
+				enum ia_gofo_buttress_reg_id reg,
+				u32 val)
+{
+	void __iomem *base = adev->isp->base;
+
+	dev_dbg(&adev->auxdev.dev,
+		"write boot param reg: %d addr: %x val: 0x%x\n",
+		reg, get_fw_boot_reg_addr(adev, reg), val);
+	writel(val, base + get_fw_boot_reg_addr(adev, reg));
+}
+
+static u32 read_fw_boot_param(const struct ipu7_bus_device *adev,
+			      enum ia_gofo_buttress_reg_id reg)
+{
+	void __iomem *base = adev->isp->base;
+
+	return readl(base + get_fw_boot_reg_addr(adev, reg));
+}
+
+static int ipu7_boot_cell_reset(const struct ipu7_bus_device *adev)
+{
+	const struct ipu7_boot_context *ctx = &contexts[adev->subsys];
+	const struct device *dev = &adev->auxdev.dev;
+	u32 ucx_ctrl_status = ctx->status_ctrl_reg;
+	u32 timeout = IPU_BOOT_CELL_RESET_TIMEOUT;
+	void __iomem *base = adev->isp->base;
+	u32 val, val2;
+	int ret;
+
+	dev_dbg(dev, "cell enter reset...\n");
+	val = readl(base + ucx_ctrl_status);
+	dev_dbg(dev, "cell_ctrl_reg addr = 0x%x, val = 0x%x\n",
+		ucx_ctrl_status, val);
+
+	dev_dbg(dev, "force cell reset...\n");
+	val |= UCX_CTL_RESET;
+	val &= ~UCX_CTL_RUN;
+
+	dev_dbg(dev, "write status_ctrl_reg(0x%x) to 0x%x\n",
+		ucx_ctrl_status, val);
+	writel(val, base + ucx_ctrl_status);
+
+	ret = readl_poll_timeout(base + ucx_ctrl_status, val2,
+				 (val2 & 0x3U) == (val & 0x3U), 100, timeout);
+	if (ret) {
+		dev_err(dev, "cell enter reset timeout. status: 0x%x\n", val2);
+		return -ETIMEDOUT;
+	}
+
+	dev_dbg(dev, "cell exit reset...\n");
+	val = readl(base + ucx_ctrl_status);
+	WARN((!(val & UCX_CTL_RESET) || val & UCX_CTL_RUN),
+	     "cell status 0x%x", val);
+
+	val &= ~(UCX_CTL_RESET | UCX_CTL_RUN);
+	dev_dbg(dev, "write status_ctrl_reg(0x%x) to 0x%x\n",
+		ucx_ctrl_status, val);
+	writel(val, base + ucx_ctrl_status);
+
+	ret = readl_poll_timeout(base + ucx_ctrl_status, val2,
+				 (val2 & 0x3U) == (val & 0x3U), 100, timeout);
+	if (ret) {
+		dev_err(dev, "cell exit reset timeout. status: 0x%x\n", val2);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static void ipu7_boot_cell_start(const struct ipu7_bus_device *adev)
+{
+	const struct ipu7_boot_context *ctx = &contexts[adev->subsys];
+	void __iomem *base = adev->isp->base;
+	const struct device *dev = &adev->auxdev.dev;
+	u32 val;
+
+	dev_dbg(dev, "starting cell...\n");
+	val = readl(base + ctx->status_ctrl_reg);
+	WARN_ON(val & (UCX_CTL_RESET | UCX_CTL_RUN));
+
+	val &= ~UCX_CTL_RESET;
+	val |= UCX_CTL_RUN;
+	dev_dbg(dev, "write status_ctrl_reg(0x%x) to 0x%x\n",
+		ctx->status_ctrl_reg, val);
+	writel(val, base + ctx->status_ctrl_reg);
+}
+
+static void ipu7_boot_cell_stop(const struct ipu7_bus_device *adev)
+{
+	const struct ipu7_boot_context *ctx = &contexts[adev->subsys];
+	void __iomem *base = adev->isp->base;
+	const struct device *dev = &adev->auxdev.dev;
+	u32 val;
+
+	dev_dbg(dev, "stopping cell...\n");
+
+	val = readl(base + ctx->status_ctrl_reg);
+	val &= ~UCX_CTL_RUN;
+	dev_dbg(dev, "write status_ctrl_reg(0x%x) to 0x%x\n",
+		ctx->status_ctrl_reg, val);
+	writel(val, base + ctx->status_ctrl_reg);
+
+	/* Wait for uC transactions complete */
+	usleep_range(10, 20);
+
+	val = readl(base + ctx->status_ctrl_reg);
+	val |= UCX_CTL_RESET;
+	dev_dbg(dev, "write status_ctrl_reg(0x%x) to 0x%x\n",
+		ctx->status_ctrl_reg, val);
+	writel(val, base + ctx->status_ctrl_reg);
+}
+
+static int ipu7_boot_cell_init(const struct ipu7_bus_device *adev)
+{
+	const struct ipu7_boot_context *ctx = &contexts[adev->subsys];
+	void __iomem *base = adev->isp->base;
+
+	dev_dbg(&adev->auxdev.dev, "write fw_start_address_reg(0x%x) to 0x%x\n",
+		ctx->fw_start_address_reg, adev->fw_entry);
+	writel(adev->fw_entry, base + ctx->fw_start_address_reg);
+
+	return ipu7_boot_cell_reset(adev);
+}
+
+static void init_boot_config(struct ia_gofo_boot_config *boot_config,
+			     u32 length, u8 major)
+{
+	/* syscom version, new syscom2 version */
+	boot_config->length = length;
+	boot_config->config_version.major = 1U;
+	boot_config->config_version.minor = 0U;
+	boot_config->config_version.subminor = 0U;
+	boot_config->config_version.patch = 0U;
+
+	/* msg version for task interface */
+	boot_config->client_version_support.num_versions = 1U;
+	boot_config->client_version_support.versions[0].major = major;
+	boot_config->client_version_support.versions[0].minor = 0U;
+	boot_config->client_version_support.versions[0].subminor = 0U;
+	boot_config->client_version_support.versions[0].patch = 0U;
+}
+
+int ipu7_boot_init_boot_config(struct ipu7_bus_device *adev,
+			       struct syscom_queue_config *qconfigs,
+			       int num_queues, u32 uc_freq,
+			       dma_addr_t subsys_config, u8 major)
+{
+	u32 total_queue_size = 0, total_queue_size_aligned = 0;
+	struct ipu7_syscom_context *syscom = adev->syscom;
+	struct ia_gofo_boot_config *boot_config;
+	struct syscom_queue_params_config *cfgs;
+	struct device *dev = &adev->auxdev.dev;
+	struct syscom_config_s *syscfg;
+	dma_addr_t queue_mem_dma_ptr;
+	void *queue_mem_ptr;
+	unsigned int i;
+
+	dev_dbg(dev, "boot config queues_nr: %d freq: %u sys_conf: 0x%llx\n",
+		num_queues, uc_freq, subsys_config);
+	/* Allocate boot config. */
+	adev->boot_config_size =
+		sizeof(*cfgs) * num_queues + sizeof(*boot_config);
+	adev->boot_config = ipu7_dma_alloc(adev, adev->boot_config_size,
+					   &adev->boot_config_dma_addr,
+					   GFP_KERNEL, 0);
+	if (!adev->boot_config) {
+		dev_err(dev, "Failed to allocate boot config.\n");
+		return -ENOMEM;
+	}
+
+	boot_config = adev->boot_config;
+	memset(boot_config, 0, sizeof(struct ia_gofo_boot_config));
+	init_boot_config(boot_config, adev->boot_config_size, major);
+	boot_config->subsys_config = subsys_config;
+
+	boot_config->uc_tile_frequency = uc_freq;
+	boot_config->uc_tile_frequency_units =
+		IA_GOFO_FW_BOOT_UC_FREQUENCY_UNITS_MHZ;
+	boot_config->syscom_context_config.max_output_queues =
+		syscom->num_output_queues;
+	boot_config->syscom_context_config.max_input_queues =
+		syscom->num_input_queues;
+
+	ipu7_dma_sync_single(adev, adev->boot_config_dma_addr,
+			     adev->boot_config_size);
+
+	for (i = 0; i < num_queues; i++) {
+		u32 queue_size = qconfigs[i].max_capacity *
+			qconfigs[i].token_size_in_bytes;
+
+		total_queue_size += queue_size;
+		queue_size = ALIGN(queue_size, 64U);
+		total_queue_size_aligned += queue_size;
+		qconfigs[i].queue_size = queue_size;
+	}
+
+	/* Allocate queue memory */
+	syscom->queue_mem = ipu7_dma_alloc(adev, total_queue_size_aligned,
+					   &syscom->queue_mem_dma_addr,
+					   GFP_KERNEL, 0);
+	if (!syscom->queue_mem) {
+		dev_err(dev, "Failed to allocate queue memory.\n");
+		return -ENOMEM;
+	}
+	syscom->queue_mem_size = total_queue_size_aligned;
+
+	syscfg = &boot_config->syscom_context_config;
+	cfgs = ipu7_syscom_get_queue_config(syscfg);
+	queue_mem_ptr = syscom->queue_mem;
+	queue_mem_dma_ptr = syscom->queue_mem_dma_addr;
+	for (i = 0; i < num_queues; i++) {
+		cfgs[i].token_array_mem = queue_mem_dma_ptr;
+		cfgs[i].max_capacity = qconfigs[i].max_capacity;
+		cfgs[i].token_size_in_bytes = qconfigs[i].token_size_in_bytes;
+		qconfigs[i].token_array_mem = queue_mem_ptr;
+		queue_mem_dma_ptr += qconfigs[i].queue_size;
+		queue_mem_ptr += qconfigs[i].queue_size;
+	}
+
+	ipu7_dma_sync_single(adev, syscom->queue_mem_dma_addr,
+			     total_queue_size_aligned);
+
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_boot_init_boot_config, "INTEL_IPU7");
+
+void ipu7_boot_release_boot_config(struct ipu7_bus_device *adev)
+{
+	struct ipu7_syscom_context *syscom = adev->syscom;
+
+	if (syscom->queue_mem) {
+		ipu7_dma_free(adev, syscom->queue_mem_size,
+			      syscom->queue_mem,
+			      syscom->queue_mem_dma_addr, 0);
+		syscom->queue_mem = NULL;
+		syscom->queue_mem_dma_addr = 0;
+	}
+
+	if (adev->boot_config) {
+		ipu7_dma_free(adev, adev->boot_config_size,
+			      adev->boot_config,
+			      adev->boot_config_dma_addr, 0);
+		adev->boot_config = NULL;
+		adev->boot_config_dma_addr = 0;
+	}
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_boot_release_boot_config, "INTEL_IPU7");
+
+int ipu7_boot_start_fw(const struct ipu7_bus_device *adev)
+{
+	const struct device *dev = &adev->auxdev.dev;
+	u32 timeout = IPU_FW_START_STOP_TIMEOUT;
+	void __iomem *base = adev->isp->base;
+	u32 boot_state, last_boot_state;
+	u32 indices_addr, msg_ver, id;
+	int ret;
+
+	ret = ipu7_boot_cell_init(adev);
+	if (ret)
+		return ret;
+
+	dev_dbg(dev, "start booting fw...\n");
+	/* store "uninit" state to syscom/boot state reg */
+	write_fw_boot_param(adev, IA_GOFO_FW_BOOT_STATE_ID,
+			    IA_GOFO_FW_BOOT_STATE_UNINIT);
+	/*
+	 * Set registers to zero
+	 * (not strictly required, but recommended for diagnostics)
+	 */
+	write_fw_boot_param(adev,
+			    IA_GOFO_FW_BOOT_SYSCOM_QUEUE_INDICES_BASE_ID, 0);
+	write_fw_boot_param(adev, IA_GOFO_FW_BOOT_MESSAGING_VERSION_ID, 0);
+	/* store firmware configuration address */
+	write_fw_boot_param(adev, IA_GOFO_FW_BOOT_CONFIG_ID,
+			    adev->boot_config_dma_addr);
+
+	/* Kick uC, then wait for boot complete */
+	ipu7_boot_cell_start(adev);
+
+	last_boot_state = IA_GOFO_FW_BOOT_STATE_UNINIT;
+	while (timeout--) {
+		boot_state = read_fw_boot_param(adev,
+						IA_GOFO_FW_BOOT_STATE_ID);
+		if (boot_state != last_boot_state) {
+			dev_dbg(dev, "boot state changed from 0x%x to 0x%x\n",
+				last_boot_state, boot_state);
+			last_boot_state = boot_state;
+		}
+		if (BOOT_STATE_IS_CRITICAL(boot_state) ||
+		    BOOT_STATE_IS_READY(boot_state))
+			break;
+		usleep_range(1000, 1200);
+	}
+
+	if (BOOT_STATE_IS_CRITICAL(boot_state)) {
+		ipu7_dump_fw_error_log(adev);
+		dev_err(dev, "critical boot state error 0x%x\n", boot_state);
+		return -EINVAL;
+	} else if (!BOOT_STATE_IS_READY(boot_state)) {
+		dev_err(dev, "fw boot timeout. state: 0x%x\n", boot_state);
+		return -ETIMEDOUT;
+	}
+	dev_dbg(dev, "fw boot done.\n");
+
+	/* Get FW syscom queue indices addr */
+	id = IA_GOFO_FW_BOOT_SYSCOM_QUEUE_INDICES_BASE_ID;
+	indices_addr = read_fw_boot_param(adev, id);
+	adev->syscom->queue_indices = base + indices_addr;
+	dev_dbg(dev, "fw queue indices offset is 0x%x\n", indices_addr);
+
+	/* Get message version. */
+	msg_ver = read_fw_boot_param(adev,
+				     IA_GOFO_FW_BOOT_MESSAGING_VERSION_ID);
+	dev_dbg(dev, "ipu message version is 0x%08x\n", msg_ver);
+
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_boot_start_fw, "INTEL_IPU7");
+
+int ipu7_boot_stop_fw(const struct ipu7_bus_device *adev)
+{
+	const struct device *dev = &adev->auxdev.dev;
+	u32 timeout = IPU_FW_START_STOP_TIMEOUT;
+	u32 boot_state;
+
+	boot_state = read_fw_boot_param(adev, IA_GOFO_FW_BOOT_STATE_ID);
+	if (BOOT_STATE_IS_CRITICAL(boot_state) ||
+	    !BOOT_STATE_IS_READY(boot_state)) {
+		dev_err(dev, "fw not ready for shutdown, state 0x%x\n",
+			boot_state);
+		return -EBUSY;
+	}
+
+	/* Issue shutdown to start shutdown process */
+	dev_dbg(dev, "stopping fw...\n");
+	write_fw_boot_param(adev, IA_GOFO_FW_BOOT_STATE_ID,
+			    IA_GOFO_FW_BOOT_STATE_SHUTDOWN_CMD);
+	while (timeout--) {
+		boot_state = read_fw_boot_param(adev,
+						IA_GOFO_FW_BOOT_STATE_ID);
+		if (BOOT_STATE_IS_CRITICAL(boot_state) ||
+		    BOOT_STATE_IS_INACTIVE(boot_state))
+			break;
+		usleep_range(1000, 1200);
+	}
+
+	if (BOOT_STATE_IS_CRITICAL(boot_state)) {
+		ipu7_dump_fw_error_log(adev);
+		dev_err(dev, "critical boot state error 0x%x\n", boot_state);
+		return -EINVAL;
+	} else if (!BOOT_STATE_IS_INACTIVE(boot_state)) {
+		dev_err(dev, "stop fw timeout. state: 0x%x\n", boot_state);
+		return -ETIMEDOUT;
+	}
+
+	ipu7_boot_cell_stop(adev);
+	dev_dbg(dev, "stop fw done.\n");
+
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_boot_stop_fw, "INTEL_IPU7");
+
+u32 ipu7_boot_get_boot_state(const struct ipu7_bus_device *adev)
+{
+	return read_fw_boot_param(adev, IA_GOFO_FW_BOOT_STATE_ID);
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_boot_get_boot_state, "INTEL_IPU7");
diff --git a/drivers/staging/media/ipu7/ipu7-boot.h b/drivers/staging/media/ipu7/ipu7-boot.h
new file mode 100644
index 000000000000..5600be849931
--- /dev/null
+++ b/drivers/staging/media/ipu7/ipu7-boot.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2022 - 2025 Intel Corporation
+ */
+
+#ifndef IPU7_BOOT_H
+#define IPU7_BOOT_H
+
+#include <linux/types.h>
+
+struct ipu7_bus_device;
+struct syscom_queue_config;
+
+#define FW_QUEUE_CONFIG_SIZE(num_queues)	\
+	(sizeof(struct syscom_queue_config) * (num_queues))
+
+int ipu7_boot_init_boot_config(struct ipu7_bus_device *adev,
+			       struct syscom_queue_config *qconfigs,
+			       int num_queues, u32 uc_freq,
+			       dma_addr_t subsys_config, u8 major);
+void ipu7_boot_release_boot_config(struct ipu7_bus_device *adev);
+int ipu7_boot_start_fw(const struct ipu7_bus_device *adev);
+int ipu7_boot_stop_fw(const struct ipu7_bus_device *adev);
+u32 ipu7_boot_get_boot_state(const struct ipu7_bus_device *adev);
+#endif
diff --git a/drivers/staging/media/ipu7/ipu7-cpd.c b/drivers/staging/media/ipu7/ipu7-cpd.c
new file mode 100644
index 000000000000..4f49fb57eae4
--- /dev/null
+++ b/drivers/staging/media/ipu7/ipu7-cpd.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 - 2025 Intel Corporation
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/gfp_types.h>
+#include <linux/pci.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "ipu7.h"
+#include "ipu7-cpd.h"
+
+/* $CPD */
+#define CPD_HDR_MARK		0x44504324
+
+/* Maximum size is 4K DWORDs or 16KB */
+#define MAX_MANIFEST_SIZE	(SZ_4K * sizeof(u32))
+
+#define CPD_MANIFEST_IDX	0
+#define CPD_BINARY_START_IDX	1U
+#define CPD_METADATA_START_IDX	2U
+#define CPD_BINARY_NUM		2U /* ISYS + PSYS */
+/*
+ * Entries include:
+ * 1 manifest entry.
+ * 1 metadata entry for each sub system(ISYS and PSYS).
+ * 1 binary entry for each sub system(ISYS and PSYS).
+ */
+#define CPD_ENTRY_NUM		(CPD_BINARY_NUM * 2U + 1U)
+
+#define CPD_METADATA_ATTR	0xa
+#define CPD_METADATA_IPL	0x1c
+#define ONLINE_METADATA_SIZE	128U
+#define ONLINE_METADATA_LINES	6U
+
+struct ipu7_cpd_hdr {
+	u32 hdr_mark;
+	u32 ent_cnt;
+	u8 hdr_ver;
+	u8 ent_ver;
+	u8 hdr_len;
+	u8 rsvd;
+	u8 partition_name[4];
+	u32 crc32;
+} __packed;
+
+struct ipu7_cpd_ent {
+	u8 name[12];
+	u32 offset;
+	u32 len;
+	u8 rsvd[4];
+} __packed;
+
+struct ipu7_cpd_metadata_hdr {
+	u32 type;
+	u32 len;
+} __packed;
+
+struct ipu7_cpd_metadata_attr {
+	struct ipu7_cpd_metadata_hdr hdr;
+	u8 compression_type;
+	u8 encryption_type;
+	u8 rsvd[2];
+	u32 uncompressed_size;
+	u32 compressed_size;
+	u32 module_id;
+	u8 hash[48];
+} __packed;
+
+struct ipu7_cpd_metadata_ipl {
+	struct ipu7_cpd_metadata_hdr hdr;
+	u32 param[4];
+	u8 rsvd[8];
+} __packed;
+
+struct ipu7_cpd_metadata {
+	struct ipu7_cpd_metadata_attr attr;
+	struct ipu7_cpd_metadata_ipl ipl;
+} __packed;
+
+static inline struct ipu7_cpd_ent *ipu7_cpd_get_entry(const void *cpd, int idx)
+{
+	const struct ipu7_cpd_hdr *cpd_hdr = cpd;
+
+	return ((struct ipu7_cpd_ent *)((u8 *)cpd + cpd_hdr->hdr_len)) + idx;
+}
+
+#define ipu7_cpd_get_manifest(cpd) ipu7_cpd_get_entry(cpd, 0)
+
+static struct ipu7_cpd_metadata *ipu7_cpd_get_metadata(const void *cpd, int idx)
+{
+	struct ipu7_cpd_ent *cpd_ent =
+		ipu7_cpd_get_entry(cpd, CPD_METADATA_START_IDX + idx * 2);
+
+	return (struct ipu7_cpd_metadata *)((u8 *)cpd + cpd_ent->offset);
+}
+
+static int ipu7_cpd_validate_cpd(struct ipu7_device *isp,
+				 const void *cpd, unsigned long data_size)
+{
+	const struct ipu7_cpd_hdr *cpd_hdr = cpd;
+	struct device *dev = &isp->pdev->dev;
+	struct ipu7_cpd_ent *ent;
+	unsigned int i;
+	u8 len;
+
+	len = cpd_hdr->hdr_len;
+
+	/* Ensure cpd hdr is within moduledata */
+	if (data_size < len) {
+		dev_err(dev, "Invalid CPD moduledata size\n");
+		return -EINVAL;
+	}
+
+	/* Check for CPD file marker */
+	if (cpd_hdr->hdr_mark != CPD_HDR_MARK) {
+		dev_err(dev, "Invalid CPD header marker\n");
+		return -EINVAL;
+	}
+
+	/* Sanity check for CPD entry header */
+	if (cpd_hdr->ent_cnt != CPD_ENTRY_NUM) {
+		dev_err(dev, "Invalid CPD entry number %d\n",
+			cpd_hdr->ent_cnt);
+		return -EINVAL;
+	}
+	if ((data_size - len) / sizeof(*ent) < cpd_hdr->ent_cnt) {
+		dev_err(dev, "Invalid CPD entry headers\n");
+		return -EINVAL;
+	}
+
+	/* Ensure that all entries are within moduledata */
+	ent = (struct ipu7_cpd_ent *)(((u8 *)cpd_hdr) + len);
+	for (i = 0; i < cpd_hdr->ent_cnt; i++) {
+		if (data_size < ent->offset ||
+		    data_size - ent->offset < ent->len) {
+			dev_err(dev, "Invalid CPD entry %d\n", i);
+			return -EINVAL;
+		}
+		ent++;
+	}
+
+	return 0;
+}
+
+static int ipu7_cpd_validate_metadata(struct ipu7_device *isp,
+				      const void *cpd, int idx)
+{
+	const struct ipu7_cpd_ent *cpd_ent =
+		ipu7_cpd_get_entry(cpd, CPD_METADATA_START_IDX + idx * 2);
+	const struct ipu7_cpd_metadata *metadata =
+		ipu7_cpd_get_metadata(cpd, idx);
+	struct device *dev = &isp->pdev->dev;
+
+	/* Sanity check for metadata size */
+	if (cpd_ent->len != sizeof(struct ipu7_cpd_metadata)) {
+		dev_err(dev, "Invalid metadata size\n");
+		return -EINVAL;
+	}
+
+	/* Validate type and length of metadata sections */
+	if (metadata->attr.hdr.type != CPD_METADATA_ATTR) {
+		dev_err(dev, "Invalid metadata attr type (%d)\n",
+			metadata->attr.hdr.type);
+		return -EINVAL;
+	}
+	if (metadata->attr.hdr.len != sizeof(struct ipu7_cpd_metadata_attr)) {
+		dev_err(dev, "Invalid metadata attr size (%d)\n",
+			metadata->attr.hdr.len);
+		return -EINVAL;
+	}
+	if (metadata->ipl.hdr.type != CPD_METADATA_IPL) {
+		dev_err(dev, "Invalid metadata ipl type (%d)\n",
+			metadata->ipl.hdr.type);
+		return -EINVAL;
+	}
+	if (metadata->ipl.hdr.len != sizeof(struct ipu7_cpd_metadata_ipl)) {
+		dev_err(dev, "Invalid metadata ipl size (%d)\n",
+			metadata->ipl.hdr.len);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int ipu7_cpd_validate_cpd_file(struct ipu7_device *isp, const void *cpd_file,
+			       unsigned long cpd_file_size)
+{
+	struct device *dev = &isp->pdev->dev;
+	struct ipu7_cpd_ent *ent;
+	unsigned int i;
+	int ret;
+	char *buf;
+
+	ret = ipu7_cpd_validate_cpd(isp, cpd_file, cpd_file_size);
+	if (ret) {
+		dev_err(dev, "Invalid CPD in file\n");
+		return -EINVAL;
+	}
+
+	/* Sanity check for manifest size */
+	ent = ipu7_cpd_get_manifest(cpd_file);
+	if (ent->len > MAX_MANIFEST_SIZE) {
+		dev_err(dev, "Invalid manifest size\n");
+		return -EINVAL;
+	}
+
+	/* Validate metadata */
+	for (i = 0; i < CPD_BINARY_NUM; i++) {
+		ret = ipu7_cpd_validate_metadata(isp, cpd_file, i);
+		if (ret) {
+			dev_err(dev, "Invalid metadata%d\n", i);
+			return ret;
+		}
+	}
+
+	/* Get fw binary version. */
+	buf = kmalloc(ONLINE_METADATA_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	for (i = 0; i < CPD_BINARY_NUM; i++) {
+		char *lines[ONLINE_METADATA_LINES];
+		char *info = buf;
+		unsigned int l;
+
+		ent = ipu7_cpd_get_entry(cpd_file,
+					 CPD_BINARY_START_IDX + i * 2U);
+		memcpy(info, (u8 *)cpd_file + ent->offset + ent->len -
+		       ONLINE_METADATA_SIZE, ONLINE_METADATA_SIZE);
+		for (l = 0; l < ONLINE_METADATA_LINES; l++) {
+			lines[l] = strsep((char **)&info, "\n");
+			if (!lines[l])
+				break;
+		}
+		if (l < ONLINE_METADATA_LINES) {
+			dev_err(dev, "Failed to parse fw binary%d info.\n", i);
+			continue;
+		}
+		dev_info(dev, "FW binary%d info:\n", i);
+		dev_info(dev, "Name: %s\n", lines[1]);
+		dev_info(dev, "Version: %s\n", lines[2]);
+		dev_info(dev, "Timestamp: %s\n", lines[3]);
+		dev_info(dev, "Commit: %s\n", lines[4]);
+	}
+	kfree(buf);
+
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_cpd_validate_cpd_file, "INTEL_IPU7");
+
+int ipu7_cpd_copy_binary(const void *cpd, const char *name,
+			 void *code_region, u32 *entry)
+{
+	unsigned int i;
+
+	for (i = 0; i < CPD_BINARY_NUM; i++) {
+		const struct ipu7_cpd_ent *binary =
+			ipu7_cpd_get_entry(cpd, CPD_BINARY_START_IDX + i * 2U);
+		const struct ipu7_cpd_metadata *metadata =
+			ipu7_cpd_get_metadata(cpd, i);
+
+		if (!strncmp(binary->name, name, sizeof(binary->name))) {
+			memcpy(code_region + metadata->ipl.param[0],
+			       cpd + binary->offset, binary->len);
+			*entry = metadata->ipl.param[2];
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_cpd_copy_binary, "INTEL_IPU7");
diff --git a/drivers/staging/media/ipu7/ipu7-cpd.h b/drivers/staging/media/ipu7/ipu7-cpd.h
new file mode 100644
index 000000000000..b4178848c6b9
--- /dev/null
+++ b/drivers/staging/media/ipu7/ipu7-cpd.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2015 - 2025 Intel Corporation
+ */
+
+#ifndef IPU7_CPD_H
+#define IPU7_CPD_H
+
+struct ipu7_device;
+
+int ipu7_cpd_validate_cpd_file(struct ipu7_device *isp,
+			       const void *cpd_file,
+			       unsigned long cpd_file_size);
+int ipu7_cpd_copy_binary(const void *cpd, const char *name,
+			 void *code_region, u32 *entry);
+#endif /* IPU7_CPD_H */
diff --git a/drivers/staging/media/ipu7/ipu7-syscom.c b/drivers/staging/media/ipu7/ipu7-syscom.c
new file mode 100644
index 000000000000..3f9f9c5c3cce
--- /dev/null
+++ b/drivers/staging/media/ipu7/ipu7-syscom.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 - 2025 Intel Corporation
+ */
+
+#include <linux/export.h>
+#include <linux/io.h>
+
+#include "abi/ipu7_fw_syscom_abi.h"
+
+#include "ipu7.h"
+#include "ipu7-syscom.h"
+
+static void __iomem *ipu7_syscom_get_indices(struct ipu7_syscom_context *ctx,
+					     u32 q)
+{
+	return ctx->queue_indices + (q * sizeof(struct syscom_queue_indices_s));
+}
+
+void *ipu7_syscom_get_token(struct ipu7_syscom_context *ctx, int q)
+{
+	struct syscom_queue_config *queue_params = &ctx->queue_configs[q];
+	void __iomem *queue_indices = ipu7_syscom_get_indices(ctx, q);
+	u32 write_index = readl(queue_indices +
+				offsetof(struct syscom_queue_indices_s,
+					 write_index));
+	u32 read_index = readl(queue_indices +
+			       offsetof(struct syscom_queue_indices_s,
+					read_index));
+	void *token = NULL;
+
+	if (q < ctx->num_output_queues) {
+		/* Output queue */
+		bool empty = (write_index == read_index);
+
+		if (!empty)
+			token = queue_params->token_array_mem +
+				read_index *
+				queue_params->token_size_in_bytes;
+	} else {
+		/* Input queue */
+		bool full = (read_index == ((write_index + 1U) %
+					    (u32)queue_params->max_capacity));
+
+		if (!full)
+			token = queue_params->token_array_mem +
+				write_index * queue_params->token_size_in_bytes;
+	}
+	return token;
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_syscom_get_token, "INTEL_IPU7");
+
+void ipu7_syscom_put_token(struct ipu7_syscom_context *ctx, int q)
+{
+	struct syscom_queue_config *queue_params = &ctx->queue_configs[q];
+	void __iomem *queue_indices = ipu7_syscom_get_indices(ctx, q);
+	u32 offset, index;
+
+	if (q < ctx->num_output_queues)
+		/* Output queue */
+		offset = offsetof(struct syscom_queue_indices_s, read_index);
+
+	else
+		/* Input queue */
+		offset = offsetof(struct syscom_queue_indices_s, write_index);
+
+	index = readl(queue_indices + offset);
+	writel((index + 1U) % queue_params->max_capacity,
+	       queue_indices + offset);
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_syscom_put_token, "INTEL_IPU7");
+
+struct syscom_queue_params_config *
+ipu7_syscom_get_queue_config(struct syscom_config_s *config)
+{
+	return (struct syscom_queue_params_config *)(&config[1]);
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_syscom_get_queue_config, "INTEL_IPU7");
diff --git a/drivers/staging/media/ipu7/ipu7-syscom.h b/drivers/staging/media/ipu7/ipu7-syscom.h
new file mode 100644
index 000000000000..e1fbe3b7914e
--- /dev/null
+++ b/drivers/staging/media/ipu7/ipu7-syscom.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2013 - 2025 Intel Corporation
+ */
+
+#ifndef IPU7_SYSCOM_H
+#define IPU7_SYSCOM_H
+
+#include <linux/types.h>
+
+struct syscom_config_s;
+struct syscom_queue_params_config;
+
+struct syscom_queue_config {
+	void *token_array_mem;
+	u32 queue_size;
+	u16 token_size_in_bytes;
+	u16 max_capacity;
+};
+
+struct ipu7_syscom_context {
+	u16 num_input_queues;
+	u16 num_output_queues;
+	struct syscom_queue_config *queue_configs;
+	void __iomem *queue_indices;
+	dma_addr_t queue_mem_dma_addr;
+	void *queue_mem;
+	u32 queue_mem_size;
+};
+
+void ipu7_syscom_put_token(struct ipu7_syscom_context *ctx, int q);
+void *ipu7_syscom_get_token(struct ipu7_syscom_context *ctx, int q);
+struct syscom_queue_params_config *
+ipu7_syscom_get_queue_config(struct syscom_config_s *config);
+#endif
