1
2#include <linux/clk.h>
3#include <linux/clk-provider.h>
4#include <linux/err.h>
5#include <linux/io.h>
6#include <linux/of.h>
7#include <linux/slab.h>
8#include <linux/spinlock.h>
9#include "clk.h"
10
11#define CCM_CCDR 0x4
12#define CCDR_MMDC_CH0_MASK BIT(17)
13#define CCDR_MMDC_CH1_MASK BIT(16)
14
15DEFINE_SPINLOCK(imx_ccm_lock);
16
17void __init imx_mmdc_mask_handshake(void __iomem *ccm_base,
18 unsigned int chn)
19{
20 unsigned int reg;
21
22 reg = readl_relaxed(ccm_base + CCM_CCDR);
23 reg |= chn == 0 ? CCDR_MMDC_CH0_MASK : CCDR_MMDC_CH1_MASK;
24 writel_relaxed(reg, ccm_base + CCM_CCDR);
25}
26
27void imx_check_clocks(struct clk *clks[], unsigned int count)
28{
29 unsigned i;
30
31 for (i = 0; i < count; i++)
32 if (IS_ERR(clks[i]))
33 pr_err("i.MX clk %u: register failed with %ld\n",
34 i, PTR_ERR(clks[i]));
35}
36
37void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count)
38{
39 unsigned int i;
40
41 for (i = 0; i < count; i++)
42 if (IS_ERR(clks[i]))
43 pr_err("i.MX clk %u: register failed with %ld\n",
44 i, PTR_ERR(clks[i]));
45}
46
47static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
48{
49 struct of_phandle_args phandle;
50 struct clk *clk = ERR_PTR(-ENODEV);
51 char *path;
52
53 path = kasprintf(GFP_KERNEL, "/clocks/%s", name);
54 if (!path)
55 return ERR_PTR(-ENOMEM);
56
57 phandle.np = of_find_node_by_path(path);
58 kfree(path);
59
60 if (phandle.np) {
61 clk = of_clk_get_from_provider(&phandle);
62 of_node_put(phandle.np);
63 }
64 return clk;
65}
66
67struct clk * __init imx_obtain_fixed_clock(
68 const char *name, unsigned long rate)
69{
70 struct clk *clk;
71
72 clk = imx_obtain_fixed_clock_from_dt(name);
73 if (IS_ERR(clk))
74 clk = imx_clk_fixed(name, rate);
75 return clk;
76}
77
78struct clk_hw * __init imx_obtain_fixed_clock_hw(
79 const char *name, unsigned long rate)
80{
81 struct clk *clk;
82
83 clk = imx_obtain_fixed_clock_from_dt(name);
84 if (IS_ERR(clk))
85 clk = imx_clk_fixed(name, rate);
86 return __clk_get_hw(clk);
87}
88
89struct clk_hw * __init imx_obtain_fixed_clk_hw(struct device_node *np,
90 const char *name)
91{
92 struct clk *clk;
93
94 clk = of_clk_get_by_name(np, name);
95 if (IS_ERR(clk))
96 return ERR_PTR(-ENOENT);
97
98 return __clk_get_hw(clk);
99}
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119#define CSCMR1_FIXUP 0x00600000
120
121void imx_cscmr1_fixup(u32 *val)
122{
123 *val ^= CSCMR1_FIXUP;
124 return;
125}
126
127static int imx_keep_uart_clocks;
128static struct clk ** const *imx_uart_clocks;
129
130static int __init imx_keep_uart_clocks_param(char *str)
131{
132 imx_keep_uart_clocks = 1;
133
134 return 0;
135}
136__setup_param("earlycon", imx_keep_uart_earlycon,
137 imx_keep_uart_clocks_param, 0);
138__setup_param("earlyprintk", imx_keep_uart_earlyprintk,
139 imx_keep_uart_clocks_param, 0);
140
141void imx_register_uart_clocks(struct clk ** const clks[])
142{
143 if (imx_keep_uart_clocks) {
144 int i;
145
146 imx_uart_clocks = clks;
147 for (i = 0; imx_uart_clocks[i]; i++)
148 clk_prepare_enable(*imx_uart_clocks[i]);
149 }
150}
151
152static int __init imx_clk_disable_uart(void)
153{
154 if (imx_keep_uart_clocks && imx_uart_clocks) {
155 int i;
156
157 for (i = 0; imx_uart_clocks[i]; i++)
158 clk_disable_unprepare(*imx_uart_clocks[i]);
159 }
160
161 return 0;
162}
163late_initcall_sync(imx_clk_disable_uart);
164