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 <andriy.shevchenko@linux.intel.com>
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
This commit is contained in:
Shyam Sundar S K 2024-09-23 13:34:00 +05:30 committed by Andi Shyti
parent 9b25419ad3
commit b1f8921dfb

View File

@ -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");