pinctrl: ti: ti-iodelay: Fix some error handling paths

In the probe, if an error occurs after the ti_iodelay_pinconf_init_dev()
call, it is likely that ti_iodelay_pinconf_deinit_dev() should be called,
as already done in the remove function.

Also in ti_iodelay_pinconf_init_dev(), if an error occurs after the first
regmap_update_bits() call, it is also likely that the deinit() function
should be called.

The easier way to fix it is to add a devm_add_action_or_reset() at the
rigtht place to have ti_iodelay_pinconf_deinit_dev() called when needed.

Doing so, the .remove() function can be removed, and the associated
platform_set_drvdata() call in the probe as well.

Fixes: 003910ebc8 ("pinctrl: Introduce TI IOdelay configuration driver")
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Link: https://lore.kernel.org/0220fa5b925bd08e361be8206a5438f6229deaac.1720556038.git.christophe.jaillet@wanadoo.fr
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Christophe JAILLET 2024-07-09 22:37:43 +02:00 committed by Linus Walleij
parent bebf833d33
commit a9f2b249ad

View File

@ -273,6 +273,22 @@ static int ti_iodelay_pinconf_set(struct ti_iodelay_device *iod,
return r;
}
/**
* ti_iodelay_pinconf_deinit_dev() - deinit the iodelay device
* @data: IODelay device
*
* Deinitialize the IODelay device (basically just lock the region back up.
*/
static void ti_iodelay_pinconf_deinit_dev(void *data)
{
struct ti_iodelay_device *iod = data;
const struct ti_iodelay_reg_data *reg = iod->reg_data;
/* lock the iodelay region back again */
regmap_update_bits(iod->regmap, reg->reg_global_lock_offset,
reg->global_lock_mask, reg->global_lock_val);
}
/**
* ti_iodelay_pinconf_init_dev() - Initialize IODelay device
* @iod: iodelay device
@ -295,6 +311,11 @@ static int ti_iodelay_pinconf_init_dev(struct ti_iodelay_device *iod)
if (r)
return r;
r = devm_add_action_or_reset(iod->dev, ti_iodelay_pinconf_deinit_dev,
iod);
if (r)
return r;
/* Read up Recalibration sequence done by bootloader */
r = regmap_read(iod->regmap, reg->reg_refclk_offset, &val);
if (r)
@ -353,21 +374,6 @@ static int ti_iodelay_pinconf_init_dev(struct ti_iodelay_device *iod)
return 0;
}
/**
* ti_iodelay_pinconf_deinit_dev() - deinit the iodelay device
* @iod: IODelay device
*
* Deinitialize the IODelay device (basically just lock the region back up.
*/
static void ti_iodelay_pinconf_deinit_dev(struct ti_iodelay_device *iod)
{
const struct ti_iodelay_reg_data *reg = iod->reg_data;
/* lock the iodelay region back again */
regmap_update_bits(iod->regmap, reg->reg_global_lock_offset,
reg->global_lock_mask, reg->global_lock_val);
}
/**
* ti_iodelay_get_pingroup() - Find the group mapped by a group selector
* @iod: iodelay device
@ -877,27 +883,11 @@ static int ti_iodelay_probe(struct platform_device *pdev)
return ret;
}
platform_set_drvdata(pdev, iod);
return pinctrl_enable(iod->pctl);
}
/**
* ti_iodelay_remove() - standard remove
* @pdev: platform device
*/
static void ti_iodelay_remove(struct platform_device *pdev)
{
struct ti_iodelay_device *iod = platform_get_drvdata(pdev);
ti_iodelay_pinconf_deinit_dev(iod);
/* Expect other allocations to be freed by devm */
}
static struct platform_driver ti_iodelay_driver = {
.probe = ti_iodelay_probe,
.remove_new = ti_iodelay_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = ti_iodelay_of_match,