[PATCH] media: i2c: imx258: Add support for the reset GPIO
From: Asdlerto Korry
Date: Sun Nov 01 2026 - 19:48:20 EST
The binding documents an optional reset-gpios property for the XCLR pin,
but the driver never requests it. On boards that wire XCLR to a GPIO the
sensor then stays in reset (or is released at an undefined time before
its supplies and clock are up) and does not answer on I2C.
Request the GPIO as optional, keep the sensor in reset while it is
powered off, and release XCLR after the supplies and INCK are enabled,
followed by a delay before the first I2C access.
Found on a Samsung Galaxy M52 5G (SM7325), where the ultra-wide rear
camera (IMX258) has XCLR on a GPIO; with this change the sensor is
detected and streams.
Signed-off-by: Asdlerto Korry <korryasdlerto@xxxxxxxxx>
---
drivers/media/i2c/imx258.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 065c33380f60..899dca4be650 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -4,6 +4,7 @@
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
@@ -681,6 +682,7 @@ struct imx258 {
struct clk *clk;
struct regulator_bulk_data supplies[IMX258_NUM_SUPPLIES];
+ struct gpio_desc *reset_gpio;
};
static inline struct imx258 *to_imx258(struct v4l2_subdev *_sd)
@@ -1130,9 +1132,18 @@ static int imx258_power_on(struct device *dev)
if (ret) {
dev_err(dev, "failed to enable clock\n");
regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies);
+ return ret;
}
- return ret;
+ if (imx258->reset_gpio) {
+ /* Release XCLR once the supplies and INCK are stable */
+ usleep_range(2000, 3000);
+ gpiod_set_value_cansleep(imx258->reset_gpio, 0);
+ /* Give the sensor time to boot before the first I2C access */
+ usleep_range(12000, 13000);
+ }
+
+ return 0;
}
static int imx258_power_off(struct device *dev)
@@ -1140,6 +1151,7 @@ static int imx258_power_off(struct device *dev)
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct imx258 *imx258 = to_imx258(sd);
+ gpiod_set_value_cansleep(imx258->reset_gpio, 1);
clk_disable_unprepare(imx258->clk);
regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies);
@@ -1389,6 +1401,12 @@ static int imx258_probe(struct i2c_client *client)
return dev_err_probe(imx258->dev, ret,
"failed to get regulators\n");
+ imx258->reset_gpio = devm_gpiod_get_optional(imx258->dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(imx258->reset_gpio))
+ return dev_err_probe(imx258->dev, PTR_ERR(imx258->reset_gpio),
+ "failed to get reset gpio\n");
+
imx258->clk = devm_v4l2_sensor_clk_get_legacy(imx258->dev, NULL, false,
0);
if (IS_ERR(imx258->clk))
--
2.25.1