2 * Marvell EBU SoC common clock handling
4 * Copyright (C) 2012 Marvell
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
8 * Andrew Lunn <andrew@lunn.ch>
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
15 #include <linux/kernel.h>
16 #include <linux/clk.h>
17 #include <linux/clkdev.h>
18 #include <linux/clk-provider.h>
21 #include <linux/of_address.h>
29 static struct clk_onecell_data clk_data
;
31 void __init
mvebu_coreclk_setup(struct device_node
*np
,
32 const struct coreclk_soc_desc
*desc
)
34 const char *tclk_name
= "tclk";
35 const char *cpuclk_name
= "cpuclk";
40 base
= of_iomap(np
, 0);
44 /* Allocate struct for TCLK, cpu clk, and core ratio clocks */
45 clk_data
.clk_num
= 2 + desc
->num_ratios
;
46 clk_data
.clks
= kzalloc(clk_data
.clk_num
* sizeof(struct clk
*),
48 if (WARN_ON(!clk_data
.clks
)) {
54 of_property_read_string_index(np
, "clock-output-names", 0,
56 rate
= desc
->get_tclk_freq(base
);
57 clk_data
.clks
[0] = clk_register_fixed_rate(NULL
, tclk_name
, NULL
,
59 WARN_ON(IS_ERR(clk_data
.clks
[0]));
61 /* Register CPU clock */
62 of_property_read_string_index(np
, "clock-output-names", 1,
64 rate
= desc
->get_cpu_freq(base
);
65 clk_data
.clks
[1] = clk_register_fixed_rate(NULL
, cpuclk_name
, NULL
,
67 WARN_ON(IS_ERR(clk_data
.clks
[1]));
69 /* Register fixed-factor clocks derived from CPU clock */
70 for (n
= 0; n
< desc
->num_ratios
; n
++) {
71 const char *rclk_name
= desc
->ratios
[n
].name
;
74 of_property_read_string_index(np
, "clock-output-names",
76 desc
->get_clk_ratio(base
, desc
->ratios
[n
].id
, &mult
, &div
);
77 clk_data
.clks
[2+n
] = clk_register_fixed_factor(NULL
, rclk_name
,
78 cpuclk_name
, 0, mult
, div
);
79 WARN_ON(IS_ERR(clk_data
.clks
[2+n
]));
82 /* SAR register isn't needed anymore */
85 of_clk_add_provider(np
, of_clk_src_onecell_get
, &clk_data
);
89 * Clock Gating Control
92 struct clk_gating_ctrl
{
98 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
100 static struct clk
*clk_gating_get_src(
101 struct of_phandle_args
*clkspec
, void *data
)
103 struct clk_gating_ctrl
*ctrl
= (struct clk_gating_ctrl
*)data
;
106 if (clkspec
->args_count
< 1)
107 return ERR_PTR(-EINVAL
);
109 for (n
= 0; n
< ctrl
->num_gates
; n
++) {
110 struct clk_gate
*gate
=
111 to_clk_gate(__clk_get_hw(ctrl
->gates
[n
]));
112 if (clkspec
->args
[0] == gate
->bit_idx
)
113 return ctrl
->gates
[n
];
115 return ERR_PTR(-ENODEV
);
118 void __init
mvebu_clk_gating_setup(struct device_node
*np
,
119 const struct clk_gating_soc_desc
*desc
)
121 struct clk_gating_ctrl
*ctrl
;
124 const char *default_parent
= NULL
;
127 base
= of_iomap(np
, 0);
131 clk
= of_clk_get(np
, 0);
133 default_parent
= __clk_get_name(clk
);
137 ctrl
= kzalloc(sizeof(*ctrl
), GFP_KERNEL
);
141 spin_lock_init(&ctrl
->lock
);
143 /* Count, allocate, and register clock gates */
144 for (n
= 0; desc
[n
].name
;)
148 ctrl
->gates
= kzalloc(ctrl
->num_gates
* sizeof(struct clk
*),
150 if (WARN_ON(!ctrl
->gates
))
153 for (n
= 0; n
< ctrl
->num_gates
; n
++) {
155 (desc
[n
].parent
) ? desc
[n
].parent
: default_parent
;
156 ctrl
->gates
[n
] = clk_register_gate(NULL
, desc
[n
].name
, parent
,
157 desc
[n
].flags
, base
, desc
[n
].bit_idx
,
159 WARN_ON(IS_ERR(ctrl
->gates
[n
]));
162 of_clk_add_provider(np
, clk_gating_get_src
, ctrl
);