From: Bingbu Cao <bingbu.cao@linux.intel.com>
To: phasta@kernel.org, bingbu.cao@intel.com,
linux-media@vger.kernel.org, sakari.ailus@linux.intel.com,
hdegoede@redhat.com
Cc: hans@hansg.org, stanislaw.gruszka@linux.intel.com,
jerry.w.hu@intel.com, tian.shu.qiu@intel.com,
daxing.li@intel.com, hao.yao@intel.com
Subject: Re: [RFC PATCH 2/7] media: ipu7: add Intel IPU7 PCI device driver
Date: Thu, 27 Feb 2025 12:06:09 +0800 [thread overview]
Message-ID: <adb53b1f-29e1-3d14-0e61-351fd2d3ff0d@linux.intel.com> (raw)
In-Reply-To: <873cbddbc43638c2564ce27e373c25fe2f3dc2e9.camel@mailbox.org>
On 2/24/25 10:38 PM, Philipp Stanner wrote:
> Hi,
>
> see below
>
> On Fri, 2025-02-21 at 15:52 +0800, bingbu.cao@intel.com wrote:
>> From: Bingbu Cao <bingbu.cao@intel.com>
>>
>> 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@intel.com>
>> ---
>> 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
>>
---snip---
>> +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()
Philipp,
I see that pcim_iomap_regions() and pcim_add_mapping_to_legacy_table()
have simple 'bar' checking, how does pcim_iomap_region() check that?
>
>
>> + if (!iomap)
>> + return dev_err_probe(dev, -ENODEV, "Failed to iomap
>> table\n");
>> +
>> + isp->base = iomap[IPU_PCI_BAR];
>> + isp->pb_base = iomap[IPU_PCI_PBBAR];
>> + dev_info(dev, "IPU7 PCI BAR0 mapped at %p\n BAR2 mapped at
>> %p\n",
>> + isp->base, isp->pb_base);
>> +
>> + pci_set_drvdata(pdev, isp);
>> + pci_set_master(pdev);
>> +
>> + switch (id->device) {
>> + case IPU7_PCI_ID:
>> + isp->hw_ver = IPU_VER_7;
>> + isp->cpd_fw_name = IPU7_FIRMWARE_NAME;
>> + isys_ipdata = &ipu7_isys_ipdata;
>> + psys_ipdata = &ipu7_psys_ipdata;
>> + isys_buttress_ctrl = &ipu7_isys_buttress_ctrl;
>> + psys_buttress_ctrl = &ipu7_psys_buttress_ctrl;
>> + break;
>> + case IPU7P5_PCI_ID:
>> + isp->hw_ver = IPU_VER_7P5;
>> + isp->cpd_fw_name = IPU7P5_FIRMWARE_NAME;
>> + isys_ipdata = &ipu7p5_isys_ipdata;
>> + psys_ipdata = &ipu7p5_psys_ipdata;
>> + isys_buttress_ctrl = &ipu7_isys_buttress_ctrl;
>> + psys_buttress_ctrl = &ipu7_psys_buttress_ctrl;
>> + break;
>> + case IPU8_PCI_ID:
>> + isp->hw_ver = IPU_VER_8;
>> + isp->cpd_fw_name = IPU8_FIRMWARE_NAME;
>> + isys_ipdata = &ipu8_isys_ipdata;
>> + psys_ipdata = &ipu8_psys_ipdata;
>> + isys_buttress_ctrl = &ipu8_isys_buttress_ctrl;
>> + psys_buttress_ctrl = &ipu8_psys_buttress_ctrl;
>> + break;
>> + default:
>> + WARN(1, "Unsupported IPU device");
>> + return -ENODEV;
>> + }
>> +
>> + ipu_internal_pdata_init(isys_ipdata, psys_ipdata);
>> +
>> + isys_base = isp->base + isys_ipdata->hw_variant.offset;
>> + psys_base = isp->base + psys_ipdata->hw_variant.offset;
>> +
>> + ret = dma_set_mask_and_coherent(dev,
>> DMA_BIT_MASK(dma_mask));
>> + if (ret)
>> + return dev_err_probe(dev, ret, "Failed to set DMA
>> mask\n");
>> +
>> + dma_set_max_seg_size(dev, UINT_MAX);
>> +
>> + ret = ipu7_pci_config_setup(pdev);
>> + if (ret)
>> + return ret;
>> +
>> + ret = ipu_buttress_init(isp);
>> + if (ret)
>> + return ret;
>> +
>> + dev_info(dev, "firmware cpd file: %s\n", isp->cpd_fw_name);
>> +
>> + ret = request_firmware(&isp->cpd_fw, isp->cpd_fw_name, dev);
>> + if (ret) {
>> + dev_err_probe(dev, ret,
>> + "Requesting signed firmware %s
>> failed\n",
>> + isp->cpd_fw_name);
>> + goto buttress_exit;
>> + }
>> +
>> + ret = ipu7_cpd_validate_cpd_file(isp, isp->cpd_fw->data,
>> + isp->cpd_fw->size);
>> + if (ret) {
>> + dev_err_probe(dev, ret, "Failed to validate cpd\n");
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + isys_ctrl = devm_kmemdup(dev, isys_buttress_ctrl,
>> + sizeof(*isys_buttress_ctrl),
>> GFP_KERNEL);
>> + if (!isys_ctrl) {
>> + ret = -ENOMEM;
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + isp->isys = ipu7_isys_init(pdev, dev, isys_ctrl, isys_base,
>> + isys_ipdata, 0);
>> + if (IS_ERR(isp->isys)) {
>> + ret = PTR_ERR(isp->isys);
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + psys_ctrl = devm_kmemdup(dev, psys_buttress_ctrl,
>> + sizeof(*psys_buttress_ctrl),
>> GFP_KERNEL);
>> + if (!psys_ctrl) {
>> + ret = -ENOMEM;
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + isp->psys = ipu7_psys_init(pdev, &isp->isys->auxdev.dev,
>> + psys_ctrl, psys_base,
>> + psys_ipdata, 0);
>> + if (IS_ERR(isp->psys)) {
>> + ret = PTR_ERR(isp->psys);
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + ret = devm_request_threaded_irq(dev, pdev->irq,
>> + ipu_buttress_isr,
>> + ipu_buttress_isr_threaded,
>> + IRQF_SHARED, IPU_NAME, isp);
>> + if (ret)
>> + goto out_ipu_bus_del_devices;
>> +
>> + if (!isp->secure_mode) {
>> + ret = ipu7_init_fw_code_region(isp);
>> + if (ret)
>> + goto out_ipu_bus_del_devices;
>> + } else {
>> + ret = pm_runtime_get_sync(&isp->psys->auxdev.dev);
>> + if (ret < 0) {
>> + dev_err(&isp->psys->auxdev.dev,
>> + "Failed to get runtime PM\n");
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + ret = ipu7_mmu_hw_init(isp->psys->mmu);
>> + if (ret) {
>> + dev_err_probe(&isp->pdev->dev, ret,
>> + "Failed to init MMU
>> hardware\n");
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + ret = ipu7_map_fw_code_region(isp->psys,
>> + (void *)isp->cpd_fw-
>>> data,
>> + isp->cpd_fw->size);
>> + if (ret) {
>> + dev_err_probe(&isp->pdev->dev, ret,
>> + "failed to map fw image\n");
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + ret = ipu_buttress_authenticate(isp);
>> + if (ret) {
>> + dev_err_probe(&isp->pdev->dev, ret,
>> + "FW authentication failed\n");
>> + goto out_ipu_bus_del_devices;
>> + }
>> +
>> + ipu7_mmu_hw_cleanup(isp->psys->mmu);
>> + pm_runtime_put(&isp->psys->auxdev.dev);
>> + }
>> +
>> + pm_runtime_put_noidle(dev);
>> + pm_runtime_allow(dev);
>> +
>> + isp->ipu7_bus_ready_to_probe = true;
>> +
>> + return 0;
>> +
>> +out_ipu_bus_del_devices:
>> + if (!IS_ERR_OR_NULL(isp->isys) && isp->isys->fw_sgt.nents)
>> + ipu7_unmap_fw_code_region(isp->isys);
>> + if (!IS_ERR_OR_NULL(isp->psys) && isp->psys->fw_sgt.nents)
>> + ipu7_unmap_fw_code_region(isp->psys);
>> + if (!IS_ERR_OR_NULL(isp->psys) && !IS_ERR_OR_NULL(isp->psys-
>>> mmu))
>> + ipu7_mmu_cleanup(isp->psys->mmu);
>> + if (!IS_ERR_OR_NULL(isp->isys) && !IS_ERR_OR_NULL(isp->isys-
>>> mmu))
>> + ipu7_mmu_cleanup(isp->isys->mmu);
>> + if (!IS_ERR_OR_NULL(isp->psys))
>> + pm_runtime_put(&isp->psys->auxdev.dev);
>> + ipu7_bus_del_devices(pdev);
>> + release_firmware(isp->cpd_fw);
>> +buttress_exit:
>> + ipu_buttress_exit(isp);
>> +
>> + return ret;
>> +}
>> +
>> +static void ipu7_pci_remove(struct pci_dev *pdev)
>> +{
>> + struct ipu7_device *isp = pci_get_drvdata(pdev);
>> +
>> + if (!IS_ERR_OR_NULL(isp->isys) && isp->isys->fw_sgt.nents)
>> + ipu7_unmap_fw_code_region(isp->isys);
>> + if (!IS_ERR_OR_NULL(isp->psys) && isp->psys->fw_sgt.nents)
>> + ipu7_unmap_fw_code_region(isp->psys);
>> +
>> + if (!IS_ERR_OR_NULL(isp->fw_code_region))
>> + vfree(isp->fw_code_region);
>> +
>> + ipu7_bus_del_devices(pdev);
>> +
>> + pm_runtime_forbid(&pdev->dev);
>> + pm_runtime_get_noresume(&pdev->dev);
>> +
>> + pci_release_regions(pdev);
>
> You don't need this if you request with a pcim_ function. The 'm'
> stands for "managed". Those are devres functions that will clean up
> automatically if probe() fails or once remove() is invoked.
>
> Furthermore, you should not mix pcim_ and pci_ functions; at least not
> those.
>
> And even if the pcim_ functions wouldn't do a cleanup, you would leak
> the IO mappings above, since pci_release_regions() just removes the
> region requests, but not the mapping cookies.
>
> I recommend taking a look to the PCI subystem's documentation.
>
>> + pci_disable_device(pdev);
>
> You also don't need this since you used pcim_enable_device(), which
> will disable the device automatically on driver-detach.
>
>
> P.
>
>> +
>> + ipu_buttress_exit(isp);
>> +
>> + release_firmware(isp->cpd_fw);
>> +
>> + ipu7_mmu_cleanup(isp->psys->mmu);
>> + ipu7_mmu_cleanup(isp->isys->mmu);
>> +}
>> +
>> +static void ipu7_pci_reset_prepare(struct pci_dev *pdev)
>> +{
>> + struct ipu7_device *isp = pci_get_drvdata(pdev);
>> +
>> + dev_warn(&pdev->dev, "FLR prepare\n");
>> + pm_runtime_forbid(&isp->pdev->dev);
>> +}
>> +
>> +static void ipu7_pci_reset_done(struct pci_dev *pdev)
>> +{
>> + struct ipu7_device *isp = pci_get_drvdata(pdev);
>> +
>> + ipu_buttress_restore(isp);
>> + if (isp->secure_mode)
>> + ipu_buttress_reset_authentication(isp);
>> +
>> + isp->ipc_reinit = true;
>> + pm_runtime_allow(&isp->pdev->dev);
>> +
>> + dev_warn(&pdev->dev, "FLR completed\n");
>> +}
>> +
>> +/*
>> + * PCI base driver code requires driver to provide these to enable
>> + * PCI device level PM state transitions (D0<->D3)
>> + */
>> +static int ipu7_suspend(struct device *dev)
>> +{
>> + return 0;
>> +}
>> +
>> +static int ipu7_resume(struct device *dev)
>> +{
>> + struct pci_dev *pdev = to_pci_dev(dev);
>> + struct ipu7_device *isp = pci_get_drvdata(pdev);
>> + struct ipu_buttress *b = &isp->buttress;
>> + int ret;
>> +
>> + isp->secure_mode = ipu_buttress_get_secure_mode(isp);
>> + dev_info(dev, "IPU7 in %s mode\n",
>> + isp->secure_mode ? "secure" : "non-secure");
>> +
>> + ipu_buttress_restore(isp);
>> +
>> + ret = ipu_buttress_ipc_reset(isp, &b->cse);
>> + if (ret)
>> + dev_err(dev, "IPC reset protocol failed!\n");
>> +
>> + ret = pm_runtime_get_sync(&isp->psys->auxdev.dev);
>> + if (ret < 0) {
>> + dev_err(dev, "Failed to get runtime PM\n");
>> + return 0;
>> + }
>> +
>> + ret = ipu_buttress_authenticate(isp);
>> + if (ret)
>> + dev_err(dev, "FW authentication failed(%d)\n", ret);
>> +
>> + pm_runtime_put(&isp->psys->auxdev.dev);
>> +
>> + return 0;
>> +}
>> +
>> +static int ipu7_runtime_resume(struct device *dev)
>> +{
>> + struct pci_dev *pdev = to_pci_dev(dev);
>> + struct ipu7_device *isp = pci_get_drvdata(pdev);
>> + int ret;
>> +
>> + ipu_buttress_restore(isp);
>> +
>> + if (isp->ipc_reinit) {
>> + struct ipu_buttress *b = &isp->buttress;
>> +
>> + isp->ipc_reinit = false;
>> + ret = ipu_buttress_ipc_reset(isp, &b->cse);
>> + if (ret)
>> + dev_err(dev, "IPC reset protocol
>> failed!\n");
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static const struct dev_pm_ops ipu7_pm_ops = {
>> + SET_SYSTEM_SLEEP_PM_OPS(&ipu7_suspend, &ipu7_resume)
>> + SET_RUNTIME_PM_OPS(&ipu7_suspend, /* Same as in
>> suspend flow */
>> + &ipu7_runtime_resume,
>> + NULL)
>> +};
>> +
>> +static const struct pci_device_id ipu7_pci_tbl[] = {
>> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU7_PCI_ID)},
>> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU7P5_PCI_ID)},
>> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU8_PCI_ID)},
>> + {0,}
>> +};
>> +MODULE_DEVICE_TABLE(pci, ipu7_pci_tbl);
>> +
>> +static const struct pci_error_handlers pci_err_handlers = {
>> + .reset_prepare = ipu7_pci_reset_prepare,
>> + .reset_done = ipu7_pci_reset_done,
>> +};
>> +
>> +static struct pci_driver ipu7_pci_driver = {
>> + .name = IPU_NAME,
>> + .id_table = ipu7_pci_tbl,
>> + .probe = ipu7_pci_probe,
>> + .remove = ipu7_pci_remove,
>> + .driver = {
>> + .pm = &ipu7_pm_ops,
>> + },
>> + .err_handler = &pci_err_handlers,
>> +};
>> +
>> +module_pci_driver(ipu7_pci_driver);
>> +
>> +MODULE_IMPORT_NS("INTEL_IPU_BRIDGE");
>> +MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
>> +MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>");
>> +MODULE_AUTHOR("Qingwu Zhang <qingwu.zhang@intel.com>");
>> +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
next prev parent reply other threads:[~2025-02-27 4:11 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-21 7:52 [RFC PATCH 0/7] Intel IPU7 PCI and input system device drivers bingbu.cao
2025-02-21 7:52 ` [RFC PATCH 1/7] media: Rename the IPU PCI device table header and add IPU7 PCI IDs bingbu.cao
2025-02-21 7:52 ` [RFC PATCH 2/7] media: ipu7: add Intel IPU7 PCI device driver bingbu.cao
2025-02-24 14:38 ` Philipp Stanner
2025-02-25 9:39 ` Bingbu Cao
2025-02-27 4:06 ` Bingbu Cao [this message]
2025-03-03 15:01 ` Philipp Stanner
2025-03-03 15:18 ` Philipp Stanner
2025-02-26 10:00 ` Philipp Stanner
2025-02-27 3:47 ` Bingbu Cao
2025-02-21 7:52 ` [RFC PATCH 3/7] media: ipu7: add IPU7 DMA APIs and MMU mapping bingbu.cao
2025-03-03 16:13 ` Bjorn Helgaas
2025-02-21 7:52 ` [RFC PATCH 4/7] media: ipu7: add firmware parse, syscom interface and boot sequence bingbu.cao
2025-02-21 7:52 ` [RFC PATCH 5/7] media: ipu7: add IPU7 firmware ABI headers bingbu.cao
2025-02-21 7:52 ` [RFC PATCH 6/7] media: ipu7: add IPU7 input system device driver bingbu.cao
2025-02-21 7:52 ` [RFC PATCH 7/7] media: ipu7: add Makefile and Kconfig for IPU7 bingbu.cao
2025-02-25 5:55 ` Bingbu Cao
2025-02-21 12:55 ` [RFC PATCH 0/7] Intel IPU7 PCI and input system device drivers Sakari Ailus
2025-04-09 20:23 ` Laurent Pinchart
2025-03-03 16:23 ` Bjorn Helgaas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=adb53b1f-29e1-3d14-0e61-351fd2d3ff0d@linux.intel.com \
--to=bingbu.cao@linux.intel.com \
--cc=bingbu.cao@intel.com \
--cc=daxing.li@intel.com \
--cc=hans@hansg.org \
--cc=hao.yao@intel.com \
--cc=hdegoede@redhat.com \
--cc=jerry.w.hu@intel.com \
--cc=linux-media@vger.kernel.org \
--cc=phasta@kernel.org \
--cc=sakari.ailus@linux.intel.com \
--cc=stanislaw.gruszka@linux.intel.com \
--cc=tian.shu.qiu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox