From f792492db1f42c43eb4b8bb72ce573418afc933d Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Tue, 31 Dec 2019 18:35:24 +0530 Subject: [PATCH 088/117] drm/sun4i: tcon_top: Register reset, clock gates in probe 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 Signed-off-by: Samuel Holland --- drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 42 ++++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) --- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c @@ -124,14 +124,29 @@ static struct clk_hw *sun8i_tcon_top_reg 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; 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) @@ -222,7 +237,7 @@ static int sun8i_tcon_top_bind(struct de 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++) @@ -235,13 +250,15 @@ err_assert_reset: 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; + component_del(dev, &sun8i_tcon_top_ops); + of_clk_del_provider(dev->of_node); for (i = 0; i < CLK_NUM; i++) if (clk_data->hws[i]) @@ -249,21 +266,6 @@ static void sun8i_tcon_top_unbind(struct 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); return 0; }