All of lore.kernel.org
 help / color / mirror / Atom feed
* FAILED: patch "[PATCH] drm/xe/i2c: Keep the i2c controller always enabled" failed to apply to 7.2-stable tree
@ 2026-09-09 11:42 gregkh
  2026-09-12 14:21 ` [PATCH 7.2.y 1/3] accel/amdxdna: Disable device buffer exporting Sasha Levin
  2026-09-12 14:42 ` [PATCH 7.2.y 1/3] accel/amdxdna: Disable device buffer exporting Sasha Levin
  0 siblings, 2 replies; 8+ messages in thread
From: gregkh @ 2026-09-09 11:42 UTC (permalink / raw)
  To: heikki.krogerus, rodrigo.vivi; +Cc: stable


The patch below does not apply to the 7.2-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-7.2.y
git checkout FETCH_HEAD
git cherry-pick -x 244abef7f280a6a84297bfab5fd2e77147bc419a
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090957-lilac-mocha-69d6@gregkh' --subject-prefix 'PATCH 7.2.y' 'HEAD^..'

Possible dependencies:



thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 244abef7f280a6a84297bfab5fd2e77147bc419a Mon Sep 17 00:00:00 2001
From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Date: Tue, 11 Aug 2026 14:10:08 +0200
Subject: [PATCH] drm/xe/i2c: Keep the i2c controller always enabled

Some platforms make an assumption that the i2c controller's
enabled state indicates also the power state of the
controller. This can create a problem when the controller is
in disabled state, because the hardware may assume
incorrectly that it is then also in low-power state.

To fix this, the controller is kept enabled by taking over
the IC_ENABLE register. The controller has to be disabled
when the configuration is updated and when the target
address or the slave address are assigned, so disabling it
when IC_CON, IC_TAR or IC_SAR registers are programmed, and
then re-enabling it again.

Fixes: f0e53aadd702 ("drm/xe: Support for I2C attached MCUs")
Cc: stable@vger.kernel.org
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patch.msgid.link/20260811121008.1493015-4-heikki.krogerus@linux.intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
(cherry picked from commit 76cc14e2faed1adae20f4ee144ead0e3a7566c49)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

diff --git a/drivers/gpu/drm/xe/xe_i2c.c b/drivers/gpu/drm/xe/xe_i2c.c
index 32767570e43d..d8fa68206f41 100644
--- a/drivers/gpu/drm/xe/xe_i2c.c
+++ b/drivers/gpu/drm/xe/xe_i2c.c
@@ -8,6 +8,7 @@
 #include <drm/drm_print.h>
 #include <linux/array_size.h>
 #include <linux/container_of.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
@@ -215,11 +216,40 @@ void xe_i2c_irq_postinstall(struct xe_device *xe)
 	xe_mmio_rmw32(mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
 }
 
+/* See "Disabling DW_apb_i2c" in the DesignWare DW_abp_i2c databook. */
+static void xe_i2c_disable(struct xe_i2c *i2c)
+{
+	int timeout = 100;
+	u32 status;
+
+	xe_mmio_rmw32(i2c->mmio, I2C_REG(DW_IC_ENABLE), DW_IC_ENABLE_ENABLE, 0);
+
+	do {
+		status = xe_mmio_read32(i2c->mmio, I2C_REG(DW_IC_ENABLE_STATUS));
+		if (!(status & DW_IC_ENABLE_ENABLE))
+			return;
+		/* Can't sleep here. */
+		udelay(25);
+	} while (timeout--);
+
+	dev_warn(i2c->drm_dev, "timeout in disabling i2c adapter\n");
+}
+
 static int xe_i2c_read(void *context, unsigned int reg, unsigned int *val)
 {
 	struct xe_i2c *i2c = context;
 
-	*val = xe_mmio_read32(i2c->mmio, XE_REG(reg + I2C_MEM_SPACE_OFFSET));
+	*val = xe_mmio_read32(i2c->mmio, I2C_REG(reg));
+
+	switch (reg) {
+	case DW_IC_ENABLE:
+	case DW_IC_ENABLE_STATUS:
+		FIELD_MODIFY(DW_IC_ENABLE_ENABLE, val,
+			     i2c->ic_enable & DW_IC_ENABLE_ENABLE);
+		break;
+	default:
+		break;
+	}
 
 	return 0;
 }
