TCON TOP is processing clock gates and reset control for TV0, TV1 and DSI channels during bind and release the same during unbind component ops. The usual DSI initialization would setup all controller clocks along with DPHY clocking during probe. Since the actual clock gates (along with DSI clock gate) are initialized during ton top bind, the DPHY is failed to get the DSI clock during that time. To solve, this circular dependency move the reset control, clock gate registration from bind to probe and release the same from unbind to remove. This eventually give a chance DPHY to initialize the DSI clock gate. Signed-off-by: Jagan Teki <jagan@xxxxxxxxxxxxxxxxxxxx> --- Changes for v3: - fixed comments from Chen-Yu - move reset control methods into probe drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 41 +++++++++++++------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c index e0b3c5330b9a..732ac19b4371 100644 --- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c @@ -124,7 +124,22 @@ static struct clk_hw *sun8i_tcon_top_register_gate(struct device *dev, static int sun8i_tcon_top_bind(struct device *dev, struct device *master, void *data) { - struct platform_device *pdev = to_platform_device(dev); + return 0; +} + +static void sun8i_tcon_top_unbind(struct device *dev, struct device *master, + void *data) +{ +} + +static const struct component_ops sun8i_tcon_top_ops = { + .bind = sun8i_tcon_top_bind, + .unbind = sun8i_tcon_top_unbind, +}; + +static int sun8i_tcon_top_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; struct clk_hw_onecell_data *clk_data; struct sun8i_tcon_top *tcon_top; const struct sun8i_tcon_top_quirks *quirks; @@ -132,7 +147,7 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master, void __iomem *regs; int ret, i; - quirks = of_device_get_match_data(&pdev->dev); + quirks = of_device_get_match_data(dev); tcon_top = devm_kzalloc(dev, sizeof(*tcon_top), GFP_KERNEL); if (!tcon_top) @@ -226,22 +241,21 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master, dev_set_drvdata(dev, tcon_top); - return 0; + return component_add(dev, &sun8i_tcon_top_ops); err_unregister_gates: for (i = 0; i < CLK_NUM; i++) if (!IS_ERR_OR_NULL(clk_data->hws[i])) clk_hw_unregister_gate(clk_data->hws[i]); - clk_disable_unprepare(tcon_top->bus); err_assert_reset: reset_control_assert(tcon_top->rst); return ret; } -static void sun8i_tcon_top_unbind(struct device *dev, struct device *master, - void *data) +static int sun8i_tcon_top_remove(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct sun8i_tcon_top *tcon_top = dev_get_drvdata(dev); struct clk_hw_onecell_data *clk_data = tcon_top->clk_data; int i; @@ -253,21 +267,8 @@ static void sun8i_tcon_top_unbind(struct device *dev, struct device *master, clk_disable_unprepare(tcon_top->bus); reset_control_assert(tcon_top->rst); -} - -static const struct component_ops sun8i_tcon_top_ops = { - .bind = sun8i_tcon_top_bind, - .unbind = sun8i_tcon_top_unbind, -}; - -static int sun8i_tcon_top_probe(struct platform_device *pdev) -{ - return component_add(&pdev->dev, &sun8i_tcon_top_ops); -} -static int sun8i_tcon_top_remove(struct platform_device *pdev) -{ - component_del(&pdev->dev, &sun8i_tcon_top_ops); + component_del(dev, &sun8i_tcon_top_ops); return 0; } -- 2.18.0.321.gffc6fa0e3