usb: dwc2: Fix some error handling paths
[ Upstream commitada050c691
] dwc2_driver_probe() calls dwc2_lowlevel_hw_init() which deassert some reset lines. Should an error happen in dwc2_lowlevel_hw_init() after calling reset_control_deassert() or in the probe after calling dwc2_lowlevel_hw_init(), the reset lines remain deasserted. Add some devm_add_action_or_reset() calls to re-assert the lines if needed. Update the remove function accordingly. This change is compile-tested only. Fixes:83f8da562f
("usb: dwc2: Add reset control to dwc2") Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Link: https://lore.kernel.org/r/c64537b5339342bd00f7c2152b8fc23792b9f95a.1683306479.git.christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
98b6582b37
commit
b6e30a54a5
|
@ -175,6 +175,11 @@ int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dwc2_reset_control_assert(void *data)
|
||||||
|
{
|
||||||
|
reset_control_assert(data);
|
||||||
|
}
|
||||||
|
|
||||||
static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
|
static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
@ -185,6 +190,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
|
||||||
"error getting reset control\n");
|
"error getting reset control\n");
|
||||||
|
|
||||||
reset_control_deassert(hsotg->reset);
|
reset_control_deassert(hsotg->reset);
|
||||||
|
ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert,
|
||||||
|
hsotg->reset);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc");
|
hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc");
|
||||||
if (IS_ERR(hsotg->reset_ecc))
|
if (IS_ERR(hsotg->reset_ecc))
|
||||||
|
@ -192,6 +201,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
|
||||||
"error getting reset control for ecc\n");
|
"error getting reset control for ecc\n");
|
||||||
|
|
||||||
reset_control_deassert(hsotg->reset_ecc);
|
reset_control_deassert(hsotg->reset_ecc);
|
||||||
|
ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert,
|
||||||
|
hsotg->reset_ecc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to find a generic PHY, then look for an old style
|
* Attempt to find a generic PHY, then look for an old style
|
||||||
|
@ -306,9 +319,6 @@ static int dwc2_driver_remove(struct platform_device *dev)
|
||||||
if (hsotg->ll_hw_enabled)
|
if (hsotg->ll_hw_enabled)
|
||||||
dwc2_lowlevel_hw_disable(hsotg);
|
dwc2_lowlevel_hw_disable(hsotg);
|
||||||
|
|
||||||
reset_control_assert(hsotg->reset);
|
|
||||||
reset_control_assert(hsotg->reset_ecc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue