Skip to content

Commit 7a6146a

Browse files
committed
media: i2c: imx500: GPIO acquire/release semantics
When the imx500 driver is used as part of the 'AI Camera', the poweroff state is never reached as the camera and gpio driver share a regulator. By releasing the GPIOs when they are not in use, 'AI Camera' is able to achieve a powered-down state. Signed-off-by: Richard Oliver <richard.oliver@raspberrypi.com>
1 parent dc95aef commit 7a6146a

File tree

1 file changed

+52
-10
lines changed

1 file changed

+52
-10
lines changed

drivers/media/i2c/imx500.c

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2360,9 +2360,11 @@ static int imx500_state_transition(struct imx500 *imx500, const u8 *fw,
23602360
}
23612361

23622362
/* Do SPI transfer */
2363-
gpiod_set_value_cansleep(imx500->led_gpio, 1);
2363+
if (imx500->led_gpio)
2364+
gpiod_set_value_cansleep(imx500->led_gpio, 1);
23642365
ret = imx500_spi_write(imx500, data, size);
2365-
gpiod_set_value_cansleep(imx500->led_gpio, 0);
2366+
if (imx500->led_gpio)
2367+
gpiod_set_value_cansleep(imx500->led_gpio, 0);
23662368

23672369
imx500->fw_progress += size;
23682370

@@ -2683,11 +2685,28 @@ static int imx500_power_on(struct device *dev)
26832685
struct imx500 *imx500 = to_imx500(sd);
26842686
int ret;
26852687

2688+
/* Acquire GPIOs first to ensure reset is asserted before power is applied */
2689+
imx500->led_gpio = devm_gpiod_get_optional(dev, "led", GPIOD_OUT_LOW);
2690+
if (IS_ERR(imx500->led_gpio)) {
2691+
ret = PTR_ERR(imx500->led_gpio);
2692+
dev_err(&client->dev, "%s: failed to get led gpio\n", __func__);
2693+
return ret;
2694+
}
2695+
2696+
imx500->reset_gpio =
2697+
devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
2698+
if (IS_ERR(imx500->reset_gpio)) {
2699+
ret = PTR_ERR(imx500->reset_gpio);
2700+
dev_err(&client->dev, "%s: failed to get reset gpio\n",
2701+
__func__);
2702+
goto gpio_led_put;
2703+
}
2704+
26862705
ret = regulator_bulk_enable(IMX500_NUM_SUPPLIES, imx500->supplies);
26872706
if (ret) {
26882707
dev_err(&client->dev, "%s: failed to enable regulators\n",
26892708
__func__);
2690-
return ret;
2709+
goto gpio_reset_put;
26912710
}
26922711

26932712
/* T4 - 1us
@@ -2707,7 +2726,8 @@ static int imx500_power_on(struct device *dev)
27072726
* as 0ms but also "XCLR pin should be set to 'High' after INCK supplied.".
27082727
* T4 and T5 are shown as overlapping.
27092728
*/
2710-
gpiod_set_value_cansleep(imx500->reset_gpio, 1);
2729+
if (imx500->reset_gpio)
2730+
gpiod_set_value_cansleep(imx500->reset_gpio, 1);
27112731

27122732
/* T7 - 9ms
27132733
* "INCK start and CXLR rising till Send Streaming Command wait time"
@@ -2718,6 +2738,16 @@ static int imx500_power_on(struct device *dev)
27182738

27192739
reg_off:
27202740
regulator_bulk_disable(IMX500_NUM_SUPPLIES, imx500->supplies);
2741+
gpio_reset_put:
2742+
if (imx500->reset_gpio) {
2743+
devm_gpiod_put(dev, imx500->reset_gpio);
2744+
imx500->reset_gpio = NULL;
2745+
}
2746+
gpio_led_put:
2747+
if (imx500->led_gpio) {
2748+
devm_gpiod_put(dev, imx500->led_gpio);
2749+
imx500->led_gpio = NULL;
2750+
}
27212751
return ret;
27222752
}
27232753

@@ -2734,7 +2764,19 @@ static int imx500_power_off(struct device *dev)
27342764
* Note, this is not the reverse order of power up.
27352765
*/
27362766
clk_disable_unprepare(imx500->xclk);
2737-
gpiod_set_value_cansleep(imx500->reset_gpio, 0);
2767+
if (imx500->reset_gpio)
2768+
gpiod_set_value_cansleep(imx500->reset_gpio, 0);
2769+
2770+
/* Release GPIOs before disabling regulators */
2771+
if (imx500->reset_gpio) {
2772+
devm_gpiod_put(&client->dev, imx500->reset_gpio);
2773+
imx500->reset_gpio = NULL;
2774+
}
2775+
if (imx500->led_gpio) {
2776+
devm_gpiod_put(&client->dev, imx500->led_gpio);
2777+
imx500->led_gpio = NULL;
2778+
}
2779+
27382780
regulator_bulk_disable(IMX500_NUM_SUPPLIES, imx500->supplies);
27392781

27402782
/* Force reprogramming of the common registers when powered up again. */
@@ -3052,14 +3094,14 @@ static int imx500_probe(struct i2c_client *client)
30523094
return ret;
30533095
}
30543096

3055-
imx500->led_gpio = devm_gpiod_get_optional(dev, "led", GPIOD_OUT_LOW);
3056-
3057-
imx500->reset_gpio =
3058-
devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
3097+
/* GPIOs are acquired in imx500_power_on() to avoid preventing
3098+
* regulator power down when shared with other drivers.
3099+
*/
30593100

30603101
/*
30613102
* The sensor must be powered for imx500_identify_module()
3062-
* to be able to read the CHIP_ID register
3103+
* to be able to read the CHIP_ID register. This also ensures
3104+
* GPIOs are available.
30633105
*/
30643106
ret = imx500_power_on(dev);
30653107
if (ret)

0 commit comments

Comments
 (0)