From b1f8921dfbaa6d3aaee0598b20043d28fac876a9 Mon Sep 17 00:00:00 2001 From: Shyam Sundar S K Date: Mon, 23 Sep 2024 13:34:00 +0530 Subject: [PATCH] i2c: amd-asf: Clear remote IRR bit to get successive interrupt To ensure successive interrupts upon packet reception, it is necessary to clear the remote IRR bit by writing the interrupt number to the EOI register. The base address for this operation is provided by the BIOS and retrieved by the driver by traversing the ASF object's namespace. Reviewed-by: Andy Shevchenko Co-developed-by: Sanket Goswami Signed-off-by: Sanket Goswami Signed-off-by: Shyam Sundar S K Signed-off-by: Andi Shyti --- drivers/i2c/busses/i2c-amd-asf-plat.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/i2c/busses/i2c-amd-asf-plat.c b/drivers/i2c/busses/i2c-amd-asf-plat.c index 408c4bf6979f0..47e0c90341aed 100644 --- a/drivers/i2c/busses/i2c-amd-asf-plat.c +++ b/drivers/i2c/busses/i2c-amd-asf-plat.c @@ -48,6 +48,7 @@ struct amd_asf_dev { struct i2c_adapter adap; + void __iomem *eoi_base; struct i2c_client *target; struct delayed_work work_buf; struct sb800_mmio_cfg mmio_cfg; @@ -299,6 +300,7 @@ static int amd_asf_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct amd_asf_dev *asf_dev; + struct resource *eoi_addr; int ret, irq; asf_dev = devm_kzalloc(dev, sizeof(*asf_dev), GFP_KERNEL); @@ -310,6 +312,21 @@ static int amd_asf_probe(struct platform_device *pdev) if (!asf_dev->port_addr) return dev_err_probe(dev, -EINVAL, "missing IO resources\n"); + /* + * The resource obtained via ACPI might not belong to the ASF device address space. Instead, + * it could be within other IP blocks of the ASIC, which are crucial for generating + * subsequent interrupts. Therefore, we avoid using devm_platform_ioremap_resource() and + * use platform_get_resource() and devm_ioremap() separately to prevent any address space + * conflicts. + */ + eoi_addr = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!eoi_addr) + return dev_err_probe(dev, -EINVAL, "missing MEM resources\n"); + + asf_dev->eoi_base = devm_ioremap(dev, eoi_addr->start, resource_size(eoi_addr)); + if (!asf_dev->eoi_base) + return dev_err_probe(dev, -EBUSY, "failed mapping IO region\n"); + ret = devm_delayed_work_autocancel(dev, &asf_dev->work_buf, amd_asf_process_target); if (ret) return dev_err_probe(dev, ret, "failed to create work queue\n"); -- 2.39.5