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: 003910ebc83b ("pinctrl: Introduce TI IOdelay configuration driver") Signed-off-by: Christophe JAILLET <christophe.jaillet@xxxxxxxxxx> --- Compile tested-only. This patch is speculative, review with care! --- drivers/pinctrl/ti/pinctrl-ti-iodelay.c | 52 ++++++++++--------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/drivers/pinctrl/ti/pinctrl-ti-iodelay.c b/drivers/pinctrl/ti/pinctrl-ti-iodelay.c index f5e5a23d2226..451801acdc40 100644 --- a/drivers/pinctrl/ti/pinctrl-ti-iodelay.c +++ b/drivers/pinctrl/ti/pinctrl-ti-iodelay.c @@ -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, -- 2.45.2