summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-18 16:53:38 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-18 16:53:38 +0200
commit5895db67c12464003afd16c08049b73aa09e58ea (patch)
treec3855a7ab889dffc2a02460f65abbbe6b800b6e6 /drivers/i2c
parent1c5f3df9481bb6275aeb079a8312d037da69715b (diff)
parentf89c296854b755a66657065c35b05406fc18264d (diff)
Merge v6.18.39linux-rolling-lts
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-davinci.c4
-rw-r--r--drivers/i2c/busses/i2c-i801.c2
-rw-r--r--drivers/i2c/busses/i2c-imx-lpi2c.c15
-rw-r--r--drivers/i2c/busses/i2c-mpc.c2
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c9
-rw-r--r--drivers/i2c/i2c-core-base.c81
6 files changed, 77 insertions, 36 deletions
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 66c23535656b..0617f416cb0b 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -818,12 +818,14 @@ static int davinci_i2c_probe(struct platform_device *pdev)
adap->nr = pdev->id;
r = i2c_add_numbered_adapter(adap);
if (r)
- goto err_unuse_clocks;
+ goto err_cpufreq;
pm_runtime_put_autosuspend(dev->dev);
return 0;
+err_cpufreq:
+ i2c_davinci_cpufreq_deregister(dev);
err_unuse_clocks:
pm_runtime_dont_use_autosuspend(dev->dev);
pm_runtime_put_sync(dev->dev);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 506d69b156f7..217dea2743e8 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -927,13 +927,13 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
*/
if (hwpec)
iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv));
-out:
/*
* Unlock the SMBus device for use by BIOS/ACPI,
* and clear status flags if not done already.
*/
iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv));
+out:
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
mutex_unlock(&priv->acpi_lock);
return ret;
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 3bf138eba04c..24c70ea371bb 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -1588,7 +1588,18 @@ static int __maybe_unused lpi2c_runtime_resume(struct device *dev)
static int __maybe_unused lpi2c_suspend_noirq(struct device *dev)
{
- return pm_runtime_force_suspend(dev);
+ struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
+ int ret;
+
+ i2c_mark_adapter_suspended(&lpi2c_imx->adapter);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret) {
+ i2c_mark_adapter_resumed(&lpi2c_imx->adapter);
+ return ret;
+ }
+
+ return 0;
}
static int __maybe_unused lpi2c_resume_noirq(struct device *dev)
@@ -1608,6 +1619,8 @@ static int __maybe_unused lpi2c_resume_noirq(struct device *dev)
if (lpi2c_imx->target)
lpi2c_imx_target_init(lpi2c_imx);
+ i2c_mark_adapter_resumed(&lpi2c_imx->adapter);
+
return 0;
}
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 28c5c5c1fb7a..a21fa45bd64c 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -844,7 +844,7 @@ static int fsl_i2c_probe(struct platform_device *op)
"fsl,timeout", &mpc_ops.timeout);
if (!result) {
- mpc_ops.timeout *= HZ / 1000000;
+ mpc_ops.timeout = mpc_ops.timeout * HZ / 1000000;
if (mpc_ops.timeout < 5)
mpc_ops.timeout = 5;
} else {
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
index 905aa9ab64e1..c57dda9866cf 100644
--- a/drivers/i2c/busses/i2c-stm32f7.c
+++ b/drivers/i2c/busses/i2c-stm32f7.c
@@ -464,8 +464,13 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
{
struct stm32f7_i2c_spec *specs;
u32 p_prev = STM32F7_PRESC_MAX;
- u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC,
- setup->clock_src);
+ /*
+ * Truncate instead of rounding to closest: if the clock period is
+ * overestimated, the computed SCL timings will come out shorter on
+ * the wire, which can push the bus above the target rate and below
+ * the spec's tLOW/tHIGH minimums.
+ */
+ u32 i2cclk = NSEC_PER_SEC / setup->clock_src;
u32 i2cbus = DIV_ROUND_CLOSEST(NSEC_PER_SEC,
setup->speed_freq);
u32 clk_error_prev = i2cbus;
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 05b315405639..e049fa908231 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -63,6 +63,7 @@
static DEFINE_MUTEX(core_lock);
static DEFINE_IDR(i2c_adapter_idr);
+static void i2c_deregister_clients(struct i2c_adapter *adap);
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
@@ -1556,11 +1557,18 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
goto out_list;
}
- dev_set_name(&adap->dev, "i2c-%d", adap->nr);
+ res = dev_set_name(&adap->dev, "i2c-%d", adap->nr);
+ if (res)
+ goto err_remove_irq_domain;
+
adap->dev.bus = &i2c_bus_type;
adap->dev.type = &i2c_adapter_type;
device_initialize(&adap->dev);
+ res = i2c_init_recovery(adap);
+ if (res == -EPROBE_DEFER)
+ goto err_put_adap;
+
/*
* This adapter can be used as a parent immediately after device_add(),
* setup runtime-pm (especially ignore-children) before hand.
@@ -1574,23 +1582,18 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
idr_replace(&i2c_adapter_idr, adap, adap->nr);
mutex_unlock(&core_lock);
+ adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root);
+
res = device_add(&adap->dev);
if (res) {
pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);
- put_device(&adap->dev);
- goto out_list;
+ goto err_replace_id;
}
- adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root);
-
res = i2c_setup_smbus_alert(adap);
if (res)
goto out_reg;
- res = i2c_init_recovery(adap);
- if (res == -EPROBE_DEFER)
- goto out_reg;
-
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
/* create pre-declared device nodes */
@@ -1609,10 +1612,19 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
return 0;
out_reg:
+ i2c_deregister_clients(adap);
+ device_del(&adap->dev);
+err_replace_id:
+ mutex_lock(&core_lock);
+ idr_replace(&i2c_adapter_idr, NULL, adap->nr);
+ mutex_unlock(&core_lock);
debugfs_remove_recursive(adap->debugfs);
+err_put_adap:
init_completion(&adap->dev_released);
- device_unregister(&adap->dev);
+ put_device(&adap->dev);
wait_for_completion(&adap->dev_released);
+err_remove_irq_domain:
+ i2c_host_notify_irq_teardown(adap);
out_list:
mutex_lock(&core_lock);
idr_remove(&i2c_adapter_idr, adap->nr);
@@ -1748,29 +1760,10 @@ static int __process_removed_adapter(struct device_driver *d, void *data)
return 0;
}
-/**
- * i2c_del_adapter - unregister I2C adapter
- * @adap: the adapter being unregistered
- * Context: can sleep
- *
- * This unregisters an I2C adapter which was previously registered
- * by @i2c_add_adapter or @i2c_add_numbered_adapter.
- */
-void i2c_del_adapter(struct i2c_adapter *adap)
+static void i2c_deregister_clients(struct i2c_adapter *adap)
{
- struct i2c_adapter *found;
struct i2c_client *client, *next;
- /* First make sure that this adapter was ever added */
- mutex_lock(&core_lock);
- found = idr_find(&i2c_adapter_idr, adap->nr);
- mutex_unlock(&core_lock);
- if (found != adap) {
- pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
- return;
- }
-
- i2c_acpi_remove_space_handler(adap);
/* Tell drivers about this removal */
mutex_lock(&core_lock);
bus_for_each_drv(&i2c_bus_type, NULL, adap,
@@ -1796,6 +1789,34 @@ void i2c_del_adapter(struct i2c_adapter *adap)
* them up properly, so we give them a chance to do that first. */
device_for_each_child(&adap->dev, NULL, __unregister_client);
device_for_each_child(&adap->dev, NULL, __unregister_dummy);
+}
+
+/**
+ * i2c_del_adapter - unregister I2C adapter
+ * @adap: the adapter being unregistered
+ * Context: can sleep
+ *
+ * This unregisters an I2C adapter which was previously registered
+ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+ */
+void i2c_del_adapter(struct i2c_adapter *adap)
+{
+ struct i2c_adapter *found;
+
+ /* First make sure that this adapter was ever added */
+ mutex_lock(&core_lock);
+ found = idr_find(&i2c_adapter_idr, adap->nr);
+ if (found == adap)
+ idr_replace(&i2c_adapter_idr, NULL, adap->nr);
+ mutex_unlock(&core_lock);
+ if (found != adap) {
+ pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
+ return;
+ }
+
+ i2c_acpi_remove_space_handler(adap);
+
+ i2c_deregister_clients(adap);
/* device name is gone after device_unregister */
dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);