[PATCH v3 5/9] drm/sun4i: tcon_top: Register reset, clock gates in probe
From: Jagan Teki
Date: Tue Dec 31 2019 - 08:06:11 EST
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