2 * Marvell MVEBU clock gating control.
4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5 * Andrew Lunn <andrew@lunn.ch>
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
11 #include <linux/kernel.h>
12 #include <linux/bitops.h>
14 #include <linux/clk.h>
15 #include <linux/clkdev.h>
16 #include <linux/clk-provider.h>
17 #include <linux/clk/mvebu.h>
19 #include <linux/of_address.h>
21 struct mvebu_gating_ctrl {
27 struct mvebu_soc_descr {
33 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
35 static struct clk *mvebu_clk_gating_get_src(
36 struct of_phandle_args *clkspec, void *data)
38 struct mvebu_gating_ctrl *ctrl = (struct mvebu_gating_ctrl *)data;
41 if (clkspec->args_count < 1)
42 return ERR_PTR(-EINVAL);
44 for (n = 0; n < ctrl->num_gates; n++) {
45 struct clk_gate *gate =
46 to_clk_gate(__clk_get_hw(ctrl->gates[n]));
47 if (clkspec->args[0] == gate->bit_idx)
48 return ctrl->gates[n];
50 return ERR_PTR(-ENODEV);
53 static void __init mvebu_clk_gating_setup(
54 struct device_node *np, const struct mvebu_soc_descr *descr)
56 struct mvebu_gating_ctrl *ctrl;
59 const char *default_parent = NULL;
62 base = of_iomap(np, 0);
64 clk = of_clk_get(np, 0);
66 default_parent = __clk_get_name(clk);
70 ctrl = kzalloc(sizeof(struct mvebu_gating_ctrl), GFP_KERNEL);
74 spin_lock_init(&ctrl->lock);
77 * Count, allocate, and register clock gates
79 for (n = 0; descr[n].name;)
83 ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
85 if (WARN_ON(!ctrl->gates)) {
90 for (n = 0; n < ctrl->num_gates; n++) {
93 (descr[n].parent) ? descr[n].parent : default_parent;
96 * On Armada 370, the DDR clock is a special case: it
97 * isn't taken by any driver, but should anyway be
98 * kept enabled, so we mark it as IGNORE_UNUSED for
101 if (!strcmp(descr[n].name, "ddr"))
102 flags |= CLK_IGNORE_UNUSED;
104 ctrl->gates[n] = clk_register_gate(NULL, descr[n].name, parent,
105 flags, base, descr[n].bit_idx, 0, &ctrl->lock);
106 WARN_ON(IS_ERR(ctrl->gates[n]));
108 of_clk_add_provider(np, mvebu_clk_gating_get_src, ctrl);
112 * SoC specific clock gating control
115 #ifdef CONFIG_MACH_ARMADA_370
116 static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = {
117 { "audio", NULL, 0 },
118 { "pex0_en", NULL, 1 },
119 { "pex1_en", NULL, 2 },
124 { "sata0", NULL, 15 },
125 { "sdio", NULL, 17 },
128 { "sata1", NULL, 30 },
133 #ifdef CONFIG_MACH_ARMADA_XP
134 static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = {
135 { "audio", NULL, 0 },
145 { "sata0lnk", NULL, 14 },
146 { "sata0", "sata0lnk", 15 },
148 { "sdio", NULL, 17 },
149 { "usb0", NULL, 18 },
150 { "usb1", NULL, 19 },
151 { "usb2", NULL, 20 },
152 { "xor0", NULL, 22 },
153 { "crypto", NULL, 23 },
155 { "xor1", NULL, 28 },
156 { "sata1lnk", NULL, 29 },
157 { "sata1", "sata1lnk", 30 },
162 #ifdef CONFIG_ARCH_DOVE
163 static const struct mvebu_soc_descr __initconst dove_gating_descr[] = {
166 { "ge", "gephy", 2 },
170 { "sdio0", NULL, 8 },
171 { "sdio1", NULL, 9 },
172 { "nand", NULL, 10 },
173 { "camera", NULL, 11 },
174 { "i2s0", NULL, 12 },
175 { "i2s1", NULL, 13 },
176 { "crypto", NULL, 15 },
177 { "ac97", NULL, 21 },
178 { "pdma", NULL, 22 },
179 { "xor0", NULL, 23 },
180 { "xor1", NULL, 24 },
181 { "gephy", NULL, 30 },
186 #ifdef CONFIG_ARCH_KIRKWOOD
187 static const struct mvebu_soc_descr __initconst kirkwood_gating_descr[] = {
193 { "runit", NULL, 7 },
195 { "audio", NULL, 9 },
196 { "sata0", NULL, 14 },
197 { "sata1", NULL, 15 },
198 { "xor1", NULL, 16 },
199 { "crypto", NULL, 17 },
200 { "pex1", NULL, 18 },
207 static const __initdata struct of_device_id clk_gating_match[] = {
208 #ifdef CONFIG_MACH_ARMADA_370
210 .compatible = "marvell,armada-370-gating-clock",
211 .data = armada_370_gating_descr,
215 #ifdef CONFIG_MACH_ARMADA_XP
217 .compatible = "marvell,armada-xp-gating-clock",
218 .data = armada_xp_gating_descr,
222 #ifdef CONFIG_ARCH_DOVE
224 .compatible = "marvell,dove-gating-clock",
225 .data = dove_gating_descr,
229 #ifdef CONFIG_ARCH_KIRKWOOD
231 .compatible = "marvell,kirkwood-gating-clock",
232 .data = kirkwood_gating_descr,
239 void __init mvebu_gating_clk_init(void)
241 struct device_node *np;
243 for_each_matching_node(np, clk_gating_match) {
244 const struct of_device_id *match =
245 of_match_node(clk_gating_match, np);
246 mvebu_clk_gating_setup(np,
247 (const struct mvebu_soc_descr *)match->data);