@@ -229,6 +259,23 @@ static int xe_i2c_write(void *context, unsigned int reg, unsigned int val)
 	struct xe_i2c *i2c = context;
 
 	switch (reg) {
+	case DW_IC_CON:
+	case DW_IC_TAR:
+	case DW_IC_SAR:
+		/* Disable the controller. */
+		xe_i2c_disable(i2c);
+
+		/* Write the register. */
+		xe_mmio_write32(i2c->mmio, I2C_REG(reg), val);
+
+		/* Enable the controller. */
+		xe_mmio_rmw32(i2c->mmio, I2C_REG(DW_IC_ENABLE), 0, DW_IC_ENABLE_ENABLE);
+		return 0;
+	case DW_IC_ENABLE:
+		i2c->ic_enable = val;
+		/* Other fields can be updated except the enable bit. */
+		val |= DW_IC_ENABLE_ENABLE;
+		break;
 	case DW_IC_SMBUS_INTR_MASK:
 		/* Make sure the Alert is never masked. */
 		val |= DW_IC_SMBUS_INTR_ALERT;
diff --git a/drivers/gpu/drm/xe/xe_i2c.h b/drivers/gpu/drm/xe/xe_i2c.h
index b200966b0048..d63adacfefe7 100644
--- a/drivers/gpu/drm/xe/xe_i2c.h
+++ b/drivers/gpu/drm/xe/xe_i2c.h
@@ -37,6 +37,7 @@ struct xe_i2c {
 	struct platform_device *pdev;
 	struct i2c_adapter *adapter;
 	struct i2c_client *client[XE_I2C_MAX_CLIENTS];
+	unsigned int ic_enable;
 
 	struct notifier_block bus_notifier;
 	struct work_struct work;


^ permalink raw reply related	[flat|nested] 8+ messages in thread
* FAILED: patch "[PATCH] drm/xe/i2c: Fix the interrupt handling" failed to apply to 7.2-stable tree
@ 2026-09-09 11:42 gregkh
  2026-09-12 14:20 ` [PATCH 7.2.y 1/3] accel/amdxdna: Disable device buffer exporting Sasha Levin
  0 siblings, 1 reply; 8+ messages in thread
From: gregkh @ 2026-09-09 11:42 UTC (permalink / raw)
  To: heikki.krogerus, raag.jadav, ramesh.babu.b, rodrigo.vivi; +Cc: stable


The patch below does not apply to the 7.2-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-7.2.y
git checkout FETCH_HEAD
git cherry-pick -x f43fa4b8522ba6038b77e86e5f0d94be35effcde
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090944-turf-outthink-f4fa@gregkh' --subject-prefix 'PATCH 7.2.y' 'HEAD^..'

Possible dependencies:



thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From f43fa4b8522ba6038b77e86e5f0d94be35effcde Mon Sep 17 00:00:00 2001
From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Date: Tue, 11 Aug 2026 14:10:07 +0200
Subject: [PATCH] drm/xe/i2c: Fix the interrupt handling

The platforms that support the interrupt from the I2C
adapter can not handle the amount of interrupts the adapter
generates because of the way the IRQ is routed in the
hardware. The I2C controller driver has to be kept in
polling mode because of that.

The AMC MCU can still generate critical alerts that have to
be handled. The interrupt from SMBus Alert is left enabled
and handled separately in the Xe. The alerts from the AMC
will cause the device to be declared wedged for now.

Fixes: f0e53aadd702 ("drm/xe: Support for I2C attached MCUs")
Cc: stable@vger.kernel.org
Reviewed-by: Raag Jadav <raag.jadav@intel.com>
Co-developed-by: Ramesh Babu B <ramesh.babu.b@intel.com>
Signed-off-by: Ramesh Babu B <ramesh.babu.b@intel.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://patch.msgid.link/20260811121008.1493015-3-heikki.krogerus@linux.intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
(cherry picked from commit a55b76b8bc2c49b11d753c1c6d06ec3a2c61c85e)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 67ada1d6c2fb..c92468cb9b89 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -153,7 +153,9 @@ xe-y += xe_bb.o \
 	xe_wait_user_fence.o \
 	xe_wopcm.o
 
-xe-$(CONFIG_I2C)	+= xe_i2c.o
+xe-$(CONFIG_I2C)	+= xe_i2c.o \
+			   xe_amc.o
+
 xe-$(CONFIG_DRM_XE_GPUSVM) += xe_svm.o
 xe-$(CONFIG_DRM_GPUSVM) += xe_userptr.o
 
diff --git a/drivers/gpu/drm/xe/regs/xe_i2c_regs.h b/drivers/gpu/drm/xe/regs/xe_i2c_regs.h
index f2e455e2bfe4..37550e4a20f8 100644
--- a/drivers/gpu/drm/xe/regs/xe_i2c_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_i2c_regs.h
@@ -20,4 +20,6 @@
 #define I2C_CONFIG_CMD			XE_REG(I2C_CONFIG_SPACE_OFFSET + PCI_COMMAND)
 #define I2C_CONFIG_PMCSR		XE_REG(I2C_CONFIG_SPACE_OFFSET + 0x84)
 
+#define I2C_REG(reg)			XE_REG((reg) + I2C_MEM_SPACE_OFFSET)
+
 #endif /* _XE_I2C_REGS_H_ */
diff --git a/drivers/gpu/drm/xe/xe_amc.c b/drivers/gpu/drm/xe/xe_amc.c
new file mode 100644
index 000000000000..8ecadee6eea3
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_amc.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 Intel Corporation.
+ */
+
+#include <linux/delay.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+
+#include "regs/xe_i2c_regs.h"
+
+#include "xe_amc.h"
+#include "xe_device.h"
+#include "xe_i2c.h"
+#include "xe_mmio.h"
+
+/**
+ * DOC: Add-In Management Controller (AMC)
+ *
+ * Handler for the SMBus Alerts from the AMC. All the alerts from AMC will cause
+ * the device to be declared wedged.
+ */
+
+#define AMC_COMMAND		0x0f
+#define AMC_GPU_I2C_ADDR	0x8f
+#define AMC_VERSION_V1		0x01
+#define AMC_DESTINATION_ID	12
+#define AMC_SOURCE_ID		8
+#define AMC_FLAGS		0xc8
+
+#define AMC_MSG_TYPE		0x7e
+#define AMC_GET_ALERT_REASON	0x01
+
+enum xe_amc_alert {
+	AMC_ALERT_UNKNOWN,
+	AMC_ALERT_FW_DOWNLOAD,
+	AMC_ALERT_THERMAL_TRIP,
+	AMC_ALERT_OOB_REQUEST,
+	AMC_ALERT_OOB_RESET,
+	AMC_ALERT_CATERR,
+};
+
+static const char * const amc_alert[] = {
+	[AMC_ALERT_FW_DOWNLOAD]		= "Firmware Download",
+	[AMC_ALERT_THERMAL_TRIP]	= "Thermal Trip",
+	[AMC_ALERT_OOB_REQUEST]		= "OOB Request",
+	[AMC_ALERT_OOB_RESET]		= "OOB Reset",
+	[AMC_ALERT_CATERR]		= "Catastrophic",
+};
+
+struct xe_amc {
+	struct xe_i2c *i2c;
+	struct work_struct work;
+};
+
+struct amc_header {
+	u8 command;
+	u8 len;
+	u8 address;
+	u8 version;
+	u8 destination;
+	u8 source;
+	u8 flags;
+} __packed;
+
+struct amc_message {
+	u8 type;
+	u16 vendor;
+	u8 command;
+} __packed;
+
+struct amc_request {
+	struct amc_header header;
+	struct amc_message message;
+	u32 reserved;
+} __packed;
+
+struct amc_response {
+	struct amc_header header;
+	struct amc_message message;
+	u8 error;
+	u8 value;
+} __packed;
+
+static const struct amc_request amc_get_alert_reason = {
+	.header = {
+		.command	= AMC_COMMAND,
+		.len		= sizeof(struct amc_request) - 2,
+		.address	= AMC_GPU_I2C_ADDR,
+		.version	= AMC_VERSION_V1,
+		.destination	= AMC_DESTINATION_ID,
+		.source		= AMC_SOURCE_ID,
+		.flags		= AMC_FLAGS,
+	},
+	.message = {
+		.type		= AMC_MSG_TYPE,
+		.vendor		= htons(PCI_VENDOR_ID_INTEL),
+		.command	= AMC_GET_ALERT_REASON,
+	},
+};
+
+static void xe_amc_work(struct work_struct *work)
+{
+	const struct amc_request *request = &amc_get_alert_reason;
+	struct xe_amc *amc = from_work(amc, work, work);
+	u8 alert_reason = AMC_ALERT_UNKNOWN;
+	struct amc_response response;
+	struct i2c_client *client;
+	int ret;
+
+	client = amc->i2c->client[XE_I2C_CLIENT_AMC];
+	if (IS_ERR_OR_NULL(client))
+		goto out_reassert_interrupt;
+
+	ret = i2c_master_send(client, (u8 *)request, sizeof(*request));
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to send request (%d)\n", ret);
+		goto out_reassert_interrupt;
+	}
+
+	/* AMC needs 20ms to generate the response. */
+	fsleep(20 * USEC_PER_MSEC);
+
+	ret = i2c_master_recv(client, (u8 *)&response, sizeof(response));
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to read response (%d)\n", ret);
+		goto out_reassert_interrupt;
+	}
+
+	if (!response.header.len) {
+		dev_err(&client->dev, "empty response from AMC\n");
+		goto out_reassert_interrupt;
+	}
+
+	if (memcmp(&response.message, &request->message, sizeof(struct amc_message))) {
+		dev_err(&client->dev, "response does not match the request\n");
+		goto out_reassert_interrupt;
+	}
+
+	if (response.error) {
+		dev_err(&client->dev, "AMC error 0x%02x\n", response.error);
+		goto out_reassert_interrupt;
+	}
+
+	alert_reason = response.value;
+	dev_dbg(&client->dev, "Alert reason: %d\n", alert_reason);
+
+out_reassert_interrupt:
+	xe_mmio_rmw32(amc->i2c->mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
+
+	switch (alert_reason) {
+	case AMC_ALERT_FW_DOWNLOAD:
+	case AMC_ALERT_THERMAL_TRIP:
+	case AMC_ALERT_OOB_REQUEST:
+	case AMC_ALERT_OOB_RESET:
+	case AMC_ALERT_CATERR:
+		dev_warn(amc->i2c->drm_dev, "AMC Alert: %s\n", amc_alert[alert_reason]);
+		xe_device_declare_wedged(i2c_client_to_xe_device(client));
+		break;
+	default:
+		dev_warn(amc->i2c->drm_dev, "unknown AMC alert: %d\n", alert_reason);
+		break;
+	}
+}
+
+void xe_amc_handle_alert(struct xe_i2c *i2c)
+{
+	queue_work(system_long_wq, &i2c->amc->work);
+}
+
+int xe_amc_init(struct xe_i2c *i2c)
+{
+	struct xe_amc *amc;
+
+	amc = kzalloc(sizeof(*amc), GFP_KERNEL);
+	if (!amc)
+		return -ENOMEM;
+
+	INIT_WORK(&amc->work, xe_amc_work);
+	i2c->amc = amc;
+	amc->i2c = i2c;
+
+	return 0;
+}
+
+void xe_amc_exit(struct xe_i2c *i2c)
+{
+	if (i2c->amc) {
+		cancel_work_sync(&i2c->amc->work);
+		kfree(i2c->amc);
+	}
+}
diff --git a/drivers/gpu/drm/xe/xe_amc.h b/drivers/gpu/drm/xe/xe_amc.h
new file mode 100644
index 000000000000..b1d5311fee53
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_amc.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _XE_AMC_H_
+#define _XE_AMC_H_
+
+#include <linux/i2c.h>
+
+#include "xe_device.h"
+
+struct xe_i2c;
+
+static inline struct xe_device *i2c_adapter_to_xe_device(struct i2c_adapter *adapter)
+{
+	return kdev_to_xe_device(adapter->dev.parent->parent);
+}
+
+static inline struct xe_device *i2c_client_to_xe_device(struct i2c_client *client)
+{
+	return i2c_adapter_to_xe_device(client->adapter);
+}
+
+int xe_amc_init(struct xe_i2c *i2c);
+void xe_amc_exit(struct xe_i2c *i2c);
+void xe_amc_handle_alert(struct xe_i2c *i2c);
+
+#endif /* _XE_AMC_H_ */
diff --git a/drivers/gpu/drm/xe/xe_i2c.c b/drivers/gpu/drm/xe/xe_i2c.c
index a26c38bb17a1..32767570e43d 100644
--- a/drivers/gpu/drm/xe/xe_i2c.c
+++ b/drivers/gpu/drm/xe/xe_i2c.c
@@ -12,8 +12,6 @@
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/notifier.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
@@ -24,9 +22,12 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
+#include <linux/designware_i2c.h>
+
 #include "regs/xe_i2c_regs.h"
 #include "regs/xe_irq_regs.h"
 
+#include "xe_amc.h"
 #include "xe_device.h"
 #include "xe_i2c.h"
 #include "xe_mmio.h"
@@ -61,16 +62,32 @@ static inline void xe_i2c_read_endpoint(struct xe_mmio *mmio, void *ep)
 	val[1] = xe_mmio_read32(mmio, REG_SG_REMAP_ADDR_POSTFIX);
 }
 
+static void xe_i2c_handle_smbus_alert(struct xe_i2c *i2c)
+{
+	u32 stat;
+
+	stat = xe_mmio_read32(i2c->mmio, I2C_REG(DW_IC_SMBUS_INTR_STAT));
+	if (!stat)
+		return;
+
+	xe_mmio_write32(i2c->mmio, I2C_REG(DW_IC_CLR_SMBUS_INTR), stat);
+
+	if (stat & DW_IC_SMBUS_INTR_ALERT && i2c->amc)
+		xe_amc_handle_alert(i2c);
+	else
+		xe_mmio_rmw32(i2c->mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
+}
+
 static void xe_i2c_client_work(struct work_struct *work)
 {
 	struct xe_i2c *i2c = container_of(work, struct xe_i2c, work);
 	struct i2c_board_info info = {
 		.type	= "amc",
 		.flags	= I2C_CLIENT_HOST_NOTIFY,
-		.addr	= i2c->ep.addr[1],
+		.addr	= i2c->ep.addr[XE_I2C_CLIENT_AMC],
 	};
 
-	i2c->client[0] = i2c_new_client_device(i2c->adapter, &info);
+	i2c->client[XE_I2C_CLIENT_AMC] = i2c_new_client_device(i2c->adapter, &info);
 }
 
 static int xe_i2c_notifier(struct notifier_block *nb, unsigned long action, void *data)
@@ -115,16 +132,6 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)
 		goto err_fwnode_remove;
 	}
 
-	if (i2c->adapter_irq) {
-		struct resource res;
-
-		res = DEFINE_RES_IRQ_NAMED(i2c->adapter_irq, "xe_i2c");
-
-		ret = platform_device_add_resources(pdev, &res, 1);
-		if (ret)
-			goto err_pdev_put;
-	}
-
 	pdev->dev.parent = i2c->drm_dev;
 	pdev->dev.fwnode = fwnode;
 	i2c->adapter_node = fwnode;
@@ -166,7 +173,8 @@ bool xe_i2c_present(struct xe_device *xe)
 
 static bool xe_i2c_irq_present(struct xe_device *xe)
 {
-	return xe->i2c && xe->i2c->adapter_irq;
+	return xe->i2c && xe->i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ &&
+		!xe_survivability_mode_is_boot_enabled(xe);
 }
 
 /**
@@ -179,18 +187,10 @@ static bool xe_i2c_irq_present(struct xe_device *xe)
  */
 void xe_i2c_irq_handler(struct xe_device *xe, u32 master_ctl)
 {
-	struct xe_mmio *mmio = xe_root_tile_mmio(xe);
-
 	if (!(master_ctl & I2C_IRQ) || !xe_i2c_irq_present(xe))
 		return;
 
-	/* Forward interrupt to I2C adapter */
-	generic_handle_irq_safe(xe->i2c->adapter_irq);
-
-	/* Deassert after I2C adapter clears the interrupt */
-	xe_mmio_rmw32(mmio, I2C_CONFIG_CMD, 0, PCI_COMMAND_INTX_DISABLE);
-	/* Reassert to allow subsequent interrupt generation */
-	xe_mmio_rmw32(mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
+	xe_i2c_handle_smbus_alert(xe->i2c);
 }
 
 void xe_i2c_irq_reset(struct xe_device *xe)
@@ -215,45 +215,6 @@ void xe_i2c_irq_postinstall(struct xe_device *xe)
 	xe_mmio_rmw32(mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
 }
 
-static int xe_i2c_irq_map(struct irq_domain *h, unsigned int virq,
-			  irq_hw_number_t hw_irq_num)
-{
-	irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_simple_irq);
-	return 0;
-}
-
-static const struct irq_domain_ops xe_i2c_irq_ops = {
-	.map = xe_i2c_irq_map,
-};
-
-static int xe_i2c_create_irq(struct xe_device *xe)
-{
-	struct xe_i2c *i2c = xe->i2c;
-	struct irq_domain *domain;
-
-	if (!(i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ) ||
-	    xe_survivability_mode_is_boot_enabled(xe))
-		return 0;
-
-	domain = irq_domain_create_linear(dev_fwnode(i2c->drm_dev), 1, &xe_i2c_irq_ops, NULL);
-	if (!domain)
-		return -ENOMEM;
-
-	i2c->adapter_irq = irq_create_mapping(domain, 0);
-	i2c->irqdomain = domain;
-
-	return 0;
-}
-
-static void xe_i2c_remove_irq(struct xe_i2c *i2c)
-{
-	if (!i2c->irqdomain)
-		return;
-
-	irq_dispose_mapping(i2c->adapter_irq);
-	irq_domain_remove(i2c->irqdomain);
-}
-
 static int xe_i2c_read(void *context, unsigned int reg, unsigned int *val)
 {
 	struct xe_i2c *i2c = context;
@@ -267,8 +228,16 @@ static int xe_i2c_write(void *context, unsigned int reg, unsigned int val)
 {
 	struct xe_i2c *i2c = context;
 
-	xe_mmio_write32(i2c->mmio, XE_REG(reg + I2C_MEM_SPACE_OFFSET), val);
+	switch (reg) {
+	case DW_IC_SMBUS_INTR_MASK:
+		/* Make sure the Alert is never masked. */
+		val |= DW_IC_SMBUS_INTR_ALERT;
+		break;
+	default:
+		break;
+	}
 
+	xe_mmio_write32(i2c->mmio, I2C_REG(reg), val);
 	return 0;
 }
 
@@ -310,12 +279,15 @@ static void xe_i2c_remove(void *data)
 	struct xe_i2c *i2c = data;
 	unsigned int i;
 
-	for (i = 0; i < XE_I2C_MAX_CLIENTS; i++)
+	xe_amc_exit(i2c);
+
+	for (i = 0; i < XE_I2C_MAX_CLIENTS; i++) {
 		i2c_unregister_device(i2c->client[i]);
+		i2c->client[i] = NULL;
+	}
 
 	bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
 	xe_i2c_unregister_adapter(i2c);
-	xe_i2c_remove_irq(i2c);
 }
 
 /**
@@ -363,22 +335,18 @@ int xe_i2c_probe(struct xe_device *xe)
 	if (ret)
 		return ret;
 
-	ret = xe_i2c_create_irq(xe);
-	if (ret)
-		goto err_unregister_notifier;
-
 	ret = xe_i2c_register_adapter(i2c);
-	if (ret)
-		goto err_remove_irq;
+	if (ret) {
+		bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
+		return ret;
+	}
+
+	ret = xe_amc_init(i2c);
+	if (ret) {
+		xe_i2c_remove(i2c);
+		return ret;
+	}
 
 	xe_i2c_irq_postinstall(xe);
 	return devm_add_action_or_reset(drm_dev, xe_i2c_remove, i2c);
-
-err_remove_irq:
-	xe_i2c_remove_irq(i2c);
-
-err_unregister_notifier:
-	bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
-
-	return ret;
 }
diff --git a/drivers/gpu/drm/xe/xe_i2c.h b/drivers/gpu/drm/xe/xe_i2c.h
index 425d8160835f..b200966b0048 100644
--- a/drivers/gpu/drm/xe/xe_i2c.h
+++ b/drivers/gpu/drm/xe/xe_i2c.h
@@ -11,18 +11,21 @@ struct device;
 struct fwnode_handle;
 struct i2c_adapter;
 struct i2c_client;
-struct irq_domain;
 struct platform_device;
+struct xe_amc;
 struct xe_device;
 struct xe_mmio;
 
-#define XE_I2C_MAX_CLIENTS		3
-
 #define XE_I2C_EP_COOKIE_DEVICE		0xde
 
 /* Endpoint Capabilities */
 #define XE_I2C_EP_CAP_IRQ		BIT(0)
 
+enum XE_I2C_CLIENT {
+	XE_I2C_CLIENT_AMC = 1,
+	XE_I2C_MAX_CLIENTS = 3,
+};
+
 struct xe_i2c_endpoint {
 	u8 cookie;
 	u8 capabilities;
@@ -38,13 +41,11 @@ struct xe_i2c {
 	struct notifier_block bus_notifier;
 	struct work_struct work;
 
-	struct irq_domain *irqdomain;
-	int adapter_irq;
-
 	struct xe_i2c_endpoint ep;
 	struct device *drm_dev;
 
 	struct xe_mmio *mmio;
+	struct xe_amc *amc;
 };
 
 #if IS_ENABLED(CONFIG_I2C)


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-09-12 14:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 11:42 FAILED: patch "[PATCH] drm/xe/i2c: Keep the i2c controller always enabled" failed to apply to 7.2-stable tree gregkh
2026-09-12 14:21 ` [PATCH 7.2.y 1/3] accel/amdxdna: Disable device buffer exporting Sasha Levin
2026-09-12 14:21   ` [PATCH 7.2.y 2/3] i2c: designware: Global register definitions Sasha Levin
2026-09-12 14:21   ` [PATCH 7.2.y 3/3] drm/xe/i2c: Keep the i2c controller always enabled Sasha Levin
2026-09-12 14:42 ` [PATCH 7.2.y 1/3] accel/amdxdna: Disable device buffer exporting Sasha Levin
2026-09-12 14:42   ` [PATCH 7.2.y 2/3] i2c: designware: Global register definitions Sasha Levin
2026-09-12 14:42   ` [PATCH 7.2.y 3/3] drm/xe/i2c: Keep the i2c controller always enabled Sasha Levin
  -- strict thread matches above, loose matches on Subject: below --
2026-09-09 11:42 FAILED: patch "[PATCH] drm/xe/i2c: Fix the interrupt handling" failed to apply to 7.2-stable tree gregkh
2026-09-12 14:20 ` [PATCH 7.2.y 1/3] accel/amdxdna: Disable device buffer exporting Sasha Levin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.