FAILED: patch "[PATCH] drm/xe/i2c: Keep the i2c controller always enabled" failed to apply to 6.18-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.18-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 <[email protected]>.
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-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 244abef7f280a6a84297bfab5fd2e77147bc419a
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090913-blazer-trash-f040@gregkh' --subject-prefix 'PATCH 6.18.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 <[email protected]>
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.
drivers/gpu/drm/xe/xe_i2c.c +48 -1
@@ -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 ;
drivers/gpu/drm/xe/xe_i2c.h +1 -0
@@ -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;
Sasha Levin
maintainerPATCH 1/2 i2c: designware: Global register definitions
From: Heikki Krogerus <[email protected]>
[ Upstream commit 874ef9a6f2fc45d3f6021842d92fa5420fa4c825 ]
Moving the register definitions to a global header file include/linux/designware_i2c.h. That removes the need to duplicate them in the adaptation layers for this driver outside of drivers/i2c/busses/. There is at least one of those in drivers/gpu/drm/xe/xe_i2c.c.
Backport notes for 6.18:
Move the register definitions already present in this tree to the shared header. Omit the surrounding register-access and FIFO-depth constants from 518edab3ad4f6, since that independent cleanup is absent here.
Prepare the existing Xe register-write callback for 244abef7f280 by including the shared definitions, providing I2C_REG(), and adding a pass-through DW_IC_SMBUS_INTR_MASK case. Keep the adapter driver's mask
unchanged: the newer SMBus alert handler from f43fa4b8522ba is absent. Include bitfield.h explicitly for the target's FIELD_MODIFY() use. This lets the target cherry-pick cleanly without importing the newer interrupt implementation or adding any functions to this dependency.
Stable-dep-of: 244abef7f280 ("drm/xe/i2c: Keep the i2c controller always enabled")
--- MAINTAINERS | 1 + drivers/gpu/drm/xe/regs/xe_i2c_regs.h | 2 + drivers/gpu/drm/xe/xe_i2c.c | 12 ++- drivers/i2c/busses/i2c-designware-common.c | 2 + drivers/i2c/busses/i2c-designware-core.h | 85 +--------------- drivers/i2c/busses/i2c-designware-master.c | 2 + drivers/i2c/busses/i2c-designware-slave.c | 2 + include/linux/designware_i2c.h | 107 +++++++++++++++++++++ 8 files changed, 129 insertions(+), 84 deletions(-) create mode 100644 include/linux/designware_i2c.h
MAINTAINERS +1 -0
@@ -24961,6 +24961,7 @@ R: Jan Dabros <[email protected]> L: [email protected] S: Supported F: drivers/i2c/busses/i2c-designware-* +F: include/linux/designware_i2c.h SYNOPSYS DESIGNWARE I2C DRIVER - AMDISP M: Nirujogi Pratap <[email protected]>
drivers/gpu/drm/xe/regs/xe_i2c_regs.h +2 -0
@@ -17,4 +17,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_ */
drivers/gpu/drm/xe/xe_i2c.c +11 -1
@@ -6,6 +6,7 @@*/ #include <linux/array_size.h> +#include <linux/bitfield.h> #include <linux/container_of.h> #include <linux/device.h> #include <linux/err.h>
@@ -23,6 +24,8 @@#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"
@@ -230,8 +233,15 @@ 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 : +/* Preserve the interrupt mask requested by the adapter driver. */ +break ; +default : +break ; + } +xe_mmio_write32 (i2c->mmio,I2C_REG (reg), val);return 0 ; }
drivers/i2c/busses/i2c-designware-common.c +2 -0
@@ -32,6 +32,8 @@#include <linux/types.h> #include <linux/units.h> +#include <linux/designware_i2c.h> +#include "i2c-designware-core.h" static const char *const abort_sources[] = {
drivers/i2c/busses/i2c-designware-core.h +2 -83
106 lines not on this page · raw message
drivers/i2c/busses/i2c-designware-master.c +2 -0
@@ -25,6 +25,8 @@#include <linux/regmap.h> #include <linux/reset.h> +#include <linux/designware_i2c.h> +#include "i2c-designware-core.h" #define AMD_TIMEOUT_MIN_US 25
drivers/i2c/busses/i2c-designware-slave.c +2 -0
@@ -19,6 +19,8 @@#include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/designware_i2c.h> +#include "i2c-designware-core.h" static void i2c_dw_configure_fifo_slave (struct dw_i2c_dev *dev)
include/linux/designware_i2c.h new file +107 -0
107 lines not on this page · raw message
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 drm/xe/i2c: Keep the i2c controller always enabled
From: Heikki Krogerus <[email protected]>
[ Upstream commit 244abef7f280a6a84297bfab5fd2e77147bc419a ]
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.
--- drivers/gpu/drm/xe/xe_i2c.c | 49 ++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/xe/xe_i2c.h | 1 + 2 files changed, 49 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_i2c.c +48 -1
@@ -8,6 +8,7 @@#include <linux/array_size.h> #include <linux/bitfield.h> #include <linux/container_of.h> +#include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> #include <linux/i2c.h>
@@ -220,11 +221,40 @@ static void xe_i2c_remove_irq(struct xe_i2c *i2c)irq_domain_remove (i2c->irqdomain); } +/* 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 ; }
@@ -234,6 +264,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 :/* Preserve the interrupt mask requested by the adapter driver. */ break ;
drivers/gpu/drm/xe/xe_i2c.h +1 -0
@@ -34,6 +34,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;
Signature · 1 line
2.53.0