aboutsummaryrefslogtreecommitdiff
path: root/target/linux/d1/patches-6.1/0088-drm-sun4i-tcon_top-Register-reset-clock-gates-in-pro.patch
blob: fae19b8087072e863755dbb41c108774aa204be4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
From f792492db1f42c43eb4b8bb72ce573418afc933d Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@amarulasolutions.com>
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 <jagan@amarulasolutions.com>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
 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;
 }