xref: /openbmc/linux/drivers/clk/at91/dt-compat.c (revision 077782e3)
162061d35SAlexandre Belloni // SPDX-License-Identifier: GPL-2.0
262061d35SAlexandre Belloni #include <linux/clk-provider.h>
362061d35SAlexandre Belloni #include <linux/clk/at91_pmc.h>
462061d35SAlexandre Belloni #include <linux/of.h>
562061d35SAlexandre Belloni #include <linux/mfd/syscon.h>
662061d35SAlexandre Belloni #include <linux/regmap.h>
762061d35SAlexandre Belloni #include <linux/slab.h>
862061d35SAlexandre Belloni 
962061d35SAlexandre Belloni #include "pmc.h"
1062061d35SAlexandre Belloni 
1162061d35SAlexandre Belloni #define MASTER_SOURCE_MAX	4
1262061d35SAlexandre Belloni 
1362061d35SAlexandre Belloni #define PERIPHERAL_AT91RM9200	0
1462061d35SAlexandre Belloni #define PERIPHERAL_AT91SAM9X5	1
1562061d35SAlexandre Belloni 
1662061d35SAlexandre Belloni #define PERIPHERAL_MAX		64
1762061d35SAlexandre Belloni 
1862061d35SAlexandre Belloni #define PERIPHERAL_ID_MIN	2
1962061d35SAlexandre Belloni 
2062061d35SAlexandre Belloni #define PROG_SOURCE_MAX		5
2162061d35SAlexandre Belloni #define PROG_ID_MAX		7
2262061d35SAlexandre Belloni 
2362061d35SAlexandre Belloni #define SYSTEM_MAX_ID		31
2462061d35SAlexandre Belloni 
2564c9247bSClaudiu Beznea #define GCK_INDEX_DT_AUDIO_PLL	5
2664c9247bSClaudiu Beznea 
277a110b91SClaudiu Beznea static DEFINE_SPINLOCK(mck_lock);
287a110b91SClaudiu Beznea 
2962061d35SAlexandre Belloni #ifdef CONFIG_HAVE_AT91_AUDIO_PLL
of_sama5d2_clk_audio_pll_frac_setup(struct device_node * np)3062061d35SAlexandre Belloni static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
3162061d35SAlexandre Belloni {
3262061d35SAlexandre Belloni 	struct clk_hw *hw;
3362061d35SAlexandre Belloni 	const char *name = np->name;
3462061d35SAlexandre Belloni 	const char *parent_name;
3562061d35SAlexandre Belloni 	struct regmap *regmap;
36b3ff02c5SLiang He 	struct device_node *parent_np;
3762061d35SAlexandre Belloni 
38b3ff02c5SLiang He 	parent_np = of_get_parent(np);
39b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
40b3ff02c5SLiang He 	of_node_put(parent_np);
4162061d35SAlexandre Belloni 	if (IS_ERR(regmap))
4262061d35SAlexandre Belloni 		return;
4362061d35SAlexandre Belloni 
4462061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
4562061d35SAlexandre Belloni 
4662061d35SAlexandre Belloni 	hw = at91_clk_register_audio_pll_frac(regmap, name, parent_name);
4762061d35SAlexandre Belloni 	if (IS_ERR(hw))
4862061d35SAlexandre Belloni 		return;
4962061d35SAlexandre Belloni 
5062061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
5162061d35SAlexandre Belloni }
5262061d35SAlexandre Belloni CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
5362061d35SAlexandre Belloni 	       "atmel,sama5d2-clk-audio-pll-frac",
5462061d35SAlexandre Belloni 	       of_sama5d2_clk_audio_pll_frac_setup);
5562061d35SAlexandre Belloni 
of_sama5d2_clk_audio_pll_pad_setup(struct device_node * np)5662061d35SAlexandre Belloni static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
5762061d35SAlexandre Belloni {
5862061d35SAlexandre Belloni 	struct clk_hw *hw;
5962061d35SAlexandre Belloni 	const char *name = np->name;
6062061d35SAlexandre Belloni 	const char *parent_name;
6162061d35SAlexandre Belloni 	struct regmap *regmap;
62b3ff02c5SLiang He 	struct device_node *parent_np;
6362061d35SAlexandre Belloni 
64b3ff02c5SLiang He 	parent_np = of_get_parent(np);
65b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
66b3ff02c5SLiang He 	of_node_put(parent_np);
6762061d35SAlexandre Belloni 	if (IS_ERR(regmap))
6862061d35SAlexandre Belloni 		return;
6962061d35SAlexandre Belloni 
7062061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
7162061d35SAlexandre Belloni 
7262061d35SAlexandre Belloni 	hw = at91_clk_register_audio_pll_pad(regmap, name, parent_name);
7362061d35SAlexandre Belloni 	if (IS_ERR(hw))
7462061d35SAlexandre Belloni 		return;
7562061d35SAlexandre Belloni 
7662061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
7762061d35SAlexandre Belloni }
7862061d35SAlexandre Belloni CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
7962061d35SAlexandre Belloni 	       "atmel,sama5d2-clk-audio-pll-pad",
8062061d35SAlexandre Belloni 	       of_sama5d2_clk_audio_pll_pad_setup);
8162061d35SAlexandre Belloni 
of_sama5d2_clk_audio_pll_pmc_setup(struct device_node * np)8262061d35SAlexandre Belloni static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
8362061d35SAlexandre Belloni {
8462061d35SAlexandre Belloni 	struct clk_hw *hw;
8562061d35SAlexandre Belloni 	const char *name = np->name;
8662061d35SAlexandre Belloni 	const char *parent_name;
8762061d35SAlexandre Belloni 	struct regmap *regmap;
88b3ff02c5SLiang He 	struct device_node *parent_np;
8962061d35SAlexandre Belloni 
90b3ff02c5SLiang He 	parent_np = of_get_parent(np);
91b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
92b3ff02c5SLiang He 	of_node_put(parent_np);
9362061d35SAlexandre Belloni 	if (IS_ERR(regmap))
9462061d35SAlexandre Belloni 		return;
9562061d35SAlexandre Belloni 
9662061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
9762061d35SAlexandre Belloni 
9862061d35SAlexandre Belloni 	hw = at91_clk_register_audio_pll_pmc(regmap, name, parent_name);
9962061d35SAlexandre Belloni 	if (IS_ERR(hw))
10062061d35SAlexandre Belloni 		return;
10162061d35SAlexandre Belloni 
10262061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
10362061d35SAlexandre Belloni }
10462061d35SAlexandre Belloni CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
10562061d35SAlexandre Belloni 	       "atmel,sama5d2-clk-audio-pll-pmc",
10662061d35SAlexandre Belloni 	       of_sama5d2_clk_audio_pll_pmc_setup);
10762061d35SAlexandre Belloni #endif /* CONFIG_HAVE_AT91_AUDIO_PLL */
10862061d35SAlexandre Belloni 
109cb4f4949SAlexandre Belloni static const struct clk_pcr_layout dt_pcr_layout = {
110cb4f4949SAlexandre Belloni 	.offset = 0x10c,
111cb4f4949SAlexandre Belloni 	.cmd = BIT(12),
112cb4f4949SAlexandre Belloni 	.pid_mask = GENMASK(5, 0),
113cb4f4949SAlexandre Belloni 	.div_mask = GENMASK(17, 16),
114cb4f4949SAlexandre Belloni 	.gckcss_mask = GENMASK(10, 8),
115cb4f4949SAlexandre Belloni };
116cb4f4949SAlexandre Belloni 
11762061d35SAlexandre Belloni #ifdef CONFIG_HAVE_AT91_GENERATED_CLK
11862061d35SAlexandre Belloni #define GENERATED_SOURCE_MAX	6
11962061d35SAlexandre Belloni 
12062061d35SAlexandre Belloni #define GCK_ID_I2S0		54
12162061d35SAlexandre Belloni #define GCK_ID_I2S1		55
12262061d35SAlexandre Belloni #define GCK_ID_CLASSD		59
12362061d35SAlexandre Belloni 
of_sama5d2_clk_generated_setup(struct device_node * np)12462061d35SAlexandre Belloni static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
12562061d35SAlexandre Belloni {
12662061d35SAlexandre Belloni 	int num;
12762061d35SAlexandre Belloni 	u32 id;
12862061d35SAlexandre Belloni 	const char *name;
12962061d35SAlexandre Belloni 	struct clk_hw *hw;
13062061d35SAlexandre Belloni 	unsigned int num_parents;
13162061d35SAlexandre Belloni 	const char *parent_names[GENERATED_SOURCE_MAX];
132b3ff02c5SLiang He 	struct device_node *gcknp, *parent_np;
13362061d35SAlexandre Belloni 	struct clk_range range = CLK_RANGE(0, 0);
13462061d35SAlexandre Belloni 	struct regmap *regmap;
13562061d35SAlexandre Belloni 
13662061d35SAlexandre Belloni 	num_parents = of_clk_get_parent_count(np);
13762061d35SAlexandre Belloni 	if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
13862061d35SAlexandre Belloni 		return;
13962061d35SAlexandre Belloni 
14062061d35SAlexandre Belloni 	of_clk_parent_fill(np, parent_names, num_parents);
14162061d35SAlexandre Belloni 
14262061d35SAlexandre Belloni 	num = of_get_child_count(np);
14362061d35SAlexandre Belloni 	if (!num || num > PERIPHERAL_MAX)
14462061d35SAlexandre Belloni 		return;
14562061d35SAlexandre Belloni 
146b3ff02c5SLiang He 	parent_np = of_get_parent(np);
147b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
148b3ff02c5SLiang He 	of_node_put(parent_np);
14962061d35SAlexandre Belloni 	if (IS_ERR(regmap))
15062061d35SAlexandre Belloni 		return;
15162061d35SAlexandre Belloni 
15262061d35SAlexandre Belloni 	for_each_child_of_node(np, gcknp) {
15364c9247bSClaudiu Beznea 		int chg_pid = INT_MIN;
15462061d35SAlexandre Belloni 
15562061d35SAlexandre Belloni 		if (of_property_read_u32(gcknp, "reg", &id))
15662061d35SAlexandre Belloni 			continue;
15762061d35SAlexandre Belloni 
15862061d35SAlexandre Belloni 		if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
15962061d35SAlexandre Belloni 			continue;
16062061d35SAlexandre Belloni 
16162061d35SAlexandre Belloni 		if (of_property_read_string(np, "clock-output-names", &name))
16262061d35SAlexandre Belloni 			name = gcknp->name;
16362061d35SAlexandre Belloni 
16462061d35SAlexandre Belloni 		of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
16562061d35SAlexandre Belloni 				      &range);
16662061d35SAlexandre Belloni 
16762061d35SAlexandre Belloni 		if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&
16862061d35SAlexandre Belloni 		    (id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||
16962061d35SAlexandre Belloni 		     id == GCK_ID_CLASSD))
17064c9247bSClaudiu Beznea 			chg_pid = GCK_INDEX_DT_AUDIO_PLL;
17162061d35SAlexandre Belloni 
172e4cfb823SAlexandre Belloni 		hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
173e4cfb823SAlexandre Belloni 						 &dt_pcr_layout, name,
17400bd581bSClaudiu Beznea 						 parent_names, NULL, NULL,
17522a1dfe9SClaudiu Beznea 						 num_parents, id, &range,
17622a1dfe9SClaudiu Beznea 						 chg_pid);
17762061d35SAlexandre Belloni 		if (IS_ERR(hw))
17862061d35SAlexandre Belloni 			continue;
17962061d35SAlexandre Belloni 
18062061d35SAlexandre Belloni 		of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
18162061d35SAlexandre Belloni 	}
18262061d35SAlexandre Belloni }
18362061d35SAlexandre Belloni CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
18462061d35SAlexandre Belloni 	       of_sama5d2_clk_generated_setup);
18562061d35SAlexandre Belloni #endif /* CONFIG_HAVE_AT91_GENERATED_CLK */
18662061d35SAlexandre Belloni 
18762061d35SAlexandre Belloni #ifdef CONFIG_HAVE_AT91_H32MX
of_sama5d4_clk_h32mx_setup(struct device_node * np)18862061d35SAlexandre Belloni static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
18962061d35SAlexandre Belloni {
19062061d35SAlexandre Belloni 	struct clk_hw *hw;
19162061d35SAlexandre Belloni 	const char *name = np->name;
19262061d35SAlexandre Belloni 	const char *parent_name;
19362061d35SAlexandre Belloni 	struct regmap *regmap;
194b3ff02c5SLiang He 	struct device_node *parent_np;
19562061d35SAlexandre Belloni 
196b3ff02c5SLiang He 	parent_np = of_get_parent(np);
197b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
198b3ff02c5SLiang He 	of_node_put(parent_np);
19962061d35SAlexandre Belloni 	if (IS_ERR(regmap))
20062061d35SAlexandre Belloni 		return;
20162061d35SAlexandre Belloni 
20262061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
20362061d35SAlexandre Belloni 
20462061d35SAlexandre Belloni 	hw = at91_clk_register_h32mx(regmap, name, parent_name);
20562061d35SAlexandre Belloni 	if (IS_ERR(hw))
20662061d35SAlexandre Belloni 		return;
20762061d35SAlexandre Belloni 
20862061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
20962061d35SAlexandre Belloni }
21062061d35SAlexandre Belloni CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
21162061d35SAlexandre Belloni 	       of_sama5d4_clk_h32mx_setup);
21262061d35SAlexandre Belloni #endif /* CONFIG_HAVE_AT91_H32MX */
21362061d35SAlexandre Belloni 
21462061d35SAlexandre Belloni #ifdef CONFIG_HAVE_AT91_I2S_MUX_CLK
21562061d35SAlexandre Belloni #define	I2S_BUS_NR	2
21662061d35SAlexandre Belloni 
of_sama5d2_clk_i2s_mux_setup(struct device_node * np)21762061d35SAlexandre Belloni static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
21862061d35SAlexandre Belloni {
21962061d35SAlexandre Belloni 	struct regmap *regmap_sfr;
22062061d35SAlexandre Belloni 	u8 bus_id;
22162061d35SAlexandre Belloni 	const char *parent_names[2];
22262061d35SAlexandre Belloni 	struct device_node *i2s_mux_np;
22362061d35SAlexandre Belloni 	struct clk_hw *hw;
22462061d35SAlexandre Belloni 	int ret;
22562061d35SAlexandre Belloni 
22662061d35SAlexandre Belloni 	regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
22762061d35SAlexandre Belloni 	if (IS_ERR(regmap_sfr))
22862061d35SAlexandre Belloni 		return;
22962061d35SAlexandre Belloni 
23062061d35SAlexandre Belloni 	for_each_child_of_node(np, i2s_mux_np) {
23162061d35SAlexandre Belloni 		if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
23262061d35SAlexandre Belloni 			continue;
23362061d35SAlexandre Belloni 
23462061d35SAlexandre Belloni 		if (bus_id > I2S_BUS_NR)
23562061d35SAlexandre Belloni 			continue;
23662061d35SAlexandre Belloni 
23762061d35SAlexandre Belloni 		ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
23862061d35SAlexandre Belloni 		if (ret != 2)
23962061d35SAlexandre Belloni 			continue;
24062061d35SAlexandre Belloni 
24162061d35SAlexandre Belloni 		hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
24262061d35SAlexandre Belloni 					       parent_names, 2, bus_id);
24362061d35SAlexandre Belloni 		if (IS_ERR(hw))
24462061d35SAlexandre Belloni 			continue;
24562061d35SAlexandre Belloni 
24662061d35SAlexandre Belloni 		of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
24762061d35SAlexandre Belloni 	}
24862061d35SAlexandre Belloni }
24962061d35SAlexandre Belloni CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
25062061d35SAlexandre Belloni 	       of_sama5d2_clk_i2s_mux_setup);
25162061d35SAlexandre Belloni #endif /* CONFIG_HAVE_AT91_I2S_MUX_CLK */
25262061d35SAlexandre Belloni 
of_at91rm9200_clk_main_osc_setup(struct device_node * np)25362061d35SAlexandre Belloni static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
25462061d35SAlexandre Belloni {
25562061d35SAlexandre Belloni 	struct clk_hw *hw;
25662061d35SAlexandre Belloni 	const char *name = np->name;
25762061d35SAlexandre Belloni 	const char *parent_name;
25862061d35SAlexandre Belloni 	struct regmap *regmap;
25962061d35SAlexandre Belloni 	bool bypass;
260b3ff02c5SLiang He 	struct device_node *parent_np;
26162061d35SAlexandre Belloni 
26262061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
26362061d35SAlexandre Belloni 	bypass = of_property_read_bool(np, "atmel,osc-bypass");
26462061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
26562061d35SAlexandre Belloni 
266b3ff02c5SLiang He 	parent_np = of_get_parent(np);
267b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
268b3ff02c5SLiang He 	of_node_put(parent_np);
26962061d35SAlexandre Belloni 	if (IS_ERR(regmap))
27062061d35SAlexandre Belloni 		return;
27162061d35SAlexandre Belloni 
272b5105e37SClaudiu Beznea 	hw = at91_clk_register_main_osc(regmap, name, parent_name, NULL, bypass);
27362061d35SAlexandre Belloni 	if (IS_ERR(hw))
27462061d35SAlexandre Belloni 		return;
27562061d35SAlexandre Belloni 
27662061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
27762061d35SAlexandre Belloni }
27862061d35SAlexandre Belloni CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
27962061d35SAlexandre Belloni 	       of_at91rm9200_clk_main_osc_setup);
28062061d35SAlexandre Belloni 
of_at91sam9x5_clk_main_rc_osc_setup(struct device_node * np)28162061d35SAlexandre Belloni static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
28262061d35SAlexandre Belloni {
28362061d35SAlexandre Belloni 	struct clk_hw *hw;
28462061d35SAlexandre Belloni 	u32 frequency = 0;
28562061d35SAlexandre Belloni 	u32 accuracy = 0;
28662061d35SAlexandre Belloni 	const char *name = np->name;
28762061d35SAlexandre Belloni 	struct regmap *regmap;
288b3ff02c5SLiang He 	struct device_node *parent_np;
28962061d35SAlexandre Belloni 
29062061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
29162061d35SAlexandre Belloni 	of_property_read_u32(np, "clock-frequency", &frequency);
29262061d35SAlexandre Belloni 	of_property_read_u32(np, "clock-accuracy", &accuracy);
29362061d35SAlexandre Belloni 
294b3ff02c5SLiang He 	parent_np = of_get_parent(np);
295b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
296b3ff02c5SLiang He 	of_node_put(parent_np);
29762061d35SAlexandre Belloni 	if (IS_ERR(regmap))
29862061d35SAlexandre Belloni 		return;
29962061d35SAlexandre Belloni 
30062061d35SAlexandre Belloni 	hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
30162061d35SAlexandre Belloni 	if (IS_ERR(hw))
30262061d35SAlexandre Belloni 		return;
30362061d35SAlexandre Belloni 
30462061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
30562061d35SAlexandre Belloni }
30662061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
30762061d35SAlexandre Belloni 	       of_at91sam9x5_clk_main_rc_osc_setup);
30862061d35SAlexandre Belloni 
of_at91rm9200_clk_main_setup(struct device_node * np)30962061d35SAlexandre Belloni static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
31062061d35SAlexandre Belloni {
31162061d35SAlexandre Belloni 	struct clk_hw *hw;
31262061d35SAlexandre Belloni 	const char *parent_name;
31362061d35SAlexandre Belloni 	const char *name = np->name;
31462061d35SAlexandre Belloni 	struct regmap *regmap;
315b3ff02c5SLiang He 	struct device_node *parent_np;
31662061d35SAlexandre Belloni 
31762061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
31862061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
31962061d35SAlexandre Belloni 
320b3ff02c5SLiang He 	parent_np = of_get_parent(np);
321b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
322b3ff02c5SLiang He 	of_node_put(parent_np);
32362061d35SAlexandre Belloni 	if (IS_ERR(regmap))
32462061d35SAlexandre Belloni 		return;
32562061d35SAlexandre Belloni 
326b5105e37SClaudiu Beznea 	hw = at91_clk_register_rm9200_main(regmap, name, parent_name, NULL);
32762061d35SAlexandre Belloni 	if (IS_ERR(hw))
32862061d35SAlexandre Belloni 		return;
32962061d35SAlexandre Belloni 
33062061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
33162061d35SAlexandre Belloni }
33262061d35SAlexandre Belloni CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
33362061d35SAlexandre Belloni 	       of_at91rm9200_clk_main_setup);
33462061d35SAlexandre Belloni 
of_at91sam9x5_clk_main_setup(struct device_node * np)33562061d35SAlexandre Belloni static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
33662061d35SAlexandre Belloni {
33762061d35SAlexandre Belloni 	struct clk_hw *hw;
33862061d35SAlexandre Belloni 	const char *parent_names[2];
33962061d35SAlexandre Belloni 	unsigned int num_parents;
34062061d35SAlexandre Belloni 	const char *name = np->name;
34162061d35SAlexandre Belloni 	struct regmap *regmap;
342b3ff02c5SLiang He 	struct device_node *parent_np;
34362061d35SAlexandre Belloni 
34462061d35SAlexandre Belloni 	num_parents = of_clk_get_parent_count(np);
34562061d35SAlexandre Belloni 	if (num_parents == 0 || num_parents > 2)
34662061d35SAlexandre Belloni 		return;
34762061d35SAlexandre Belloni 
34862061d35SAlexandre Belloni 	of_clk_parent_fill(np, parent_names, num_parents);
349b3ff02c5SLiang He 	parent_np = of_get_parent(np);
350b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
351b3ff02c5SLiang He 	of_node_put(parent_np);
35262061d35SAlexandre Belloni 	if (IS_ERR(regmap))
35362061d35SAlexandre Belloni 		return;
35462061d35SAlexandre Belloni 
35562061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
35662061d35SAlexandre Belloni 
357b5105e37SClaudiu Beznea 	hw = at91_clk_register_sam9x5_main(regmap, name, parent_names, NULL,
35862061d35SAlexandre Belloni 					   num_parents);
35962061d35SAlexandre Belloni 	if (IS_ERR(hw))
36062061d35SAlexandre Belloni 		return;
36162061d35SAlexandre Belloni 
36262061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
36362061d35SAlexandre Belloni }
36462061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
36562061d35SAlexandre Belloni 	       of_at91sam9x5_clk_main_setup);
36662061d35SAlexandre Belloni 
36762061d35SAlexandre Belloni static struct clk_master_characteristics * __init
of_at91_clk_master_get_characteristics(struct device_node * np)36862061d35SAlexandre Belloni of_at91_clk_master_get_characteristics(struct device_node *np)
36962061d35SAlexandre Belloni {
37062061d35SAlexandre Belloni 	struct clk_master_characteristics *characteristics;
37162061d35SAlexandre Belloni 
37262061d35SAlexandre Belloni 	characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
37362061d35SAlexandre Belloni 	if (!characteristics)
37462061d35SAlexandre Belloni 		return NULL;
37562061d35SAlexandre Belloni 
37662061d35SAlexandre Belloni 	if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
37762061d35SAlexandre Belloni 		goto out_free_characteristics;
37862061d35SAlexandre Belloni 
37962061d35SAlexandre Belloni 	of_property_read_u32_array(np, "atmel,clk-divisors",
38062061d35SAlexandre Belloni 				   characteristics->divisors, 4);
38162061d35SAlexandre Belloni 
38262061d35SAlexandre Belloni 	characteristics->have_div3_pres =
38362061d35SAlexandre Belloni 		of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
38462061d35SAlexandre Belloni 
38562061d35SAlexandre Belloni 	return characteristics;
38662061d35SAlexandre Belloni 
38762061d35SAlexandre Belloni out_free_characteristics:
38862061d35SAlexandre Belloni 	kfree(characteristics);
38962061d35SAlexandre Belloni 	return NULL;
39062061d35SAlexandre Belloni }
39162061d35SAlexandre Belloni 
39262061d35SAlexandre Belloni static void __init
of_at91_clk_master_setup(struct device_node * np,const struct clk_master_layout * layout)39362061d35SAlexandre Belloni of_at91_clk_master_setup(struct device_node *np,
39462061d35SAlexandre Belloni 			 const struct clk_master_layout *layout)
39562061d35SAlexandre Belloni {
39662061d35SAlexandre Belloni 	struct clk_hw *hw;
39762061d35SAlexandre Belloni 	unsigned int num_parents;
39862061d35SAlexandre Belloni 	const char *parent_names[MASTER_SOURCE_MAX];
39962061d35SAlexandre Belloni 	const char *name = np->name;
40062061d35SAlexandre Belloni 	struct clk_master_characteristics *characteristics;
40162061d35SAlexandre Belloni 	struct regmap *regmap;
402b3ff02c5SLiang He 	struct device_node *parent_np;
40362061d35SAlexandre Belloni 
40462061d35SAlexandre Belloni 	num_parents = of_clk_get_parent_count(np);
40562061d35SAlexandre Belloni 	if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
40662061d35SAlexandre Belloni 		return;
40762061d35SAlexandre Belloni 
40862061d35SAlexandre Belloni 	of_clk_parent_fill(np, parent_names, num_parents);
40962061d35SAlexandre Belloni 
41062061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
41162061d35SAlexandre Belloni 
41262061d35SAlexandre Belloni 	characteristics = of_at91_clk_master_get_characteristics(np);
41362061d35SAlexandre Belloni 	if (!characteristics)
41462061d35SAlexandre Belloni 		return;
41562061d35SAlexandre Belloni 
416b3ff02c5SLiang He 	parent_np = of_get_parent(np);
417b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
418b3ff02c5SLiang He 	of_node_put(parent_np);
41962061d35SAlexandre Belloni 	if (IS_ERR(regmap))
42062061d35SAlexandre Belloni 		return;
42162061d35SAlexandre Belloni 
4227a110b91SClaudiu Beznea 	hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents,
423171e502cSClaudiu Beznea 					   parent_names, NULL, layout,
4248e842f02SClaudiu Beznea 					   characteristics, &mck_lock);
4257a110b91SClaudiu Beznea 	if (IS_ERR(hw))
4267a110b91SClaudiu Beznea 		goto out_free_characteristics;
4277a110b91SClaudiu Beznea 
428171e502cSClaudiu Beznea 	hw = at91_clk_register_master_div(regmap, name, "masterck_pres", NULL,
4297a110b91SClaudiu Beznea 					  layout, characteristics,
4307029db09SClaudiu Beznea 					  &mck_lock, CLK_SET_RATE_GATE, 0);
43162061d35SAlexandre Belloni 	if (IS_ERR(hw))
43262061d35SAlexandre Belloni 		goto out_free_characteristics;
43362061d35SAlexandre Belloni 
43462061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
43562061d35SAlexandre Belloni 	return;
43662061d35SAlexandre Belloni 
43762061d35SAlexandre Belloni out_free_characteristics:
43862061d35SAlexandre Belloni 	kfree(characteristics);
43962061d35SAlexandre Belloni }
44062061d35SAlexandre Belloni 
of_at91rm9200_clk_master_setup(struct device_node * np)44162061d35SAlexandre Belloni static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
44262061d35SAlexandre Belloni {
44362061d35SAlexandre Belloni 	of_at91_clk_master_setup(np, &at91rm9200_master_layout);
44462061d35SAlexandre Belloni }
44562061d35SAlexandre Belloni CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
44662061d35SAlexandre Belloni 	       of_at91rm9200_clk_master_setup);
44762061d35SAlexandre Belloni 
of_at91sam9x5_clk_master_setup(struct device_node * np)44862061d35SAlexandre Belloni static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
44962061d35SAlexandre Belloni {
45062061d35SAlexandre Belloni 	of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
45162061d35SAlexandre Belloni }
45262061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
45362061d35SAlexandre Belloni 	       of_at91sam9x5_clk_master_setup);
45462061d35SAlexandre Belloni 
45562061d35SAlexandre Belloni static void __init
of_at91_clk_periph_setup(struct device_node * np,u8 type)45662061d35SAlexandre Belloni of_at91_clk_periph_setup(struct device_node *np, u8 type)
45762061d35SAlexandre Belloni {
45862061d35SAlexandre Belloni 	int num;
45962061d35SAlexandre Belloni 	u32 id;
46062061d35SAlexandre Belloni 	struct clk_hw *hw;
46162061d35SAlexandre Belloni 	const char *parent_name;
46262061d35SAlexandre Belloni 	const char *name;
46362061d35SAlexandre Belloni 	struct device_node *periphclknp;
46462061d35SAlexandre Belloni 	struct regmap *regmap;
465b3ff02c5SLiang He 	struct device_node *parent_np;
46662061d35SAlexandre Belloni 
46762061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
46862061d35SAlexandre Belloni 	if (!parent_name)
46962061d35SAlexandre Belloni 		return;
47062061d35SAlexandre Belloni 
47162061d35SAlexandre Belloni 	num = of_get_child_count(np);
47262061d35SAlexandre Belloni 	if (!num || num > PERIPHERAL_MAX)
47362061d35SAlexandre Belloni 		return;
47462061d35SAlexandre Belloni 
475b3ff02c5SLiang He 	parent_np = of_get_parent(np);
476b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
477b3ff02c5SLiang He 	of_node_put(parent_np);
47862061d35SAlexandre Belloni 	if (IS_ERR(regmap))
47962061d35SAlexandre Belloni 		return;
48062061d35SAlexandre Belloni 
48162061d35SAlexandre Belloni 	for_each_child_of_node(np, periphclknp) {
48262061d35SAlexandre Belloni 		if (of_property_read_u32(periphclknp, "reg", &id))
48362061d35SAlexandre Belloni 			continue;
48462061d35SAlexandre Belloni 
48562061d35SAlexandre Belloni 		if (id >= PERIPHERAL_MAX)
48662061d35SAlexandre Belloni 			continue;
48762061d35SAlexandre Belloni 
48862061d35SAlexandre Belloni 		if (of_property_read_string(np, "clock-output-names", &name))
48962061d35SAlexandre Belloni 			name = periphclknp->name;
49062061d35SAlexandre Belloni 
49162061d35SAlexandre Belloni 		if (type == PERIPHERAL_AT91RM9200) {
49262061d35SAlexandre Belloni 			hw = at91_clk_register_peripheral(regmap, name,
493c2f2ca0bSClaudiu Beznea 							  parent_name, NULL, id);
49462061d35SAlexandre Belloni 		} else {
49562061d35SAlexandre Belloni 			struct clk_range range = CLK_RANGE(0, 0);
49668b3b6f1SClaudiu Beznea 			unsigned long flags = 0;
49762061d35SAlexandre Belloni 
49862061d35SAlexandre Belloni 			of_at91_get_clk_range(periphclknp,
49962061d35SAlexandre Belloni 					      "atmel,clk-output-range",
50062061d35SAlexandre Belloni 					      &range);
50162061d35SAlexandre Belloni 
50268b3b6f1SClaudiu Beznea 			/*
50368b3b6f1SClaudiu Beznea 			 * mpddr_clk feed DDR controller and is enabled by
50468b3b6f1SClaudiu Beznea 			 * bootloader thus we need to keep it enabled in case
50568b3b6f1SClaudiu Beznea 			 * there is no Linux consumer for it.
50668b3b6f1SClaudiu Beznea 			 */
50768b3b6f1SClaudiu Beznea 			if (!strcmp(periphclknp->name, "mpddr_clk"))
50868b3b6f1SClaudiu Beznea 				flags = CLK_IS_CRITICAL;
50968b3b6f1SClaudiu Beznea 
51062061d35SAlexandre Belloni 			hw = at91_clk_register_sam9x5_peripheral(regmap,
51162061d35SAlexandre Belloni 								 &pmc_pcr_lock,
512cb4f4949SAlexandre Belloni 								 &dt_pcr_layout,
51362061d35SAlexandre Belloni 								 name,
51462061d35SAlexandre Belloni 								 parent_name,
515c2f2ca0bSClaudiu Beznea 								 NULL,
516b4c115c7SClaudiu Beznea 								 id, &range,
51768b3b6f1SClaudiu Beznea 								 INT_MIN,
51868b3b6f1SClaudiu Beznea 								 flags);
51962061d35SAlexandre Belloni 		}
52062061d35SAlexandre Belloni 
52162061d35SAlexandre Belloni 		if (IS_ERR(hw))
52262061d35SAlexandre Belloni 			continue;
52362061d35SAlexandre Belloni 
52462061d35SAlexandre Belloni 		of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
52562061d35SAlexandre Belloni 	}
52662061d35SAlexandre Belloni }
52762061d35SAlexandre Belloni 
of_at91rm9200_clk_periph_setup(struct device_node * np)52862061d35SAlexandre Belloni static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
52962061d35SAlexandre Belloni {
53062061d35SAlexandre Belloni 	of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
53162061d35SAlexandre Belloni }
53262061d35SAlexandre Belloni CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
53362061d35SAlexandre Belloni 	       of_at91rm9200_clk_periph_setup);
53462061d35SAlexandre Belloni 
of_at91sam9x5_clk_periph_setup(struct device_node * np)53562061d35SAlexandre Belloni static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
53662061d35SAlexandre Belloni {
53762061d35SAlexandre Belloni 	of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
53862061d35SAlexandre Belloni }
53962061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
54062061d35SAlexandre Belloni 	       of_at91sam9x5_clk_periph_setup);
54162061d35SAlexandre Belloni 
54262061d35SAlexandre Belloni static struct clk_pll_characteristics * __init
of_at91_clk_pll_get_characteristics(struct device_node * np)54362061d35SAlexandre Belloni of_at91_clk_pll_get_characteristics(struct device_node *np)
54462061d35SAlexandre Belloni {
54562061d35SAlexandre Belloni 	int i;
54662061d35SAlexandre Belloni 	int offset;
54762061d35SAlexandre Belloni 	u32 tmp;
54862061d35SAlexandre Belloni 	int num_output;
54962061d35SAlexandre Belloni 	u32 num_cells;
55062061d35SAlexandre Belloni 	struct clk_range input;
55162061d35SAlexandre Belloni 	struct clk_range *output;
55262061d35SAlexandre Belloni 	u8 *out = NULL;
55362061d35SAlexandre Belloni 	u16 *icpll = NULL;
55462061d35SAlexandre Belloni 	struct clk_pll_characteristics *characteristics;
55562061d35SAlexandre Belloni 
55662061d35SAlexandre Belloni 	if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
55762061d35SAlexandre Belloni 		return NULL;
55862061d35SAlexandre Belloni 
55962061d35SAlexandre Belloni 	if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
56062061d35SAlexandre Belloni 				 &num_cells))
56162061d35SAlexandre Belloni 		return NULL;
56262061d35SAlexandre Belloni 
56362061d35SAlexandre Belloni 	if (num_cells < 2 || num_cells > 4)
56462061d35SAlexandre Belloni 		return NULL;
56562061d35SAlexandre Belloni 
56662061d35SAlexandre Belloni 	if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
56762061d35SAlexandre Belloni 		return NULL;
56862061d35SAlexandre Belloni 	num_output = tmp / (sizeof(u32) * num_cells);
56962061d35SAlexandre Belloni 
57062061d35SAlexandre Belloni 	characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
57162061d35SAlexandre Belloni 	if (!characteristics)
57262061d35SAlexandre Belloni 		return NULL;
57362061d35SAlexandre Belloni 
57462061d35SAlexandre Belloni 	output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
57562061d35SAlexandre Belloni 	if (!output)
57662061d35SAlexandre Belloni 		goto out_free_characteristics;
57762061d35SAlexandre Belloni 
57862061d35SAlexandre Belloni 	if (num_cells > 2) {
57962061d35SAlexandre Belloni 		out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
58062061d35SAlexandre Belloni 		if (!out)
58162061d35SAlexandre Belloni 			goto out_free_output;
58262061d35SAlexandre Belloni 	}
58362061d35SAlexandre Belloni 
58462061d35SAlexandre Belloni 	if (num_cells > 3) {
58562061d35SAlexandre Belloni 		icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
58662061d35SAlexandre Belloni 		if (!icpll)
58762061d35SAlexandre Belloni 			goto out_free_output;
58862061d35SAlexandre Belloni 	}
58962061d35SAlexandre Belloni 
59062061d35SAlexandre Belloni 	for (i = 0; i < num_output; i++) {
59162061d35SAlexandre Belloni 		offset = i * num_cells;
59262061d35SAlexandre Belloni 		if (of_property_read_u32_index(np,
59362061d35SAlexandre Belloni 					       "atmel,pll-clk-output-ranges",
59462061d35SAlexandre Belloni 					       offset, &tmp))
59562061d35SAlexandre Belloni 			goto out_free_output;
59662061d35SAlexandre Belloni 		output[i].min = tmp;
59762061d35SAlexandre Belloni 		if (of_property_read_u32_index(np,
59862061d35SAlexandre Belloni 					       "atmel,pll-clk-output-ranges",
59962061d35SAlexandre Belloni 					       offset + 1, &tmp))
60062061d35SAlexandre Belloni 			goto out_free_output;
60162061d35SAlexandre Belloni 		output[i].max = tmp;
60262061d35SAlexandre Belloni 
60362061d35SAlexandre Belloni 		if (num_cells == 2)
60462061d35SAlexandre Belloni 			continue;
60562061d35SAlexandre Belloni 
60662061d35SAlexandre Belloni 		if (of_property_read_u32_index(np,
60762061d35SAlexandre Belloni 					       "atmel,pll-clk-output-ranges",
60862061d35SAlexandre Belloni 					       offset + 2, &tmp))
60962061d35SAlexandre Belloni 			goto out_free_output;
61062061d35SAlexandre Belloni 		out[i] = tmp;
61162061d35SAlexandre Belloni 
61262061d35SAlexandre Belloni 		if (num_cells == 3)
61362061d35SAlexandre Belloni 			continue;
61462061d35SAlexandre Belloni 
61562061d35SAlexandre Belloni 		if (of_property_read_u32_index(np,
61662061d35SAlexandre Belloni 					       "atmel,pll-clk-output-ranges",
61762061d35SAlexandre Belloni 					       offset + 3, &tmp))
61862061d35SAlexandre Belloni 			goto out_free_output;
61962061d35SAlexandre Belloni 		icpll[i] = tmp;
62062061d35SAlexandre Belloni 	}
62162061d35SAlexandre Belloni 
62262061d35SAlexandre Belloni 	characteristics->input = input;
62362061d35SAlexandre Belloni 	characteristics->num_output = num_output;
62462061d35SAlexandre Belloni 	characteristics->output = output;
62562061d35SAlexandre Belloni 	characteristics->out = out;
62662061d35SAlexandre Belloni 	characteristics->icpll = icpll;
62762061d35SAlexandre Belloni 	return characteristics;
62862061d35SAlexandre Belloni 
62962061d35SAlexandre Belloni out_free_output:
63062061d35SAlexandre Belloni 	kfree(icpll);
63162061d35SAlexandre Belloni 	kfree(out);
63262061d35SAlexandre Belloni 	kfree(output);
63362061d35SAlexandre Belloni out_free_characteristics:
63462061d35SAlexandre Belloni 	kfree(characteristics);
63562061d35SAlexandre Belloni 	return NULL;
63662061d35SAlexandre Belloni }
63762061d35SAlexandre Belloni 
63862061d35SAlexandre Belloni static void __init
of_at91_clk_pll_setup(struct device_node * np,const struct clk_pll_layout * layout)63962061d35SAlexandre Belloni of_at91_clk_pll_setup(struct device_node *np,
64062061d35SAlexandre Belloni 		      const struct clk_pll_layout *layout)
64162061d35SAlexandre Belloni {
64262061d35SAlexandre Belloni 	u32 id;
64362061d35SAlexandre Belloni 	struct clk_hw *hw;
64462061d35SAlexandre Belloni 	struct regmap *regmap;
64562061d35SAlexandre Belloni 	const char *parent_name;
64662061d35SAlexandre Belloni 	const char *name = np->name;
647b3ff02c5SLiang He 	struct device_node *parent_np;
64862061d35SAlexandre Belloni 	struct clk_pll_characteristics *characteristics;
64962061d35SAlexandre Belloni 
65062061d35SAlexandre Belloni 	if (of_property_read_u32(np, "reg", &id))
65162061d35SAlexandre Belloni 		return;
65262061d35SAlexandre Belloni 
65362061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
65462061d35SAlexandre Belloni 
65562061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
65662061d35SAlexandre Belloni 
657b3ff02c5SLiang He 	parent_np = of_get_parent(np);
658b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
659b3ff02c5SLiang He 	of_node_put(parent_np);
66062061d35SAlexandre Belloni 	if (IS_ERR(regmap))
66162061d35SAlexandre Belloni 		return;
66262061d35SAlexandre Belloni 
66362061d35SAlexandre Belloni 	characteristics = of_at91_clk_pll_get_characteristics(np);
66462061d35SAlexandre Belloni 	if (!characteristics)
66562061d35SAlexandre Belloni 		return;
66662061d35SAlexandre Belloni 
66762061d35SAlexandre Belloni 	hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
66862061d35SAlexandre Belloni 				   characteristics);
66962061d35SAlexandre Belloni 	if (IS_ERR(hw))
67062061d35SAlexandre Belloni 		goto out_free_characteristics;
67162061d35SAlexandre Belloni 
67262061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
67362061d35SAlexandre Belloni 	return;
67462061d35SAlexandre Belloni 
67562061d35SAlexandre Belloni out_free_characteristics:
67662061d35SAlexandre Belloni 	kfree(characteristics);
67762061d35SAlexandre Belloni }
67862061d35SAlexandre Belloni 
of_at91rm9200_clk_pll_setup(struct device_node * np)67962061d35SAlexandre Belloni static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
68062061d35SAlexandre Belloni {
68162061d35SAlexandre Belloni 	of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
68262061d35SAlexandre Belloni }
68362061d35SAlexandre Belloni CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
68462061d35SAlexandre Belloni 	       of_at91rm9200_clk_pll_setup);
68562061d35SAlexandre Belloni 
of_at91sam9g45_clk_pll_setup(struct device_node * np)68662061d35SAlexandre Belloni static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
68762061d35SAlexandre Belloni {
68862061d35SAlexandre Belloni 	of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
68962061d35SAlexandre Belloni }
69062061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
69162061d35SAlexandre Belloni 	       of_at91sam9g45_clk_pll_setup);
69262061d35SAlexandre Belloni 
of_at91sam9g20_clk_pllb_setup(struct device_node * np)69362061d35SAlexandre Belloni static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
69462061d35SAlexandre Belloni {
69562061d35SAlexandre Belloni 	of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
69662061d35SAlexandre Belloni }
69762061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
69862061d35SAlexandre Belloni 	       of_at91sam9g20_clk_pllb_setup);
69962061d35SAlexandre Belloni 
of_sama5d3_clk_pll_setup(struct device_node * np)70062061d35SAlexandre Belloni static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
70162061d35SAlexandre Belloni {
70262061d35SAlexandre Belloni 	of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
70362061d35SAlexandre Belloni }
70462061d35SAlexandre Belloni CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
70562061d35SAlexandre Belloni 	       of_sama5d3_clk_pll_setup);
70662061d35SAlexandre Belloni 
70762061d35SAlexandre Belloni static void __init
of_at91sam9x5_clk_plldiv_setup(struct device_node * np)70862061d35SAlexandre Belloni of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
70962061d35SAlexandre Belloni {
71062061d35SAlexandre Belloni 	struct clk_hw *hw;
71162061d35SAlexandre Belloni 	const char *parent_name;
71262061d35SAlexandre Belloni 	const char *name = np->name;
71362061d35SAlexandre Belloni 	struct regmap *regmap;
714b3ff02c5SLiang He 	struct device_node *parent_np;
71562061d35SAlexandre Belloni 
71662061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
71762061d35SAlexandre Belloni 
71862061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
71962061d35SAlexandre Belloni 
720b3ff02c5SLiang He 	parent_np = of_get_parent(np);
721b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
722b3ff02c5SLiang He 	of_node_put(parent_np);
72362061d35SAlexandre Belloni 	if (IS_ERR(regmap))
72462061d35SAlexandre Belloni 		return;
72562061d35SAlexandre Belloni 
72662061d35SAlexandre Belloni 	hw = at91_clk_register_plldiv(regmap, name, parent_name);
72762061d35SAlexandre Belloni 	if (IS_ERR(hw))
72862061d35SAlexandre Belloni 		return;
72962061d35SAlexandre Belloni 
73062061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
73162061d35SAlexandre Belloni }
73262061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
73362061d35SAlexandre Belloni 	       of_at91sam9x5_clk_plldiv_setup);
73462061d35SAlexandre Belloni 
73562061d35SAlexandre Belloni static void __init
of_at91_clk_prog_setup(struct device_node * np,const struct clk_programmable_layout * layout,u32 * mux_table)73662061d35SAlexandre Belloni of_at91_clk_prog_setup(struct device_node *np,
737c57aaaa2SClaudiu Beznea 		       const struct clk_programmable_layout *layout,
738c57aaaa2SClaudiu Beznea 		       u32 *mux_table)
73962061d35SAlexandre Belloni {
74062061d35SAlexandre Belloni 	int num;
74162061d35SAlexandre Belloni 	u32 id;
74262061d35SAlexandre Belloni 	struct clk_hw *hw;
74362061d35SAlexandre Belloni 	unsigned int num_parents;
74462061d35SAlexandre Belloni 	const char *parent_names[PROG_SOURCE_MAX];
74562061d35SAlexandre Belloni 	const char *name;
746b3ff02c5SLiang He 	struct device_node *progclknp, *parent_np;
74762061d35SAlexandre Belloni 	struct regmap *regmap;
74862061d35SAlexandre Belloni 
74962061d35SAlexandre Belloni 	num_parents = of_clk_get_parent_count(np);
75062061d35SAlexandre Belloni 	if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
75162061d35SAlexandre Belloni 		return;
75262061d35SAlexandre Belloni 
75362061d35SAlexandre Belloni 	of_clk_parent_fill(np, parent_names, num_parents);
75462061d35SAlexandre Belloni 
75562061d35SAlexandre Belloni 	num = of_get_child_count(np);
75662061d35SAlexandre Belloni 	if (!num || num > (PROG_ID_MAX + 1))
75762061d35SAlexandre Belloni 		return;
75862061d35SAlexandre Belloni 
759b3ff02c5SLiang He 	parent_np = of_get_parent(np);
760b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
761b3ff02c5SLiang He 	of_node_put(parent_np);
76262061d35SAlexandre Belloni 	if (IS_ERR(regmap))
76362061d35SAlexandre Belloni 		return;
76462061d35SAlexandre Belloni 
76562061d35SAlexandre Belloni 	for_each_child_of_node(np, progclknp) {
76662061d35SAlexandre Belloni 		if (of_property_read_u32(progclknp, "reg", &id))
76762061d35SAlexandre Belloni 			continue;
76862061d35SAlexandre Belloni 
76962061d35SAlexandre Belloni 		if (of_property_read_string(np, "clock-output-names", &name))
77062061d35SAlexandre Belloni 			name = progclknp->name;
77162061d35SAlexandre Belloni 
77262061d35SAlexandre Belloni 		hw = at91_clk_register_programmable(regmap, name,
7731a2669dfSClaudiu Beznea 						    parent_names, NULL, num_parents,
774c57aaaa2SClaudiu Beznea 						    id, layout, mux_table);
77562061d35SAlexandre Belloni 		if (IS_ERR(hw))
77662061d35SAlexandre Belloni 			continue;
77762061d35SAlexandre Belloni 
77862061d35SAlexandre Belloni 		of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
77962061d35SAlexandre Belloni 	}
78062061d35SAlexandre Belloni }
78162061d35SAlexandre Belloni 
of_at91rm9200_clk_prog_setup(struct device_node * np)78262061d35SAlexandre Belloni static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
78362061d35SAlexandre Belloni {
784c57aaaa2SClaudiu Beznea 	of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout, NULL);
78562061d35SAlexandre Belloni }
78662061d35SAlexandre Belloni CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
78762061d35SAlexandre Belloni 	       of_at91rm9200_clk_prog_setup);
78862061d35SAlexandre Belloni 
of_at91sam9g45_clk_prog_setup(struct device_node * np)78962061d35SAlexandre Belloni static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
79062061d35SAlexandre Belloni {
791c57aaaa2SClaudiu Beznea 	of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout, NULL);
79262061d35SAlexandre Belloni }
79362061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
79462061d35SAlexandre Belloni 	       of_at91sam9g45_clk_prog_setup);
79562061d35SAlexandre Belloni 
of_at91sam9x5_clk_prog_setup(struct device_node * np)79662061d35SAlexandre Belloni static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
79762061d35SAlexandre Belloni {
798c57aaaa2SClaudiu Beznea 	of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout, NULL);
79962061d35SAlexandre Belloni }
80062061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
80162061d35SAlexandre Belloni 	       of_at91sam9x5_clk_prog_setup);
80262061d35SAlexandre Belloni 
of_at91sam9260_clk_slow_setup(struct device_node * np)80362061d35SAlexandre Belloni static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
80462061d35SAlexandre Belloni {
80562061d35SAlexandre Belloni 	struct clk_hw *hw;
80662061d35SAlexandre Belloni 	const char *parent_names[2];
80762061d35SAlexandre Belloni 	unsigned int num_parents;
80862061d35SAlexandre Belloni 	const char *name = np->name;
80962061d35SAlexandre Belloni 	struct regmap *regmap;
810b3ff02c5SLiang He 	struct device_node *parent_np;
81162061d35SAlexandre Belloni 
81262061d35SAlexandre Belloni 	num_parents = of_clk_get_parent_count(np);
81362061d35SAlexandre Belloni 	if (num_parents != 2)
81462061d35SAlexandre Belloni 		return;
81562061d35SAlexandre Belloni 
81662061d35SAlexandre Belloni 	of_clk_parent_fill(np, parent_names, num_parents);
817b3ff02c5SLiang He 	parent_np = of_get_parent(np);
818b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
819b3ff02c5SLiang He 	of_node_put(parent_np);
82062061d35SAlexandre Belloni 	if (IS_ERR(regmap))
82162061d35SAlexandre Belloni 		return;
82262061d35SAlexandre Belloni 
82362061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
82462061d35SAlexandre Belloni 
82562061d35SAlexandre Belloni 	hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
82662061d35SAlexandre Belloni 					    num_parents);
82762061d35SAlexandre Belloni 	if (IS_ERR(hw))
82862061d35SAlexandre Belloni 		return;
82962061d35SAlexandre Belloni 
83062061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
83162061d35SAlexandre Belloni }
83262061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
83362061d35SAlexandre Belloni 	       of_at91sam9260_clk_slow_setup);
83462061d35SAlexandre Belloni 
83562061d35SAlexandre Belloni #ifdef CONFIG_HAVE_AT91_SMD
83662061d35SAlexandre Belloni #define SMD_SOURCE_MAX		2
83762061d35SAlexandre Belloni 
of_at91sam9x5_clk_smd_setup(struct device_node * np)83862061d35SAlexandre Belloni static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
83962061d35SAlexandre Belloni {
84062061d35SAlexandre Belloni 	struct clk_hw *hw;
84162061d35SAlexandre Belloni 	unsigned int num_parents;
84262061d35SAlexandre Belloni 	const char *parent_names[SMD_SOURCE_MAX];
84362061d35SAlexandre Belloni 	const char *name = np->name;
84462061d35SAlexandre Belloni 	struct regmap *regmap;
845b3ff02c5SLiang He 	struct device_node *parent_np;
84662061d35SAlexandre Belloni 
84762061d35SAlexandre Belloni 	num_parents = of_clk_get_parent_count(np);
84862061d35SAlexandre Belloni 	if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
84962061d35SAlexandre Belloni 		return;
85062061d35SAlexandre Belloni 
85162061d35SAlexandre Belloni 	of_clk_parent_fill(np, parent_names, num_parents);
85262061d35SAlexandre Belloni 
85362061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
85462061d35SAlexandre Belloni 
855b3ff02c5SLiang He 	parent_np = of_get_parent(np);
856b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
857b3ff02c5SLiang He 	of_node_put(parent_np);
85862061d35SAlexandre Belloni 	if (IS_ERR(regmap))
85962061d35SAlexandre Belloni 		return;
86062061d35SAlexandre Belloni 
86162061d35SAlexandre Belloni 	hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
86262061d35SAlexandre Belloni 					 num_parents);
86362061d35SAlexandre Belloni 	if (IS_ERR(hw))
86462061d35SAlexandre Belloni 		return;
86562061d35SAlexandre Belloni 
86662061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
86762061d35SAlexandre Belloni }
86862061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
86962061d35SAlexandre Belloni 	       of_at91sam9x5_clk_smd_setup);
87062061d35SAlexandre Belloni #endif /* CONFIG_HAVE_AT91_SMD */
87162061d35SAlexandre Belloni 
of_at91rm9200_clk_sys_setup(struct device_node * np)87262061d35SAlexandre Belloni static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
87362061d35SAlexandre Belloni {
87462061d35SAlexandre Belloni 	int num;
87562061d35SAlexandre Belloni 	u32 id;
87662061d35SAlexandre Belloni 	struct clk_hw *hw;
87762061d35SAlexandre Belloni 	const char *name;
878b3ff02c5SLiang He 	struct device_node *sysclknp, *parent_np;
87962061d35SAlexandre Belloni 	const char *parent_name;
88062061d35SAlexandre Belloni 	struct regmap *regmap;
88162061d35SAlexandre Belloni 
88262061d35SAlexandre Belloni 	num = of_get_child_count(np);
88362061d35SAlexandre Belloni 	if (num > (SYSTEM_MAX_ID + 1))
88462061d35SAlexandre Belloni 		return;
88562061d35SAlexandre Belloni 
886b3ff02c5SLiang He 	parent_np = of_get_parent(np);
887b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
888b3ff02c5SLiang He 	of_node_put(parent_np);
88962061d35SAlexandre Belloni 	if (IS_ERR(regmap))
89062061d35SAlexandre Belloni 		return;
89162061d35SAlexandre Belloni 
89262061d35SAlexandre Belloni 	for_each_child_of_node(np, sysclknp) {
89368b3b6f1SClaudiu Beznea 		unsigned long flags = 0;
89468b3b6f1SClaudiu Beznea 
89562061d35SAlexandre Belloni 		if (of_property_read_u32(sysclknp, "reg", &id))
89662061d35SAlexandre Belloni 			continue;
89762061d35SAlexandre Belloni 
89862061d35SAlexandre Belloni 		if (of_property_read_string(np, "clock-output-names", &name))
89962061d35SAlexandre Belloni 			name = sysclknp->name;
90062061d35SAlexandre Belloni 
90162061d35SAlexandre Belloni 		parent_name = of_clk_get_parent_name(sysclknp, 0);
90262061d35SAlexandre Belloni 
90368b3b6f1SClaudiu Beznea 		/*
90468b3b6f1SClaudiu Beznea 		 * ddrck feeds DDR controller and is enabled by bootloader thus
90568b3b6f1SClaudiu Beznea 		 * we need to keep it enabled in case there is no Linux consumer
90668b3b6f1SClaudiu Beznea 		 * for it.
90768b3b6f1SClaudiu Beznea 		 */
90868b3b6f1SClaudiu Beznea 		if (!strcmp(sysclknp->name, "ddrck"))
90968b3b6f1SClaudiu Beznea 			flags = CLK_IS_CRITICAL;
91068b3b6f1SClaudiu Beznea 
9111a537f62SClaudiu Beznea 		hw = at91_clk_register_system(regmap, name, parent_name, NULL,
9121a537f62SClaudiu Beznea 					      id, flags);
91362061d35SAlexandre Belloni 		if (IS_ERR(hw))
91462061d35SAlexandre Belloni 			continue;
91562061d35SAlexandre Belloni 
91662061d35SAlexandre Belloni 		of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
91762061d35SAlexandre Belloni 	}
91862061d35SAlexandre Belloni }
91962061d35SAlexandre Belloni CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
92062061d35SAlexandre Belloni 	       of_at91rm9200_clk_sys_setup);
92162061d35SAlexandre Belloni 
92262061d35SAlexandre Belloni #ifdef CONFIG_HAVE_AT91_USB_CLK
92362061d35SAlexandre Belloni #define USB_SOURCE_MAX		2
92462061d35SAlexandre Belloni 
of_at91sam9x5_clk_usb_setup(struct device_node * np)92562061d35SAlexandre Belloni static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
92662061d35SAlexandre Belloni {
92762061d35SAlexandre Belloni 	struct clk_hw *hw;
92862061d35SAlexandre Belloni 	unsigned int num_parents;
92962061d35SAlexandre Belloni 	const char *parent_names[USB_SOURCE_MAX];
93062061d35SAlexandre Belloni 	const char *name = np->name;
93162061d35SAlexandre Belloni 	struct regmap *regmap;
932b3ff02c5SLiang He 	struct device_node *parent_np;
93362061d35SAlexandre Belloni 
93462061d35SAlexandre Belloni 	num_parents = of_clk_get_parent_count(np);
93562061d35SAlexandre Belloni 	if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
93662061d35SAlexandre Belloni 		return;
93762061d35SAlexandre Belloni 
93862061d35SAlexandre Belloni 	of_clk_parent_fill(np, parent_names, num_parents);
93962061d35SAlexandre Belloni 
94062061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
94162061d35SAlexandre Belloni 
942b3ff02c5SLiang He 	parent_np = of_get_parent(np);
943b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
944b3ff02c5SLiang He 	of_node_put(parent_np);
94562061d35SAlexandre Belloni 	if (IS_ERR(regmap))
94662061d35SAlexandre Belloni 		return;
94762061d35SAlexandre Belloni 
94862061d35SAlexandre Belloni 	hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
94962061d35SAlexandre Belloni 					 num_parents);
95062061d35SAlexandre Belloni 	if (IS_ERR(hw))
95162061d35SAlexandre Belloni 		return;
95262061d35SAlexandre Belloni 
95362061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
95462061d35SAlexandre Belloni }
95562061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
95662061d35SAlexandre Belloni 	       of_at91sam9x5_clk_usb_setup);
95762061d35SAlexandre Belloni 
of_at91sam9n12_clk_usb_setup(struct device_node * np)95862061d35SAlexandre Belloni static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
95962061d35SAlexandre Belloni {
96062061d35SAlexandre Belloni 	struct clk_hw *hw;
96162061d35SAlexandre Belloni 	const char *parent_name;
96262061d35SAlexandre Belloni 	const char *name = np->name;
96362061d35SAlexandre Belloni 	struct regmap *regmap;
964b3ff02c5SLiang He 	struct device_node *parent_np;
96562061d35SAlexandre Belloni 
96662061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
96762061d35SAlexandre Belloni 	if (!parent_name)
96862061d35SAlexandre Belloni 		return;
96962061d35SAlexandre Belloni 
97062061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
97162061d35SAlexandre Belloni 
972b3ff02c5SLiang He 	parent_np = of_get_parent(np);
973b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
974b3ff02c5SLiang He 	of_node_put(parent_np);
97562061d35SAlexandre Belloni 	if (IS_ERR(regmap))
97662061d35SAlexandre Belloni 		return;
97762061d35SAlexandre Belloni 
97862061d35SAlexandre Belloni 	hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
97962061d35SAlexandre Belloni 	if (IS_ERR(hw))
98062061d35SAlexandre Belloni 		return;
98162061d35SAlexandre Belloni 
98262061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
98362061d35SAlexandre Belloni }
98462061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
98562061d35SAlexandre Belloni 	       of_at91sam9n12_clk_usb_setup);
98662061d35SAlexandre Belloni 
of_at91rm9200_clk_usb_setup(struct device_node * np)98762061d35SAlexandre Belloni static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
98862061d35SAlexandre Belloni {
98962061d35SAlexandre Belloni 	struct clk_hw *hw;
99062061d35SAlexandre Belloni 	const char *parent_name;
99162061d35SAlexandre Belloni 	const char *name = np->name;
99262061d35SAlexandre Belloni 	u32 divisors[4] = {0, 0, 0, 0};
99362061d35SAlexandre Belloni 	struct regmap *regmap;
994b3ff02c5SLiang He 	struct device_node *parent_np;
99562061d35SAlexandre Belloni 
99662061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
99762061d35SAlexandre Belloni 	if (!parent_name)
99862061d35SAlexandre Belloni 		return;
99962061d35SAlexandre Belloni 
100062061d35SAlexandre Belloni 	of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
100162061d35SAlexandre Belloni 	if (!divisors[0])
100262061d35SAlexandre Belloni 		return;
100362061d35SAlexandre Belloni 
100462061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
100562061d35SAlexandre Belloni 
1006b3ff02c5SLiang He 	parent_np = of_get_parent(np);
1007b3ff02c5SLiang He 	regmap = syscon_node_to_regmap(parent_np);
1008b3ff02c5SLiang He 	of_node_put(parent_np);
100962061d35SAlexandre Belloni 	if (IS_ERR(regmap))
101062061d35SAlexandre Belloni 		return;
101162061d35SAlexandre Belloni 	hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
101262061d35SAlexandre Belloni 	if (IS_ERR(hw))
101362061d35SAlexandre Belloni 		return;
101462061d35SAlexandre Belloni 
101562061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
101662061d35SAlexandre Belloni }
101762061d35SAlexandre Belloni CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
101862061d35SAlexandre Belloni 	       of_at91rm9200_clk_usb_setup);
101962061d35SAlexandre Belloni #endif /* CONFIG_HAVE_AT91_USB_CLK */
102062061d35SAlexandre Belloni 
102162061d35SAlexandre Belloni #ifdef CONFIG_HAVE_AT91_UTMI
of_at91sam9x5_clk_utmi_setup(struct device_node * np)102262061d35SAlexandre Belloni static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
102362061d35SAlexandre Belloni {
102462061d35SAlexandre Belloni 	struct clk_hw *hw;
102562061d35SAlexandre Belloni 	const char *parent_name;
102662061d35SAlexandre Belloni 	const char *name = np->name;
102762061d35SAlexandre Belloni 	struct regmap *regmap_pmc, *regmap_sfr;
1028b3ff02c5SLiang He 	struct device_node *parent_np;
102962061d35SAlexandre Belloni 
103062061d35SAlexandre Belloni 	parent_name = of_clk_get_parent_name(np, 0);
103162061d35SAlexandre Belloni 
103262061d35SAlexandre Belloni 	of_property_read_string(np, "clock-output-names", &name);
103362061d35SAlexandre Belloni 
1034b3ff02c5SLiang He 	parent_np = of_get_parent(np);
1035b3ff02c5SLiang He 	regmap_pmc = syscon_node_to_regmap(parent_np);
1036b3ff02c5SLiang He 	of_node_put(parent_np);
103762061d35SAlexandre Belloni 	if (IS_ERR(regmap_pmc))
103862061d35SAlexandre Belloni 		return;
103962061d35SAlexandre Belloni 
104062061d35SAlexandre Belloni 	/*
104162061d35SAlexandre Belloni 	 * If the device supports different mainck rates, this value has to be
104262061d35SAlexandre Belloni 	 * set in the UTMI Clock Trimming register.
104362061d35SAlexandre Belloni 	 * - 9x5: mainck supports several rates but it is indicated that a
104462061d35SAlexandre Belloni 	 *   12 MHz is needed in case of USB.
104562061d35SAlexandre Belloni 	 * - sama5d3 and sama5d2: mainck supports several rates. Configuring
104662061d35SAlexandre Belloni 	 *   the FREQ field of the UTMI Clock Trimming register is mandatory.
104762061d35SAlexandre Belloni 	 * - sama5d4: mainck is at 12 MHz.
104862061d35SAlexandre Belloni 	 *
104962061d35SAlexandre Belloni 	 * We only need to retrieve sama5d3 or sama5d2 sfr regmap.
105062061d35SAlexandre Belloni 	 */
105162061d35SAlexandre Belloni 	regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
105262061d35SAlexandre Belloni 	if (IS_ERR(regmap_sfr)) {
105362061d35SAlexandre Belloni 		regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
105462061d35SAlexandre Belloni 		if (IS_ERR(regmap_sfr))
105562061d35SAlexandre Belloni 			regmap_sfr = NULL;
105662061d35SAlexandre Belloni 	}
105762061d35SAlexandre Belloni 
1058*077782e3SClaudiu Beznea 	hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name, NULL);
105962061d35SAlexandre Belloni 	if (IS_ERR(hw))
106062061d35SAlexandre Belloni 		return;
106162061d35SAlexandre Belloni 
106262061d35SAlexandre Belloni 	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
106362061d35SAlexandre Belloni }
106462061d35SAlexandre Belloni CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
106562061d35SAlexandre Belloni 	       of_at91sam9x5_clk_utmi_setup);
106662061d35SAlexandre Belloni #endif /* CONFIG_HAVE_AT91_UTMI */
1067