Re: [RFC PATCH 2/7] media: ipu7: add Intel IPU7 PCI device driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

see below

On Fri, 2025-02-21 at 15:52 +0800, bingbu.cao@xxxxxxxxx wrote:
> From: Bingbu Cao <bingbu.cao@xxxxxxxxx>
> 
> Intel Image Processing Unit 7th Gen includes input and processing
> systems
> and the hardware presents itself as a single PCI device in system
> same
> as IPU6.
> 
> The IPU7 PCI device driver basically does PCI configurations, basic
> hardware configuration by its buttress interfaces, loads the
> firmware binary, register the auxiliary device which serve for the
> ISYS
> device driver.
> 
> Signed-off-by: Bingbu Cao <bingbu.cao@xxxxxxxxx>
> ---
>  drivers/media/pci/intel/ipu7/ipu7-bus.c       |  158 +
>  drivers/media/pci/intel/ipu7/ipu7-bus.h       |   69 +
>  .../media/pci/intel/ipu7/ipu7-buttress-regs.h |  465 +++
>  drivers/media/pci/intel/ipu7/ipu7-buttress.c  | 1187 +++++++
>  drivers/media/pci/intel/ipu7/ipu7-buttress.h  |   84 +
>  .../media/pci/intel/ipu7/ipu7-platform-regs.h |  146 +
>  drivers/media/pci/intel/ipu7/ipu7.c           | 2791
> +++++++++++++++++
>  drivers/media/pci/intel/ipu7/ipu7.h           |  244 ++
>  8 files changed, 5144 insertions(+)
>  create mode 100644 drivers/media/pci/intel/ipu7/ipu7-bus.c
>  create mode 100644 drivers/media/pci/intel/ipu7/ipu7-bus.h
>  create mode 100644 drivers/media/pci/intel/ipu7/ipu7-buttress-regs.h
>  create mode 100644 drivers/media/pci/intel/ipu7/ipu7-buttress.c
>  create mode 100644 drivers/media/pci/intel/ipu7/ipu7-buttress.h
>  create mode 100644 drivers/media/pci/intel/ipu7/ipu7-platform-regs.h
>  create mode 100644 drivers/media/pci/intel/ipu7/ipu7.c
>  create mode 100644 drivers/media/pci/intel/ipu7/ipu7.h
> 
> diff --git a/drivers/media/pci/intel/ipu7/ipu7-bus.c
> b/drivers/media/pci/intel/ipu7/ipu7-bus.c
> new file mode 100644
> index 000000000000..6c2825afaca7
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu7/ipu7-bus.c
> @@ -0,0 +1,158 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2013 - 2024 Intel Corporation
> + */
> +
> +#include <linux/auxiliary_bus.h>
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/err.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +#include <linux/pci.h>
> +#include <linux/pm_domain.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> +
> +#include "ipu7.h"
> +#include "ipu7-bus.h"
> +#include "ipu7-boot.h"
> +#include "ipu7-dma.h"
> +
> +static int bus_pm_runtime_suspend(struct device *dev)
> +{
> +	struct ipu7_bus_device *adev = to_ipu7_bus_device(dev);
> +	int ret;
> +
> +	ret = pm_generic_runtime_suspend(dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = ipu_buttress_powerdown(dev, adev->ctrl);
> +	if (!ret)
> +		return 0;
> +
> +	dev_err(dev, "power down failed!\n");
> +
> +	/* Powering down failed, attempt to resume device now */
> +	ret = pm_generic_runtime_resume(dev);
> +	if (!ret)
> +		return -EBUSY;
> +
> +	return -EIO;
> +}
> +
> +static int bus_pm_runtime_resume(struct device *dev)
> +{
> +	struct ipu7_bus_device *adev = to_ipu7_bus_device(dev);
> +	int ret;
> +
> +	ret = ipu_buttress_powerup(dev, adev->ctrl);
> +	if (ret)
> +		return ret;
> +
> +	ret = pm_generic_runtime_resume(dev);
> +	if (ret)
> +		goto out_err;
> +
> +	return 0;
> +
> +out_err:
> +	ipu_buttress_powerdown(dev, adev->ctrl);
> +
> +	return -EBUSY;
> +}
> +
> +static struct dev_pm_domain ipu7_bus_pm_domain = {
> +	.ops = {
> +		.runtime_suspend = bus_pm_runtime_suspend,
> +		.runtime_resume = bus_pm_runtime_resume,
> +	},
> +};
> +
> +static DEFINE_MUTEX(ipu7_bus_mutex);
> +static void ipu7_bus_release(struct device *dev)
> +{
> +	struct ipu7_bus_device *adev = to_ipu7_bus_device(dev);
> +
> +	kfree(adev->pdata);
> +	kfree(adev);
> +}
> +
> +struct ipu7_bus_device *
> +ipu7_bus_initialize_device(struct pci_dev *pdev, struct device
> *parent,
> +			   void *pdata, const struct
> ipu_buttress_ctrl *ctrl,
> +			   char *name)
> +{
> +	struct auxiliary_device *auxdev;
> +	struct ipu7_bus_device *adev;
> +	struct ipu7_device *isp = pci_get_drvdata(pdev);
> +	int ret;
> +
> +	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
> +	if (!adev)
> +		return ERR_PTR(-ENOMEM);
> +
> +	adev->isp = isp;
> +	adev->ctrl = ctrl;
> +	adev->pdata = pdata;
> +	auxdev = &adev->auxdev;
> +	auxdev->name = name;
> +	auxdev->id = (pci_domain_nr(pdev->bus) << 16) |
> +		PCI_DEVID(pdev->bus->number, pdev->devfn);
> +
> +	auxdev->dev.parent = parent;
> +	auxdev->dev.release = ipu7_bus_release;
> +
> +	ret = auxiliary_device_init(auxdev);
> +	if (ret < 0) {
> +		dev_err(&isp->pdev->dev, "auxiliary device init
> failed (%d)\n",
> +			ret);
> +		kfree(adev);
> +		return ERR_PTR(ret);
> +	}
> +
> +	dev_pm_domain_set(&auxdev->dev, &ipu7_bus_pm_domain);
> +
> +	pm_runtime_forbid(&adev->auxdev.dev);
> +	pm_runtime_enable(&adev->auxdev.dev);
> +
> +	return adev;
> +}
> +
> +int ipu7_bus_add_device(struct ipu7_bus_device *adev)
> +{
> +	struct auxiliary_device *auxdev = &adev->auxdev;
> +	int ret;
> +
> +	ret = auxiliary_device_add(auxdev);
> +	if (ret) {
> +		auxiliary_device_uninit(auxdev);
> +		return ret;
> +	}
> +
> +	mutex_lock(&ipu7_bus_mutex);
> +	list_add(&adev->list, &adev->isp->devices);
> +	mutex_unlock(&ipu7_bus_mutex);
> +
> +	pm_runtime_allow(&auxdev->dev);
> +
> +	return 0;
> +}
> +
> +void ipu7_bus_del_devices(struct pci_dev *pdev)
> +{
> +	struct ipu7_device *isp = pci_get_drvdata(pdev);
> +	struct ipu7_bus_device *adev, *save;
> +
> +	mutex_lock(&ipu7_bus_mutex);
> +
> +	list_for_each_entry_safe(adev, save, &isp->devices, list) {
> +		pm_runtime_disable(&adev->auxdev.dev);
> +		list_del(&adev->list);
> +		auxiliary_device_delete(&adev->auxdev);
> +		auxiliary_device_uninit(&adev->auxdev);
> +	}
> +
> +	mutex_unlock(&ipu7_bus_mutex);
> +}
> diff --git a/drivers/media/pci/intel/ipu7/ipu7-bus.h
> b/drivers/media/pci/intel/ipu7/ipu7-bus.h
> new file mode 100644
> index 000000000000..b180b332cf2a
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu7/ipu7-bus.h
> @@ -0,0 +1,69 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2013 - 2024 Intel Corporation
> + */
> +
> +#ifndef IPU7_BUS_H
> +#define IPU7_BUS_H
> +
> +#include <linux/auxiliary_bus.h>
> +#include <linux/container_of.h>
> +#include <linux/device.h>
> +#include <linux/irqreturn.h>
> +#include <linux/list.h>
> +#include <linux/scatterlist.h>
> +#include <linux/types.h>
> +
> +#include "abi/ipu7_fw_boot_abi.h"
> +
> +#include "ipu7-syscom.h"
> +
> +struct pci_dev;
> +struct ipu_buttress_ctrl;
> +struct ipu7_mmu;
> +struct ipu7_device;
> +
> +enum ipu7_subsys {
> +	IPU_IS = 0,
> +	IPU_PS = 1,
> +	IPU_SUBSYS_NUM = 2,
> +};
> +
> +struct ipu7_bus_device {
> +	struct auxiliary_device auxdev;
> +	const struct auxiliary_driver *auxdrv;
> +	const struct ipu7_auxdrv_data *auxdrv_data;
> +	struct list_head list;
> +	enum ipu7_subsys subsys;
> +	void *pdata;
> +	struct ipu7_mmu *mmu;
> +	struct ipu7_device *isp;
> +	const struct ipu_buttress_ctrl *ctrl;
> +	u64 dma_mask;
> +	struct sg_table fw_sgt;
> +	u32 fw_entry;
> +	struct ipu7_syscom_context *syscom;
> +	struct ia_gofo_boot_config *boot_config;
> +	dma_addr_t boot_config_dma_addr;
> +	u32 boot_config_size;
> +};
> +
> +struct ipu7_auxdrv_data {
> +	irqreturn_t (*isr)(struct ipu7_bus_device *adev);
> +	irqreturn_t (*isr_threaded)(struct ipu7_bus_device *adev);
> +	bool wake_isr_thread;
> +};
> +
> +#define
> to_ipu7_bus_device(_dev)					\
> +	container_of(to_auxiliary_dev(_dev), struct ipu7_bus_device,
> auxdev)
> +#define
> auxdev_to_adev(_auxdev)					\
> +	container_of(_auxdev, struct ipu7_bus_device, auxdev)
> +#define ipu7_bus_get_drvdata(adev) dev_get_drvdata(&(adev)-
> >auxdev.dev)
> +
> +struct ipu7_bus_device *
> +ipu7_bus_initialize_device(struct pci_dev *pdev, struct device
> *parent,
> +			   void *pdata, const struct
> ipu_buttress_ctrl *ctrl,
> +			   char *name);
> +int ipu7_bus_add_device(struct ipu7_bus_device *adev);
> +void ipu7_bus_del_devices(struct pci_dev *pdev);
> +#endif
> diff --git a/drivers/media/pci/intel/ipu7/ipu7-buttress-regs.h
> b/drivers/media/pci/intel/ipu7/ipu7-buttress-regs.h
> new file mode 100644
> index 000000000000..fdf6148fb95c
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu7/ipu7-buttress-regs.h
> @@ -0,0 +1,465 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2020 - 2024 Intel Corporation
> + */
> +
> +#ifndef IPU7_BUTTRESS_REGS_H
> +#define IPU7_BUTTRESS_REGS_H
> +
> +#define
> BUTTRESS_REG_IRQ_STATUS					0x2000
> +#define
> BUTTRESS_REG_IRQ_STATUS_UNMASKED			0x2004
> +#define
> BUTTRESS_REG_IRQ_ENABLE					0x2008
> +#define
> BUTTRESS_REG_IRQ_CLEAR					0x200c
> +#define
> BUTTRESS_REG_IRQ_MASK					0x2010
> +#define
> BUTTRESS_REG_TSC_CMD					0x2014
> +#define
> BUTTRESS_REG_TSC_CTL					0x2018
> +#define
> BUTTRESS_REG_TSC_LO					0x201c
> +#define
> BUTTRESS_REG_TSC_HI					0x2020
> +
> +/* valid for PTL */
> +#define
> BUTTRESS_REG_PB_TIMESTAMP_LO				0x2030
> +#define
> BUTTRESS_REG_PB_TIMESTAMP_HI				0x2034
> +#define
> BUTTRESS_REG_PB_TIMESTAMP_VALID				0x2038
> +
> +#define
> BUTTRESS_REG_PS_WORKPOINT_REQ				0x2100
> +#define
> BUTTRESS_REG_IS_WORKPOINT_REQ				0x2104
> +#define
> BUTTRESS_REG_PS_WORKPOINT_DOMAIN_REQ			0x2108
> +#define
> BUTTRESS_REG_PS_DOMAINS_STATUS				0x2110
> +#define
> BUTTRESS_REG_PWR_STATUS					0x2114
> +#define
> BUTTRESS_REG_PS_WORKPOINT_REQ_SHADOW			0x2120
> +#define
> BUTTRESS_REG_IS_WORKPOINT_REQ_SHADOW			0x2124
> +#define
> BUTTRESS_REG_PS_WORKPOINT_DOMAIN_REQ_SHADOW		0x2128
> +#define
> BUTTRESS_REG_ISPS_WORKPOINT_DOWNLOAD			0x212c
> +#define
> BUTTRESS_REG_PG_FLOW_OVERRIDE				0x2180
> +#define
> BUTTRESS_REG_GLOBAL_OVERRIDE_UNGATE_CTL			0x2184
> +#define
> BUTTRESS_REG_PWR_FSM_CTL				0x2188
> +#define
> BUTTRESS_REG_IDLE_WDT					0x218c
> +#define
> BUTTRESS_REG_PS_PWR_DOMAIN_EVENTQ_EN			0x2190
> +#define
> BUTTRESS_REG_PS_PWR_DOMAIN_EVENTQ_ADDR			0x2194
> +#define
> BUTTRESS_REG_PS_PWR_DOMAIN_EVENTQ_DATA			0x2198
> +#define
> BUTTRESS_REG_POWER_EN_DELAY				0x219c
> +#define
> IPU7_BUTTRESS_REG_LTR_CONTROL				0x21a0
> +#define
> IPU7_BUTTRESS_REG_NDE_CONTROL				0x21a4
> +#define
> IPU7_BUTTRESS_REG_INT_FRM_PUNIT				0x21a8
> +#define
> IPU8_BUTTRESS_REG_LTR_CONTROL				0x21a4
> +#define
> IPU8_BUTTRESS_REG_NDE_CONTROL				0x21a8
> +#define
> IPU8_BUTTRESS_REG_INT_FRM_PUNIT				0x21ac
> +#define
> BUTTRESS_REG_SLEEP_LEVEL_CFG				0x21b0
> +#define
> BUTTRESS_REG_SLEEP_LEVEL_STS				0x21b4
> +#define
> BUTTRESS_REG_DVFS_FSM_STATUS				0x21b8
> +#define
> BUTTRESS_REG_PS_PLL_ENABLE				0x21bc
> +#define
> BUTTRESS_REG_D2D_CTL					0x21d4
> +#define
> BUTTRESS_REG_IB_CLK_CTL					0x21d8
> +#define
> BUTTRESS_REG_IB_CRO_CLK_CTL				0x21dc
> +#define
> BUTTRESS_REG_FUNC_FUSES					0x21e0
> +#define
> BUTTRESS_REG_ISOCH_CTL					0x21e4
> +#define
> BUTTRESS_REG_WORKPOINT_CTL				0x21f0
> +#define
> BUTTRESS_REG_DRV_IS_UCX_CONTROL_STATUS			0x2200
> +#define
> BUTTRESS_REG_DRV_IS_UCX_START_ADDR			0x2204
> +#define
> BUTTRESS_REG_DRV_PS_UCX_CONTROL_STATUS			0x2208
> +#define
> BUTTRESS_REG_DRV_PS_UCX_START_ADDR			0x220c
> +#define
> BUTTRESS_REG_DRV_UCX_RESET_CFG				0x2210
> +
> +/* configured by CSE */
> +#define
> BUTTRESS_REG_CSE_IS_UCX_CONTROL_STATUS			0x2300
> +#define
> BUTTRESS_REG_CSE_IS_UCX_START_ADDR			0x2304
> +#define
> BUTTRESS_REG_CSE_PS_UCX_CONTROL_STATUS			0x2308
> +#define
> BUTTRESS_REG_CSE_PS_UCX_START_ADDR			0x230c
> +
> +#define
> BUTTRESS_REG_CAMERA_MASK				0x2310
> +#define
> BUTTRESS_REG_FW_CTL					0x2314
> +#define
> BUTTRESS_REG_SECURITY_CTL				0x2318
> +#define
> BUTTRESS_REG_FUNCTIONAL_FW_SETUP			0x231c
> +#define
> BUTTRESS_REG_FW_BASE					0x2320
> +#define
> BUTTRESS_REG_FW_BASE_LIMIT				0x2324
> +#define
> BUTTRESS_REG_FW_SCRATCH_BASE				0x2328
> +#define
> BUTTRESS_REG_FW_SCRATCH_LIMIT				0x232c
> +#define
> BUTTRESS_REG_CSE_ACTION					0x2330
> +
> +/* configured by SW */
> +#define
> BUTTRESS_REG_FW_RESET_CTL				0x2334
> +#define
> BUTTRESS_REG_FW_SOURCE_SIZE				0x2338
> +#define
> BUTTRESS_REG_FW_SOURCE_BASE				0x233c
> +
> +#define
> BUTTRESS_REG_IPU_SEC_CP_LSB				0x2400
> +#define
> BUTTRESS_REG_IPU_SEC_CP_MSB				0x2404
> +#define
> BUTTRESS_REG_IPU_SEC_WAC_LSB				0x2408
> +#define
> BUTTRESS_REG_IPU_SEC_WAC_MSB				0x240c
> +#define
> BUTTRESS_REG_IPU_SEC_RAC_LSB				0x2410
> +#define
> BUTTRESS_REG_IPU_SEC_RAC_MSB				0x2414
> +#define
> BUTTRESS_REG_IPU_DRV_CP_LSB				0x2418
> +#define
> BUTTRESS_REG_IPU_DRV_CP_MSB				0x241c
> +#define
> BUTTRESS_REG_IPU_DRV_WAC_LSB				0x2420
> +#define
> BUTTRESS_REG_IPU_DRV_WAC_MSB				0x2424
> +#define
> BUTTRESS_REG_IPU_DRV_RAC_LSB				0x2428
> +#define
> BUTTRESS_REG_IPU_DRV_RAC_MSB				0x242c
> +#define
> BUTTRESS_REG_IPU_FW_CP_LSB				0x2430
> +#define
> BUTTRESS_REG_IPU_FW_CP_MSB				0x2434
> +#define
> BUTTRESS_REG_IPU_FW_WAC_LSB				0x2438
> +#define
> BUTTRESS_REG_IPU_FW_WAC_MSB				0x243c
> +#define
> BUTTRESS_REG_IPU_FW_RAC_LSB				0x2440
> +#define
> BUTTRESS_REG_IPU_FW_RAC_MSB				0x2444
> +#define
> BUTTRESS_REG_IPU_BIOS_SEC_CP_LSB			0x2448
> +#define
> BUTTRESS_REG_IPU_BIOS_SEC_CP_MSB			0x244c
> +#define
> BUTTRESS_REG_IPU_BIOS_SEC_WAC_LSB			0x2450
> +#define
> BUTTRESS_REG_IPU_BIOS_SEC_WAC_MSB			0x2454
> +#define
> BUTTRESS_REG_IPU_BIOS_SEC_RAC_LSB			0x2458
> +#define
> BUTTRESS_REG_IPU_BIOS_SEC_RAC_MSB			0x245c
> +#define
> BUTTRESS_REG_IPU_DFD_CP_LSB				0x2460
> +#define
> BUTTRESS_REG_IPU_DFD_CP_MSB				0x2464
> +#define
> BUTTRESS_REG_IPU_DFD_WAC_LSB				0x2468
> +#define
> BUTTRESS_REG_IPU_DFD_WAC_MSB				0x246c
> +#define
> BUTTRESS_REG_IPU_DFD_RAC_LSB				0x2470
> +#define
> BUTTRESS_REG_IPU_DFD_RAC_MSB				0x2474
> +#define
> BUTTRESS_REG_CSE2IUDB0					0x2500
> +#define
> BUTTRESS_REG_CSE2IUDATA0				0x2504
> +#define
> BUTTRESS_REG_CSE2IUCSR					0x2508
> +#define
> BUTTRESS_REG_IU2CSEDB0					0x250c
> +#define
> BUTTRESS_REG_IU2CSEDATA0				0x2510
> +#define
> BUTTRESS_REG_IU2CSECSR					0x2514
> +#define
> BUTTRESS_REG_CSE2IUDB0_CR_SHADOW			0x2520
> +#define
> BUTTRESS_REG_CSE2IUDATA0_CR_SHADOW			0x2524
> +#define
> BUTTRESS_REG_CSE2IUCSR_CR_SHADOW			0x2528
> +#define
> BUTTRESS_REG_IU2CSEDB0_CR_SHADOW			0x252c
> +#define
> BUTTRESS_REG_DVFS_FSM_SURVIVABILITY			0x2900
> +#define
> BUTTRESS_REG_FLOWS_FSM_SURVIVABILITY			0x2904
> +#define
> BUTTRESS_REG_FABRICS_FSM_SURVIVABILITY			0x2908
> +#define
> BUTTRESS_REG_PS_SUB1_PM_FSM_SURVIVABILITY		0x290c
> +#define
> BUTTRESS_REG_PS_SUB0_PM_FSM_SURVIVABILITY		0x2910
> +#define
> BUTTRESS_REG_PS_PM_FSM_SURVIVABILITY			0x2914
> +#define
> BUTTRESS_REG_IS_PM_FSM_SURVIVABILITY			0x2918
> +#define
> BUTTRESS_REG_FLR_RST_FSM_SURVIVABILITY			0x291c
> +#define
> BUTTRESS_REG_FW_RST_FSM_SURVIVABILITY			0x2920
> +#define
> BUTTRESS_REG_RESETPREP_FSM_SURVIVABILITY		0x2924
> +#define
> BUTTRESS_REG_POWER_FSM_DOMAIN_STATUS			0x3000
> +#define
> BUTTRESS_REG_IDLEREQ_STATUS1				0x3004
> +#define
> BUTTRESS_REG_POWER_FSM_STATUS_IS_PS			0x3008
> +#define
> BUTTRESS_REG_POWER_ACK_B_STATUS				0x300c
> +#define
> BUTTRESS_REG_DOMAIN_RETENTION_CTL			0x3010
> +#define
> BUTTRESS_REG_CG_CTRL_BITS				0x3014
> +#define
> BUTTRESS_REG_IS_IFC_STATUS0				0x3018
> +#define
> BUTTRESS_REG_IS_IFC_STATUS1				0x301c
> +#define
> BUTTRESS_REG_PS_IFC_STATUS0				0x3020
> +#define
> BUTTRESS_REG_PS_IFC_STATUS1				0x3024
> +#define
> BUTTRESS_REG_BTRS_IFC_STATUS0				0x3028
> +#define
> BUTTRESS_REG_BTRS_IFC_STATUS1				0x302c
> +#define
> BUTTRESS_REG_IPU_SKU					0x3030
> +#define
> BUTTRESS_REG_PS_IDLEACK					0x3034
> +#define
> BUTTRESS_REG_IS_IDLEACK					0x3038
> +#define
> BUTTRESS_REG_SPARE_REGS_0				0x303c
> +#define
> BUTTRESS_REG_SPARE_REGS_1				0x3040
> +#define
> BUTTRESS_REG_SPARE_REGS_2				0x3044
> +#define
> BUTTRESS_REG_SPARE_REGS_3				0x3048
> +#define
> BUTTRESS_REG_IUNIT_ACV					0x304c
> +#define
> BUTTRESS_REG_CHICKEN_BITS				0x3050
> +#define
> BUTTRESS_REG_SBENDPOINT_CFG				0x3054
> +#define
> BUTTRESS_REG_ECC_ERR_LOG				0x3058
> +#define
> BUTTRESS_REG_POWER_FSM_STATUS				0x3070
> +#define
> BUTTRESS_REG_RESET_FSM_STATUS				0x3074
> +#define
> BUTTRESS_REG_IDLE_STATUS				0x3078
> +#define
> BUTTRESS_REG_IDLEACK_STATUS				0x307c
> +#define
> BUTTRESS_REG_IPU_DEBUG					0x3080
> +
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS0				0x4000
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS1				0x4004
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS2				0x4008
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS3				0x400c
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS4				0x4010
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS5				0x4014
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS6				0x4018
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS7				0x401c
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS8				0x4020
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS9				0x4024
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS10				0x4028
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS11				0x402c
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS12				0x4030
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS13				0x4034
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS14				0x4038
> +#define
> BUTTRESS_REG_FW_BOOT_PARAMS15				0x403c
> +
> +#define BUTTRESS_FW_BOOT_PARAMS_ENTRY(i) \
> +	(BUTTRESS_REG_FW_BOOT_PARAMS0 + ((i) * 4U))
> +#define BUTTRESS_REG_FW_GP(i)				(0x4040 +
> 0x4 * (i))
> +#define BUTTRESS_REG_FPGA_SUPPORT(i)			(0x40c0 +
> 0x4 * (i))
> +
> +#define
> BUTTRESS_REG_FW_GP8					0x4060
> +#define
> BUTTRESS_REG_FW_GP24					0x40a0
> +
> +#define
> BUTTRESS_REG_GPIO_0_PADCFG_ADDR_CR			0x4100
> +#define
> BUTTRESS_REG_GPIO_1_PADCFG_ADDR_CR			0x4104
> +#define
> BUTTRESS_REG_GPIO_2_PADCFG_ADDR_CR			0x4108
> +#define
> BUTTRESS_REG_GPIO_3_PADCFG_ADDR_CR			0x410c
> +#define
> BUTTRESS_REG_GPIO_4_PADCFG_ADDR_CR			0x4110
> +#define
> BUTTRESS_REG_GPIO_5_PADCFG_ADDR_CR			0x4114
> +#define
> BUTTRESS_REG_GPIO_6_PADCFG_ADDR_CR			0x4118
> +#define
> BUTTRESS_REG_GPIO_7_PADCFG_ADDR_CR			0x411c
> +#define
> BUTTRESS_REG_GPIO_ENABLE				0x4140
> +#define
> BUTTRESS_REG_GPIO_VALUE_CR				0x4144
> +
> +#define
> BUTTRESS_REG_IS_MEM_CORRECTABLE_ERROR_STATUS		0x5000
> +#define
> BUTTRESS_REG_IS_MEM_FATAL_ERROR_STATUS			0x5004
> +#define
> BUTTRESS_REG_IS_MEM_NON_FATAL_ERROR_STATUS		0x5008
> +#define
> BUTTRESS_REG_IS_MEM_CHECK_PASSED			0x500c
> +#define
> BUTTRESS_REG_IS_MEM_ERROR_INJECT			0x5010
> +#define
> BUTTRESS_REG_IS_MEM_ERROR_CLEAR				0x5014
> +#define
> BUTTRESS_REG_PS_MEM_CORRECTABLE_ERROR_STATUS		0x5040
> +#define
> BUTTRESS_REG_PS_MEM_FATAL_ERROR_STATUS			0x5044
> +#define
> BUTTRESS_REG_PS_MEM_NON_FATAL_ERROR_STATUS		0x5048
> +#define
> BUTTRESS_REG_PS_MEM_CHECK_PASSED			0x504c
> +#define
> BUTTRESS_REG_PS_MEM_ERROR_INJECT			0x5050
> +#define
> BUTTRESS_REG_PS_MEM_ERROR_CLEAR				0x5054
> +
> +#define BUTTRESS_REG_IS_AB_REGION_MIN_ADDRESS(i)	(0x6000 +
> 0x8 * (i))
> +#define BUTTRESS_REG_IS_AB_REGION_MAX_ADDRESS(i)	(0x6004 +
> 0x8 * (i))
> +#define
> BUTTRESS_REG_IS_AB_VIOLATION_LOG0			0x6080
> +#define
> BUTTRESS_REG_IS_AB_VIOLATION_LOG1			0x6084
> +#define BUTTRESS_REG_PS_AB_REGION_MIN_ADDRESS(i)	(0x6100 +
> 0x8 * (i))
> +#define BUTTRESS_REG_PS_AB_REGION_MAX_ADDRESS0		(0x6104 +
> 0x8 * (i))
> +#define
> BUTTRESS_REG_PS_AB_VIOLATION_LOG0			0x6180
> +#define
> BUTTRESS_REG_PS_AB_VIOLATION_LOG1			0x6184
> +#define
> BUTTRESS_REG_PS_DEBUG_AB_VIOLATION_LOG0			0x6200
> +#define
> BUTTRESS_REG_PS_DEBUG_AB_VIOLATION_LOG1			0x6204
> +#define
> BUTTRESS_REG_IS_DEBUG_AB_VIOLATION_LOG0			0x6208
> +#define
> BUTTRESS_REG_IS_DEBUG_AB_VIOLATION_LOG1			0x620c
> +#define
> BUTTRESS_REG_IB_DVP_AB_VIOLATION_LOG0			0x6210
> +#define
> BUTTRESS_REG_IB_DVP_AB_VIOLATION_LOG1			0x6214
> +#define
> BUTTRESS_REG_IB_ATB2DTF_AB_VIOLATION_LOG0		0x6218
> +#define
> BUTTRESS_REG_IB_ATB2DTF_AB_VIOLATION_LOG1		0x621c
> +#define
> BUTTRESS_REG_AB_ENABLE					0x6220
> +#define
> BUTTRESS_REG_AB_DEFAULT_ACCESS				0x6230
> +
> +/* Indicates CSE has received an IPU driver IPC transaction */
> +#define BUTTRESS_IRQ_IPC_EXEC_DONE_BY_CSE		BIT(0)
> +/* Indicates an IPC transaction from CSE has arrived */
> +#define BUTTRESS_IRQ_IPC_FROM_CSE_IS_WAITING		BIT(1)
> +/* Indicates a CSR update from CSE has arrived */
> +#define BUTTRESS_IRQ_CSE_CSR_SET			BIT(2)
> +/* Indicates an interrupt set by Punit (not in use at this time) */
> +#define BUTTRESS_IRQ_PUNIT_2_IUNIT_IRQ			BIT(3)
> +/* Indicates an SAI violation was detected on access to IB registers
> */
> +#define BUTTRESS_IRQ_SAI_VIOLATION			BIT(4)
> +/* Indicates a transaction to IS was not able to pass the access
> blocker */
> +#define BUTTRESS_IRQ_IS_AB_VIOLATION			BIT(5)
> +/* Indicates a transaction to PS was not able to pass the access
> blocker */
> +#define BUTTRESS_IRQ_PS_AB_VIOLATION			BIT(6)
> +/* Indicates an error response was detected by the IB config NoC */
> +#define
> BUTTRESS_IRQ_IB_CFG_NOC_ERR_IRQ			BIT(7)
> +/* Indicates an error response was detected by the IB data NoC */
> +#define BUTTRESS_IRQ_IB_DATA_NOC_ERR_IRQ		BIT(8)
> +/* Transaction to DVP regs was not able to pass the access blocker
> */
> +#define BUTTRESS_IRQ_IB_DVP_AB_VIOLATION		BIT(9)
> +/* Transaction to ATB2DTF regs was not able to pass the access
> blocker */
> +#define BUTTRESS_IRQ_ATB2DTF_AB_VIOLATION		BIT(10)
> +/* Transaction to IS debug regs was not able to pass the access
> blocker */
> +#define BUTTRESS_IRQ_IS_DEBUG_AB_VIOLATION		BIT(11)
> +/* Transaction to PS debug regs was not able to pass the access
> blocker */
> +#define BUTTRESS_IRQ_PS_DEBUG_AB_VIOLATION		BIT(12)
> +/* Indicates timeout occurred waiting for a response from a target
> */
> +#define BUTTRESS_IRQ_IB_CFG_NOC_TIMEOUT_IRQ		BIT(13)
> +/* Set when any correctable ECC error input wire to buttress is set
> */
> +#define BUTTRESS_IRQ_ECC_CORRECTABLE			BIT(14)
> +/* Any noncorrectable-nonfatal ECC error input wire to buttress is
> set */
> +#define BUTTRESS_IRQ_ECC_NONCORRECTABLE_NONFATAL	BIT(15)
> +/* Set when any noncorrectable-fatal ECC error input wire to
> buttress is set */
> +#define BUTTRESS_IRQ_ECC_NONCORRECTABLE_FATAL		BIT(16)
> +/* Set when timeout occurred waiting for a response from a target */
> +#define BUTTRESS_IRQ_IS_CFG_NOC_TIMEOUT_IRQ		BIT(17)
> +#define BUTTRESS_IRQ_PS_CFG_NOC_TIMEOUT_IRQ		BIT(18)
> +#define BUTTRESS_IRQ_LB_CFG_NOC_TIMEOUT_IRQ		BIT(19)
> +/* IS FW double exception event */
> +#define
> BUTTRESS_IRQ_IS_UC_PFATAL_ERROR			BIT(26)
> +/* PS FW double exception event */
> +#define
> BUTTRESS_IRQ_PS_UC_PFATAL_ERROR			BIT(27)
> +/* IS FW watchdog event */
> +#define BUTTRESS_IRQ_IS_WATCHDOG			BIT(28)
> +/* PS FW watchdog event */
> +#define BUTTRESS_IRQ_PS_WATCHDOG			BIT(29)
> +/* IS IRC irq out */
> +#define BUTTRESS_IRQ_IS_IRQ				BIT(30)
> +/* PS IRC irq out */
> +#define BUTTRESS_IRQ_PS_IRQ				BIT(31)
> +
> +/* buttress irq */
> +enum {
> +	BUTTRESS_PWR_STATUS_HH_STATE_IDLE,
> +	BUTTRESS_PWR_STATUS_HH_STATE_IN_PRGS,
> +	BUTTRESS_PWR_STATUS_HH_STATE_DONE,
> +	BUTTRESS_PWR_STATUS_HH_STATE_ERR,
> +};
> +
> +#define BUTTRESS_TSC_CMD_START_TSC_SYNC		BIT(0)
> +#define BUTTRESS_PWR_STATUS_HH_STATUS_SHIFT	11
> +#define BUTTRESS_PWR_STATUS_HH_STATUS_MASK	(0x3 << 11)
> +#define BUTTRESS_TSW_WA_SOFT_RESET		BIT(8)
> +/* new for PTL */
> +#define BUTTRESS_SEL_PB_TIMESTAMP		BIT(9)
> +#define BUTTRESS_IRQS		(BUTTRESS_IRQ_IS_IRQ | \
> +				 BUTTRESS_IRQ_PS_IRQ | \
> +				
> BUTTRESS_IRQ_IPC_FROM_CSE_IS_WAITING | \
> +				 BUTTRESS_IRQ_CSE_CSR_SET | \
> +				 BUTTRESS_IRQ_IPC_EXEC_DONE_BY_CSE |
> \
> +				 BUTTRESS_IRQ_PUNIT_2_IUNIT_IRQ)
> +
> +/* Iunit to CSE regs */
> +#define BUTTRESS_IU2CSEDB0_BUSY		BIT(31)
> +#define BUTTRESS_IU2CSEDB0_SHORT_FORMAT_SHIFT	27
> +#define BUTTRESS_IU2CSEDB0_CLIENT_ID_SHIFT	10
> +#define BUTTRESS_IU2CSEDB0_IPC_CLIENT_ID_VAL	2
> +
> +#define BUTTRESS_IU2CSEDATA0_IPC_BOOT_LOAD		1
> +#define BUTTRESS_IU2CSEDATA0_IPC_AUTH_RUN		2
> +#define BUTTRESS_IU2CSEDATA0_IPC_AUTH_REPLACE		3
> +#define BUTTRESS_IU2CSEDATA0_IPC_UPDATE_SECURE_TOUCH	16
> +
> +#define
> BUTTRESS_CSE2IUDATA0_IPC_BOOT_LOAD_DONE			BIT(0)
> +#define
> BUTTRESS_CSE2IUDATA0_IPC_AUTH_RUN_DONE			BIT(1)
> +#define
> BUTTRESS_CSE2IUDATA0_IPC_AUTH_REPLACE_DONE		BIT(2)
> +#define
> BUTTRESS_CSE2IUDATA0_IPC_UPDATE_SECURE_TOUCH_DONE	BIT(4)
> +
> +#define
> BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE1		BIT(0)
> +#define
> BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE2		BIT(1)
> +#define
> BUTTRESS_IU2CSECSR_IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE	BIT(
> 2)
> +#define
> BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ		BIT(3)
> +#define
> BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID			BIT(4)
> +#define
> BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ		BIT(5)
> +
> +/* 0x20 == NACK, 0xf == unknown command */
> +#define BUTTRESS_CSE2IUDATA0_IPC_NACK      0xf20
> +#define BUTTRESS_CSE2IUDATA0_IPC_NACK_MASK 0xffff
> +
> +/* IS/PS freq control */
> +#define BUTTRESS_IS_FREQ_CTL_RATIO_MASK	0xff
> +#define BUTTRESS_PS_FREQ_CTL_RATIO_MASK	0xff
> +#define BUTTRESS_IS_FREQ_CTL_CDYN_MASK	0xff
> +#define BUTTRESS_PS_FREQ_CTL_CDYN_MASK	0xff
> +
> +#define IPU7_IS_FREQ_MAX		450
> +#define IPU7_IS_FREQ_MIN		50
> +#define IPU7_PS_FREQ_MAX		750
> +#define BUTTRESS_PS_FREQ_RATIO_STEP		25U
> +/* valid for IPU8 */
> +#define BUTTRESS_IS_FREQ_RATIO_STEP		25U
> +
> +/* IS: 400mhz, PS: 500mhz */
> +#define IPU7_IS_FREQ_CTL_DEFAULT_RATIO		0x1b
> +#define IPU7_PS_FREQ_CTL_DEFAULT_RATIO		0x14
> +/* IS: 400mhz, PS: 400mhz */
> +#define IPU8_IS_FREQ_CTL_DEFAULT_RATIO		0x10
> +#define IPU8_PS_FREQ_CTL_DEFAULT_RATIO		0x10
> +
> +#define IPU_FREQ_CTL_CDYN		0x80
> +#define IPU_FREQ_CTL_RATIO_SHIFT	0x0
> +#define IPU_FREQ_CTL_CDYN_SHIFT		0x8
> +
> +/* buttree power status */
> +#define IPU_BUTTRESS_PWR_STATE_IS_PWR_SHIFT	0
> +#define IPU_BUTTRESS_PWR_STATE_IS_PWR_MASK	\
> +	(0x3 << IPU_BUTTRESS_PWR_STATE_IS_PWR_SHIFT)
> +
> +#define IPU_BUTTRESS_PWR_STATE_PS_PWR_SHIFT	4
> +#define IPU_BUTTRESS_PWR_STATE_PS_PWR_MASK	\
> +	(0x3 << IPU_BUTTRESS_PWR_STATE_PS_PWR_SHIFT)
> +
> +#define IPU_BUTTRESS_PWR_STATE_DN_DONE		0x0
> +#define IPU_BUTTRESS_PWR_STATE_UP_PROCESS	0x1
> +#define IPU_BUTTRESS_PWR_STATE_DN_PROCESS	0x2
> +#define IPU_BUTTRESS_PWR_STATE_UP_DONE		0x3
> +
> +#define BUTTRESS_PWR_STATE_IS_PWR_SHIFT	3
> +#define BUTTRESS_PWR_STATE_IS_PWR_MASK	(0x3 << 3)
> +
> +#define BUTTRESS_PWR_STATE_PS_PWR_SHIFT	6
> +#define BUTTRESS_PWR_STATE_PS_PWR_MASK	(0x3 << 6)
> +
> +#define PS_FSM_CG		BIT(3)
> +
> +#define BUTTRESS_OVERRIDE_IS_CLK	BIT(1)
> +#define BUTTRESS_OVERRIDE_PS_CLK	BIT(2)
> +/* ps_pll only valid for ipu8 */
> +#define BUTTRESS_OWN_ACK_PS_PLL		BIT(8)
> +#define BUTTRESS_OWN_ACK_IS_CLK		BIT(9)
> +#define BUTTRESS_OWN_ACK_PS_CLK		BIT(10)
> +
> +/* FW reset ctrl */
> +#define BUTTRESS_FW_RESET_CTL_START	BIT(0)
> +#define BUTTRESS_FW_RESET_CTL_DONE	BIT(1)
> +
> +/* security */
> +#define BUTTRESS_SECURITY_CTL_FW_SECURE_MODE		BIT(16)
> +#define BUTTRESS_SECURITY_CTL_FW_SETUP_MASK		GENMASK(4,
> 0)
> +
> +#define BUTTRESS_SECURITY_CTL_FW_SETUP_DONE		BIT(0)
> +#define
> BUTTRESS_SECURITY_CTL_AUTH_DONE			BIT(1)
> +#define BUTTRESS_SECURITY_CTL_AUTH_FAILED		BIT(3)
> +
> +/* D2D */
> +#define BUTTRESS_D2D_PWR_EN			BIT(0)
> +#define BUTTRESS_D2D_PWR_ACK			BIT(4)
> +
> +/* NDE */
> +#define NDE_VAL_MASK				GENMASK(9, 0)
> +#define NDE_SCALE_MASK				GENMASK(12, 10)
> +#define NDE_VALID_MASK				BIT(13)
> +#define NDE_RESVEC_MASK				GENMASK(19,
> 16)
> +#define NDE_IN_VBLANK_DIS_MASK			BIT(31)
> +
> +#define BUTTRESS_NDE_VAL_ACTIVE			48
> +#define BUTTRESS_NDE_SCALE_ACTIVE		2
> +#define BUTTRESS_NDE_VALID_ACTIVE		1
> +
> +#define BUTTRESS_NDE_VAL_DEFAULT		1023
> +#define BUTTRESS_NDE_SCALE_DEFAULT		2
> +#define BUTTRESS_NDE_VALID_DEFAULT		0
> +
> +/* IS and PS UCX control */
> +#define UCX_CTL_RESET			BIT(0)
> +#define UCX_CTL_RUN			BIT(1)
> +#define UCX_CTL_WAKEUP			BIT(2)
> +#define UCX_CTL_SPARE			GENMASK(7, 3)
> +#define UCX_STS_PWR			GENMASK(17, 16)
> +#define UCX_STS_SLEEPING		BIT(18)
> +
> +/* offset from PHY base */
> +#define PHY_CSI_CFG			0xc0
> +#define PHY_CSI_RCOMP_CONTROL		0xc8
> +#define PHY_CSI_BSCAN_EXCLUDE		0xd8
> +
> +#define PHY_CPHY_DLL_OVRD(x)		(0x100 + 0x100 * (x))
> +#define PHY_DPHY_DLL_OVRD(x)		(0x14c + 0x100 * (x))
> +#define PHY_CPHY_RX_CONTROL1(x)		(0x110 + 0x100 *
> (x))
> +#define PHY_CPHY_RX_CONTROL2(x)		(0x114 + 0x100 *
> (x))
> +#define PHY_DPHY_CFG(x)			(0x148 + 0x100 *
> (x))
> +#define PHY_BB_AFE_CONFIG(x)		(0x174 + 0x100 * (x))
> +
> +/* PB registers */
> +#define INTERRUPT_STATUS			0x0
> +#define BTRS_LOCAL_INTERRUPT_MASK		0x4
> +#define GLOBAL_INTERRUPT_MASK			0x8
> +#define HM_ATS					0xc
> +#define ATS_ERROR_LOG1				0x10
> +#define ATS_ERROR_LOG2				0x14
> +#define ATS_ERROR_CLEAR				0x18
> +#define CFI_0_ERROR_LOG				0x1c
> +#define CFI_0_ERROR_CLEAR			0x20
> +#define HASH_CONFIG				0x2c
> +#define TLBID_HASH_ENABLE_31_0			0x30
> +#define TLBID_HASH_ENABLE_63_32			0x34
> +#define TLBID_HASH_ENABLE_95_64			0x38
> +#define TLBID_HASH_ENABLE_127_96		0x3c
> +#define CFI_1_ERROR_LOGGING			0x40
> +#define CFI_1_ERROR_CLEAR			0x44
> +#define IMR_ERROR_LOGGING_LOW			0x48
> +#define IMR_ERROR_LOGGING_HIGH			0x4c
> +#define IMR_ERROR_CLEAR				0x50
> +#define PORT_ARBITRATION_WEIGHTS		0x54
> +#define IMR_ERROR_LOGGING_CFI_1_LOW		0x58
> +#define IMR_ERROR_LOGGING_CFI_1_HIGH		0x5c
> +#define IMR_ERROR_CLEAR_CFI_1			0x60
> +#define BAR2_MISC_CONFIG			0x64
> +#define RSP_ID_CONFIG_AXI2CFI_0			0x68
> +#define RSP_ID_CONFIG_AXI2CFI_1			0x6c
> +#define PB_DRIVER_PCODE_MAILBOX_STATUS		0x70
> +#define PB_DRIVER_PCODE_MAILBOX_INTERFACE	0x74
> +#define PORT_ARBITRATION_WEIGHTS_ATS		0x78
> +
> +#endif /* IPU7_BUTTRESS_REGS_H */
> diff --git a/drivers/media/pci/intel/ipu7/ipu7-buttress.c
> b/drivers/media/pci/intel/ipu7/ipu7-buttress.c
> new file mode 100644
> index 000000000000..4b488f834b1a
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu7/ipu7-buttress.c
> @@ -0,0 +1,1187 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2013 - 2024 Intel Corporation
> + */
> +
> +#include <asm/cpu_device_id.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/completion.h>
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/firmware.h>
> +#include <linux/interrupt.h>
> +#include <linux/iopoll.h>
> +#include <linux/math64.h>
> +#include <linux/mm.h>
> +#include <linux/mutex.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/scatterlist.h>
> +#include <linux/types.h>
> +
> +#include "ipu7.h"
> +#include "ipu7-bus.h"
> +#include "ipu7-buttress.h"
> +#include "ipu7-buttress-regs.h"
> +
> +#define BOOTLOADER_STATUS_OFFSET	BUTTRESS_REG_FW_BOOT_PARAMS7
> +
> +#define BOOTLOADER_MAGIC_KEY		0xb00710ad
> +
> +#define ENTRY	BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE1
> +#define EXIT	BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE2
> +#define
> QUERY	BUTTRESS_IU2CSECSR_IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE
> +
> +#define BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX	10
> +
> +#define BUTTRESS_POWER_TIMEOUT_US		(200 *
> USEC_PER_MSEC)
> +
> +#define BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US	(5 * USEC_PER_SEC)
> +#define BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US	(10 * USEC_PER_SEC)
> +#define BUTTRESS_CSE_FWRESET_TIMEOUT_US		(100 *
> USEC_PER_MSEC)
> +
> +#define BUTTRESS_IPC_TX_TIMEOUT_MS		MSEC_PER_SEC
> +#define BUTTRESS_IPC_RX_TIMEOUT_MS		MSEC_PER_SEC
> +#define BUTTRESS_IPC_VALIDITY_TIMEOUT_US	(1 * USEC_PER_SEC)
> +#define BUTTRESS_TSC_SYNC_TIMEOUT_US		(5 * USEC_PER_MSEC)
> +
> +#define BUTTRESS_IPC_RESET_RETRY		2000
> +#define BUTTRESS_CSE_IPC_RESET_RETRY		4
> +#define BUTTRESS_IPC_CMD_SEND_RETRY		1
> +
> +static const u32 ipu7_adev_irq_mask[2] = {
> +	BUTTRESS_IRQ_IS_IRQ,
> +	BUTTRESS_IRQ_PS_IRQ
> +};
> +
> +int ipu_buttress_ipc_reset(struct ipu7_device *isp,
> +			   struct ipu_buttress_ipc *ipc)
> +{
> +	unsigned int retries = BUTTRESS_IPC_RESET_RETRY;
> +	struct ipu_buttress *b = &isp->buttress;
> +	struct device *dev = &isp->pdev->dev;
> +	u32 val = 0, csr_in_clr;
> +
> +	if (!isp->secure_mode) {
> +		dev_dbg(dev, "Skip IPC reset for non-secure
> mode\n");
> +		return 0;
> +	}
> +
> +	mutex_lock(&b->ipc_mutex);
> +
> +	/* Clear-by-1 CSR (all bits), corresponding internal states.
> */
> +	val = readl(isp->base + ipc->csr_in);
> +	writel(val, isp->base + ipc->csr_in);
> +
> +	/* Set peer CSR bit IPC_PEER_COMP_ACTIONS_RST_PHASE1 */
> +	writel(ENTRY, isp->base + ipc->csr_out);
> +	/*
> +	 * Clear-by-1 all CSR bits EXCEPT following
> +	 * bits:
> +	 * A. IPC_PEER_COMP_ACTIONS_RST_PHASE1.
> +	 * B. IPC_PEER_COMP_ACTIONS_RST_PHASE2.
> +	 * C. Possibly custom bits, depending on
> +	 * their role.
> +	 */
> +	csr_in_clr =
> BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ |
> +		BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID |
> +		BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ |
> QUERY;
> +
> +	do {
> +		usleep_range(400, 500);
> +		val = readl(isp->base + ipc->csr_in);
> +		switch (val) {
> +		case ENTRY | EXIT:
> +		case ENTRY | EXIT | QUERY:
> +			/*
> +			 * 1) Clear-by-1 CSR bits
> +			 * (IPC_PEER_COMP_ACTIONS_RST_PHASE1,
> +			 * IPC_PEER_COMP_ACTIONS_RST_PHASE2).
> +			 * 2) Set peer CSR bit
> +			 *
> IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE.
> +			 */
> +			writel(ENTRY | EXIT, isp->base + ipc-
> >csr_in);
> +			writel(QUERY, isp->base + ipc->csr_out);
> +			break;
> +		case ENTRY:
> +		case ENTRY | QUERY:
> +			/*
> +			 * 1) Clear-by-1 CSR bits
> +			 * (IPC_PEER_COMP_ACTIONS_RST_PHASE1,
> +			 *
> IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE).
> +			 * 2) Set peer CSR bit
> +			 * IPC_PEER_COMP_ACTIONS_RST_PHASE1.
> +			 */
> +			writel(ENTRY | QUERY, isp->base + ipc-
> >csr_in);
> +			writel(ENTRY, isp->base + ipc->csr_out);
> +			break;
> +		case EXIT:
> +		case EXIT | QUERY:
> +			/*
> +			 * Clear-by-1 CSR bit
> +			 * IPC_PEER_COMP_ACTIONS_RST_PHASE2.
> +			 * 1) Clear incoming doorbell.
> +			 * 2) Clear-by-1 all CSR bits EXCEPT
> following
> +			 * bits:
> +			 * A. IPC_PEER_COMP_ACTIONS_RST_PHASE1.
> +			 * B. IPC_PEER_COMP_ACTIONS_RST_PHASE2.
> +			 * C. Possibly custom bits, depending on
> +			 * their role.
> +			 * 3) Set peer CSR bit
> +			 * IPC_PEER_COMP_ACTIONS_RST_PHASE2.
> +			 */
> +			writel(EXIT, isp->base + ipc->csr_in);
> +			writel(0, isp->base + ipc->db0_in);
> +			writel(csr_in_clr, isp->base + ipc->csr_in);
> +			writel(EXIT, isp->base + ipc->csr_out);
> +
> +			/*
> +			 * Read csr_in again to make sure if
> RST_PHASE2 is done.
> +			 * If csr_in is QUERY, it should be handled
> again.
> +			 */
> +			usleep_range(200, 300);
> +			val = readl(isp->base + ipc->csr_in);
> +			if (val & QUERY) {
> +				dev_dbg(dev,
> +					"RST_PHASE2 retry csr_in =
> %x\n", val);
> +				break;
> +			}
> +			mutex_unlock(&b->ipc_mutex);
> +			return 0;
> +		case QUERY:
> +			/*
> +			 * 1) Clear-by-1 CSR bit
> +			 *
> IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE.
> +			 * 2) Set peer CSR bit
> +			 * IPC_PEER_COMP_ACTIONS_RST_PHASE1
> +			 */
> +			writel(QUERY, isp->base + ipc->csr_in);
> +			writel(ENTRY, isp->base + ipc->csr_out);
> +			break;
> +		default:
> +			dev_dbg_ratelimited(dev, "Unexpected CSR
> 0x%x\n", val);
> +			break;
> +		}
> +	} while (retries--);
> +
> +	mutex_unlock(&b->ipc_mutex);
> +	dev_err(dev, "Timed out while waiting for CSE\n");
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static void ipu_buttress_ipc_validity_close(struct ipu7_device *isp,
> +					    struct ipu_buttress_ipc
> *ipc)
> +{
> +	writel(BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ,
> +	       isp->base + ipc->csr_out);
> +}
> +
> +static int
> +ipu_buttress_ipc_validity_open(struct ipu7_device *isp,
> +			       struct ipu_buttress_ipc *ipc)
> +{
> +	unsigned int mask =
> BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID;
> +	void __iomem *addr;
> +	int ret;
> +	u32 val;
> +
> +	writel(BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ,
> +	       isp->base + ipc->csr_out);
> +
> +	addr = isp->base + ipc->csr_in;
> +	ret = readl_poll_timeout(addr, val, val & mask, 200,
> +				 BUTTRESS_IPC_VALIDITY_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(&isp->pdev->dev, "CSE validity timeout
> 0x%x\n", val);
> +		ipu_buttress_ipc_validity_close(isp, ipc);
> +	}
> +
> +	return ret;
> +}
> +
> +static void ipu_buttress_ipc_recv(struct ipu7_device *isp,
> +				  struct ipu_buttress_ipc *ipc, u32
> *ipc_msg)
> +{
> +	if (ipc_msg)
> +		*ipc_msg = readl(isp->base + ipc->data0_in);
> +	writel(0, isp->base + ipc->db0_in);
> +}
> +
> +static int ipu_buttress_ipc_send_bulk(struct ipu7_device *isp,
> +				      struct
> ipu7_ipc_buttress_bulk_msg *msgs,
> +				      u32 size)
> +{
> +	unsigned long tx_timeout_jiffies, rx_timeout_jiffies;
> +	unsigned int i, retry = BUTTRESS_IPC_CMD_SEND_RETRY;
> +	struct ipu_buttress *b = &isp->buttress;
> +	struct ipu_buttress_ipc *ipc = &b->cse;
> +	struct device *dev = &isp->pdev->dev;
> +	int tout;
> +	u32 val;
> +	int ret;
> +
> +	mutex_lock(&b->ipc_mutex);
> +
> +	ret = ipu_buttress_ipc_validity_open(isp, ipc);
> +	if (ret) {
> +		dev_err(dev, "IPC validity open failed\n");
> +		goto out;
> +	}
> +
> +	tx_timeout_jiffies =
> msecs_to_jiffies(BUTTRESS_IPC_TX_TIMEOUT_MS);
> +	rx_timeout_jiffies =
> msecs_to_jiffies(BUTTRESS_IPC_RX_TIMEOUT_MS);
> +
> +	for (i = 0; i < size; i++) {
> +		reinit_completion(&ipc->send_complete);
> +		if (msgs[i].require_resp)
> +			reinit_completion(&ipc->recv_complete);
> +
> +		dev_dbg(dev, "bulk IPC command: 0x%x\n",
> msgs[i].cmd);
> +		writel(msgs[i].cmd, isp->base + ipc->data0_out);
> +		val = BUTTRESS_IU2CSEDB0_BUSY | msgs[i].cmd_size;
> +		writel(val, isp->base + ipc->db0_out);
> +
> +		tout = wait_for_completion_timeout(&ipc-
> >send_complete,
> +						  
> tx_timeout_jiffies);
> +		if (!tout) {
> +			dev_err(dev, "send IPC response timeout\n");
> +			if (!retry--) {
> +				ret = -ETIMEDOUT;
> +				goto out;
> +			}
> +
> +			/* Try again if CSE is not responding on
> first try */
> +			writel(0, isp->base + ipc->db0_out);
> +			i--;
> +			continue;
> +		}
> +
> +		retry = BUTTRESS_IPC_CMD_SEND_RETRY;
> +
> +		if (!msgs[i].require_resp)
> +			continue;
> +
> +		tout = wait_for_completion_timeout(&ipc-
> >recv_complete,
> +						  
> rx_timeout_jiffies);
> +		if (!tout) {
> +			dev_err(dev, "recv IPC response timeout\n");
> +			ret = -ETIMEDOUT;
> +			goto out;
> +		}
> +
> +		if (ipc->nack_mask &&
> +		    (ipc->recv_data & ipc->nack_mask) == ipc->nack)
> {
> +			dev_err(dev, "IPC NACK for cmd 0x%x\n",
> msgs[i].cmd);
> +			ret = -EIO;
> +			goto out;
> +		}
> +
> +		if (ipc->recv_data != msgs[i].expected_resp) {
> +			dev_err(dev,
> +				"expected resp: 0x%x, IPC response:
> 0x%x\n",
> +				msgs[i].expected_resp, ipc-
> >recv_data);
> +			ret = -EIO;
> +			goto out;
> +		}
> +	}
> +
> +	dev_dbg(dev, "bulk IPC commands done\n");
> +
> +out:
> +	ipu_buttress_ipc_validity_close(isp, ipc);
> +	mutex_unlock(&b->ipc_mutex);
> +
> +	return ret;
> +}
> +
> +static int ipu_buttress_ipc_send(struct ipu7_device *isp,
> +				 u32 ipc_msg, u32 size, bool
> require_resp,
> +				 u32 expected_resp)
> +{
> +	struct ipu7_ipc_buttress_bulk_msg msg = {
> +		.cmd = ipc_msg,
> +		.cmd_size = size,
> +		.require_resp = require_resp,
> +		.expected_resp = expected_resp,
> +	};
> +
> +	return ipu_buttress_ipc_send_bulk(isp, &msg, 1);
> +}
> +
> +static irqreturn_t ipu_buttress_call_isr(struct ipu7_bus_device
> *adev)
> +{
> +	irqreturn_t ret = IRQ_WAKE_THREAD;
> +
> +	if (!adev || !adev->auxdrv || !adev->auxdrv_data)
> +		return IRQ_NONE;
> +
> +	if (adev->auxdrv_data->isr)
> +		ret = adev->auxdrv_data->isr(adev);
> +
> +	if (ret == IRQ_WAKE_THREAD && !adev->auxdrv_data-
> >isr_threaded)
> +		ret = IRQ_NONE;
> +
> +	return ret;
> +}
> +
> +irqreturn_t ipu_buttress_isr(int irq, void *isp_ptr)
> +{
> +	struct ipu7_device *isp = isp_ptr;
> +	struct ipu7_bus_device *adev[] = { isp->isys, isp->psys };
> +	struct ipu_buttress *b = &isp->buttress;
> +	struct device *dev = &isp->pdev->dev;
> +	irqreturn_t ret = IRQ_NONE;
> +	u32 pb_irq, pb_local_irq;
> +	u32 disable_irqs = 0;
> +	u32 irq_status;
> +	unsigned int i;
> +
> +	pm_runtime_get_noresume(dev);
> +
> +	pb_irq = readl(isp->pb_base + INTERRUPT_STATUS);
> +	writel(pb_irq, isp->pb_base + INTERRUPT_STATUS);
> +
> +	/* check btrs ATS, CFI and IMR errors, BIT(0) is unused for
> IPU */
> +	pb_local_irq = readl(isp->pb_base +
> BTRS_LOCAL_INTERRUPT_MASK);
> +	if (pb_local_irq & ~BIT(0)) {
> +		dev_warn(dev, "PB interrupt status 0x%x local
> 0x%x\n", pb_irq,
> +			 pb_local_irq);
> +		dev_warn(dev, "Details: %x %x %x %x %x %x %x %x\n",
> +			 readl(isp->pb_base + ATS_ERROR_LOG1),
> +			 readl(isp->pb_base + ATS_ERROR_LOG2),
> +			 readl(isp->pb_base + CFI_0_ERROR_LOG),
> +			 readl(isp->pb_base + CFI_1_ERROR_LOGGING),
> +			 readl(isp->pb_base +
> IMR_ERROR_LOGGING_LOW),
> +			 readl(isp->pb_base +
> IMR_ERROR_LOGGING_HIGH),
> +			 readl(isp->pb_base +
> IMR_ERROR_LOGGING_CFI_1_LOW),
> +			 readl(isp->pb_base +
> IMR_ERROR_LOGGING_CFI_1_HIGH));
> +	}
> +
> +	irq_status = readl(isp->base + BUTTRESS_REG_IRQ_STATUS);
> +	if (!irq_status) {
> +		pm_runtime_put_noidle(dev);
> +		return IRQ_NONE;
> +	}
> +
> +	do {
> +		writel(irq_status, isp->base +
> BUTTRESS_REG_IRQ_CLEAR);
> +
> +		for (i = 0; i < ARRAY_SIZE(ipu7_adev_irq_mask); i++)
> {
> +			irqreturn_t r =
> ipu_buttress_call_isr(adev[i]);
> +
> +			if (!(irq_status & ipu7_adev_irq_mask[i]))
> +				continue;
> +
> +			if (r == IRQ_WAKE_THREAD) {
> +				ret = IRQ_WAKE_THREAD;
> +				disable_irqs |=
> ipu7_adev_irq_mask[i];
> +			} else if (ret == IRQ_NONE && r ==
> IRQ_HANDLED) {
> +				ret = IRQ_HANDLED;
> +			}
> +		}
> +
> +		if (irq_status & (BUTTRESS_IRQS |
> BUTTRESS_IRQ_SAI_VIOLATION) &&
> +		    ret == IRQ_NONE)
> +			ret = IRQ_HANDLED;
> +
> +		if (irq_status &
> BUTTRESS_IRQ_IPC_FROM_CSE_IS_WAITING) {
> +			dev_dbg(dev,
> "BUTTRESS_IRQ_IPC_FROM_CSE_IS_WAITING\n");
> +			ipu_buttress_ipc_recv(isp, &b->cse, &b-
> >cse.recv_data);
> +			complete(&b->cse.recv_complete);
> +		}
> +
> +		if (irq_status & BUTTRESS_IRQ_CSE_CSR_SET)
> +			dev_dbg(dev, "BUTTRESS_IRQ_CSE_CSR_SET\n");
> +
> +		if (irq_status & BUTTRESS_IRQ_IPC_EXEC_DONE_BY_CSE)
> {
> +			dev_dbg(dev,
> "BUTTRESS_IRQ_IPC_EXEC_DONE_BY_CSE\n");
> +			complete(&b->cse.send_complete);
> +		}
> +
> +		if (irq_status & BUTTRESS_IRQ_PUNIT_2_IUNIT_IRQ)
> +			dev_dbg(dev,
> "BUTTRESS_IRQ_PUNIT_2_IUNIT_IRQ\n");
> +
> +		if (irq_status & BUTTRESS_IRQ_SAI_VIOLATION &&
> +		    ipu_buttress_get_secure_mode(isp))
> +			dev_err(dev,
> "BUTTRESS_IRQ_SAI_VIOLATION\n");
> +
> +		irq_status = readl(isp->base +
> BUTTRESS_REG_IRQ_STATUS);
> +	} while (irq_status);
> +
> +	if (disable_irqs)
> +		writel(BUTTRESS_IRQS & ~disable_irqs,
> +		       isp->base + BUTTRESS_REG_IRQ_ENABLE);
> +
> +	pm_runtime_put(dev);
> +
> +	return ret;
> +}
> +
> +irqreturn_t ipu_buttress_isr_threaded(int irq, void *isp_ptr)
> +{
> +	struct ipu7_device *isp = isp_ptr;
> +	struct ipu7_bus_device *adev[] = { isp->isys, isp->psys };
> +	const struct ipu7_auxdrv_data *drv_data = NULL;
> +	irqreturn_t ret = IRQ_NONE;
> +	unsigned int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(ipu7_adev_irq_mask) && adev[i];
> i++) {
> +		drv_data = adev[i]->auxdrv_data;
> +		if (!drv_data)
> +			continue;
> +
> +		if (drv_data->wake_isr_thread &&
> +		    drv_data->isr_threaded(adev[i]) == IRQ_HANDLED)
> +			ret = IRQ_HANDLED;
> +	}
> +
> +	writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_IRQ_ENABLE);
> +
> +	return ret;
> +}
> +
> +static int isys_d2d_power(struct device *dev, bool on)
> +{
> +	struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp;
> +	int ret = 0;
> +	u32 val;
> +
> +	dev_dbg(dev, "power %s isys d2d.\n", on ? "UP" : "DOWN");
> +	val = readl(isp->base + BUTTRESS_REG_D2D_CTL);
> +	if (!(val & BUTTRESS_D2D_PWR_ACK) ^ on) {
> +		dev_info(dev, "d2d already in %s state.\n",
> +			 on ? "UP" : "DOWN");
> +		return 0;
> +	}
> +
> +	val = on ? val | BUTTRESS_D2D_PWR_EN : val &
> (~BUTTRESS_D2D_PWR_EN);
> +	writel(val, isp->base + BUTTRESS_REG_D2D_CTL);
> +	ret = readl_poll_timeout(isp->base + BUTTRESS_REG_D2D_CTL,
> +				 val, (!(val & BUTTRESS_D2D_PWR_ACK)
> ^ on),
> +				 100, BUTTRESS_POWER_TIMEOUT_US);
> +	if (ret)
> +		dev_err(dev, "power %s d2d timeout. status: 0x%x\n",
> +			on ? "UP" : "DOWN", val);
> +
> +	return ret;
> +}
> +
> +static void isys_nde_control(struct device *dev, bool on)
> +{
> +	struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp;
> +	u32 val, value, scale, valid, resvec;
> +	u32 nde_reg;
> +
> +	if (on) {
> +		value = BUTTRESS_NDE_VAL_ACTIVE;
> +		scale = BUTTRESS_NDE_SCALE_ACTIVE;
> +		valid = BUTTRESS_NDE_VALID_ACTIVE;
> +	} else {
> +		value = BUTTRESS_NDE_VAL_DEFAULT;
> +		scale = BUTTRESS_NDE_SCALE_DEFAULT;
> +		valid = BUTTRESS_NDE_VALID_DEFAULT;
> +	}
> +
> +	/* only set the fabrics resource ownership for ipu8 */
> +	nde_reg = is_ipu8(isp->hw_ver) ?
> IPU8_BUTTRESS_REG_NDE_CONTROL :
> +		IPU7_BUTTRESS_REG_NDE_CONTROL;
> +	resvec = is_ipu8(isp->hw_ver) ? 0x2 : 0xe;
> +	val = FIELD_PREP(NDE_VAL_MASK, value) |
> +		FIELD_PREP(NDE_SCALE_MASK, scale) |
> +		FIELD_PREP(NDE_VALID_MASK, valid) |
> +		FIELD_PREP(NDE_RESVEC_MASK, resvec);
> +
> +	writel(val, isp->base + nde_reg);
> +}
> +
> +static int ipu7_buttress_powerup(struct device *dev,
> +				 const struct ipu_buttress_ctrl
> *ctrl)
> +{
> +	struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp;
> +	u32 val, exp_sts;
> +	int ret = 0;
> +
> +	if (!ctrl)
> +		return 0;
> +
> +	mutex_lock(&isp->buttress.power_mutex);
> +
> +	exp_sts = ctrl->pwr_sts_on << ctrl->pwr_sts_shift;
> +	if (ctrl->subsys_id == IPU_IS) {
> +		ret = isys_d2d_power(dev, true);
> +		if (ret)
> +			goto out_power;
> +		isys_nde_control(dev, true);
> +	}
> +
> +	/* request clock resource ownership */
> +	val = readl(isp->base + BUTTRESS_REG_SLEEP_LEVEL_CFG);
> +	val |= ctrl->ovrd_clk;
> +	writel(val, isp->base + BUTTRESS_REG_SLEEP_LEVEL_CFG);
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_SLEEP_LEVEL_STS,
> +				 val, (val & ctrl->own_clk_ack),
> +				 100, BUTTRESS_POWER_TIMEOUT_US);
> +	if (ret)
> +		dev_warn(dev, "request clk ownership timeout. status
> 0x%x\n",
> +			 val);
> +
> +	val = ctrl->ratio << ctrl->ratio_shift | ctrl->cdyn << ctrl-
> >cdyn_shift;
> +
> +	dev_dbg(dev, "set 0x%x to %s_WORKPOINT_REQ.\n", val,
> +		ctrl->subsys_id == IPU_IS ? "IS" : "PS");
> +	writel(val, isp->base + ctrl->freq_ctl);
> +
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_PWR_STATUS,
> +				 val, ((val & ctrl->pwr_sts_mask) ==
> exp_sts),
> +				 100, BUTTRESS_POWER_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(dev, "%s power up timeout with status:
> 0x%x\n",
> +			ctrl->subsys_id == IPU_IS ? "IS" : "PS",
> val);
> +		goto out_power;
> +	}
> +
> +	dev_dbg(dev, "%s power up successfully. status: 0x%x\n",
> +		ctrl->subsys_id == IPU_IS ? "IS" : "PS", val);
> +
> +	/* release clock resource ownership */
> +	val = readl(isp->base + BUTTRESS_REG_SLEEP_LEVEL_CFG);
> +	val &= ~ctrl->ovrd_clk;
> +	writel(val, isp->base + BUTTRESS_REG_SLEEP_LEVEL_CFG);
> +
> +out_power:
> +	mutex_unlock(&isp->buttress.power_mutex);
> +
> +	return ret;
> +}
> +
> +static int ipu7_buttress_powerdown(struct device *dev,
> +				   const struct ipu_buttress_ctrl
> *ctrl)
> +{
> +	struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp;
> +	u32 val, exp_sts;
> +	int ret = 0;
> +
> +	if (!ctrl)
> +		return 0;
> +
> +	mutex_lock(&isp->buttress.power_mutex);
> +
> +	exp_sts = ctrl->pwr_sts_off << ctrl->pwr_sts_shift;
> +	val = 0x8 << ctrl->ratio_shift;
> +
> +	dev_dbg(dev, "set 0x%x to %s_WORKPOINT_REQ.\n", val,
> +		ctrl->subsys_id == IPU_IS ? "IS" : "PS");
> +	writel(val, isp->base + ctrl->freq_ctl);
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_PWR_STATUS,
> +				 val, ((val & ctrl->pwr_sts_mask) ==
> exp_sts),
> +				 100, BUTTRESS_POWER_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(dev, "%s power down timeout with status:
> 0x%x\n",
> +			ctrl->subsys_id == IPU_IS ? "IS" : "PS",
> val);
> +		goto out_power;
> +	}
> +
> +	dev_dbg(dev, "%s power down successfully. status: 0x%x\n",
> +		ctrl->subsys_id == IPU_IS ? "IS" : "PS", val);
> +out_power:
> +	if (ctrl->subsys_id == IPU_IS && !ret) {
> +		isys_d2d_power(dev, false);
> +		isys_nde_control(dev, false);
> +	}
> +
> +	mutex_unlock(&isp->buttress.power_mutex);
> +
> +	return ret;
> +}
> +
> +static int ipu8_buttress_powerup(struct device *dev,
> +				 const struct ipu_buttress_ctrl
> *ctrl)
> +{
> +	struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp;
> +	u32 sleep_level_reg = BUTTRESS_REG_SLEEP_LEVEL_STS;
> +	u32 val, exp_sts;
> +	int ret = 0;
> +
> +	if (!ctrl)
> +		return 0;
> +
> +	mutex_lock(&isp->buttress.power_mutex);
> +	exp_sts = ctrl->pwr_sts_on << ctrl->pwr_sts_shift;
> +	if (ctrl->subsys_id == IPU_IS) {
> +		ret = isys_d2d_power(dev, true);
> +		if (ret)
> +			goto out_power;
> +		isys_nde_control(dev, true);
> +	}
> +
> +	/* request ps_pll when psys freq > 400Mhz */
> +	if (ctrl->subsys_id == IPU_PS && ctrl->ratio > 0x10) {
> +		writel(1, isp->base + BUTTRESS_REG_PS_PLL_ENABLE);
> +		ret = readl_poll_timeout(isp->base +
> sleep_level_reg,
> +					 val, (val & ctrl-
> >own_clk_ack),
> +					 100,
> BUTTRESS_POWER_TIMEOUT_US);
> +		if (ret)
> +			dev_warn(dev, "ps_pll req ack timeout.
> status 0x%x\n",
> +				 val);
> +	}
> +
> +	val = ctrl->ratio << ctrl->ratio_shift | ctrl->cdyn << ctrl-
> >cdyn_shift;
> +	dev_dbg(dev, "set 0x%x to %s_WORKPOINT_REQ.\n", val,
> +		ctrl->subsys_id == IPU_IS ? "IS" : "PS");
> +	writel(val, isp->base + ctrl->freq_ctl);
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_PWR_STATUS,
> +				 val, ((val & ctrl->pwr_sts_mask) ==
> exp_sts),
> +				 100, BUTTRESS_POWER_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(dev, "%s power up timeout with status:
> 0x%x\n",
> +			ctrl->subsys_id == IPU_IS ? "IS" : "PS",
> val);
> +		goto out_power;
> +	}
> +
> +	dev_dbg(dev, "%s power up successfully. status: 0x%x\n",
> +		ctrl->subsys_id == IPU_IS ? "IS" : "PS", val);
> +out_power:
> +	mutex_unlock(&isp->buttress.power_mutex);
> +
> +	return ret;
> +}
> +
> +static int ipu8_buttress_powerdown(struct device *dev,
> +				   const struct ipu_buttress_ctrl
> *ctrl)
> +{
> +	struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp;
> +	u32 val, exp_sts;
> +	int ret = 0;
> +
> +	if (!ctrl)
> +		return 0;
> +
> +	mutex_lock(&isp->buttress.power_mutex);
> +	exp_sts = ctrl->pwr_sts_off << ctrl->pwr_sts_shift;
> +
> +	if (ctrl->subsys_id == IPU_PS)
> +		val = 0x10 << ctrl->ratio_shift;
> +	else
> +		val = 0x8 << ctrl->ratio_shift;
> +
> +	dev_dbg(dev, "set 0x%x to %s_WORKPOINT_REQ.\n", val,
> +		ctrl->subsys_id == IPU_IS ? "IS" : "PS");
> +	writel(val, isp->base + ctrl->freq_ctl);
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_PWR_STATUS,
> +				 val, ((val & ctrl->pwr_sts_mask) ==
> exp_sts),
> +				 100, BUTTRESS_POWER_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(dev, "%s power down timeout with status:
> 0x%x\n",
> +			ctrl->subsys_id == IPU_IS ? "IS" : "PS",
> val);
> +		goto out_power;
> +	}
> +
> +	dev_dbg(dev, "%s power down successfully. status: 0x%x\n",
> +		ctrl->subsys_id == IPU_IS ? "IS" : "PS", val);
> +out_power:
> +	if (ctrl->subsys_id == IPU_IS && !ret) {
> +		isys_d2d_power(dev, false);
> +		isys_nde_control(dev, false);
> +	}
> +
> +	if (ctrl->subsys_id == IPU_PS) {
> +		val = readl(isp->base +
> BUTTRESS_REG_SLEEP_LEVEL_STS);
> +		if (val & ctrl->own_clk_ack)
> +			writel(0, isp->base +
> BUTTRESS_REG_PS_PLL_ENABLE);
> +	}
> +	mutex_unlock(&isp->buttress.power_mutex);
> +
> +	return ret;
> +}
> +
> +int ipu_buttress_powerup(struct device *dev,
> +			 const struct ipu_buttress_ctrl *ctrl)
> +{
> +	struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp;
> +
> +	if (is_ipu8(isp->hw_ver))
> +		return ipu8_buttress_powerup(dev, ctrl);
> +
> +	return ipu7_buttress_powerup(dev, ctrl);
> +}
> +
> +int ipu_buttress_powerdown(struct device *dev,
> +			   const struct ipu_buttress_ctrl *ctrl)
> +{
> +	struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp;
> +
> +	if (is_ipu8(isp->hw_ver))
> +		return ipu8_buttress_powerdown(dev, ctrl);
> +
> +	return ipu7_buttress_powerdown(dev, ctrl);
> +}
> +
> +bool ipu_buttress_get_secure_mode(struct ipu7_device *isp)
> +{
> +	u32 val;
> +
> +	val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL);
> +
> +	return val & BUTTRESS_SECURITY_CTL_FW_SECURE_MODE;
> +}
> +
> +bool ipu_buttress_auth_done(struct ipu7_device *isp)
> +{
> +	u32 val;
> +
> +	if (!isp->secure_mode)
> +		return true;
> +
> +	val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL);
> +	val = FIELD_GET(BUTTRESS_SECURITY_CTL_FW_SETUP_MASK, val);
> +
> +	return val == BUTTRESS_SECURITY_CTL_AUTH_DONE;
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu_buttress_auth_done, "INTEL_IPU7");
> +
> +int ipu_buttress_get_isys_freq(struct ipu7_device *isp, u32 *freq)
> +{
> +	u32 reg_val;
> +	int ret;
> +
> +	ret = pm_runtime_get_sync(&isp->isys->auxdev.dev);
> +	if (ret < 0) {
> +		pm_runtime_put(&isp->isys->auxdev.dev);
> +		dev_err(&isp->pdev->dev, "Runtime PM failed (%d)\n",
> ret);
> +		return ret;
> +	}
> +
> +	reg_val = readl(isp->base + BUTTRESS_REG_IS_WORKPOINT_REQ);
> +
> +	pm_runtime_put(&isp->isys->auxdev.dev);
> +
> +	if (is_ipu8(isp->hw_ver))
> +		*freq = (reg_val & BUTTRESS_IS_FREQ_CTL_RATIO_MASK)
> * 25;
> +	else
> +		*freq = (reg_val & BUTTRESS_IS_FREQ_CTL_RATIO_MASK)
> * 50 / 3;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu_buttress_get_isys_freq, "INTEL_IPU7");
> +
> +int ipu_buttress_get_psys_freq(struct ipu7_device *isp, u32 *freq)
> +{
> +	u32 reg_val;
> +	int ret;
> +
> +	ret = pm_runtime_get_sync(&isp->psys->auxdev.dev);
> +	if (ret < 0) {
> +		pm_runtime_put(&isp->psys->auxdev.dev);
> +		dev_err(&isp->pdev->dev, "Runtime PM failed (%d)\n",
> ret);
> +		return ret;
> +	}
> +
> +	reg_val = readl(isp->base + BUTTRESS_REG_PS_WORKPOINT_REQ);
> +
> +	pm_runtime_put(&isp->psys->auxdev.dev);
> +
> +	reg_val &= BUTTRESS_PS_FREQ_CTL_RATIO_MASK;
> +	*freq = BUTTRESS_PS_FREQ_RATIO_STEP * reg_val;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu_buttress_get_psys_freq, "INTEL_IPU7");
> +
> +int ipu_buttress_reset_authentication(struct ipu7_device *isp)
> +{
> +	struct device *dev = &isp->pdev->dev;
> +	int ret;
> +	u32 val;
> +
> +	if (!isp->secure_mode) {
> +		dev_dbg(dev, "Skip auth for non-secure mode\n");
> +		return 0;
> +	}
> +
> +	writel(BUTTRESS_FW_RESET_CTL_START, isp->base +
> +	       BUTTRESS_REG_FW_RESET_CTL);
> +
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_FW_RESET_CTL, val,
> +				 val & BUTTRESS_FW_RESET_CTL_DONE,
> 500,
> +				 BUTTRESS_CSE_FWRESET_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(dev, "Time out while resetting
> authentication state\n");
> +		return ret;
> +	}
> +
> +	dev_dbg(dev, "FW reset for authentication done\n");
> +	writel(0, isp->base + BUTTRESS_REG_FW_RESET_CTL);
> +	/* leave some time for HW restore */
> +	usleep_range(800, 1000);
> +
> +	return 0;
> +}
> +
> +int ipu_buttress_authenticate(struct ipu7_device *isp)
> +{
> +	struct ipu_buttress *b = &isp->buttress;
> +	struct device *dev = &isp->pdev->dev;
> +	u32 data, mask, done, fail;
> +	int ret;
> +
> +	if (!isp->secure_mode) {
> +		dev_dbg(dev, "Skip auth for non-secure mode\n");
> +		return 0;
> +	}
> +
> +	mutex_lock(&b->auth_mutex);
> +
> +	if (ipu_buttress_auth_done(isp)) {
> +		ret = 0;
> +		goto out_unlock;
> +	}
> +
> +	/*
> +	 * BUTTRESS_REG_FW_SOURCE_BASE needs to be set with FW CPD
> +	 * package address for secure mode.
> +	 */
> +
> +	writel(isp->cpd_fw->size, isp->base +
> BUTTRESS_REG_FW_SOURCE_SIZE);
> +	writel(sg_dma_address(isp->psys->fw_sgt.sgl),
> +	       isp->base + BUTTRESS_REG_FW_SOURCE_BASE);
> +
> +	/*
> +	 * Write boot_load into IU2CSEDATA0
> +	 * Write sizeof(boot_load) | 0x2 << CLIENT_ID to
> +	 * IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as
> +	 */
> +	dev_info(dev, "Sending BOOT_LOAD to CSE\n");
> +	ret = ipu_buttress_ipc_send(isp,
> BUTTRESS_IU2CSEDATA0_IPC_BOOT_LOAD,
> +				    1, true,
> +				   
> BUTTRESS_CSE2IUDATA0_IPC_BOOT_LOAD_DONE);
> +	if (ret) {
> +		dev_err(dev, "CSE boot_load failed\n");
> +		goto out_unlock;
> +	}
> +
> +	mask = BUTTRESS_SECURITY_CTL_FW_SETUP_MASK;
> +	done = BUTTRESS_SECURITY_CTL_FW_SETUP_DONE;
> +	fail = BUTTRESS_SECURITY_CTL_AUTH_FAILED;
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_SECURITY_CTL, data,
> +				 ((data & mask) == done ||
> +				  (data & mask) == fail), 500,
> +				 BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(dev, "CSE boot_load timeout\n");
> +		goto out_unlock;
> +	}
> +
> +	if ((data & mask) == fail) {
> +		dev_err(dev, "CSE auth failed\n");
> +		ret = -EINVAL;
> +		goto out_unlock;
> +	}
> +
> +	ret = readl_poll_timeout(isp->base +
> BOOTLOADER_STATUS_OFFSET,
> +				 data, data == BOOTLOADER_MAGIC_KEY,
> 500,
> +				 BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(dev, "Unexpected magic number 0x%x\n",
> data);
> +		goto out_unlock;
> +	}
> +
> +	/*
> +	 * Write authenticate_run into IU2CSEDATA0
> +	 * Write sizeof(boot_load) | 0x2 << CLIENT_ID to
> +	 * IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as
> +	 */
> +	dev_info(dev, "Sending AUTHENTICATE_RUN to CSE\n");
> +	ret = ipu_buttress_ipc_send(isp,
> BUTTRESS_IU2CSEDATA0_IPC_AUTH_RUN,
> +				    1, true,
> +				   
> BUTTRESS_CSE2IUDATA0_IPC_AUTH_RUN_DONE);
> +	if (ret) {
> +		dev_err(dev, "CSE authenticate_run failed\n");
> +		goto out_unlock;
> +	}
> +
> +	done = BUTTRESS_SECURITY_CTL_AUTH_DONE;
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_SECURITY_CTL, data,
> +				 ((data & mask) == done ||
> +				  (data & mask) == fail), 500,
> +				
> BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(dev, "CSE authenticate timeout\n");
> +		goto out_unlock;
> +	}
> +
> +	if ((data & mask) == fail) {
> +		dev_err(dev, "CSE boot_load failed\n");
> +		ret = -EINVAL;
> +		goto out_unlock;
> +	}
> +
> +	dev_info(dev, "CSE authenticate_run done\n");
> +
> +out_unlock:
> +	mutex_unlock(&b->auth_mutex);
> +
> +	return ret;
> +}
> +
> +static int ipu_buttress_send_tsc_request(struct ipu7_device *isp)
> +{
> +	u32 val, mask, done;
> +	int ret;
> +
> +	mask = BUTTRESS_PWR_STATUS_HH_STATUS_MASK;
> +
> +	writel(BUTTRESS_TSC_CMD_START_TSC_SYNC,
> +	       isp->base + BUTTRESS_REG_TSC_CMD);
> +
> +	val = readl(isp->base + BUTTRESS_REG_PWR_STATUS);
> +	val = FIELD_GET(mask, val);
> +	if (val == BUTTRESS_PWR_STATUS_HH_STATE_ERR) {
> +		dev_err(&isp->pdev->dev, "Start tsc sync failed\n");
> +		return -EINVAL;
> +	}
> +
> +	done = BUTTRESS_PWR_STATUS_HH_STATE_DONE;
> +	ret = readl_poll_timeout(isp->base +
> BUTTRESS_REG_PWR_STATUS, val,
> +				 FIELD_GET(mask, val) == done, 500,
> +				 BUTTRESS_TSC_SYNC_TIMEOUT_US);
> +	if (ret)
> +		dev_err(&isp->pdev->dev, "Start tsc sync
> timeout\n");
> +
> +	return ret;
> +}
> +
> +int ipu_buttress_start_tsc_sync(struct ipu7_device *isp)
> +{
> +	void __iomem *base = isp->base;
> +	unsigned int i;
> +	u32 val;
> +
> +	if (is_ipu8(isp->hw_ver)) {
> +		for (i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX;
> i++) {
> +			val = readl(base +
> BUTTRESS_REG_PB_TIMESTAMP_VALID);
> +			if (val == 1)
> +				return 0;
> +			usleep_range(40, 50);
> +		}
> +
> +		dev_err(&isp->pdev->dev, "PB HH sync failed (valid
> %u)\n", val);
> +		return -ETIMEDOUT;
> +	}
> +
> +	if (is_ipu7p5(isp->hw_ver)) {
> +		val = readl(base + BUTTRESS_REG_TSC_CTL);
> +		val |= BUTTRESS_SEL_PB_TIMESTAMP;
> +		writel(val, base + BUTTRESS_REG_TSC_CTL);
> +
> +		for (i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX;
> i++) {
> +			val = readl(base +
> BUTTRESS_REG_PB_TIMESTAMP_VALID);
> +			if (val == 1)
> +				return 0;
> +			usleep_range(40, 50);
> +		}
> +
> +		dev_err(&isp->pdev->dev, "PB HH sync failed (valid
> %u)\n", val);
> +
> +		return -ETIMEDOUT;
> +	}
> +
> +	for (i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX; i++) {
> +		int ret;
> +
> +		ret = ipu_buttress_send_tsc_request(isp);
> +		if (ret != -ETIMEDOUT)
> +			return ret;
> +
> +		val = readl(base + BUTTRESS_REG_TSC_CTL);
> +		val = val | BUTTRESS_TSW_WA_SOFT_RESET;
> +		writel(val, base + BUTTRESS_REG_TSC_CTL);
> +		val = val & (~BUTTRESS_TSW_WA_SOFT_RESET);
> +		writel(val, base + BUTTRESS_REG_TSC_CTL);
> +	}
> +
> +	dev_err(&isp->pdev->dev, "TSC sync failed (timeout)\n");
> +
> +	return -ETIMEDOUT;
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu_buttress_start_tsc_sync, "INTEL_IPU7");
> +
> +void ipu_buttress_tsc_read(struct ipu7_device *isp, u64 *val)
> +{
> +	unsigned long flags;
> +	u32 tsc_hi, tsc_lo;
> +
> +	local_irq_save(flags);
> +	if (is_ipu7(isp->hw_ver)) {
> +		tsc_lo = readl(isp->base + BUTTRESS_REG_TSC_LO);
> +		tsc_hi = readl(isp->base + BUTTRESS_REG_TSC_HI);
> +	} else {
> +		tsc_lo = readl(isp->base +
> BUTTRESS_REG_PB_TIMESTAMP_LO);
> +		tsc_hi = readl(isp->base +
> BUTTRESS_REG_PB_TIMESTAMP_HI);
> +	}
> +	*val = (u64)tsc_hi << 32 | tsc_lo;
> +	local_irq_restore(flags);
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu_buttress_tsc_read, "INTEL_IPU7");
> +
> +u64 ipu_buttress_tsc_ticks_to_ns(u64 ticks, const struct ipu7_device
> *isp)
> +{
> +	u64 ns = ticks * 10000;
> +
> +	/*
> +	 * converting TSC tick count to ns is calculated by:
> +	 * Example (TSC clock frequency is 19.2MHz):
> +	 * ns = ticks * 1000 000 000 / 19.2Mhz
> +	 *    = ticks * 1000 000 000 / 19200000Hz
> +	 *    = ticks * 10000 / 192 ns
> +	 */
> +	return div_u64(ns, isp->buttress.ref_clk);
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu_buttress_tsc_ticks_to_ns, "INTEL_IPU7");
> +
> +/* trigger uc control to wakeup fw */
> +void ipu_buttress_wakeup_is_uc(const struct ipu7_device *isp)
> +{
> +	u32 val;
> +
> +	val = readl(isp->base +
> BUTTRESS_REG_DRV_IS_UCX_CONTROL_STATUS);
> +	val |= UCX_CTL_WAKEUP;
> +	writel(val, isp->base +
> BUTTRESS_REG_DRV_IS_UCX_CONTROL_STATUS);
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu_buttress_wakeup_is_uc, "INTEL_IPU7");
> +
> +void ipu_buttress_wakeup_ps_uc(const struct ipu7_device *isp)
> +{
> +	u32 val;
> +
> +	val = readl(isp->base +
> BUTTRESS_REG_DRV_PS_UCX_CONTROL_STATUS);
> +	val |= UCX_CTL_WAKEUP;
> +	writel(val, isp->base +
> BUTTRESS_REG_DRV_PS_UCX_CONTROL_STATUS);
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu_buttress_wakeup_ps_uc, "INTEL_IPU7");
> +
> +static const struct x86_cpu_id ipu_misc_cfg_exclusion[] = {
> +	X86_MATCH_VFM_STEPS(INTEL_PANTHERLAKE_L, 0x1, 0x1, 0),
> +	{},
> +};
> +
> +static void ipu_buttress_setup(struct ipu7_device *isp)
> +{
> +	struct device *dev = &isp->pdev->dev;
> +	u32 val;
> +
> +	/* program PB BAR */
> +#define WRXREQOP_OVRD_VAL_MASK  GENMASK(22, 19)
> +	writel(0, isp->pb_base + GLOBAL_INTERRUPT_MASK);
> +	val = readl(isp->pb_base + BAR2_MISC_CONFIG);
> +	if (is_ipu7(isp->hw_ver) ||
> x86_match_cpu(ipu_misc_cfg_exclusion))
> +		val |= 0x100U;
> +	else
> +		val |= FIELD_PREP(WRXREQOP_OVRD_VAL_MASK, 0xf) |
> +			BIT(18) | 0x100U;
> +
> +	writel(val, isp->pb_base + BAR2_MISC_CONFIG);
> +	val = readl(isp->pb_base + BAR2_MISC_CONFIG);
> +
> +	if (is_ipu8(isp->hw_ver)) {
> +		writel(BIT(13), isp->pb_base +
> TLBID_HASH_ENABLE_63_32);
> +		writel(BIT(9), isp->pb_base +
> TLBID_HASH_ENABLE_95_64);
> +		dev_dbg(dev, "IPU8 TLBID_HASH %x %x\n",
> +			readl(isp->pb_base +
> TLBID_HASH_ENABLE_63_32),
> +			readl(isp->pb_base +
> TLBID_HASH_ENABLE_95_64));
> +	} else if (is_ipu7p5(isp->hw_ver)) {
> +		writel(BIT(14), isp->pb_base +
> TLBID_HASH_ENABLE_63_32);
> +		writel(BIT(9), isp->pb_base +
> TLBID_HASH_ENABLE_95_64);
> +		dev_dbg(dev, "IPU7P5 TLBID_HASH %x %x\n",
> +			readl(isp->pb_base +
> TLBID_HASH_ENABLE_63_32),
> +			readl(isp->pb_base +
> TLBID_HASH_ENABLE_95_64));
> +	} else {
> +		writel(BIT(22), isp->pb_base +
> TLBID_HASH_ENABLE_63_32);
> +		writel(BIT(1), isp->pb_base +
> TLBID_HASH_ENABLE_127_96);
> +		dev_dbg(dev, "TLBID_HASH %x %x\n",
> +			readl(isp->pb_base +
> TLBID_HASH_ENABLE_63_32),
> +			readl(isp->pb_base +
> TLBID_HASH_ENABLE_127_96));
> +	}
> +
> +	writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_IRQ_CLEAR);
> +	writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_IRQ_MASK);
> +	writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_IRQ_ENABLE);
> +	/* LNL SW workaround for PS PD hang when PS sub-domain
> during PD */
> +	writel(PS_FSM_CG, isp->base + BUTTRESS_REG_CG_CTRL_BITS);
> +}
> +
> +void ipu_buttress_restore(struct ipu7_device *isp)
> +{
> +	struct ipu_buttress *b = &isp->buttress;
> +
> +	ipu_buttress_setup(isp);
> +
> +	writel(b->wdt_cached_value, isp->base +
> BUTTRESS_REG_IDLE_WDT);
> +}
> +
> +int ipu_buttress_init(struct ipu7_device *isp)
> +{
> +	int ret, ipc_reset_retry = BUTTRESS_CSE_IPC_RESET_RETRY;
> +	struct ipu_buttress *b = &isp->buttress;
> +	struct device *dev = &isp->pdev->dev;
> +	u32 val;
> +
> +	mutex_init(&b->power_mutex);
> +	mutex_init(&b->auth_mutex);
> +	mutex_init(&b->cons_mutex);
> +	mutex_init(&b->ipc_mutex);
> +	init_completion(&b->cse.send_complete);
> +	init_completion(&b->cse.recv_complete);
> +
> +	b->cse.nack = BUTTRESS_CSE2IUDATA0_IPC_NACK;
> +	b->cse.nack_mask = BUTTRESS_CSE2IUDATA0_IPC_NACK_MASK;
> +	b->cse.csr_in = BUTTRESS_REG_CSE2IUCSR;
> +	b->cse.csr_out = BUTTRESS_REG_IU2CSECSR;
> +	b->cse.db0_in = BUTTRESS_REG_CSE2IUDB0;
> +	b->cse.db0_out = BUTTRESS_REG_IU2CSEDB0;
> +	b->cse.data0_in = BUTTRESS_REG_CSE2IUDATA0;
> +	b->cse.data0_out = BUTTRESS_REG_IU2CSEDATA0;
> +
> +	isp->secure_mode = ipu_buttress_get_secure_mode(isp);
> +	val = readl(isp->base + BUTTRESS_REG_IPU_SKU);
> +	dev_info(dev, "IPU%u SKU %u in %s mode mask 0x%x\n", val &
> 0xf,
> +		 (val >> 4) & 0x7, isp->secure_mode ? "secure" :
> "non-secure",
> +		 readl(isp->base + BUTTRESS_REG_CAMERA_MASK));
> +	b->wdt_cached_value = readl(isp->base +
> BUTTRESS_REG_IDLE_WDT);
> +	b->ref_clk = 384;
> +
> +	ipu_buttress_setup(isp);
> +
> +	/* Retry couple of times in case of CSE initialization is
> delayed */
> +	do {
> +		ret = ipu_buttress_ipc_reset(isp, &b->cse);
> +		if (ret) {
> +			dev_warn(dev, "IPC reset protocol failed,
> retrying\n");
> +		} else {
> +			dev_dbg(dev, "IPC reset done\n");
> +			return 0;
> +		}
> +	} while (ipc_reset_retry--);
> +
> +	dev_err(dev, "IPC reset protocol failed\n");
> +
> +	mutex_destroy(&b->power_mutex);
> +	mutex_destroy(&b->auth_mutex);
> +	mutex_destroy(&b->cons_mutex);
> +	mutex_destroy(&b->ipc_mutex);
> +
> +	return ret;
> +}
> +
> +void ipu_buttress_exit(struct ipu7_device *isp)
> +{
> +	struct ipu_buttress *b = &isp->buttress;
> +
> +	writel(0, isp->base + BUTTRESS_REG_IRQ_ENABLE);
> +	mutex_destroy(&b->power_mutex);
> +	mutex_destroy(&b->auth_mutex);
> +	mutex_destroy(&b->cons_mutex);
> +	mutex_destroy(&b->ipc_mutex);
> +}
> diff --git a/drivers/media/pci/intel/ipu7/ipu7-buttress.h
> b/drivers/media/pci/intel/ipu7/ipu7-buttress.h
> new file mode 100644
> index 000000000000..045b11992331
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu7/ipu7-buttress.h
> @@ -0,0 +1,84 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2013 - 2024 Intel Corporation
> + */
> +
> +#ifndef IPU7_BUTTRESS_H
> +#define IPU7_BUTTRESS_H
> +
> +#include <linux/completion.h>
> +#include <linux/irqreturn.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +
> +struct device;
> +struct ipu7_device;
> +
> +struct ipu_buttress_ctrl {
> +	u32 subsys_id;
> +	u32 freq_ctl, pwr_sts_shift, pwr_sts_mask, pwr_sts_on,
> pwr_sts_off;
> +	u32 ratio;
> +	u32 ratio_shift;
> +	u32 cdyn;
> +	u32 cdyn_shift;
> +	u32 ovrd_clk;
> +	u32 own_clk_ack;
> +};
> +
> +struct ipu_buttress_ipc {
> +	struct completion send_complete;
> +	struct completion recv_complete;
> +	u32 nack;
> +	u32 nack_mask;
> +	u32 recv_data;
> +	u32 csr_out;
> +	u32 csr_in;
> +	u32 db0_in;
> +	u32 db0_out;
> +	u32 data0_out;
> +	u32 data0_in;
> +};
> +
> +struct ipu_buttress {
> +	struct mutex power_mutex, auth_mutex, cons_mutex, ipc_mutex;
> +	struct ipu_buttress_ipc cse;
> +	u32 psys_min_freq;
> +	u32 wdt_cached_value;
> +	u8 psys_force_ratio;
> +	bool force_suspend;
> +	u32 ref_clk;
> +};
> +
> +struct ipu7_ipc_buttress_bulk_msg {
> +	u32 cmd;
> +	u32 expected_resp;
> +	bool require_resp;
> +	u8 cmd_size;
> +};
> +
> +int ipu_buttress_ipc_reset(struct ipu7_device *isp,
> +			   struct ipu_buttress_ipc *ipc);
> +int ipu_buttress_powerup(struct device *dev,
> +			 const struct ipu_buttress_ctrl *ctrl);
> +int ipu_buttress_powerdown(struct device *dev,
> +			   const struct ipu_buttress_ctrl *ctrl);
> +bool ipu_buttress_get_secure_mode(struct ipu7_device *isp);
> +int ipu_buttress_authenticate(struct ipu7_device *isp);
> +int ipu_buttress_reset_authentication(struct ipu7_device *isp);
> +bool ipu_buttress_auth_done(struct ipu7_device *isp);
> +int ipu_buttress_get_isys_freq(struct ipu7_device *isp, u32 *freq);
> +int ipu_buttress_get_psys_freq(struct ipu7_device *isp, u32 *freq);
> +int ipu_buttress_start_tsc_sync(struct ipu7_device *isp);
> +void ipu_buttress_tsc_read(struct ipu7_device *isp, u64 *val);
> +u64 ipu_buttress_tsc_ticks_to_ns(u64 ticks, const struct ipu7_device
> *isp);
> +
> +irqreturn_t ipu_buttress_isr(int irq, void *isp_ptr);
> +irqreturn_t ipu_buttress_isr_threaded(int irq, void *isp_ptr);
> +int ipu_buttress_init(struct ipu7_device *isp);
> +void ipu_buttress_exit(struct ipu7_device *isp);
> +void ipu_buttress_csi_port_config(struct ipu7_device *isp,
> +				  u32 legacy, u32 combo);
> +void ipu_buttress_restore(struct ipu7_device *isp);
> +void ipu_buttress_wakeup_is_uc(const struct ipu7_device *isp);
> +void ipu_buttress_wakeup_ps_uc(const struct ipu7_device *isp);
> +#endif /* IPU7_BUTTRESS_H */
> diff --git a/drivers/media/pci/intel/ipu7/ipu7-platform-regs.h
> b/drivers/media/pci/intel/ipu7/ipu7-platform-regs.h
> new file mode 100644
> index 000000000000..377acca35ab0
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu7/ipu7-platform-regs.h
> @@ -0,0 +1,146 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2018 - 2024 Intel Corporation
> + */
> +
> +#ifndef IPU7_PLATFORM_REGS_H
> +#define IPU7_PLATFORM_REGS_H
> +
> +#define IS_BASE					0x230000
> +#define IS_UC_CTRL_BASE				(IS_BASE +
> 0x0)
> +
> +#define PS_BASE					0x130000
> +#define PS_UC_CTRL_BASE				(PS_BASE +
> 0x0)
> +
> +/*
> + * bit 0: IRQ from FW,
> + * bit 1, 2 and 3: IRQ from HW
> + */
> +#define TO_SW_IRQ_MASK				0xf
> +#define TO_SW_IRQ_FW				BIT(0)
> +
> +#define FW_CODE_BASE				0x0
> +#define FW_DATA_BASE				0x4
> +#define CPU_AXI_CNTL				0x8
> +#define CPU_QOS_CNTL				0xc
> +#define IDMA_AXI_CNTL				0x10
> +#define IDMA_QOS_CNTL				0x14
> +#define MEF_SPLIT_SIZE				0x18
> +#define FW_MSG_CONTROL				0x1c
> +#define FW_MSG_CREDITS_STATUS			0x20
> +#define FW_MSG_CREDIT_TAKEN			0x24
> +#define FW_MSG_CREDIT_RETURNED			0x28
> +#define TRIG_IDMA_IN				0x2c
> +#define IDMA_DONE				0x30
> +#define IDMA_DONE_CLEAR				0x34
> +#define DMEM_CAPACITY				0x38
> +#define NON_SECURE_CODE_OFFSET			0x3c
> +#define UC_CG_CTRL_BITS				0x40
> +#define ALT_RESET_VEC				0x44
> +#define WDT_NMI_DURATION			0x104
> +#define WDT_RST_REQ_DURATION			0x108
> +#define WDT_CNTL				0x10c
> +#define WDT_NMI_CURRENT_COUNT			0x110
> +#define WDT_RST_CURRENT_COUNT			0x114
> +#define WDT_HALT				0x118
> +#define WDT_STATUS				0x11c
> +#define SPARE_REG_RW				0x120
> +#define SPARE_REG_RO				0x124
> +#define FW_TO_FW_IRQ_CNTL_EDGE			0x200
> +#define FW_TO_FW_IRQ_CNTL_MASK_N		0x204
> +#define FW_TO_FW_IRQ_CNTL_STATUS		0x208
> +#define FW_TO_FW_IRQ_CNTL_CLEAR			0x20c
> +#define FW_TO_FW_IRQ_CNTL_ENABLE		0x210
> +#define FW_TO_FW_IRQ_CNTL_LEVEL_NOT_PULSE	0x214
> +#define CLK_GATE_DIS				0x218
> +#define DEBUG_STATUS				0x1000
> +#define DEBUG_EXCPETION				0x1004
> +#define TIE_GENERAL_INPUT			0x1008
> +#define ERR_STATUS				0x100c
> +#define UC_ERR_INFO				0x1010
> +#define SPARE_CNTL				0x1014
> +#define MEF_TRC_CNTL				0x1100
> +#define DBG_MEF_LAST_PUSH			0x1104
> +#define DBG_MEF_LAST_POP			0x1108
> +#define DBG_MEF_COUNT_CNTL			0x110c
> +#define DBG_MEF_COUNT1				0x1110
> +#define DBG_MEF_COUNT2				0x1114
> +#define DBG_MEF_ACC_OCCUPANCY			0x1118
> +#define DBG_MEF_MAX_IRQ_TO_POP			0x111c
> +#define DBG_IRQ_CNTL				0x1120
> +#define DBG_IRQ_COUNT				0x1124
> +#define DBG_CYC_COUNT				0x1128
> +#define DBG_CNTL				0x1130
> +#define DBG_RST_REG				0x1134
> +#define DBG_MEF_STATUS0				0x1138
> +#define DBG_MEF_STATUS1				0x113c
> +#define PDEBUG_CTL				0x1140
> +#define PDEBUG_DATA				0x1144
> +#define PDEBUG_INST				0x1148
> +#define PDEBUG_LS0ADDR				0x114c
> +#define PDEBUG_LS0DATA				0x1150
> +#define PDEBUG_LS0STAT				0x1154
> +#define PDEBUG_PC				0x1158
> +#define PDEBUG_MISC				0x115c
> +#define PDEBUG_PREF_STS				0x1160
> +#define MEF0_ADDR				0x2000
> +#define MEF1_ADDR				0x2020
> +#define PRINTF_EN_THROUGH_TRACE			0x3004
> +#define PRINTF_EN_DIRECTLY_TO_DDR		0x3008
> +#define PRINTF_DDR_BASE_ADDR			0x300c
> +#define PRINTF_DDR_SIZE				0x3010
> +#define PRINTF_DDR_NEXT_ADDR			0x3014
> +#define PRINTF_STATUS				0x3018
> +#define PRINTF_AXI_CNTL				0x301c
> +#define PRINTF_MSG_LENGTH			0x3020
> +#define TO_SW_IRQ_CNTL_EDGE			0x4000
> +#define TO_SW_IRQ_CNTL_MASK_N			0x4004
> +#define TO_SW_IRQ_CNTL_STATUS			0x4008
> +#define TO_SW_IRQ_CNTL_CLEAR			0x400c
> +#define TO_SW_IRQ_CNTL_ENABLE			0x4010
> +#define TO_SW_IRQ_CNTL_LEVEL_NOT_PULSE		0x4014
> +#define ERR_IRQ_CNTL_EDGE			0x4018
> +#define ERR_IRQ_CNTL_MASK_N			0x401c
> +#define ERR_IRQ_CNTL_STATUS			0x4020
> +#define ERR_IRQ_CNTL_CLEAR			0x4024
> +#define ERR_IRQ_CNTL_ENABLE			0x4028
> +#define ERR_IRQ_CNTL_LEVEL_NOT_PULSE		0x402c
> +#define LOCAL_DMEM_BASE_ADDR			0x1300000
> +
> +/*
> + * IS_UC_TO_SW irqs
> + * bit 0: IRQ from local FW
> + * bit 1~3: IRQ from HW
> + */
> +#define IS_UC_TO_SW_IRQ_MASK			0xf
> +
> +#define IPU_ISYS_SPC_OFFSET			0x210000
> +#define IPU7_PSYS_SPC_OFFSET			0x118000
> +#define IPU_ISYS_DMEM_OFFSET			0x200000
> +#define IPU_PSYS_DMEM_OFFSET			0x100000
> +
> +#define IPU7_ISYS_CSI_PORT_NUM			4
> +
> +/* IRQ-related registers in PSYS */
> +#define IPU_REG_PSYS_TO_SW_IRQ_CNTL_EDGE		0x134000
> +#define IPU_REG_PSYS_TO_SW_IRQ_CNTL_MASK		0x134004
> +#define IPU_REG_PSYS_TO_SW_IRQ_CNTL_STATUS		0x134008
> +#define IPU_REG_PSYS_TO_SW_IRQ_CNTL_CLEAR		0x13400c
> +#define IPU_REG_PSYS_TO_SW_IRQ_CNTL_ENABLE		0x134010
> +#define IPU_REG_PSYS_TO_SW_IRQ_CNTL_LEVEL_NOT_PULSE	0x134014
> +#define IRQ_FROM_LOCAL_FW				BIT(0)
> +
> +/*
> + * psys subdomains power request regs
> + */
> +enum ipu7_device_buttress_psys_domain_pos {
> +	IPU_PSYS_SUBDOMAIN_LB		= 0,
> +	IPU_PSYS_SUBDOMAIN_BB		= 1,
> +};
> +
> +#define
> IPU7_PSYS_DOMAIN_POWER_MASK		(BIT(IPU_PSYS_SUBDOMAIN_LB) | \
> +						
> BIT(IPU_PSYS_SUBDOMAIN_BB))
> +#define
> IPU8_PSYS_DOMAIN_POWER_MASK		BIT(IPU_PSYS_SUBDOMAIN_LB)
> +#define IPU_PSYS_DOMAIN_POWER_IN_PROGRESS	BIT(31)
> +
> +#endif /* IPU7_PLATFORM_REGS_H */
> diff --git a/drivers/media/pci/intel/ipu7/ipu7.c
> b/drivers/media/pci/intel/ipu7/ipu7.c
> new file mode 100644
> index 000000000000..a0eec938fbea
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu7/ipu7.c
> @@ -0,0 +1,2791 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2013 - 2024 Intel Corporation
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/bug.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/kernel.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/property.h>
> +#include <linux/scatterlist.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/vmalloc.h>
> +#include <linux/version.h>
> +
> +#include <media/ipu-bridge.h>
> +
> +#include "abi/ipu7_fw_common_abi.h"
> +
> +#include "ipu7.h"
> +#include "ipu7-bus.h"
> +#include "ipu7-buttress.h"
> +#include "ipu7-buttress-regs.h"
> +#include "ipu7-cpd.h"
> +#include "ipu7-dma.h"
> +#include "ipu7-isys-csi2-regs.h"
> +#include "ipu7-mmu.h"
> +#include "ipu7-platform-regs.h"
> +
> +#define IPU_PCI_BAR		0
> +#define IPU_PCI_PBBAR		4
> +
> +static unsigned int ipu7_csi_offsets[] = {
> +	IPU_CSI_PORT_A_ADDR_OFFSET,
> +	IPU_CSI_PORT_B_ADDR_OFFSET,
> +	IPU_CSI_PORT_C_ADDR_OFFSET,
> +	IPU_CSI_PORT_D_ADDR_OFFSET,
> +};
> +
> +static struct ipu_isys_internal_pdata ipu7p5_isys_ipdata = {
> +	.csi2 = {
> +		.gpreg = IS_IO_CSI2_GPREGS_BASE,
> +	},
> +	.hw_variant = {
> +		.offset = IPU_UNIFIED_OFFSET,
> +		.nr_mmus = IPU7P5_IS_MMU_NUM,
> +		.mmu_hw = {
> +			{
> +				.name = "IS_FW_RD",
> +				.offset =
> IPU7P5_IS_MMU_FW_RD_OFFSET,
> +				.zlx_offset =
> IPU7P5_IS_ZLX_UC_RD_OFFSET,
> +				.uao_offset =
> IPU7P5_IS_UAO_UC_RD_OFFSET,
> +				.info_bits = 0x20005101,
> +				.refill = 0x00002726,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU7P5_IS_MMU_FW_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7P5_IS_MMU_FW_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7P5_IS_MMU_FW_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU7P5_IS_MMU_FW_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x8, 0xa,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4,
> +				},
> +				.zlx_nr = IPU7P5_IS_ZLX_UC_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					0, 1, 0, 0
> +				},
> +				.zlx_conf = {
> +					0x0,
> +				},
> +				.uao_p_num =
> IPU7P5_IS_UAO_UC_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000049,
> +					0x0000004c,
> +					0x0000004d,
> +					0x00000000,
> +				},
> +			},
> +			{
> +				.name = "IS_FW_WR",
> +				.offset =
> IPU7P5_IS_MMU_FW_WR_OFFSET,
> +				.zlx_offset =
> IPU7P5_IS_ZLX_UC_WR_OFFSET,
> +				.uao_offset =
> IPU7P5_IS_UAO_UC_WR_OFFSET,
> +				.info_bits = 0x20005001,
> +				.refill = 0x00002524,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU7P5_IS_MMU_FW_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7P5_IS_MMU_FW_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7P5_IS_MMU_FW_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU7P5_IS_MMU_FW_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x8, 0xa,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4,
> +				},
> +				.zlx_nr = IPU7P5_IS_ZLX_UC_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					0, 1, 1, 0,
> +				},
> +				.zlx_conf = {
> +					0x0,
> +					0x00010101,
> +					0x00010101,
> +					0x0,
> +				},
> +				.uao_p_num =
> IPU7P5_IS_UAO_UC_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000049,
> +					0x0000004a,
> +					0x0000004b,
> +					0x00000000,
> +				},
> +			},
> +			{
> +				.name = "IS_DATA_WR_ISOC",
> +				.offset = IPU7P5_IS_MMU_M0_OFFSET,
> +				.zlx_offset =
> IPU7P5_IS_ZLX_M0_OFFSET,
> +				.uao_offset =
> IPU7P5_IS_UAO_M0_WR_OFFSET,
> +				.info_bits = 0x20004e01,
> +				.refill = 0x00002120,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU7P5_IS_MMU_M0_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7P5_IS_MMU_M0_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7P5_IS_MMU_M0_STREAM_NUM,
> +				.nr_l2streams =
> IPU7P5_IS_MMU_M0_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.zlx_nr = IPU7P5_IS_ZLX_M0_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f10,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +				},
> +				.zlx_conf = {
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +				},
> +				.uao_p_num =
> IPU7P5_IS_UAO_M0_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000041,
> +					0x00000042,
> +					0x00000043,
> +					0x00000044,
> +					0x00000041,
> +					0x00000042,
> +					0x00000043,
> +					0x00000044,
> +					0x00000041,
> +					0x00000042,
> +					0x00000043,
> +					0x00000044,
> +					0x00000041,
> +					0x00000042,
> +					0x00000043,
> +					0x00000044,
> +				},
> +			},
> +			{
> +				.name = "IS_DATA_WR_SNOOP",
> +				.offset = IPU7P5_IS_MMU_M1_OFFSET,
> +				.zlx_offset =
> IPU7P5_IS_ZLX_M1_OFFSET,
> +				.uao_offset =
> IPU7P5_IS_UAO_M1_WR_OFFSET,
> +				.info_bits = 0x20004f01,
> +				.refill = 0x00002322,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU7P5_IS_MMU_M1_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7P5_IS_MMU_M1_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7P5_IS_MMU_M1_STREAM_NUM,
> +				.nr_l2streams =
> IPU7P5_IS_MMU_M1_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.zlx_nr = IPU7P5_IS_ZLX_M1_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +				},
> +				.zlx_conf = {
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +				},
> +				.uao_p_num =
> IPU7P5_IS_UAO_M1_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000045,
> +					0x00000046,
> +					0x00000047,
> +					0x00000048,
> +					0x00000045,
> +					0x00000046,
> +					0x00000047,
> +					0x00000048,
> +					0x00000045,
> +					0x00000046,
> +					0x00000047,
> +					0x00000048,
> +					0x00000045,
> +					0x00000046,
> +					0x00000047,
> +					0x00000048,
> +				},
> +			},
> +		},
> +		.cdc_fifos = 3,
> +		.cdc_fifo_threshold = {6, 8, 2},
> +		.dmem_offset = IPU_ISYS_DMEM_OFFSET,
> +		.spc_offset = IPU_ISYS_SPC_OFFSET,
> +	},
> +	.isys_dma_overshoot = IPU_ISYS_OVERALLOC_MIN,
> +};
> +
> +static struct ipu_psys_internal_pdata ipu7p5_psys_ipdata = {
> +	.hw_variant = {
> +		.offset = IPU_UNIFIED_OFFSET,
> +		.nr_mmus = IPU7P5_PS_MMU_NUM,
> +		.mmu_hw = {
> +			{
> +				.name = "PS_FW_RD",
> +				.offset =
> IPU7P5_PS_MMU_FW_RD_OFFSET,
> +				.zlx_offset =
> IPU7P5_PS_ZLX_FW_RD_OFFSET,
> +				.uao_offset =
> IPU7P5_PS_UAO_FW_RD_OFFSET,
> +				.info_bits = 0x20004001,
> +				.refill = 0x00002726,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU7P5_PS_MMU_FW_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7P5_PS_MMU_FW_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7P5_PS_MMU_FW_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU7P5_PS_MMU_FW_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000d,
> +					0x0000000f,
> +					0x00000011,
> +					0x00000012,
> +					0x00000013,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x00000019,
> +					0x0000001a,
> +					0x0000001a,
> +					0x0000001a,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.zlx_nr = IPU7P5_PS_ZLX_FW_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					0, 1, 0, 0, 1, 1, 0, 0,
> +					0, 1, 1, 0, 0, 0, 0, 0,
> +				},
> +				.zlx_conf = {
> +					0x00000000,
> +					0x00010101,
> +					0x00000000,
> +					0x00000000,
> +					0x00010101,
> +					0x00010101,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00010101,
> +					0x00010101,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +				},
> +				.uao_p_num =
> IPU7P5_PS_UAO_FW_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x0000002e,
> +					0x00000035,
> +					0x00000036,
> +					0x00000031,
> +					0x00000037,
> +					0x00000038,
> +					0x00000039,
> +					0x00000032,
> +					0x00000033,
> +					0x0000003a,
> +					0x0000003b,
> +					0x0000003c,
> +					0x00000034,
> +					0x0,
> +					0x0,
> +					0x0,
> +				},
> +			},
> +			{
> +				.name = "PS_FW_WR",
> +				.offset =
> IPU7P5_PS_MMU_FW_WR_OFFSET,
> +				.zlx_offset =
> IPU7P5_PS_ZLX_FW_WR_OFFSET,
> +				.uao_offset =
> IPU7P5_PS_UAO_FW_WR_OFFSET,
> +				.info_bits = 0x20003e01,
> +				.refill = 0x00002322,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU7P5_PS_MMU_FW_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7P5_PS_MMU_FW_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7P5_PS_MMU_FW_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU7P5_PS_MMU_FW_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000d,
> +					0x0000000e,
> +					0x0000000f,
> +					0x00000010,
> +					0x00000010,
> +					0x00000010,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +				},
> +				.zlx_nr = IPU7P5_PS_ZLX_FW_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					0, 1, 1, 0, 0, 0, 0, 0, 0,
> 0,
> +				},
> +				.zlx_conf = {
> +					0x00000000,
> +					0x00010101,
> +					0x00010101,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +				},
> +				.uao_p_num =
> IPU7P5_PS_UAO_FW_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x0000002e,
> +					0x0000002f,
> +					0x00000030,
> +					0x00000031,
> +					0x00000032,
> +					0x00000033,
> +					0x00000034,
> +					0x0,
> +					0x0,
> +					0x0,
> +				},
> +			},
> +			{
> +				.name = "PS_DATA_RD",
> +				.offset =
> IPU7P5_PS_MMU_SRT_RD_OFFSET,
> +				.zlx_offset =
> IPU7P5_PS_ZLX_DATA_RD_OFFSET,
> +				.uao_offset =
> IPU7P5_PS_UAO_SRT_RD_OFFSET,
> +				.info_bits = 0x20003f01,
> +				.refill = 0x00002524,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU7P5_PS_MMU_SRT_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7P5_PS_MMU_SRT_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7P5_PS_MMU_SRT_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU7P5_PS_MMU_SRT_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000b,
> +					0x0000000d,
> +					0x0000000f,
> +					0x00000013,
> +					0x00000017,
> +					0x00000019,
> +					0x0000001b,
> +					0x0000001d,
> +					0x0000001f,
> +					0x0000002b,
> +					0x00000033,
> +					0x0000003f,
> +					0x00000047,
> +					0x00000049,
> +					0x0000004b,
> +					0x0000004c,
> +					0x0000004d,
> +					0x0000004e,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +					0x00000020,
> +					0x00000022,
> +					0x00000024,
> +					0x00000026,
> +					0x00000028,
> +					0x0000002a,
> +				},
> +				.zlx_nr = IPU7P5_PS_ZLX_DATA_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 0, 0, 0, 0,
> +				},
> +				.zlx_conf = {
> +					0x00030303,
> +					0x00010101,
> +					0x00010101,
> +					0x00030202,
> +					0x00010101,
> +					0x00010101,
> +					0x00030303,
> +					0x00030303,
> +					0x00010101,
> +					0x00030800,
> +					0x00030500,
> +					0x00020101,
> +					0x00042000,
> +					0x00031000,
> +					0x00042000,
> +					0x00031000,
> +					0x00020400,
> +					0x00010101,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +				},
> +				.uao_p_num =
> IPU7P5_PS_UAO_SRT_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x0000001c,
> +					0x0000001d,
> +					0x0000001e,
> +					0x0000001f,
> +					0x00000020,
> +					0x00000021,
> +					0x00000022,
> +					0x00000023,
> +					0x00000024,
> +					0x00000025,
> +					0x00000026,
> +					0x00000027,
> +					0x00000028,
> +					0x00000029,
> +					0x0000002a,
> +					0x0000002b,
> +					0x0000002c,
> +					0x0000002d,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +				},
> +			},
> +			{
> +				.name = "PS_DATA_WR",
> +				.offset =
> IPU7P5_PS_MMU_SRT_WR_OFFSET,
> +				.zlx_offset =
> IPU7P5_PS_ZLX_DATA_WR_OFFSET,
> +				.uao_offset =
> IPU7P5_PS_UAO_SRT_WR_OFFSET,
> +				.info_bits = 0x20003d01,
> +				.refill = 0x00002120,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU7P5_PS_MMU_SRT_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7P5_PS_MMU_SRT_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7P5_PS_MMU_SRT_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU7P5_PS_MMU_SRT_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000006,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +					0x00000020,
> +					0x00000022,
> +					0x00000024,
> +					0x00000028,
> +					0x0000002a,
> +					0x00000036,
> +					0x0000003e,
> +					0x00000040,
> +					0x00000042,
> +					0x0000004e,
> +					0x00000056,
> +					0x0000005c,
> +					0x00000068,
> +					0x00000070,
> +					0x00000076,
> +					0x00000077,
> +					0x00000078,
> +					0x00000079,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000006,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +					0x00000020,
> +					0x00000022,
> +					0x00000024,
> +					0x00000028,
> +					0x0000002a,
> +					0x00000036,
> +					0x0000003e,
> +					0x00000040,
> +					0x00000042,
> +					0x0000004e,
> +					0x00000056,
> +					0x0000005c,
> +					0x00000068,
> +					0x00000070,
> +					0x00000076,
> +					0x00000077,
> +					0x00000078,
> +					0x00000079,
> +				},
> +				.zlx_nr = IPU7P5_PS_ZLX_DATA_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f50,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					0, 0, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 0, 0, 0, 0,
> +				},
> +				.zlx_conf = {
> +					0x00010102,
> +					0x00030103,
> +					0x00030103,
> +					0x00010101,
> +					0x00010101,
> +					0x00030101,
> +					0x00010101,
> +					0x38010101,
> +					0x00000000,
> +					0x00000000,
> +					0x38010101,
> +					0x38010101,
> +					0x38010101,
> +					0x38010101,
> +					0x38010101,
> +					0x38010101,
> +					0x00030303,
> +					0x00010101,
> +					0x00042000,
> +					0x00031000,
> +					0x00010101,
> +					0x00010101,
> +					0x00042000,
> +					0x00031000,
> +					0x00031000,
> +					0x00042000,
> +					0x00031000,
> +					0x00031000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +				},
> +				.uao_p_num =
> IPU7P5_PS_UAO_SRT_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000000,
> +					0x00000001,
> +					0x00000002,
> +					0x00000003,
> +					0x00000004,
> +					0x00000005,
> +					0x00000006,
> +					0x00000007,
> +					0x00000008,
> +					0x00000009,
> +					0x0000000a,
> +					0x0000000b,
> +					0x0000000c,
> +					0x0000000d,
> +					0x0000000e,
> +					0x0000000f,
> +					0x00000010,
> +					0x00000011,
> +					0x00000012,
> +					0x00000013,
> +					0x00000014,
> +					0x00000015,
> +					0x00000016,
> +					0x00000017,
> +					0x00000018,
> +					0x00000019,
> +					0x0000001a,
> +					0x0000001b,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +				},
> +			},
> +		},
> +		.dmem_offset = IPU_PSYS_DMEM_OFFSET,
> +	},
> +};
> +
> +static struct ipu_isys_internal_pdata ipu7_isys_ipdata = {
> +	.csi2 = {
> +		.gpreg = IS_IO_CSI2_GPREGS_BASE,
> +	},
> +	.hw_variant = {
> +		.offset = IPU_UNIFIED_OFFSET,
> +		.nr_mmus = IPU7_IS_MMU_NUM,
> +		.mmu_hw = {
> +			{
> +				.name = "IS_FW_RD",
> +				.offset = IPU7_IS_MMU_FW_RD_OFFSET,
> +				.zlx_offset =
> IPU7_IS_ZLX_UC_RD_OFFSET,
> +				.uao_offset =
> IPU7_IS_UAO_UC_RD_OFFSET,
> +				.info_bits = 0x20006701,
> +				.refill = 0x00002726,
> +				.collapse_en_bitmap = 0x0,
> +				.l1_block =
> IPU7_IS_MMU_FW_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7_IS_MMU_FW_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7_IS_MMU_FW_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU7_IS_MMU_FW_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x8, 0xa,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4,
> +				},
> +				.zlx_nr = IPU7_IS_ZLX_UC_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					0, 0, 0, 0
> +				},
> +				.zlx_conf = {
> +					0x0, 0x0, 0x0, 0x0,
> +				},
> +				.uao_p_num =
> IPU7_IS_UAO_UC_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000061,
> +					0x00000064,
> +					0x00000065,
> +				},
> +			},
> +			{
> +				.name = "IS_FW_WR",
> +				.offset = IPU7_IS_MMU_FW_WR_OFFSET,
> +				.zlx_offset =
> IPU7_IS_ZLX_UC_WR_OFFSET,
> +				.uao_offset =
> IPU7_IS_UAO_UC_WR_OFFSET,
> +				.info_bits = 0x20006801,
> +				.refill = 0x00002524,
> +				.collapse_en_bitmap = 0x0,
> +				.l1_block =
> IPU7_IS_MMU_FW_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7_IS_MMU_FW_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7_IS_MMU_FW_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU7_IS_MMU_FW_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x8, 0xa,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4,
> +				},
> +				.zlx_nr = IPU7_IS_ZLX_UC_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					0, 1, 1, 0,
> +				},
> +				.zlx_conf = {
> +					0x0,
> +					0x00010101,
> +					0x00010101,
> +				},
> +				.uao_p_num =
> IPU7_IS_UAO_UC_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000061,
> +					0x00000062,
> +					0x00000063,
> +				},
> +			},
> +			{
> +				.name = "IS_DATA_WR_ISOC",
> +				.offset = IPU7_IS_MMU_M0_OFFSET,
> +				.zlx_offset = IPU7_IS_ZLX_M0_OFFSET,
> +				.uao_offset =
> IPU7_IS_UAO_M0_WR_OFFSET,
> +				.info_bits = 0x20006601,
> +				.refill = 0x00002120,
> +				.collapse_en_bitmap = 0x0,
> +				.l1_block =
> IPU7_IS_MMU_M0_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7_IS_MMU_M0_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7_IS_MMU_M0_STREAM_NUM,
> +				.nr_l2streams =
> IPU7_IS_MMU_M0_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x3, 0x6, 0x8, 0xa,
> 0xc, 0xe, 0x10,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4, 0x6, 0x8,
> 0xa, 0xc, 0xe,
> +				},
> +				.zlx_nr = IPU7_IS_ZLX_M0_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f10,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +				},
> +				.zlx_conf = {
> +					0x00010103,
> +					0x00010103,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +				},
> +				.uao_p_num =
> IPU7_IS_UAO_M0_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000049,
> +					0x0000004a,
> +					0x0000004b,
> +					0x0000004c,
> +					0x0000004d,
> +					0x0000004e,
> +					0x0000004f,
> +					0x00000050,
> +				},
> +			},
> +			{
> +				.name = "IS_DATA_WR_SNOOP",
> +				.offset = IPU7_IS_MMU_M1_OFFSET,
> +				.zlx_offset = IPU7_IS_ZLX_M1_OFFSET,
> +				.uao_offset =
> IPU7_IS_UAO_M1_WR_OFFSET,
> +				.info_bits = 0x20006901,
> +				.refill = 0x00002322,
> +				.collapse_en_bitmap = 0x0,
> +				.l1_block =
> IPU7_IS_MMU_M1_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7_IS_MMU_M1_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7_IS_MMU_M1_STREAM_NUM,
> +				.nr_l2streams =
> IPU7_IS_MMU_M1_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x3, 0x6, 0x9, 0xc,
> +					0xe, 0x10, 0x12, 0x14, 0x16,
> +					0x18, 0x1a, 0x1c, 0x1e,
> 0x20,
> +					0x22,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4, 0x6, 0x8,
> +					0xa, 0xc, 0xe, 0x10, 0x12,
> +					0x14, 0x16, 0x18, 0x1a,
> 0x1c,
> +					0x1e,
> +				},
> +				.zlx_nr = IPU7_IS_ZLX_M1_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +				},
> +				.zlx_conf = {
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010103,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +				},
> +				.uao_p_num =
> IPU7_IS_UAO_M1_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000051,
> +					0x00000052,
> +					0x00000053,
> +					0x00000054,
> +					0x00000055,
> +					0x00000056,
> +					0x00000057,
> +					0x00000058,
> +					0x00000059,
> +					0x0000005a,
> +					0x0000005b,
> +					0x0000005c,
> +					0x0000005d,
> +					0x0000005e,
> +					0x0000005f,
> +					0x00000060,
> +				},
> +			},
> +		},
> +		.cdc_fifos = 3,
> +		.cdc_fifo_threshold = {6, 8, 2},
> +		.dmem_offset = IPU_ISYS_DMEM_OFFSET,
> +		.spc_offset = IPU_ISYS_SPC_OFFSET,
> +	},
> +	.isys_dma_overshoot = IPU_ISYS_OVERALLOC_MIN,
> +};
> +
> +static struct ipu_psys_internal_pdata ipu7_psys_ipdata = {
> +	.hw_variant = {
> +		.offset = IPU_UNIFIED_OFFSET,
> +		.nr_mmus = IPU7_PS_MMU_NUM,
> +		.mmu_hw = {
> +			{
> +				.name = "PS_FW_RD",
> +				.offset = IPU7_PS_MMU_FW_RD_OFFSET,
> +				.zlx_offset =
> IPU7_PS_ZLX_FW_RD_OFFSET,
> +				.uao_offset =
> IPU7_PS_UAO_FW_RD_OFFSET,
> +				.info_bits = 0x20004801,
> +				.refill = 0x00002726,
> +				.collapse_en_bitmap = 0x0,
> +				.l1_block =
> IPU7_PS_MMU_FW_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7_PS_MMU_FW_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7_PS_MMU_FW_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU7_PS_MMU_FW_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0, 0x8, 0xa, 0xc, 0xd,
> +					0xf, 0x11, 0x12, 0x13, 0x14,
> +					0x16, 0x18, 0x19, 0x1a,
> 0x1a,
> +					0x1a, 0x1a, 0x1a, 0x1a,
> 0x1a,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4, 0x6, 0x8,
> +					0xa, 0xc, 0xe, 0x10, 0x12,
> +					0x14, 0x16, 0x18, 0x1a,
> 0x1c,
> +					0x1e, 0x20, 0x22, 0x24,
> 0x26,
> +				},
> +				.zlx_nr = IPU7_PS_ZLX_FW_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					0, 0, 0, 0, 0, 0, 0, 0,
> +					0, 0, 0, 0, 0, 0, 0, 0,
> +				},
> +				.zlx_conf = {
> +					0x0,
> +				},
> +				.uao_p_num =
> IPU7_PS_UAO_FW_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000036,
> +					0x0000003d,
> +					0x0000003e,
> +					0x00000039,
> +					0x0000003f,
> +					0x00000040,
> +					0x00000041,
> +					0x0000003a,
> +					0x0000003b,
> +					0x00000042,
> +					0x00000043,
> +					0x00000044,
> +					0x0000003c,
> +				},
> +			},
> +			{
> +				.name = "PS_FW_WR",
> +				.offset = IPU7_PS_MMU_FW_WR_OFFSET,
> +				.zlx_offset =
> IPU7_PS_ZLX_FW_WR_OFFSET,
> +				.uao_offset =
> IPU7_PS_UAO_FW_WR_OFFSET,
> +				.info_bits = 0x20004601,
> +				.refill = 0x00002322,
> +				.collapse_en_bitmap = 0x0,
> +				.l1_block =
> IPU7_PS_MMU_FW_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7_PS_MMU_FW_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7_PS_MMU_FW_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU7_PS_MMU_FW_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0, 0x8, 0xa, 0xc, 0xd,
> +					0xe, 0xf, 0x10, 0x10, 0x10,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4, 0x6, 0x8,
> +					0xa, 0xc, 0xe, 0x10, 0x12,
> +				},
> +				.zlx_nr = IPU7_PS_ZLX_FW_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					0, 1, 1, 0, 0, 0, 0, 0,
> +					0, 0,
> +				},
> +				.zlx_conf = {
> +					0x0,
> +					0x00010101,
> +					0x00010101,
> +				},
> +				.uao_p_num =
> IPU7_PS_UAO_FW_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000036,
> +					0x00000037,
> +					0x00000038,
> +					0x00000039,
> +					0x0000003a,
> +					0x0000003b,
> +					0x0000003c,
> +				},
> +			},
> +			{
> +				.name = "PS_DATA_RD",
> +				.offset = IPU7_PS_MMU_SRT_RD_OFFSET,
> +				.zlx_offset =
> IPU7_PS_ZLX_DATA_RD_OFFSET,
> +				.uao_offset =
> IPU7_PS_UAO_SRT_RD_OFFSET,
> +				.info_bits = 0x20004701,
> +				.refill = 0x00002120,
> +				.collapse_en_bitmap = 0x0,
> +				.l1_block =
> IPU7_PS_MMU_SRT_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7_PS_MMU_SRT_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7_PS_MMU_SRT_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU7_PS_MMU_SRT_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x4, 0x6, 0x8, 0xb,
> +					0xd, 0xf, 0x11, 0x13, 0x15,
> +					0x17, 0x23, 0x2b, 0x37,
> 0x3f,
> +					0x41, 0x43, 0x44, 0x45,
> 0x46,
> +					0x47, 0x48, 0x49, 0x4a,
> 0x4b,
> +					0x4c, 0x4d, 0x4e, 0x4f,
> 0x50,
> +					0x51, 0x52, 0x53, 0x55,
> 0x57,
> +					0x59, 0x5b, 0x5d, 0x5f,
> 0x61,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4, 0x6, 0x8,
> +					0xa, 0xc, 0xe, 0x10, 0x12,
> +					0x14, 0x16, 0x18, 0x1a,
> 0x1c,
> +					0x1e, 0x20, 0x22, 0x24,
> 0x26,
> +					0x28, 0x2a, 0x2c, 0x2e,
> 0x30,
> +					0x32, 0x34, 0x36, 0x38,
> 0x3a,
> +					0x3c, 0x3e, 0x40, 0x42,
> 0x44,
> +					0x46, 0x48, 0x4a, 0x4c,
> 0x4e,
> +				},
> +				.zlx_nr = IPU7_PS_ZLX_DATA_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					0, 0, 0, 0, 0, 0, 0, 0,
> +					0, 0, 0, 0, 0, 0, 0, 0,
> +				},
> +				.zlx_conf = {
> +					0x00030303,
> +					0x00010101,
> +					0x00010101,
> +					0x00030202,
> +					0x00010101,
> +					0x00010101,
> +					0x00010101,
> +					0x00030800,
> +					0x00030500,
> +					0x00020101,
> +					0x00042000,
> +					0x00031000,
> +					0x00042000,
> +					0x00031000,
> +					0x00020400,
> +					0x00010101,
> +				},
> +				.uao_p_num =
> IPU7_PS_UAO_SRT_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000022,
> +					0x00000023,
> +					0x00000024,
> +					0x00000025,
> +					0x00000026,
> +					0x00000027,
> +					0x00000028,
> +					0x00000029,
> +					0x0000002a,
> +					0x0000002b,
> +					0x0000002c,
> +					0x0000002d,
> +					0x0000002e,
> +					0x0000002f,
> +					0x00000030,
> +					0x00000031,
> +					0x0, 0x0, 0x0, 0x0, 0x0,
> 0x0, 0x0, 0x0,
> +					0x0, 0x0, 0x0, 0x0, 0x0,
> 0x0, 0x0, 0x0,
> +					0x0000001e,
> +					0x0000001f,
> +					0x00000020,
> +					0x00000021,
> +					0x00000032,
> +					0x00000033,
> +					0x00000034,
> +					0x00000035,
> +				},
> +			},
> +			{
> +				.name = "PS_DATA_WR",
> +				.offset = IPU7_PS_MMU_SRT_WR_OFFSET,
> +				.zlx_offset =
> IPU7_PS_ZLX_DATA_WR_OFFSET,
> +				.uao_offset =
> IPU7_PS_UAO_SRT_WR_OFFSET,
> +				.info_bits = 0x20004501,
> +				.refill = 0x00002120,
> +				.collapse_en_bitmap = 0x0,
> +				.l1_block =
> IPU7_PS_MMU_SRT_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU7_PS_MMU_SRT_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU7_PS_MMU_SRT_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU7_PS_MMU_SRT_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x2, 0x6, 0xa, 0xc,
> +					0xe, 0x10, 0x12, 0x14, 0x16,
> +					0x18, 0x1a, 0x1c, 0x1e,
> 0x20,
> +					0x22, 0x24, 0x26, 0x32,
> 0x3a,
> +					0x3c, 0x3e, 0x4a, 0x52,
> 0x58,
> +					0x64, 0x6c, 0x72, 0x7e,
> 0x86,
> +					0x8c, 0x8d, 0x8e, 0x8f,
> 0x90,
> +					0x91, 0x92, 0x94, 0x96,
> 0x98,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4, 0x6, 0x8,
> +					0xa, 0xc, 0xe, 0x10, 0x12,
> +					0x14, 0x16, 0x18, 0x1a,
> 0x1c,
> +					0x1e, 0x20, 0x22, 0x24,
> 0x26,
> +					0x28, 0x2a, 0x2c, 0x2e,
> 0x30,
> +					0x32, 0x34, 0x36, 0x38,
> 0x3a,
> +					0x3c, 0x3e, 0x40, 0x42,
> 0x44,
> +					0x46, 0x48, 0x4a, 0x4c,
> 0x4e,
> +				},
> +				.zlx_nr = IPU7_PS_ZLX_DATA_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f50,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					0, 0, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 0, 0,
> +				},
> +				.zlx_conf = {
> +					0x00010102,
> +					0x00030103,
> +					0x00030103,
> +					0x00010101,
> +					0x00010101,
> +					0x00030101,
> +					0x00010101,
> +					0x38010101,
> +					0x0,
> +					0x0,
> +					0x38010101,
> +					0x38010101,
> +					0x38010101,
> +					0x38010101,
> +					0x38010101,
> +					0x38010101,
> +					0x00010101,
> +					0x00042000,
> +					0x00031000,
> +					0x00010101,
> +					0x00010101,
> +					0x00042000,
> +					0x00031000,
> +					0x00031000,
> +					0x00042000,
> +					0x00031000,
> +					0x00031000,
> +					0x00042000,
> +					0x00031000,
> +					0x00031000,
> +					0x0,
> +					0x0,
> +				},
> +				.uao_p_num =
> IPU7_PS_UAO_SRT_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000000,
> +					0x00000001,
> +					0x00000002,
> +					0x00000003,
> +					0x00000004,
> +					0x00000005,
> +					0x00000006,
> +					0x00000007,
> +					0x00000008,
> +					0x00000009,
> +					0x0000000a,
> +					0x0000000b,
> +					0x0000000c,
> +					0x0000000d,
> +					0x0000000e,
> +					0x0000000f,
> +					0x00000010,
> +					0x00000011,
> +					0x00000012,
> +					0x00000013,
> +					0x00000014,
> +					0x00000015,
> +					0x00000016,
> +					0x00000017,
> +					0x00000018,
> +					0x00000019,
> +					0x0000001a,
> +					0x0000001b,
> +					0x0000001c,
> +					0x0000001d,
> +					0x0, 0x0, 0x0, 0x0, 0x0,
> 0x0,
> +					0x0000001e,
> +					0x0000001f,
> +					0x00000020,
> +					0x00000021,
> +				},
> +			},
> +		},
> +		.dmem_offset = IPU_PSYS_DMEM_OFFSET,
> +	},
> +};
> +
> +static struct ipu_isys_internal_pdata ipu8_isys_ipdata = {
> +	.csi2 = {
> +		.gpreg = IPU8_IS_IO_CSI2_GPREGS_BASE,
> +	},
> +	.hw_variant = {
> +		.offset = IPU_UNIFIED_OFFSET,
> +		.nr_mmus = IPU8_IS_MMU_NUM,
> +		.mmu_hw = {
> +			{
> +				.name = "IS_FW_RD",
> +				.offset = IPU8_IS_MMU_FW_RD_OFFSET,
> +				.zlx_offset =
> IPU8_IS_ZLX_UC_RD_OFFSET,
> +				.uao_offset =
> IPU8_IS_UAO_UC_RD_OFFSET,
> +				.info_bits = 0x20005101,
> +				.refill = 0x00002726,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_IS_MMU_FW_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_IS_MMU_FW_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_IS_MMU_FW_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_IS_MMU_FW_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x8, 0xa,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4,
> +				},
> +				.zlx_nr = IPU8_IS_ZLX_UC_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					0, 1, 0, 0
> +				},
> +				.zlx_conf = {
> +					0, 2, 0, 0
> +				},
> +				.uao_p_num =
> IPU8_IS_UAO_UC_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000049,
> +					0x0000004c,
> +					0x0000004d,
> +					0x00000000,
> +				},
> +			},
> +			{
> +				.name = "IS_FW_WR",
> +				.offset = IPU8_IS_MMU_FW_WR_OFFSET,
> +				.zlx_offset =
> IPU8_IS_ZLX_UC_WR_OFFSET,
> +				.uao_offset =
> IPU8_IS_UAO_UC_WR_OFFSET,
> +				.info_bits = 0x20005001,
> +				.refill = 0x00002524,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_IS_MMU_FW_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_IS_MMU_FW_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_IS_MMU_FW_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_IS_MMU_FW_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x0, 0x8, 0xa,
> +				},
> +				.l2_block_sz = {
> +					0x0, 0x2, 0x4,
> +				},
> +				.zlx_nr = IPU8_IS_ZLX_UC_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					0, 1, 1, 0,
> +				},
> +				.zlx_conf = {
> +					0x0,
> +					0x2,
> +					0x2,
> +					0x0,
> +				},
> +				.uao_p_num =
> IPU8_IS_UAO_UC_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000049,
> +					0x0000004a,
> +					0x0000004b,
> +					0x00000000,
> +				},
> +			},
> +			{
> +				.name = "IS_DATA_WR_ISOC",
> +				.offset = IPU8_IS_MMU_M0_OFFSET,
> +				.zlx_offset = IPU8_IS_ZLX_M0_OFFSET,
> +				.uao_offset =
> IPU8_IS_UAO_M0_WR_OFFSET,
> +				.info_bits = 0x20004e01,
> +				.refill = 0x00002120,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_IS_MMU_M0_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_IS_MMU_M0_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_IS_MMU_M0_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_IS_MMU_M0_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.zlx_nr = IPU8_IS_ZLX_M0_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f10,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +				},
> +				.zlx_conf = {
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +				},
> +				.uao_p_num =
> IPU8_IS_UAO_M0_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x0000003b,
> +					0x0000003c,
> +					0x0000003d,
> +					0x0000003e,
> +					0x0000003b,
> +					0x0000003c,
> +					0x0000003d,
> +					0x0000003e,
> +					0x0000003b,
> +					0x0000003c,
> +					0x0000003d,
> +					0x0000003e,
> +					0x0000003b,
> +					0x0000003c,
> +					0x0000003d,
> +					0x0000003e,
> +				},
> +			},
> +			{
> +				.name = "IS_DATA_WR_SNOOP",
> +				.offset = IPU8_IS_MMU_M1_OFFSET,
> +				.zlx_offset = IPU8_IS_ZLX_M1_OFFSET,
> +				.uao_offset =
> IPU8_IS_UAO_M1_WR_OFFSET,
> +				.info_bits = 0x20004f01,
> +				.refill = 0x00002322,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_IS_MMU_M1_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_IS_MMU_M1_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_IS_MMU_M1_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_IS_MMU_M1_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +				},
> +				.zlx_nr = IPU8_IS_ZLX_M1_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +				},
> +				.zlx_conf = {
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +				},
> +				.uao_p_num =
> IPU8_IS_UAO_M1_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x0000003f,
> +					0x00000040,
> +					0x00000041,
> +					0x00000042,
> +					0x0000003f,
> +					0x00000040,
> +					0x00000041,
> +					0x00000042,
> +					0x0000003f,
> +					0x00000040,
> +					0x00000041,
> +					0x00000042,
> +					0x0000003f,
> +					0x00000040,
> +					0x00000041,
> +					0x00000042,
> +				},
> +			},
> +			{
> +				.name = "IS_UPIPE",
> +				.offset = IPU8_IS_MMU_UPIPE_OFFSET,
> +				.zlx_offset =
> IPU8_IS_ZLX_UPIPE_OFFSET,
> +				.uao_offset =
> IPU8_IS_UAO_UPIPE_OFFSET,
> +				.info_bits = 0x20005201,
> +				.refill = 0x00002928,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_IS_MMU_UPIPE_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_IS_MMU_UPIPE_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_IS_MMU_UPIPE_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_IS_MMU_UPIPE_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +				},
> +				.zlx_nr = IPU8_IS_ZLX_UPIPE_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1,
> +				},
> +				.zlx_conf = {
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +					0x3,
> +				},
> +				.uao_p_num =
> IPU8_IS_UAO_UPIPE_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000043,
> +					0x00000044,
> +					0x00000045,
> +					0x00000046,
> +					0x00000047,
> +					0x00000048,
> +				},
> +			},
> +		},
> +		.cdc_fifos = 3,
> +		.cdc_fifo_threshold = {6, 8, 2},
> +		.dmem_offset = IPU_ISYS_DMEM_OFFSET,
> +		.spc_offset = IPU_ISYS_SPC_OFFSET,
> +	},
> +	.isys_dma_overshoot = IPU_ISYS_OVERALLOC_MIN,
> +};
> +
> +static struct ipu_psys_internal_pdata ipu8_psys_ipdata = {
> +	.hw_variant = {
> +		.offset = IPU_UNIFIED_OFFSET,
> +		.nr_mmus = IPU8_PS_MMU_NUM,
> +		.mmu_hw = {
> +			{
> +				.name = "PS_FW_RD",
> +				.offset = IPU8_PS_MMU_FW_RD_OFFSET,
> +				.zlx_offset =
> IPU8_PS_ZLX_FW_RD_OFFSET,
> +				.uao_offset =
> IPU8_PS_UAO_FW_RD_OFFSET,
> +				.info_bits = 0x20003a01,
> +				.refill = 0x00002726,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_PS_MMU_FW_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_PS_MMU_FW_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_PS_MMU_FW_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_PS_MMU_FW_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x00000018,
> +					0x00000018,
> +					0x00000018,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +				},
> +				.zlx_nr = IPU8_PS_ZLX_FW_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					0, 1, 0, 0, 1, 1, 0, 0,
> +					0, 0, 0, 0,
> +				},
> +				.zlx_conf = {
> +					0x0,
> +					0x2,
> +					0x0,
> +					0x0,
> +					0x2,
> +					0x2,
> +					0x0,
> +					0x0,
> +					0x0,
> +					0x0,
> +					0x0,
> +					0x0,
> +				},
> +				.uao_p_num =
> IPU8_PS_UAO_FW_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x0000002d,
> +					0x00000032,
> +					0x00000033,
> +					0x00000030,
> +					0x00000034,
> +					0x00000035,
> +					0x00000036,
> +					0x00000031,
> +					0x0,
> +					0x0,
> +					0x0,
> +					0x0,
> +				},
> +			},
> +			{
> +				.name = "PS_FW_WR",
> +				.offset = IPU8_PS_MMU_FW_WR_OFFSET,
> +				.zlx_offset =
> IPU8_PS_ZLX_FW_WR_OFFSET,
> +				.uao_offset =
> IPU8_PS_UAO_FW_WR_OFFSET,
> +				.info_bits = 0x20003901,
> +				.refill = 0x00002524,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_PS_MMU_FW_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_PS_MMU_FW_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_PS_MMU_FW_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_PS_MMU_FW_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000010,
> +					0x00000010,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +				},
> +				.zlx_nr = IPU8_PS_ZLX_FW_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f20,
> +				},
> +				.zlx_en = {
> +					0, 1, 1, 0, 0, 0, 0, 0,
> +				},
> +				.zlx_conf = {
> +					0x0, 0x2, 0x2, 0x0,
> +					0x0, 0x0, 0x0, 0x0,
> +				},
> +				.uao_p_num =
> IPU8_PS_UAO_FW_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x0000002d,
> +					0x0000002e,
> +					0x0000002f,
> +					0x00000030,
> +					0x00000031,
> +					0x0,
> +					0x0,
> +					0x0,
> +				},
> +			},
> +			{
> +				.name = "PS_DATA_RD",
> +				.offset = IPU8_PS_MMU_SRT_RD_OFFSET,
> +				.zlx_offset =
> IPU8_PS_ZLX_DATA_RD_OFFSET,
> +				.uao_offset =
> IPU8_PS_UAO_SRT_RD_OFFSET,
> +				.info_bits = 0x20003801,
> +				.refill = 0x00002322,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_PS_MMU_SRT_RD_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_PS_MMU_SRT_RD_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_PS_MMU_SRT_RD_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_PS_MMU_SRT_RD_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000014,
> +					0x00000018,
> +					0x0000001c,
> +					0x0000001e,
> +					0x00000022,
> +					0x00000024,
> +					0x00000026,
> +					0x00000028,
> +					0x0000002a,
> +					0x0000002c,
> +					0x0000002e,
> +					0x00000030,
> +					0x00000032,
> +					0x00000036,
> +					0x0000003a,
> +					0x0000003c,
> +					0x0000003c,
> +					0x0000003c,
> +					0x0000003c,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +					0x00000020,
> +					0x00000022,
> +					0x00000024,
> +					0x00000026,
> +					0x00000028,
> +					0x0000002a,
> +					0x0000002c,
> +					0x0000002e,
> +					0x00000030,
> +					0x00000032,
> +				},
> +				.zlx_nr = IPU8_PS_ZLX_DATA_RD_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f30,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 0, 0,
> +					0, 0,
> +				},
> +				.zlx_conf = {
> +					0x6, 0x3, 0x3, 0x6,
> +					0x2, 0x2, 0x6, 0x6,
> +					0x6, 0x3, 0x6, 0x3,
> +					0x3, 0x2, 0x2, 0x2,
> +					0x2, 0x2, 0x2, 0x6,
> +					0x6, 0x3, 0x0, 0x0,
> +					0x0, 0x0,
> +				},
> +				.uao_p_num =
> IPU8_PS_UAO_SRT_RD_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000017,
> +					0x00000018,
> +					0x00000019,
> +					0x0000001a,
> +					0x0000001b,
> +					0x0000001c,
> +					0x0000001d,
> +					0x0000001e,
> +					0x0000001f,
> +					0x00000020,
> +					0x00000021,
> +					0x00000022,
> +					0x00000023,
> +					0x00000024,
> +					0x00000025,
> +					0x00000026,
> +					0x00000027,
> +					0x00000028,
> +					0x00000029,
> +					0x0000002a,
> +					0x0000002b,
> +					0x0000002c,
> +					0x0,
> +					0x0,
> +					0x0,
> +					0x0,
> +				},
> +			},
> +			{
> +				.name = "PS_DATA_WR",
> +				.offset = IPU8_PS_MMU_SRT_WR_OFFSET,
> +				.zlx_offset =
> IPU8_PS_ZLX_DATA_WR_OFFSET,
> +				.uao_offset =
> IPU8_PS_UAO_SRT_WR_OFFSET,
> +				.info_bits = 0x20003701,
> +				.refill = 0x00002120,
> +				.collapse_en_bitmap = 0x1,
> +				.at_sp_arb_cfg = 0x1,
> +				.l1_block =
> IPU8_PS_MMU_SRT_WR_L1_BLOCKNR_REG,
> +				.l2_block =
> IPU8_PS_MMU_SRT_WR_L2_BLOCKNR_REG,
> +				.nr_l1streams =
> IPU8_PS_MMU_SRT_WR_STREAM_NUM,
> +				.nr_l2streams =
> IPU8_PS_MMU_SRT_WR_STREAM_NUM,
> +				.l1_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001c,
> +					0x0000001e,
> +					0x00000022,
> +					0x00000024,
> +					0x00000028,
> +					0x0000002a,
> +					0x0000002e,
> +					0x00000030,
> +					0x00000032,
> +					0x00000036,
> +					0x00000038,
> +					0x0000003a,
> +					0x0000003a,
> +					0x0000003a,
> +				},
> +				.l2_block_sz = {
> +					0x00000000,
> +					0x00000002,
> +					0x00000004,
> +					0x00000006,
> +					0x00000008,
> +					0x0000000a,
> +					0x0000000c,
> +					0x0000000e,
> +					0x00000010,
> +					0x00000012,
> +					0x00000014,
> +					0x00000016,
> +					0x00000018,
> +					0x0000001a,
> +					0x0000001c,
> +					0x0000001e,
> +					0x00000020,
> +					0x00000022,
> +					0x00000024,
> +					0x00000026,
> +					0x00000028,
> +					0x0000002a,
> +					0x0000002c,
> +					0x0000002e,
> +					0x00000030,
> +					0x00000032,
> +				},
> +				.zlx_nr = IPU8_PS_ZLX_DATA_WR_NUM,
> +				.zlx_axi_pool = {
> +					0x00000f50,
> +				},
> +				.zlx_en = {
> +					1, 1, 1, 0, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 1,
> +					1, 1, 1, 1, 1, 1, 1, 0,
> +					0, 0,
> +				},
> +				.zlx_conf = {
> +					0x3,
> +					0x6,
> +					0x38000002,
> +					0x38000000,
> +					0x3,
> +					0x38000002,
> +					0x38000002,
> +					0x38000002,
> +					0x38000002,
> +					0x38000002,
> +					0x38000002,
> +					0x6,
> +					0x3,
> +					0x6,
> +					0x3,
> +					0x6,
> +					0x3,
> +					0x6,
> +					0x3,
> +					0x3,
> +					0x6,
> +					0x3,
> +					0x3,
> +					0x0,
> +					0x0,
> +					0x0,
> +				},
> +				.uao_p_num =
> IPU8_PS_UAO_SRT_WR_PLANENUM,
> +				.uao_p2tlb = {
> +					0x00000000,
> +					0x00000001,
> +					0x00000002,
> +					0x00000003,
> +					0x00000004,
> +					0x00000005,
> +					0x00000006,
> +					0x00000007,
> +					0x00000008,
> +					0x00000009,
> +					0x0000000a,
> +					0x0000000b,
> +					0x0000000c,
> +					0x0000000d,
> +					0x0000000e,
> +					0x0000000f,
> +					0x00000010,
> +					0x00000011,
> +					0x00000012,
> +					0x00000013,
> +					0x00000014,
> +					0x00000015,
> +					0x00000016,
> +					0x00000000,
> +					0x00000000,
> +					0x00000000,
> +				},
> +			},
> +		},
> +		.dmem_offset = IPU_PSYS_DMEM_OFFSET,
> +	},
> +};
> +
> +static const struct ipu_buttress_ctrl ipu7_isys_buttress_ctrl = {
> +	.subsys_id = IPU_IS,
> +	.ratio = IPU7_IS_FREQ_CTL_DEFAULT_RATIO,
> +	.ratio_shift = IPU_FREQ_CTL_RATIO_SHIFT,
> +	.cdyn = IPU_FREQ_CTL_CDYN,
> +	.cdyn_shift = IPU_FREQ_CTL_CDYN_SHIFT,
> +	.freq_ctl = BUTTRESS_REG_IS_WORKPOINT_REQ,
> +	.pwr_sts_shift = IPU_BUTTRESS_PWR_STATE_IS_PWR_SHIFT,
> +	.pwr_sts_mask = IPU_BUTTRESS_PWR_STATE_IS_PWR_MASK,
> +	.pwr_sts_on = IPU_BUTTRESS_PWR_STATE_UP_DONE,
> +	.pwr_sts_off = IPU_BUTTRESS_PWR_STATE_DN_DONE,
> +	.ovrd_clk = BUTTRESS_OVERRIDE_IS_CLK,
> +	.own_clk_ack = BUTTRESS_OWN_ACK_IS_CLK,
> +};
> +
> +static const struct ipu_buttress_ctrl ipu7_psys_buttress_ctrl = {
> +	.subsys_id = IPU_PS,
> +	.ratio = IPU7_PS_FREQ_CTL_DEFAULT_RATIO,
> +	.ratio_shift = IPU_FREQ_CTL_RATIO_SHIFT,
> +	.cdyn = IPU_FREQ_CTL_CDYN,
> +	.cdyn_shift = IPU_FREQ_CTL_CDYN_SHIFT,
> +	.freq_ctl = BUTTRESS_REG_PS_WORKPOINT_REQ,
> +	.pwr_sts_shift = IPU_BUTTRESS_PWR_STATE_PS_PWR_SHIFT,
> +	.pwr_sts_mask = IPU_BUTTRESS_PWR_STATE_PS_PWR_MASK,
> +	.pwr_sts_on = IPU_BUTTRESS_PWR_STATE_UP_DONE,
> +	.pwr_sts_off = IPU_BUTTRESS_PWR_STATE_DN_DONE,
> +	.ovrd_clk = BUTTRESS_OVERRIDE_PS_CLK,
> +	.own_clk_ack = BUTTRESS_OWN_ACK_PS_CLK,
> +};
> +
> +static const struct ipu_buttress_ctrl ipu8_isys_buttress_ctrl = {
> +	.subsys_id = IPU_IS,
> +	.ratio = IPU8_IS_FREQ_CTL_DEFAULT_RATIO,
> +	.ratio_shift = IPU_FREQ_CTL_RATIO_SHIFT,
> +	.cdyn = IPU_FREQ_CTL_CDYN,
> +	.cdyn_shift = IPU_FREQ_CTL_CDYN_SHIFT,
> +	.freq_ctl = BUTTRESS_REG_IS_WORKPOINT_REQ,
> +	.pwr_sts_shift = IPU_BUTTRESS_PWR_STATE_IS_PWR_SHIFT,
> +	.pwr_sts_mask = IPU_BUTTRESS_PWR_STATE_IS_PWR_MASK,
> +	.pwr_sts_on = IPU_BUTTRESS_PWR_STATE_UP_DONE,
> +	.pwr_sts_off = IPU_BUTTRESS_PWR_STATE_DN_DONE,
> +};
> +
> +static const struct ipu_buttress_ctrl ipu8_psys_buttress_ctrl = {
> +	.subsys_id = IPU_PS,
> +	.ratio = IPU8_PS_FREQ_CTL_DEFAULT_RATIO,
> +	.ratio_shift = IPU_FREQ_CTL_RATIO_SHIFT,
> +	.cdyn = IPU_FREQ_CTL_CDYN,
> +	.cdyn_shift = IPU_FREQ_CTL_CDYN_SHIFT,
> +	.freq_ctl = BUTTRESS_REG_PS_WORKPOINT_REQ,
> +	.pwr_sts_shift = IPU_BUTTRESS_PWR_STATE_PS_PWR_SHIFT,
> +	.pwr_sts_mask = IPU_BUTTRESS_PWR_STATE_PS_PWR_MASK,
> +	.pwr_sts_on = IPU_BUTTRESS_PWR_STATE_UP_DONE,
> +	.pwr_sts_off = IPU_BUTTRESS_PWR_STATE_DN_DONE,
> +	.own_clk_ack = BUTTRESS_OWN_ACK_PS_PLL,
> +};
> +
> +void ipu_internal_pdata_init(struct ipu_isys_internal_pdata
> *isys_ipdata,
> +			     struct ipu_psys_internal_pdata
> *psys_ipdata)
> +{
> +	isys_ipdata->csi2.nports = ARRAY_SIZE(ipu7_csi_offsets);
> +	isys_ipdata->csi2.offsets = ipu7_csi_offsets;
> +	isys_ipdata->num_parallel_streams = IPU7_ISYS_NUM_STREAMS;
> +	psys_ipdata->hw_variant.spc_offset = IPU7_PSYS_SPC_OFFSET;
> +}
> +
> +static int ipu7_isys_check_fwnode_graph(struct fwnode_handle
> *fwnode)
> +{
> +	struct fwnode_handle *endpoint;
> +
> +	if (IS_ERR_OR_NULL(fwnode))
> +		return -EINVAL;
> +
> +	endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL);
> +	if (endpoint) {
> +		fwnode_handle_put(endpoint);
> +		return 0;
> +	}
> +
> +	return ipu7_isys_check_fwnode_graph(fwnode->secondary);
> +}
> +
> +static struct ipu7_bus_device *
> +ipu7_isys_init(struct pci_dev *pdev, struct device *parent,
> +	       const struct ipu_buttress_ctrl *ctrl, void __iomem
> *base,
> +	       const struct ipu_isys_internal_pdata *ipdata,
> +	       unsigned int nr)
> +{
> +	struct fwnode_handle *fwnode = dev_fwnode(&pdev->dev);
> +	struct ipu7_bus_device *isys_adev;
> +	struct device *dev = &pdev->dev;
> +	struct ipu7_isys_pdata *pdata;
> +	int ret;
> +
> +	ret = ipu7_isys_check_fwnode_graph(fwnode);
> +	if (ret) {
> +		if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) {
> +			dev_err(dev,
> +				"fwnode graph has no endpoints
> connection\n");
> +			return ERR_PTR(-EINVAL);
> +		}
> +
> +		ret = ipu_bridge_init(dev, ipu_bridge_parse_ssdb);
> +		if (ret) {
> +			dev_err_probe(dev, ret, "IPU bridge init
> failed\n");
> +			return ERR_PTR(ret);
> +		}
> +	}
> +
> +	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return ERR_PTR(-ENOMEM);
> +
> +	pdata->base = base;
> +	pdata->ipdata = ipdata;
> +
> +	isys_adev = ipu7_bus_initialize_device(pdev, parent, pdata,
> ctrl,
> +					       IPU_ISYS_NAME);
> +	if (IS_ERR(isys_adev)) {
> +		dev_err_probe(dev, PTR_ERR(isys_adev),
> +			      "ipu7_bus_initialize_device isys
> failed\n");
> +		kfree(pdata);
> +		return ERR_CAST(isys_adev);
> +	}
> +
> +	isys_adev->mmu = ipu7_mmu_init(dev, base, ISYS_MMID,
> +				       &ipdata->hw_variant);
> +	if (IS_ERR(isys_adev->mmu)) {
> +		dev_err_probe(dev, PTR_ERR(isys_adev),
> +			      "ipu7_mmu_init(isys_adev->mmu)
> failed\n");
> +		put_device(&isys_adev->auxdev.dev);
> +		kfree(pdata);
> +		return ERR_CAST(isys_adev->mmu);
> +	}
> +
> +	isys_adev->mmu->dev = &isys_adev->auxdev.dev;
> +	isys_adev->subsys = IPU_IS;
> +
> +	ret = ipu7_bus_add_device(isys_adev);
> +	if (ret) {
> +		kfree(pdata);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return isys_adev;
> +}
> +
> +static struct ipu7_bus_device *
> +ipu7_psys_init(struct pci_dev *pdev, struct device *parent,
> +	       const struct ipu_buttress_ctrl *ctrl, void __iomem
> *base,
> +	       const struct ipu_psys_internal_pdata *ipdata,
> unsigned int nr)
> +{
> +	struct ipu7_bus_device *psys_adev;
> +	struct ipu7_psys_pdata *pdata;
> +	int ret;
> +
> +	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return ERR_PTR(-ENOMEM);
> +
> +	pdata->base = base;
> +	pdata->ipdata = ipdata;
> +
> +	psys_adev = ipu7_bus_initialize_device(pdev, parent, pdata,
> ctrl,
> +					       IPU_PSYS_NAME);
> +	if (IS_ERR(psys_adev)) {
> +		dev_err_probe(&pdev->dev, PTR_ERR(psys_adev),
> +			      "ipu7_bus_initialize_device psys
> failed\n");
> +		kfree(pdata);
> +		return ERR_CAST(psys_adev);
> +	}
> +
> +	psys_adev->mmu = ipu7_mmu_init(&pdev->dev, base, PSYS_MMID,
> +				       &ipdata->hw_variant);
> +	if (IS_ERR(psys_adev->mmu)) {
> +		dev_err_probe(&pdev->dev, PTR_ERR(psys_adev),
> +			      "ipu7_mmu_init(psys_adev->mmu)
> failed\n");
> +		put_device(&psys_adev->auxdev.dev);
> +		kfree(pdata);
> +		return ERR_CAST(psys_adev->mmu);
> +	}
> +
> +	psys_adev->mmu->dev = &psys_adev->auxdev.dev;
> +	psys_adev->subsys = IPU_PS;
> +
> +	ret = ipu7_bus_add_device(psys_adev);
> +	if (ret) {
> +		kfree(pdata);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return psys_adev;
> +}
> +
> +static struct ia_gofo_msg_log_info_ts fw_error_log[IPU_SUBSYS_NUM];
> +void ipu7_dump_fw_error_log(const struct ipu7_bus_device *adev)
> +{
> +	void __iomem *reg = adev->isp->base + ((adev->subsys ==
> IPU_IS) ?
> +					       BUTTRESS_REG_FW_GP24
> :
> +					       BUTTRESS_REG_FW_GP8);
> +
> +	memcpy_fromio(&fw_error_log[adev->subsys], reg,
> +		      sizeof(fw_error_log[adev->subsys]));
> +}
> +EXPORT_SYMBOL_NS_GPL(ipu7_dump_fw_error_log, "INTEL_IPU7");
> +
> +static int ipu7_pci_config_setup(struct pci_dev *dev)
> +{
> +	u16 pci_command;
> +	int ret;
> +
> +	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
> +	pci_command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
> +	pci_write_config_word(dev, PCI_COMMAND, pci_command);
> +
> +	ret = pci_enable_msi(dev);
> +	if (ret)
> +		dev_err(&dev->dev, "Failed to enable msi (%d)\n",
> ret);
> +
> +	return ret;
> +}
> +
> +static int ipu7_map_fw_code_region(struct ipu7_bus_device *sys,
> +				   void *data, size_t size)
> +{
> +	struct device *dev = &sys->auxdev.dev;
> +	struct ipu7_bus_device *adev = to_ipu7_bus_device(dev);
> +	struct sg_table *sgt = &sys->fw_sgt;
> +	struct ipu7_device *isp = adev->isp;
> +	struct pci_dev *pdev = isp->pdev;
> +	unsigned long n_pages, i;
> +	unsigned long attr = 0;
> +	struct page **pages;
> +	int ret;
> +
> +	n_pages = PFN_UP(size);
> +
> +	pages = kmalloc_array(n_pages, sizeof(*pages), GFP_KERNEL);
> +	if (!pages)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < n_pages; i++) {
> +		struct page *p = vmalloc_to_page(data);
> +
> +		if (!p) {
> +			ret = -ENODEV;
> +			goto out;
> +		}
> +
> +		pages[i] = p;
> +		data += PAGE_SIZE;
> +	}
> +
> +	ret = sg_alloc_table_from_pages(sgt, pages, n_pages, 0,
> size,
> +					GFP_KERNEL);
> +	if (ret) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	if (!isp->secure_mode)
> +		attr |= DMA_ATTR_RESERVE_REGION;
> +
> +	ret = dma_map_sgtable(&pdev->dev, sgt, DMA_BIDIRECTIONAL,
> 0);
> +	if (ret < 0) {
> +		dev_err(dev, "map fw code[%lu pages %u nents]
> failed\n",
> +			n_pages, sgt->nents);
> +		ret = -ENOMEM;
> +		sg_free_table(sgt);
> +		goto out;
> +	}
> +
> +	ret = ipu7_dma_map_sgtable(sys, sgt, DMA_BIDIRECTIONAL,
> attr);
> +	if (ret) {
> +		dma_unmap_sgtable(&pdev->dev, sgt,
> DMA_BIDIRECTIONAL, 0);
> +		sg_free_table(sgt);
> +		goto out;
> +	}
> +
> +	ipu7_dma_sync_sgtable(sys, sgt);
> +
> +	dev_dbg(dev, "fw code region mapped at 0x%llx entries %d\n",
> +		sgt->sgl->dma_address, sgt->nents);
> +
> +out:
> +	kfree(pages);
> +
> +	return ret;
> +}
> +
> +static void ipu7_unmap_fw_code_region(struct ipu7_bus_device *sys)
> +{
> +	struct pci_dev *pdev = sys->isp->pdev;
> +	struct sg_table *sgt = &sys->fw_sgt;
> +
> +	ipu7_dma_unmap_sgtable(sys, sgt, DMA_BIDIRECTIONAL, 0);
> +	dma_unmap_sgtable(&pdev->dev, sgt, DMA_BIDIRECTIONAL, 0);
> +	sg_free_table(sgt);
> +}
> +
> +static int ipu7_init_fw_code_region_by_sys(struct ipu7_bus_device
> *sys,
> +					   char *sys_name)
> +{
> +	struct device *dev = &sys->auxdev.dev;
> +	struct ipu7_device *isp = sys->isp;
> +	int ret;
> +
> +	/* Copy FW binaries to specific location. */
> +	ret = ipu7_cpd_copy_binary(isp->cpd_fw->data, sys_name,
> +				   isp->fw_code_region, &sys-
> >fw_entry);
> +	if (ret) {
> +		dev_err(dev, "%s binary not found.\n", sys_name);
> +		return ret;
> +	}
> +
> +	ret = pm_runtime_get_sync(dev);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to get runtime PM\n");
> +		return ret;
> +	}
> +
> +	ret = ipu7_mmu_hw_init(sys->mmu);
> +	if (ret) {
> +		dev_err(dev, "Failed to set mmu hw\n");
> +		pm_runtime_put(dev);
> +		return ret;
> +	}
> +
> +	/* Map code region. */
> +	ret = ipu7_map_fw_code_region(sys, isp->fw_code_region,
> +				      IPU_FW_CODE_REGION_SIZE);
> +	if (ret)
> +		dev_err(dev, "Failed to map fw code region for
> %s.\n",
> +			sys_name);
> +
> +	ipu7_mmu_hw_cleanup(sys->mmu);
> +	pm_runtime_put(dev);
> +
> +	return ret;
> +}
> +
> +static int ipu7_init_fw_code_region(struct ipu7_device *isp)
> +{
> +	int ret;
> +
> +	/*
> +	 * Allocate and map memory for FW execution.
> +	 * Not required in secure mode, in which FW runs in IMR.
> +	 */
> +	isp->fw_code_region = vmalloc(IPU_FW_CODE_REGION_SIZE);
> +	if (!isp->fw_code_region)
> +		return -ENOMEM;
> +
> +	ret = ipu7_init_fw_code_region_by_sys(isp->isys, "isys");
> +	if (ret)
> +		goto fail_init;
> +
> +	ret = ipu7_init_fw_code_region_by_sys(isp->psys, "psys");
> +	if (ret)
> +		goto fail_init;
> +
> +	return 0;
> +
> +fail_init:
> +	vfree(isp->fw_code_region);
> +
> +	return ret;
> +}
> +
> +static int ipu7_pci_probe(struct pci_dev *pdev, const struct
> pci_device_id *id)
> +{
> +	struct ipu_buttress_ctrl *isys_ctrl = NULL, *psys_ctrl =
> NULL;
> +	struct fwnode_handle *fwnode = dev_fwnode(&pdev->dev);
> +	const struct ipu_buttress_ctrl *isys_buttress_ctrl;
> +	const struct ipu_buttress_ctrl *psys_buttress_ctrl;
> +	struct ipu_isys_internal_pdata *isys_ipdata;
> +	struct ipu_psys_internal_pdata *psys_ipdata;
> +	unsigned int dma_mask = IPU_DMA_MASK;
> +	struct device *dev = &pdev->dev;
> +	void __iomem *isys_base = NULL;
> +	void __iomem *psys_base = NULL;
> +	void __iomem *const *iomap;
> +	phys_addr_t phys, pb_phys;
> +	struct ipu7_device *isp;
> +	u32 is_es;
> +	int ret;
> +
> +	if (!fwnode || fwnode_property_read_u32(fwnode, "is_es",
> &is_es))
> +		is_es = 0;
> +
> +	isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL);
> +	if (!isp)
> +		return -ENOMEM;
> +
> +	dev_set_name(dev, "intel-ipu7");
> +	isp->pdev = pdev;
> +	INIT_LIST_HEAD(&isp->devices);
> +
> +	ret = pcim_enable_device(pdev);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Enable PCI device
> failed\n");
> +
> +	dev_info(dev, "Device 0x%x (rev: 0x%x)\n",
> +		 pdev->device, pdev->revision);
> +
> +	phys = pci_resource_start(pdev, IPU_PCI_BAR);
> +	pb_phys = pci_resource_start(pdev, IPU_PCI_PBBAR);
> +	dev_info(dev, "IPU7 PCI BAR0 base %llx BAR2 base %llx\n",
> +		 phys, pb_phys);
> +
> +	ret = pcim_iomap_regions(pdev, BIT(IPU_PCI_BAR) |
> BIT(IPU_PCI_PBBAR),
> +				 pci_name(pdev));
> +	if (ret)
> +		return dev_err_probe(dev, ret,
> +				     "Failed to I/O memory remapping
> (%d)\n",
> +				     ret);
> +
> +	iomap = pcim_iomap_table(pdev);

pcim_iomap_table() and pcim_iomap_regions() have been deprecated last
year. That's also documented in those functions' docstrings. Please
don't use them anymore.

You can achieve all you need with the simpler pcim_iomap_region()


> +	if (!iomap)
> +		return dev_err_probe(dev, -ENODEV, "Failed to iomap
> table\n");
> +
> +	isp->base = iomap[IPU_PCI_BAR];
> +	isp->pb_base = iomap[IPU_PCI_PBBAR];
> +	dev_info(dev, "IPU7 PCI BAR0 mapped at %p\n BAR2 mapped at
> %p\n",
> +		 isp->base, isp->pb_base);
> +
> +	pci_set_drvdata(pdev, isp);
> +	pci_set_master(pdev);
> +
> +	switch (id->device) {
> +	case IPU7_PCI_ID:
> +		isp->hw_ver = IPU_VER_7;
> +		isp->cpd_fw_name = IPU7_FIRMWARE_NAME;
> +		isys_ipdata = &ipu7_isys_ipdata;
> +		psys_ipdata = &ipu7_psys_ipdata;
> +		isys_buttress_ctrl = &ipu7_isys_buttress_ctrl;
> +		psys_buttress_ctrl = &ipu7_psys_buttress_ctrl;
> +		break;
> +	case IPU7P5_PCI_ID:
> +		isp->hw_ver = IPU_VER_7P5;
> +		isp->cpd_fw_name = IPU7P5_FIRMWARE_NAME;
> +		isys_ipdata = &ipu7p5_isys_ipdata;
> +		psys_ipdata = &ipu7p5_psys_ipdata;
> +		isys_buttress_ctrl = &ipu7_isys_buttress_ctrl;
> +		psys_buttress_ctrl = &ipu7_psys_buttress_ctrl;
> +		break;
> +	case IPU8_PCI_ID:
> +		isp->hw_ver = IPU_VER_8;
> +		isp->cpd_fw_name = IPU8_FIRMWARE_NAME;
> +		isys_ipdata = &ipu8_isys_ipdata;
> +		psys_ipdata = &ipu8_psys_ipdata;
> +		isys_buttress_ctrl = &ipu8_isys_buttress_ctrl;
> +		psys_buttress_ctrl = &ipu8_psys_buttress_ctrl;
> +		break;
> +	default:
> +		WARN(1, "Unsupported IPU device");
> +		return -ENODEV;
> +	}
> +
> +	ipu_internal_pdata_init(isys_ipdata, psys_ipdata);
> +
> +	isys_base = isp->base + isys_ipdata->hw_variant.offset;
> +	psys_base = isp->base + psys_ipdata->hw_variant.offset;
> +
> +	ret = dma_set_mask_and_coherent(dev,
> DMA_BIT_MASK(dma_mask));
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to set DMA
> mask\n");
> +
> +	dma_set_max_seg_size(dev, UINT_MAX);
> +
> +	ret = ipu7_pci_config_setup(pdev);
> +	if (ret)
> +		return ret;
> +
> +	ret = ipu_buttress_init(isp);
> +	if (ret)
> +		return ret;
> +
> +	dev_info(dev, "firmware cpd file: %s\n", isp->cpd_fw_name);
> +
> +	ret = request_firmware(&isp->cpd_fw, isp->cpd_fw_name, dev);
> +	if (ret) {
> +		dev_err_probe(dev, ret,
> +			      "Requesting signed firmware %s
> failed\n",
> +			      isp->cpd_fw_name);
> +		goto buttress_exit;
> +	}
> +
> +	ret = ipu7_cpd_validate_cpd_file(isp, isp->cpd_fw->data,
> +					 isp->cpd_fw->size);
> +	if (ret) {
> +		dev_err_probe(dev, ret, "Failed to validate cpd\n");
> +		goto out_ipu_bus_del_devices;
> +	}
> +
> +	isys_ctrl = devm_kmemdup(dev, isys_buttress_ctrl,
> +				 sizeof(*isys_buttress_ctrl),
> GFP_KERNEL);
> +	if (!isys_ctrl) {
> +		ret = -ENOMEM;
> +		goto out_ipu_bus_del_devices;
> +	}
> +
> +	isp->isys = ipu7_isys_init(pdev, dev, isys_ctrl, isys_base,
> +				   isys_ipdata, 0);
> +	if (IS_ERR(isp->isys)) {
> +		ret = PTR_ERR(isp->isys);
> +		goto out_ipu_bus_del_devices;
> +	}
> +
> +	psys_ctrl = devm_kmemdup(dev, psys_buttress_ctrl,
> +				 sizeof(*psys_buttress_ctrl),
> GFP_KERNEL);
> +	if (!psys_ctrl) {
> +		ret = -ENOMEM;
> +		goto out_ipu_bus_del_devices;
> +	}
> +
> +	isp->psys = ipu7_psys_init(pdev, &isp->isys->auxdev.dev,
> +				   psys_ctrl, psys_base,
> +				   psys_ipdata, 0);
> +	if (IS_ERR(isp->psys)) {
> +		ret = PTR_ERR(isp->psys);
> +		goto out_ipu_bus_del_devices;
> +	}
> +
> +	ret = devm_request_threaded_irq(dev, pdev->irq,
> +					ipu_buttress_isr,
> +					ipu_buttress_isr_threaded,
> +					IRQF_SHARED, IPU_NAME, isp);
> +	if (ret)
> +		goto out_ipu_bus_del_devices;
> +
> +	if (!isp->secure_mode) {
> +		ret = ipu7_init_fw_code_region(isp);
> +		if (ret)
> +			goto out_ipu_bus_del_devices;
> +	} else {
> +		ret = pm_runtime_get_sync(&isp->psys->auxdev.dev);
> +		if (ret < 0) {
> +			dev_err(&isp->psys->auxdev.dev,
> +				"Failed to get runtime PM\n");
> +			goto out_ipu_bus_del_devices;
> +		}
> +
> +		ret = ipu7_mmu_hw_init(isp->psys->mmu);
> +		if (ret) {
> +			dev_err_probe(&isp->pdev->dev, ret,
> +				      "Failed to init MMU
> hardware\n");
> +			goto out_ipu_bus_del_devices;
> +		}
> +
> +		ret = ipu7_map_fw_code_region(isp->psys,
> +					      (void *)isp->cpd_fw-
> >data,
> +					      isp->cpd_fw->size);
> +		if (ret) {
> +			dev_err_probe(&isp->pdev->dev, ret,
> +				      "failed to map fw image\n");
> +			goto out_ipu_bus_del_devices;
> +		}
> +
> +		ret = ipu_buttress_authenticate(isp);
> +		if (ret) {
> +			dev_err_probe(&isp->pdev->dev, ret,
> +				      "FW authentication failed\n");
> +			goto out_ipu_bus_del_devices;
> +		}
> +
> +		ipu7_mmu_hw_cleanup(isp->psys->mmu);
> +		pm_runtime_put(&isp->psys->auxdev.dev);
> +	}
> +
> +	pm_runtime_put_noidle(dev);
> +	pm_runtime_allow(dev);
> +
> +	isp->ipu7_bus_ready_to_probe = true;
> +
> +	return 0;
> +
> +out_ipu_bus_del_devices:
> +	if (!IS_ERR_OR_NULL(isp->isys) && isp->isys->fw_sgt.nents)
> +		ipu7_unmap_fw_code_region(isp->isys);
> +	if (!IS_ERR_OR_NULL(isp->psys) && isp->psys->fw_sgt.nents)
> +		ipu7_unmap_fw_code_region(isp->psys);
> +	if (!IS_ERR_OR_NULL(isp->psys) && !IS_ERR_OR_NULL(isp->psys-
> >mmu))
> +		ipu7_mmu_cleanup(isp->psys->mmu);
> +	if (!IS_ERR_OR_NULL(isp->isys) && !IS_ERR_OR_NULL(isp->isys-
> >mmu))
> +		ipu7_mmu_cleanup(isp->isys->mmu);
> +	if (!IS_ERR_OR_NULL(isp->psys))
> +		pm_runtime_put(&isp->psys->auxdev.dev);
> +	ipu7_bus_del_devices(pdev);
> +	release_firmware(isp->cpd_fw);
> +buttress_exit:
> +	ipu_buttress_exit(isp);
> +
> +	return ret;
> +}
> +
> +static void ipu7_pci_remove(struct pci_dev *pdev)
> +{
> +	struct ipu7_device *isp = pci_get_drvdata(pdev);
> +
> +	if (!IS_ERR_OR_NULL(isp->isys) && isp->isys->fw_sgt.nents)
> +		ipu7_unmap_fw_code_region(isp->isys);
> +	if (!IS_ERR_OR_NULL(isp->psys) && isp->psys->fw_sgt.nents)
> +		ipu7_unmap_fw_code_region(isp->psys);
> +
> +	if (!IS_ERR_OR_NULL(isp->fw_code_region))
> +		vfree(isp->fw_code_region);
> +
> +	ipu7_bus_del_devices(pdev);
> +
> +	pm_runtime_forbid(&pdev->dev);
> +	pm_runtime_get_noresume(&pdev->dev);
> +
> +	pci_release_regions(pdev);

You don't need this if you request with a pcim_ function. The 'm'
stands for "managed". Those are devres functions that will clean up
automatically if probe() fails or once remove() is invoked.

Furthermore, you should not mix pcim_ and pci_ functions; at least not
those.

And even if the pcim_ functions wouldn't do a cleanup, you would leak
the IO mappings above, since pci_release_regions() just removes the
region requests, but not the mapping cookies.

I recommend taking a look to the PCI subystem's documentation.

> +	pci_disable_device(pdev);

You also don't need this since you used pcim_enable_device(), which
will disable the device automatically on driver-detach.


P.

> +
> +	ipu_buttress_exit(isp);
> +
> +	release_firmware(isp->cpd_fw);
> +
> +	ipu7_mmu_cleanup(isp->psys->mmu);
> +	ipu7_mmu_cleanup(isp->isys->mmu);
> +}
> +
> +static void ipu7_pci_reset_prepare(struct pci_dev *pdev)
> +{
> +	struct ipu7_device *isp = pci_get_drvdata(pdev);
> +
> +	dev_warn(&pdev->dev, "FLR prepare\n");
> +	pm_runtime_forbid(&isp->pdev->dev);
> +}
> +
> +static void ipu7_pci_reset_done(struct pci_dev *pdev)
> +{
> +	struct ipu7_device *isp = pci_get_drvdata(pdev);
> +
> +	ipu_buttress_restore(isp);
> +	if (isp->secure_mode)
> +		ipu_buttress_reset_authentication(isp);
> +
> +	isp->ipc_reinit = true;
> +	pm_runtime_allow(&isp->pdev->dev);
> +
> +	dev_warn(&pdev->dev, "FLR completed\n");
> +}
> +
> +/*
> + * PCI base driver code requires driver to provide these to enable
> + * PCI device level PM state transitions (D0<->D3)
> + */
> +static int ipu7_suspend(struct device *dev)
> +{
> +	return 0;
> +}
> +
> +static int ipu7_resume(struct device *dev)
> +{
> +	struct pci_dev *pdev = to_pci_dev(dev);
> +	struct ipu7_device *isp = pci_get_drvdata(pdev);
> +	struct ipu_buttress *b = &isp->buttress;
> +	int ret;
> +
> +	isp->secure_mode = ipu_buttress_get_secure_mode(isp);
> +	dev_info(dev, "IPU7 in %s mode\n",
> +		 isp->secure_mode ? "secure" : "non-secure");
> +
> +	ipu_buttress_restore(isp);
> +
> +	ret = ipu_buttress_ipc_reset(isp, &b->cse);
> +	if (ret)
> +		dev_err(dev, "IPC reset protocol failed!\n");
> +
> +	ret = pm_runtime_get_sync(&isp->psys->auxdev.dev);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to get runtime PM\n");
> +		return 0;
> +	}
> +
> +	ret = ipu_buttress_authenticate(isp);
> +	if (ret)
> +		dev_err(dev, "FW authentication failed(%d)\n", ret);
> +
> +	pm_runtime_put(&isp->psys->auxdev.dev);
> +
> +	return 0;
> +}
> +
> +static int ipu7_runtime_resume(struct device *dev)
> +{
> +	struct pci_dev *pdev = to_pci_dev(dev);
> +	struct ipu7_device *isp = pci_get_drvdata(pdev);
> +	int ret;
> +
> +	ipu_buttress_restore(isp);
> +
> +	if (isp->ipc_reinit) {
> +		struct ipu_buttress *b = &isp->buttress;
> +
> +		isp->ipc_reinit = false;
> +		ret = ipu_buttress_ipc_reset(isp, &b->cse);
> +		if (ret)
> +			dev_err(dev, "IPC reset protocol
> failed!\n");
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops ipu7_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(&ipu7_suspend, &ipu7_resume)
> +	SET_RUNTIME_PM_OPS(&ipu7_suspend,	/* Same as in
> suspend flow */
> +			   &ipu7_runtime_resume,
> +			   NULL)
> +};
> +
> +static const struct pci_device_id ipu7_pci_tbl[] = {
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU7_PCI_ID)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU7P5_PCI_ID)},
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU8_PCI_ID)},
> +	{0,}
> +};
> +MODULE_DEVICE_TABLE(pci, ipu7_pci_tbl);
> +
> +static const struct pci_error_handlers pci_err_handlers = {
> +	.reset_prepare = ipu7_pci_reset_prepare,
> +	.reset_done = ipu7_pci_reset_done,
> +};
> +
> +static struct pci_driver ipu7_pci_driver = {
> +	.name = IPU_NAME,
> +	.id_table = ipu7_pci_tbl,
> +	.probe = ipu7_pci_probe,
> +	.remove = ipu7_pci_remove,
> +	.driver = {
> +		.pm = &ipu7_pm_ops,
> +	},
> +	.err_handler = &pci_err_handlers,
> +};
> +
> +module_pci_driver(ipu7_pci_driver);
> +
> +MODULE_IMPORT_NS("INTEL_IPU_BRIDGE");
> +MODULE_AUTHOR("Bingbu Cao <bingbu.cao@xxxxxxxxx>");
> +MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@xxxxxxxxx>");
> +MODULE_AUTHOR("Qingwu Zhang <qingwu.zhang@xxxxxxxxx>");
> +MODULE_AUTHOR("Intel");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("Intel ipu7 pci driver");
> diff --git a/drivers/media/pci/intel/ipu7/ipu7.h
> b/drivers/media/pci/intel/ipu7/ipu7.h
> new file mode 100644
> index 000000000000..6f5705f403b7
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu7/ipu7.h
> @@ -0,0 +1,244 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2013 - 2024 Intel Corporation
> + */
> +
> +#ifndef IPU7_H
> +#define IPU7_H
> +
> +#include <linux/list.h>
> +#include <linux/pci.h>
> +#include <linux/types.h>
> +
> +#include "ipu7-buttress.h"
> +
> +struct ipu7_bus_device;
> +struct pci_dev;
> +struct firmware;
> +
> +#define IPU_NAME			"intel-ipu7"
> +#define IPU_MEDIA_DEV_MODEL_NAME	"ipu7"
> +
> +#define IPU7_FIRMWARE_NAME		"intel/ipu/ipu7_fw.bin"
> +#define IPU7P5_FIRMWARE_NAME		"intel/ipu/ipu7ptl_fw.bin"
> +#define IPU8_FIRMWARE_NAME		"intel/ipu/ipu8_fw.bin"
> +
> +#define IPU7_ISYS_NUM_STREAMS		12
> +
> +#define IPU7_PCI_ID			0x645d
> +#define IPU7P5_PCI_ID			0xb05d
> +#define IPU8_PCI_ID			0xd719
> +
> +#define FW_LOG_BUF_SIZE			(2 * 1024 * 1024)
> +
> +enum ipu_version {
> +	IPU_VER_INVALID = 0,
> +	IPU_VER_7 = 1,
> +	IPU_VER_7P5 = 2,
> +	IPU_VER_8 = 3,
> +};
> +
> +static inline bool is_ipu7p5(u8 hw_ver)
> +{
> +	return hw_ver == IPU_VER_7P5;
> +}
> +
> +static inline bool is_ipu7(u8 hw_ver)
> +{
> +	return hw_ver == IPU_VER_7;
> +}
> +
> +static inline bool is_ipu8(u8 hw_ver)
> +{
> +	return hw_ver == IPU_VER_8;
> +}
> +
> +#define IPU_UNIFIED_OFFSET		0
> +
> +/*
> + * ISYS DMA can overshoot. For higher resolutions over allocation is
> one line
> + * but it must be at minimum 1024 bytes. Value could be different in
> + * different versions / generations thus provide it via platform
> data.
> + */
> +#define IPU_ISYS_OVERALLOC_MIN		1024
> +
> +#define IPU_FW_CODE_REGION_SIZE		0x1000000 /* 16MB */
> +#define IPU_FW_CODE_REGION_START	0x4000000 /* 64MB */
> +#define IPU_FW_CODE_REGION_END		(IPU_FW_CODE_REGION_START
> +	\
> +					 IPU_FW_CODE_REGION_SIZE) /*
> 80MB */
> +
> +struct ipu7_device {
> +	struct pci_dev *pdev;
> +	struct list_head devices;
> +	struct ipu7_bus_device *isys;
> +	struct ipu7_bus_device *psys;
> +	struct ipu_buttress buttress;
> +
> +	const struct firmware *cpd_fw;
> +	const char *cpd_fw_name;
> +	/* Only for non-secure mode. */
> +	void *fw_code_region;
> +
> +	void __iomem *base;
> +	void __iomem *pb_base;
> +	u8 hw_ver;
> +	bool ipc_reinit;
> +	bool secure_mode;
> +	bool ipu7_bus_ready_to_probe;
> +};
> +
> +#define IPU_DMA_MASK			39
> +#define IPU_LIB_CALL_TIMEOUT_MS		2000
> +#define IPU_PSYS_CMD_TIMEOUT_MS		2000
> +#define IPU_PSYS_OPEN_CLOSE_TIMEOUT_US	50
> +#define IPU_PSYS_OPEN_CLOSE_RETRY	(10000 /
> IPU_PSYS_OPEN_CLOSE_TIMEOUT_US)
> +
> +#define IPU_ISYS_NAME "isys"
> +#define IPU_PSYS_NAME "psys"
> +
> +#define IPU_MMU_ADDR_BITS		32
> +/* FW is accessible within the first 2 GiB only in non-secure mode.
> */
> +#define IPU_MMU_ADDR_BITS_NON_SECURE	31
> +
> +#define IPU7_IS_MMU_NUM			4
> +#define IPU7_PS_MMU_NUM			4
> +#define IPU7P5_IS_MMU_NUM		4
> +#define IPU7P5_PS_MMU_NUM		4
> +#define IPU8_IS_MMU_NUM			5
> +#define IPU8_PS_MMU_NUM			4
> +#define IPU_MMU_MAX_NUM			5 /* max(IS, PS) */
> +#define IPU_MMU_MAX_TLB_L1_STREAMS	40
> +#define IPU_MMU_MAX_TLB_L2_STREAMS	40
> +#define IPU_ZLX_MAX_NUM			32
> +#define IPU_ZLX_POOL_NUM		8
> +#define IPU_UAO_PLANE_MAX_NUM		64
> +
> +/*
> + * To maximize the IOSF utlization, IPU need to send requests in
> bursts.
> + * At the DMA interface with the buttress, there are CDC FIFOs with
> burst
> + * collection capability. CDC FIFO burst collectors have a
> configurable
> + * threshold and is configured based on the outcome of performance
> measurements.
> + *
> + * isys has 3 ports with IOSF interface for VC0, VC1 and VC2
> + * psys has 4 ports with IOSF interface for VC0, VC1w, VC1r and VC2
> + *
> + * Threshold values are pre-defined and are arrived at after
> performance
> + * evaluations on a type of IPU
> + */
> +#define IPU_MAX_VC_IOSF_PORTS		4
> +
> +/*
> + * IPU must configure correct arbitration mechanism related to the
> IOSF VC
> + * requests. There are two options per VC0 and VC1 - > 0 means
> rearbitrate on
> + * stall and 1 means stall until the request is completed.
> + */
> +#define IPU_BTRS_ARB_MODE_TYPE_REARB	0
> +#define IPU_BTRS_ARB_MODE_TYPE_STALL	1
> +
> +/* Currently chosen arbitration mechanism for VC0 */
> +#define IPU_BTRS_ARB_STALL_MODE_VC0	IPU_BTRS_ARB_MODE_TYPE_REARB
> +
> +/* Currently chosen arbitration mechanism for VC1 */
> +#define IPU_BTRS_ARB_STALL_MODE_VC1	IPU_BTRS_ARB_MODE_TYPE_REARB
> +
> +struct ipu7_isys_subdev_pdata;
> +
> +/* One L2 entry maps 1024 L1 entries and one L1 entry per page */
> +#define IPU_MMUV2_L2_RANGE		(1024 * PAGE_SIZE)
> +/* Max L2 blocks per stream */
> +#define IPU_MMUV2_MAX_L2_BLOCKS		2
> +/* Max L1 blocks per stream */
> +#define IPU_MMUV2_MAX_L1_BLOCKS		16
> +#define IPU_MMUV2_TRASH_RANGE		(IPU_MMUV2_L2_RANGE *	\
> +					 IPU_MMUV2_MAX_L2_BLOCKS)
> +/* Entries per L1 block */
> +#define MMUV2_ENTRIES_PER_L1_BLOCK	16
> +#define MMUV2_TRASH_L1_BLOCK_OFFSET	(MMUV2_ENTRIES_PER_L1_BLOCK
> * PAGE_SIZE)
> +#define MMUV2_TRASH_L2_BLOCK_OFFSET	IPU_MMUV2_L2_RANGE
> +
> +struct ipu7_mmu_hw {
> +	char name[32];
> +
> +	void __iomem *base;
> +	void __iomem *zlx_base;
> +	void __iomem *uao_base;
> +
> +	u32 offset;
> +	u32 zlx_offset;
> +	u32 uao_offset;
> +
> +	u32 info_bits;
> +	u32 refill;
> +	u32 collapse_en_bitmap;
> +	u32 at_sp_arb_cfg;
> +
> +	u32 l1_block;
> +	u32 l2_block;
> +
> +	u8 nr_l1streams;
> +	u8 nr_l2streams;
> +	u32 l1_block_sz[IPU_MMU_MAX_TLB_L1_STREAMS];
> +	u32 l2_block_sz[IPU_MMU_MAX_TLB_L2_STREAMS];
> +
> +	u8 zlx_nr;
> +	u32 zlx_axi_pool[IPU_ZLX_POOL_NUM];
> +	u32 zlx_en[IPU_ZLX_MAX_NUM];
> +	u32 zlx_conf[IPU_ZLX_MAX_NUM];
> +
> +	u32 uao_p_num;
> +	u32 uao_p2tlb[IPU_UAO_PLANE_MAX_NUM];
> +};
> +
> +struct ipu7_mmu_pdata {
> +	u32 nr_mmus;
> +	struct ipu7_mmu_hw mmu_hw[IPU_MMU_MAX_NUM];
> +	int mmid;
> +};
> +
> +struct ipu7_isys_csi2_pdata {
> +	void __iomem *base;
> +};
> +
> +struct ipu7_isys_internal_csi2_pdata {
> +	u32 nports;
> +	u32 *offsets;
> +	u32 gpreg;
> +};
> +
> +struct ipu7_hw_variants {
> +	unsigned long offset;
> +	u32 nr_mmus;
> +	struct ipu7_mmu_hw mmu_hw[IPU_MMU_MAX_NUM];
> +	u8 cdc_fifos;
> +	u8 cdc_fifo_threshold[IPU_MAX_VC_IOSF_PORTS];
> +	u32 dmem_offset;
> +	u32 spc_offset;	/* SPC offset from psys base */
> +};
> +
> +struct ipu_isys_internal_pdata {
> +	struct ipu7_isys_internal_csi2_pdata csi2;
> +	struct ipu7_hw_variants hw_variant;
> +	u32 num_parallel_streams;
> +	u32 isys_dma_overshoot;
> +};
> +
> +struct ipu7_isys_pdata {
> +	void __iomem *base;
> +	const struct ipu_isys_internal_pdata *ipdata;
> +};
> +
> +struct ipu_psys_internal_pdata {
> +	struct ipu7_hw_variants hw_variant;
> +};
> +
> +struct ipu7_psys_pdata {
> +	void __iomem *base;
> +	const struct ipu_psys_internal_pdata *ipdata;
> +};
> +
> +int request_cpd_fw(const struct firmware **firmware_p, const char
> *name,
> +		   struct device *device);
> +void ipu_internal_pdata_init(struct ipu_isys_internal_pdata
> *isys_ipdata,
> +			     struct ipu_psys_internal_pdata
> *psys_ipdata);
> +void ipu7_dump_fw_error_log(const struct ipu7_bus_device *adev);
> +#endif /* IPU7_H */






[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux