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>
23 #include <linux/clk/zynq.h>
25 static void __iomem
*slcr_base
;
29 void __iomem
*pll_ctrl
;
30 void __iomem
*pll_cfg
;
33 #define to_zynq_pll_clk(hw) container_of(hw, struct zynq_pll_clk, hw)
35 #define CTRL_PLL_FDIV(x) ((x) >> 12)
37 static unsigned long zynq_pll_recalc_rate(struct clk_hw
*hw
,
38 unsigned long parent_rate
)
40 struct zynq_pll_clk
*pll
= to_zynq_pll_clk(hw
);
41 return parent_rate
* CTRL_PLL_FDIV(ioread32(pll
->pll_ctrl
));
44 static const struct clk_ops zynq_pll_clk_ops
= {
45 .recalc_rate
= zynq_pll_recalc_rate
,
48 static void __init
zynq_pll_clk_setup(struct device_node
*np
)
50 struct clk_init_data init
;
51 struct zynq_pll_clk
*pll
;
52 const char *parent_name
;
57 ret
= of_property_read_u32_array(np
, "reg", regs
, ARRAY_SIZE(regs
));
61 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
65 pll
->pll_ctrl
= slcr_base
+ regs
[0];
66 pll
->pll_cfg
= slcr_base
+ regs
[1];
68 of_property_read_string(np
, "clock-output-names", &init
.name
);
70 init
.ops
= &zynq_pll_clk_ops
;
71 parent_name
= of_clk_get_parent_name(np
, 0);
72 init
.parent_names
= &parent_name
;
77 clk
= clk_register(NULL
, &pll
->hw
);
78 if (WARN_ON(IS_ERR(clk
)))
81 ret
= of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
85 CLK_OF_DECLARE(zynq_pll
, "xlnx,zynq-pll", zynq_pll_clk_setup
);
87 struct zynq_periph_clk
{
89 struct clk_onecell_data onecell_data
;
91 void __iomem
*clk_ctrl
;
92 spinlock_t clkact_lock
;
95 #define to_zynq_periph_clk(hw) container_of(hw, struct zynq_periph_clk, hw)
97 static const u8 periph_clk_parent_map
[] = {
100 #define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
101 #define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
103 static unsigned long zynq_periph_recalc_rate(struct clk_hw
*hw
,
104 unsigned long parent_rate
)
106 struct zynq_periph_clk
*periph
= to_zynq_periph_clk(hw
);
107 return parent_rate
/ PERIPH_CLK_CTRL_DIV(ioread32(periph
->clk_ctrl
));
110 static u8
zynq_periph_get_parent(struct clk_hw
*hw
)
112 struct zynq_periph_clk
*periph
= to_zynq_periph_clk(hw
);
113 return PERIPH_CLK_CTRL_SRC(ioread32(periph
->clk_ctrl
));
116 static const struct clk_ops zynq_periph_clk_ops
= {
117 .recalc_rate
= zynq_periph_recalc_rate
,
118 .get_parent
= zynq_periph_get_parent
,
121 static void __init
zynq_periph_clk_setup(struct device_node
*np
)
123 struct zynq_periph_clk
*periph
;
124 const char *parent_names
[3];
125 struct clk_init_data init
;
126 int clk_num
= 0, err
;
132 err
= of_property_read_u32(np
, "reg", ®
);
136 periph
= kzalloc(sizeof(*periph
), GFP_KERNEL
);
137 if (WARN_ON(!periph
))
140 periph
->clk_ctrl
= slcr_base
+ reg
;
141 spin_lock_init(&periph
->clkact_lock
);
143 init
.name
= np
->name
;
144 init
.ops
= &zynq_periph_clk_ops
;
145 for (i
= 0; i
< ARRAY_SIZE(parent_names
); i
++)
146 parent_names
[i
] = of_clk_get_parent_name(np
, i
);
147 init
.parent_names
= parent_names
;
148 init
.num_parents
= ARRAY_SIZE(parent_names
);
150 periph
->hw
.init
= &init
;
152 clk
= clk_register(NULL
, &periph
->hw
);
153 if (WARN_ON(IS_ERR(clk
)))
156 err
= of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
160 err
= of_property_read_string_index(np
, "clock-output-names", 0,
165 periph
->gates
[0] = clk_register_gate(NULL
, name
, np
->name
, 0,
166 periph
->clk_ctrl
, 0, 0,
167 &periph
->clkact_lock
);
168 if (WARN_ON(IS_ERR(periph
->gates
[0])))
172 /* some periph clks have 2 downstream gates */
173 err
= of_property_read_string_index(np
, "clock-output-names", 1,
175 if (err
!= -ENODATA
) {
176 periph
->gates
[1] = clk_register_gate(NULL
, name
, np
->name
, 0,
177 periph
->clk_ctrl
, 1, 0,
178 &periph
->clkact_lock
);
179 if (WARN_ON(IS_ERR(periph
->gates
[1])))
184 periph
->onecell_data
.clks
= periph
->gates
;
185 periph
->onecell_data
.clk_num
= clk_num
;
187 err
= of_clk_add_provider(np
, of_clk_src_onecell_get
,
188 &periph
->onecell_data
);
192 CLK_OF_DECLARE(zynq_periph
, "xlnx,zynq-periph-clock", zynq_periph_clk_setup
);
194 /* CPU Clock domain is modelled as a mux with 4 children subclks, whose
195 * derivative rates depend on CLK_621_TRUE
198 struct zynq_cpu_clk
{
200 struct clk_onecell_data onecell_data
;
201 struct clk
*subclks
[4];
202 void __iomem
*clk_ctrl
;
203 spinlock_t clkact_lock
;
206 #define to_zynq_cpu_clk(hw) container_of(hw, struct zynq_cpu_clk, hw)
208 static const u8 zynq_cpu_clk_parent_map
[] = {
211 #define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
212 #define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
214 static u8
zynq_cpu_clk_get_parent(struct clk_hw
*hw
)
216 struct zynq_cpu_clk
*cpuclk
= to_zynq_cpu_clk(hw
);
217 return CPU_CLK_SRCSEL(ioread32(cpuclk
->clk_ctrl
));
220 static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw
*hw
,
221 unsigned long parent_rate
)
223 struct zynq_cpu_clk
*cpuclk
= to_zynq_cpu_clk(hw
);
224 return parent_rate
/ CPU_CLK_CTRL_DIV(ioread32(cpuclk
->clk_ctrl
));
227 static const struct clk_ops zynq_cpu_clk_ops
= {
228 .get_parent
= zynq_cpu_clk_get_parent
,
229 .recalc_rate
= zynq_cpu_clk_recalc_rate
,
232 struct zynq_cpu_subclk
{
234 void __iomem
*clk_621
;
243 #define CLK_621_TRUE(x) ((x) & 1)
245 #define to_zynq_cpu_subclk(hw) container_of(hw, struct zynq_cpu_subclk, hw);
247 static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw
*hw
,
248 unsigned long parent_rate
)
250 unsigned long uninitialized_var(rate
);
251 struct zynq_cpu_subclk
*subclk
;
254 subclk
= to_zynq_cpu_subclk(hw
)
255 is_621
= CLK_621_TRUE(ioread32(subclk
->clk_621
));
257 switch (subclk
->which
) {
258 case CPU_SUBCLK_6X4X
:
261 case CPU_SUBCLK_3X2X
:
262 rate
= parent_rate
/ 2;
265 rate
= parent_rate
/ (is_621
? 3 : 2);
268 rate
= parent_rate
/ (is_621
? 6 : 4);
275 static const struct clk_ops zynq_cpu_subclk_ops
= {
276 .recalc_rate
= zynq_cpu_subclk_recalc_rate
,
279 static struct clk
*zynq_cpu_subclk_setup(struct device_node
*np
, u8 which
,
280 void __iomem
*clk_621
)
282 struct zynq_cpu_subclk
*subclk
;
283 struct clk_init_data init
;
287 err
= of_property_read_string_index(np
, "clock-output-names",
290 goto err_read_output_name
;
292 subclk
= kzalloc(sizeof(*subclk
), GFP_KERNEL
);
294 goto err_subclk_alloc
;
296 subclk
->clk_621
= clk_621
;
297 subclk
->which
= which
;
299 init
.ops
= &zynq_cpu_subclk_ops
;
300 init
.parent_names
= &np
->name
;
301 init
.num_parents
= 1;
303 subclk
->hw
.init
= &init
;
305 clk
= clk_register(NULL
, &subclk
->hw
);
306 if (WARN_ON(IS_ERR(clk
)))
307 goto err_clk_register
;
314 err_read_output_name
:
315 return ERR_PTR(-EINVAL
);
318 static void __init
zynq_cpu_clk_setup(struct device_node
*np
)
320 struct zynq_cpu_clk
*cpuclk
;
321 const char *parent_names
[3];
322 struct clk_init_data init
;
323 void __iomem
*clk_621
;
329 err
= of_property_read_u32_array(np
, "reg", reg
, ARRAY_SIZE(reg
));
333 cpuclk
= kzalloc(sizeof(*cpuclk
), GFP_KERNEL
);
334 if (WARN_ON(!cpuclk
))
337 cpuclk
->clk_ctrl
= slcr_base
+ reg
[0];
338 clk_621
= slcr_base
+ reg
[1];
339 spin_lock_init(&cpuclk
->clkact_lock
);
341 init
.name
= np
->name
;
342 init
.ops
= &zynq_cpu_clk_ops
;
343 for (i
= 0; i
< ARRAY_SIZE(parent_names
); i
++)
344 parent_names
[i
] = of_clk_get_parent_name(np
, i
);
345 init
.parent_names
= parent_names
;
346 init
.num_parents
= ARRAY_SIZE(parent_names
);
348 cpuclk
->hw
.init
= &init
;
350 clk
= clk_register(NULL
, &cpuclk
->hw
);
351 if (WARN_ON(IS_ERR(clk
)))
354 err
= of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
358 for (i
= 0; i
< 4; i
++) {
359 cpuclk
->subclks
[i
] = zynq_cpu_subclk_setup(np
, i
, clk_621
);
360 if (WARN_ON(IS_ERR(cpuclk
->subclks
[i
])))
364 cpuclk
->onecell_data
.clks
= cpuclk
->subclks
;
365 cpuclk
->onecell_data
.clk_num
= i
;
367 err
= of_clk_add_provider(np
, of_clk_src_onecell_get
,
368 &cpuclk
->onecell_data
);
372 CLK_OF_DECLARE(zynq_cpu
, "xlnx,zynq-cpu-clock", zynq_cpu_clk_setup
);
374 void __init
xilinx_zynq_clocks_init(void __iomem
*slcr
)