2 * Copyright (c) 2012 National Instruments
4 * Josh Cartwright <josh.cartwright@ni.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/slab.h>
21 #include <linux/kernel.h>
22 #include <linux/clk-provider.h>
24 static void __iomem
*slcr_base
;
28 void __iomem
*pll_ctrl
;
29 void __iomem
*pll_cfg
;
32 #define to_zynq_pll_clk(hw) container_of(hw, struct zynq_pll_clk, hw)
34 #define CTRL_PLL_FDIV(x) ((x) >> 12)
36 static unsigned long zynq_pll_recalc_rate(struct clk_hw
*hw
,
37 unsigned long parent_rate
)
39 struct zynq_pll_clk
*pll
= to_zynq_pll_clk(hw
);
40 return parent_rate
* CTRL_PLL_FDIV(ioread32(pll
->pll_ctrl
));
43 static const struct clk_ops zynq_pll_clk_ops
= {
44 .recalc_rate
= zynq_pll_recalc_rate
,
47 static void __init
zynq_pll_clk_setup(struct device_node
*np
)
49 struct clk_init_data init
;
50 struct zynq_pll_clk
*pll
;
51 const char *parent_name
;
56 ret
= of_property_read_u32_array(np
, "reg", regs
, ARRAY_SIZE(regs
));
60 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
64 pll
->pll_ctrl
= slcr_base
+ regs
[0];
65 pll
->pll_cfg
= slcr_base
+ regs
[1];
67 of_property_read_string(np
, "clock-output-names", &init
.name
);
69 init
.ops
= &zynq_pll_clk_ops
;
70 parent_name
= of_clk_get_parent_name(np
, 0);
71 init
.parent_names
= &parent_name
;
76 clk
= clk_register(NULL
, &pll
->hw
);
77 if (WARN_ON(IS_ERR(clk
)))
80 ret
= of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
84 CLK_OF_DECLARE(zynq_pll
, "xlnx,zynq-pll", zynq_pll_clk_setup
);
86 struct zynq_periph_clk
{
88 struct clk_onecell_data onecell_data
;
90 void __iomem
*clk_ctrl
;
91 spinlock_t clkact_lock
;
94 #define to_zynq_periph_clk(hw) container_of(hw, struct zynq_periph_clk, hw)
96 static const u8 periph_clk_parent_map
[] = {
99 #define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
100 #define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
102 static unsigned long zynq_periph_recalc_rate(struct clk_hw
*hw
,
103 unsigned long parent_rate
)
105 struct zynq_periph_clk
*periph
= to_zynq_periph_clk(hw
);
106 return parent_rate
/ PERIPH_CLK_CTRL_DIV(ioread32(periph
->clk_ctrl
));
109 static u8
zynq_periph_get_parent(struct clk_hw
*hw
)
111 struct zynq_periph_clk
*periph
= to_zynq_periph_clk(hw
);
112 return PERIPH_CLK_CTRL_SRC(ioread32(periph
->clk_ctrl
));
115 static const struct clk_ops zynq_periph_clk_ops
= {
116 .recalc_rate
= zynq_periph_recalc_rate
,
117 .get_parent
= zynq_periph_get_parent
,
120 static void __init
zynq_periph_clk_setup(struct device_node
*np
)
122 struct zynq_periph_clk
*periph
;
123 const char *parent_names
[3];
124 struct clk_init_data init
;
125 int clk_num
= 0, err
;
131 err
= of_property_read_u32(np
, "reg", ®
);
135 periph
= kzalloc(sizeof(*periph
), GFP_KERNEL
);
136 if (WARN_ON(!periph
))
139 periph
->clk_ctrl
= slcr_base
+ reg
;
140 spin_lock_init(&periph
->clkact_lock
);
142 init
.name
= np
->name
;
143 init
.ops
= &zynq_periph_clk_ops
;
144 for (i
= 0; i
< ARRAY_SIZE(parent_names
); i
++)
145 parent_names
[i
] = of_clk_get_parent_name(np
, i
);
146 init
.parent_names
= parent_names
;
147 init
.num_parents
= ARRAY_SIZE(parent_names
);
149 periph
->hw
.init
= &init
;
151 clk
= clk_register(NULL
, &periph
->hw
);
152 if (WARN_ON(IS_ERR(clk
)))
155 err
= of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
159 err
= of_property_read_string_index(np
, "clock-output-names", 0,
164 periph
->gates
[0] = clk_register_gate(NULL
, name
, np
->name
, 0,
165 periph
->clk_ctrl
, 0, 0,
166 &periph
->clkact_lock
);
167 if (WARN_ON(IS_ERR(periph
->gates
[0])))
171 /* some periph clks have 2 downstream gates */
172 err
= of_property_read_string_index(np
, "clock-output-names", 1,
174 if (err
!= -ENODATA
) {
175 periph
->gates
[1] = clk_register_gate(NULL
, name
, np
->name
, 0,
176 periph
->clk_ctrl
, 1, 0,
177 &periph
->clkact_lock
);
178 if (WARN_ON(IS_ERR(periph
->gates
[1])))
183 periph
->onecell_data
.clks
= periph
->gates
;
184 periph
->onecell_data
.clk_num
= clk_num
;
186 err
= of_clk_add_provider(np
, of_clk_src_onecell_get
,
187 &periph
->onecell_data
);
191 CLK_OF_DECLARE(zynq_periph
, "xlnx,zynq-periph-clock", zynq_periph_clk_setup
);
193 /* CPU Clock domain is modelled as a mux with 4 children subclks, whose
194 * derivative rates depend on CLK_621_TRUE
197 struct zynq_cpu_clk
{
199 struct clk_onecell_data onecell_data
;
200 struct clk
*subclks
[4];
201 void __iomem
*clk_ctrl
;
202 spinlock_t clkact_lock
;
205 #define to_zynq_cpu_clk(hw) container_of(hw, struct zynq_cpu_clk, hw)
207 static const u8 zynq_cpu_clk_parent_map
[] = {
210 #define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
211 #define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
213 static u8
zynq_cpu_clk_get_parent(struct clk_hw
*hw
)
215 struct zynq_cpu_clk
*cpuclk
= to_zynq_cpu_clk(hw
);
216 return CPU_CLK_SRCSEL(ioread32(cpuclk
->clk_ctrl
));
219 static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw
*hw
,
220 unsigned long parent_rate
)
222 struct zynq_cpu_clk
*cpuclk
= to_zynq_cpu_clk(hw
);
223 return parent_rate
/ CPU_CLK_CTRL_DIV(ioread32(cpuclk
->clk_ctrl
));
226 static const struct clk_ops zynq_cpu_clk_ops
= {
227 .get_parent
= zynq_cpu_clk_get_parent
,
228 .recalc_rate
= zynq_cpu_clk_recalc_rate
,
231 struct zynq_cpu_subclk
{
233 void __iomem
*clk_621
;
242 #define CLK_621_TRUE(x) ((x) & 1)
244 #define to_zynq_cpu_subclk(hw) container_of(hw, struct zynq_cpu_subclk, hw);
246 static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw
*hw
,
247 unsigned long parent_rate
)
249 unsigned long uninitialized_var(rate
);
250 struct zynq_cpu_subclk
*subclk
;
253 subclk
= to_zynq_cpu_subclk(hw
)
254 is_621
= CLK_621_TRUE(ioread32(subclk
->clk_621
));
256 switch (subclk
->which
) {
257 case CPU_SUBCLK_6X4X
:
260 case CPU_SUBCLK_3X2X
:
261 rate
= parent_rate
/ 2;
264 rate
= parent_rate
/ (is_621
? 3 : 2);
267 rate
= parent_rate
/ (is_621
? 6 : 4);
274 static const struct clk_ops zynq_cpu_subclk_ops
= {
275 .recalc_rate
= zynq_cpu_subclk_recalc_rate
,
278 static struct clk
*zynq_cpu_subclk_setup(struct device_node
*np
, u8 which
,
279 void __iomem
*clk_621
)
281 struct zynq_cpu_subclk
*subclk
;
282 struct clk_init_data init
;
286 err
= of_property_read_string_index(np
, "clock-output-names",
289 goto err_read_output_name
;
291 subclk
= kzalloc(sizeof(*subclk
), GFP_KERNEL
);
293 goto err_subclk_alloc
;
295 subclk
->clk_621
= clk_621
;
296 subclk
->which
= which
;
298 init
.ops
= &zynq_cpu_subclk_ops
;
299 init
.parent_names
= &np
->name
;
300 init
.num_parents
= 1;
302 subclk
->hw
.init
= &init
;
304 clk
= clk_register(NULL
, &subclk
->hw
);
305 if (WARN_ON(IS_ERR(clk
)))
306 goto err_clk_register
;
313 err_read_output_name
:
314 return ERR_PTR(-EINVAL
);
317 static void __init
zynq_cpu_clk_setup(struct device_node
*np
)
319 struct zynq_cpu_clk
*cpuclk
;
320 const char *parent_names
[3];
321 struct clk_init_data init
;
322 void __iomem
*clk_621
;
328 err
= of_property_read_u32_array(np
, "reg", reg
, ARRAY_SIZE(reg
));
332 cpuclk
= kzalloc(sizeof(*cpuclk
), GFP_KERNEL
);
333 if (WARN_ON(!cpuclk
))
336 cpuclk
->clk_ctrl
= slcr_base
+ reg
[0];
337 clk_621
= slcr_base
+ reg
[1];
338 spin_lock_init(&cpuclk
->clkact_lock
);
340 init
.name
= np
->name
;
341 init
.ops
= &zynq_cpu_clk_ops
;
342 for (i
= 0; i
< ARRAY_SIZE(parent_names
); i
++)
343 parent_names
[i
] = of_clk_get_parent_name(np
, i
);
344 init
.parent_names
= parent_names
;
345 init
.num_parents
= ARRAY_SIZE(parent_names
);
347 cpuclk
->hw
.init
= &init
;
349 clk
= clk_register(NULL
, &cpuclk
->hw
);
350 if (WARN_ON(IS_ERR(clk
)))
353 err
= of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
357 for (i
= 0; i
< 4; i
++) {
358 cpuclk
->subclks
[i
] = zynq_cpu_subclk_setup(np
, i
, clk_621
);
359 if (WARN_ON(IS_ERR(cpuclk
->subclks
[i
])))
363 cpuclk
->onecell_data
.clks
= cpuclk
->subclks
;
364 cpuclk
->onecell_data
.clk_num
= i
;
366 err
= of_clk_add_provider(np
, of_clk_src_onecell_get
,
367 &cpuclk
->onecell_data
);
371 CLK_OF_DECLARE(zynq_cpu
, "xlnx,zynq-cpu-clock", zynq_cpu_clk_setup
);
373 void __init
xilinx_zynq_clocks_init(void __iomem
*slcr
)