hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/clk/imx/clk.c
....@@ -1,14 +1,50 @@
11 // SPDX-License-Identifier: GPL-2.0
2
+#include <linux/bits.h>
23 #include <linux/clk.h>
4
+#include <linux/clk-provider.h>
35 #include <linux/err.h>
6
+#include <linux/io.h>
7
+#include <linux/module.h>
48 #include <linux/of.h>
59 #include <linux/slab.h>
610 #include <linux/spinlock.h>
711 #include "clk.h"
812
9
-DEFINE_SPINLOCK(imx_ccm_lock);
13
+#define CCM_CCDR 0x4
14
+#define CCDR_MMDC_CH0_MASK BIT(17)
15
+#define CCDR_MMDC_CH1_MASK BIT(16)
1016
11
-void __init imx_check_clocks(struct clk *clks[], unsigned int count)
17
+DEFINE_SPINLOCK(imx_ccm_lock);
18
+EXPORT_SYMBOL_GPL(imx_ccm_lock);
19
+
20
+void imx_unregister_clocks(struct clk *clks[], unsigned int count)
21
+{
22
+ unsigned int i;
23
+
24
+ for (i = 0; i < count; i++)
25
+ clk_unregister(clks[i]);
26
+}
27
+
28
+void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count)
29
+{
30
+ unsigned int i;
31
+
32
+ for (i = 0; i < count; i++)
33
+ clk_hw_unregister(hws[i]);
34
+}
35
+EXPORT_SYMBOL_GPL(imx_unregister_hw_clocks);
36
+
37
+void imx_mmdc_mask_handshake(void __iomem *ccm_base,
38
+ unsigned int chn)
39
+{
40
+ unsigned int reg;
41
+
42
+ reg = readl_relaxed(ccm_base + CCM_CCDR);
43
+ reg |= chn == 0 ? CCDR_MMDC_CH0_MASK : CCDR_MMDC_CH1_MASK;
44
+ writel_relaxed(reg, ccm_base + CCM_CCDR);
45
+}
46
+
47
+void imx_check_clocks(struct clk *clks[], unsigned int count)
1248 {
1349 unsigned i;
1450
....@@ -18,7 +54,18 @@
1854 i, PTR_ERR(clks[i]));
1955 }
2056
21
-static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
57
+void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count)
58
+{
59
+ unsigned int i;
60
+
61
+ for (i = 0; i < count; i++)
62
+ if (IS_ERR(clks[i]))
63
+ pr_err("i.MX clk %u: register failed with %ld\n",
64
+ i, PTR_ERR(clks[i]));
65
+}
66
+EXPORT_SYMBOL_GPL(imx_check_clk_hws);
67
+
68
+static struct clk *imx_obtain_fixed_clock_from_dt(const char *name)
2269 {
2370 struct of_phandle_args phandle;
2471 struct clk *clk = ERR_PTR(-ENODEV);
....@@ -38,7 +85,7 @@
3885 return clk;
3986 }
4087
41
-struct clk * __init imx_obtain_fixed_clock(
88
+struct clk *imx_obtain_fixed_clock(
4289 const char *name, unsigned long rate)
4390 {
4491 struct clk *clk;
....@@ -48,6 +95,30 @@
4895 clk = imx_clk_fixed(name, rate);
4996 return clk;
5097 }
98
+
99
+struct clk_hw *imx_obtain_fixed_clock_hw(
100
+ const char *name, unsigned long rate)
101
+{
102
+ struct clk *clk;
103
+
104
+ clk = imx_obtain_fixed_clock_from_dt(name);
105
+ if (IS_ERR(clk))
106
+ clk = imx_clk_fixed(name, rate);
107
+ return __clk_get_hw(clk);
108
+}
109
+
110
+struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
111
+ const char *name)
112
+{
113
+ struct clk *clk;
114
+
115
+ clk = of_clk_get_by_name(np, name);
116
+ if (IS_ERR(clk))
117
+ return ERR_PTR(-ENOENT);
118
+
119
+ return __clk_get_hw(clk);
120
+}
121
+EXPORT_SYMBOL_GPL(imx_obtain_fixed_clk_hw);
51122
52123 /*
53124 * This fixups the register CCM_CSCMR1 write value.
....@@ -75,8 +146,11 @@
75146 return;
76147 }
77148
78
-static int imx_keep_uart_clocks __initdata;
79
-static struct clk ** const *imx_uart_clocks __initdata;
149
+#ifndef MODULE
150
+
151
+static bool imx_keep_uart_clocks;
152
+static int imx_enabled_uart_clocks;
153
+static struct clk **imx_uart_clocks;
80154
81155 static int __init imx_keep_uart_clocks_param(char *str)
82156 {
....@@ -89,26 +163,51 @@
89163 __setup_param("earlyprintk", imx_keep_uart_earlyprintk,
90164 imx_keep_uart_clocks_param, 0);
91165
92
-void __init imx_register_uart_clocks(struct clk ** const clks[])
166
+void imx_register_uart_clocks(unsigned int clk_count)
93167 {
168
+ imx_enabled_uart_clocks = 0;
169
+
170
+/* i.MX boards use device trees now. For build tests without CONFIG_OF, do nothing */
171
+#ifdef CONFIG_OF
94172 if (imx_keep_uart_clocks) {
95173 int i;
96174
97
- imx_uart_clocks = clks;
98
- for (i = 0; imx_uart_clocks[i]; i++)
99
- clk_prepare_enable(*imx_uart_clocks[i]);
175
+ imx_uart_clocks = kcalloc(clk_count, sizeof(struct clk *), GFP_KERNEL);
176
+
177
+ if (!of_stdout)
178
+ return;
179
+
180
+ for (i = 0; i < clk_count; i++) {
181
+ imx_uart_clocks[imx_enabled_uart_clocks] = of_clk_get(of_stdout, i);
182
+
183
+ /* Stop if there are no more of_stdout references */
184
+ if (IS_ERR(imx_uart_clocks[imx_enabled_uart_clocks]))
185
+ return;
186
+
187
+ /* Only enable the clock if it's not NULL */
188
+ if (imx_uart_clocks[imx_enabled_uart_clocks])
189
+ clk_prepare_enable(imx_uart_clocks[imx_enabled_uart_clocks++]);
190
+ }
100191 }
192
+#endif
101193 }
102194
103195 static int __init imx_clk_disable_uart(void)
104196 {
105
- if (imx_keep_uart_clocks && imx_uart_clocks) {
197
+ if (imx_keep_uart_clocks && imx_enabled_uart_clocks) {
106198 int i;
107199
108
- for (i = 0; imx_uart_clocks[i]; i++)
109
- clk_disable_unprepare(*imx_uart_clocks[i]);
200
+ for (i = 0; i < imx_enabled_uart_clocks; i++) {
201
+ clk_disable_unprepare(imx_uart_clocks[i]);
202
+ clk_put(imx_uart_clocks[i]);
203
+ }
110204 }
205
+
206
+ kfree(imx_uart_clocks);
111207
112208 return 0;
113209 }
114210 late_initcall_sync(imx_clk_disable_uart);
211
+#endif
212
+
213
+MODULE_LICENSE("GPL v2");