On 2/24/25 10:38 PM, Philipp Stanner wrote: > 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. Philipp, Thanks for the review, I also found your talk at FOSDEM, I will cleanup these APIs. > > > 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 */ > > -- Best regards, Bingbu Cao