summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPengpeng Hou <pengpeng@iscas.ac.cn>2026-06-24 13:52:37 +0800
committerAndi Shyti <andi.shyti@kernel.org>2026-07-28 23:39:07 +0200
commita477626332800942f463d76aa48db0c47f1dfd18 (patch)
tree848cbf355e4610feeecab3171c2b0caa17e7e6dd
parent1275cbed80a740e4d56b6aff2745de9fce4818fa (diff)
i2c: qup: Propagate clock enable failures
The QUP I2C driver treats the core and iface clocks as required resources, but qup_i2c_enable_clocks() ignores clk_prepare_enable() failures. Probe can then continue to register the I2C adapter, and runtime/system resume can return success, even when a required clock transition failed. Make the helper return an error, unwind a partially enabled clock, and propagate failures from probe and resume paths. Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Signed-off-by: Andi Shyti <andi.shyti@kernel.org> Link: https://lore.kernel.org/r/20260624055237.29977-1-pengpeng@iscas.ac.cn
-rw-r--r--drivers/i2c/busses/i2c-qup.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index a0e076fc5f36..ee7915ee2ba2 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1657,10 +1657,21 @@ static const struct i2c_adapter_quirks qup_i2c_quirks_v2 = {
.flags = I2C_AQ_NO_ZERO_LEN,
};
-static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
+static int qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
{
- clk_prepare_enable(qup->clk);
- clk_prepare_enable(qup->pclk);
+ int ret;
+
+ ret = clk_prepare_enable(qup->clk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(qup->pclk);
+ if (ret) {
+ clk_disable_unprepare(qup->clk);
+ return ret;
+ }
+
+ return 0;
}
static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
@@ -1823,7 +1834,9 @@ nodma:
ret = PTR_ERR(qup->pclk);
goto fail_dma;
}
- qup_i2c_enable_clocks(qup);
+ ret = qup_i2c_enable_clocks(qup);
+ if (ret)
+ goto fail_dma;
src_clk_freq = clk_get_rate(qup->clk);
}
qup->src_clk_freq = src_clk_freq;
@@ -1975,8 +1988,7 @@ static int qup_i2c_pm_resume_runtime(struct device *device)
struct qup_i2c_dev *qup = dev_get_drvdata(device);
dev_dbg(device, "pm_runtime: resuming...\n");
- qup_i2c_enable_clocks(qup);
- return 0;
+ return qup_i2c_enable_clocks(qup);
}
static int qup_i2c_suspend(struct device *device)
@@ -1988,7 +2000,12 @@ static int qup_i2c_suspend(struct device *device)
static int qup_i2c_resume(struct device *device)
{
- qup_i2c_pm_resume_runtime(device);
+ int ret;
+
+ ret = qup_i2c_pm_resume_runtime(device);
+ if (ret)
+ return ret;
+
pm_request_autosuspend(device);
return 0;
}