brintos

brintos / linux-shallow public Read only

0
0
Text · 27.3 KiB · f5a5f9b Raw
1068 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <linux/clk-provider.h>3#include <linux/clk/at91_pmc.h>4#include <linux/of.h>5#include <linux/mfd/syscon.h>6#include <linux/regmap.h>7#include <linux/slab.h>8 9#include "pmc.h"10 11#define MASTER_SOURCE_MAX	412 13#define PERIPHERAL_AT91RM9200	014#define PERIPHERAL_AT91SAM9X5	115 16#define PERIPHERAL_MAX		6417 18#define PERIPHERAL_ID_MIN	219 20#define PROG_SOURCE_MAX		521#define PROG_ID_MAX		722 23#define SYSTEM_MAX_ID		3124 25#define GCK_INDEX_DT_AUDIO_PLL	526 27static DEFINE_SPINLOCK(mck_lock);28 29#ifdef CONFIG_HAVE_AT91_AUDIO_PLL30static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)31{32	struct clk_hw *hw;33	const char *name = np->name;34	const char *parent_name;35	struct regmap *regmap;36	struct device_node *parent_np;37 38	parent_np = of_get_parent(np);39	regmap = syscon_node_to_regmap(parent_np);40	of_node_put(parent_np);41	if (IS_ERR(regmap))42		return;43 44	parent_name = of_clk_get_parent_name(np, 0);45 46	hw = at91_clk_register_audio_pll_frac(regmap, name, parent_name);47	if (IS_ERR(hw))48		return;49 50	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);51}52CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,53	       "atmel,sama5d2-clk-audio-pll-frac",54	       of_sama5d2_clk_audio_pll_frac_setup);55 56static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)57{58	struct clk_hw *hw;59	const char *name = np->name;60	const char *parent_name;61	struct regmap *regmap;62	struct device_node *parent_np;63 64	parent_np = of_get_parent(np);65	regmap = syscon_node_to_regmap(parent_np);66	of_node_put(parent_np);67	if (IS_ERR(regmap))68		return;69 70	parent_name = of_clk_get_parent_name(np, 0);71 72	hw = at91_clk_register_audio_pll_pad(regmap, name, parent_name);73	if (IS_ERR(hw))74		return;75 76	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);77}78CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,79	       "atmel,sama5d2-clk-audio-pll-pad",80	       of_sama5d2_clk_audio_pll_pad_setup);81 82static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)83{84	struct clk_hw *hw;85	const char *name = np->name;86	const char *parent_name;87	struct regmap *regmap;88	struct device_node *parent_np;89 90	parent_np = of_get_parent(np);91	regmap = syscon_node_to_regmap(parent_np);92	of_node_put(parent_np);93	if (IS_ERR(regmap))94		return;95 96	parent_name = of_clk_get_parent_name(np, 0);97 98	hw = at91_clk_register_audio_pll_pmc(regmap, name, parent_name);99	if (IS_ERR(hw))100		return;101 102	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);103}104CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,105	       "atmel,sama5d2-clk-audio-pll-pmc",106	       of_sama5d2_clk_audio_pll_pmc_setup);107#endif /* CONFIG_HAVE_AT91_AUDIO_PLL */108 109static const struct clk_pcr_layout dt_pcr_layout = {110	.offset = 0x10c,111	.cmd = BIT(12),112	.pid_mask = GENMASK(5, 0),113	.div_mask = GENMASK(17, 16),114	.gckcss_mask = GENMASK(10, 8),115};116 117#ifdef CONFIG_HAVE_AT91_GENERATED_CLK118#define GENERATED_SOURCE_MAX	6119 120#define GCK_ID_I2S0		54121#define GCK_ID_I2S1		55122#define GCK_ID_CLASSD		59123 124static void __init of_sama5d2_clk_generated_setup(struct device_node *np)125{126	int num;127	u32 id;128	const char *name;129	struct clk_hw *hw;130	unsigned int num_parents;131	const char *parent_names[GENERATED_SOURCE_MAX];132	struct device_node *gcknp, *parent_np;133	struct clk_range range = CLK_RANGE(0, 0);134	struct regmap *regmap;135 136	num_parents = of_clk_get_parent_count(np);137	if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)138		return;139 140	of_clk_parent_fill(np, parent_names, num_parents);141 142	num = of_get_child_count(np);143	if (!num || num > PERIPHERAL_MAX)144		return;145 146	parent_np = of_get_parent(np);147	regmap = syscon_node_to_regmap(parent_np);148	of_node_put(parent_np);149	if (IS_ERR(regmap))150		return;151 152	for_each_child_of_node(np, gcknp) {153		int chg_pid = INT_MIN;154 155		if (of_property_read_u32(gcknp, "reg", &id))156			continue;157 158		if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)159			continue;160 161		if (of_property_read_string(np, "clock-output-names", &name))162			name = gcknp->name;163 164		of_at91_get_clk_range(gcknp, "atmel,clk-output-range",165				      &range);166 167		if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&168		    (id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||169		     id == GCK_ID_CLASSD))170			chg_pid = GCK_INDEX_DT_AUDIO_PLL;171 172		hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,173						 &dt_pcr_layout, name,174						 parent_names, NULL, NULL,175						 num_parents, id, &range,176						 chg_pid);177		if (IS_ERR(hw))178			continue;179 180		of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);181	}182}183CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",184	       of_sama5d2_clk_generated_setup);185#endif /* CONFIG_HAVE_AT91_GENERATED_CLK */186 187#ifdef CONFIG_HAVE_AT91_H32MX188static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)189{190	struct clk_hw *hw;191	const char *name = np->name;192	const char *parent_name;193	struct regmap *regmap;194	struct device_node *parent_np;195 196	parent_np = of_get_parent(np);197	regmap = syscon_node_to_regmap(parent_np);198	of_node_put(parent_np);199	if (IS_ERR(regmap))200		return;201 202	parent_name = of_clk_get_parent_name(np, 0);203 204	hw = at91_clk_register_h32mx(regmap, name, parent_name);205	if (IS_ERR(hw))206		return;207 208	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);209}210CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",211	       of_sama5d4_clk_h32mx_setup);212#endif /* CONFIG_HAVE_AT91_H32MX */213 214#ifdef CONFIG_HAVE_AT91_I2S_MUX_CLK215#define	I2S_BUS_NR	2216 217static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)218{219	struct regmap *regmap_sfr;220	u8 bus_id;221	const char *parent_names[2];222	struct device_node *i2s_mux_np;223	struct clk_hw *hw;224	int ret;225 226	regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");227	if (IS_ERR(regmap_sfr))228		return;229 230	for_each_child_of_node(np, i2s_mux_np) {231		if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))232			continue;233 234		if (bus_id > I2S_BUS_NR)235			continue;236 237		ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);238		if (ret != 2)239			continue;240 241		hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,242					       parent_names, 2, bus_id);243		if (IS_ERR(hw))244			continue;245 246		of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);247	}248}249CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",250	       of_sama5d2_clk_i2s_mux_setup);251#endif /* CONFIG_HAVE_AT91_I2S_MUX_CLK */252 253static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)254{255	struct clk_hw *hw;256	const char *name = np->name;257	const char *parent_name;258	struct regmap *regmap;259	bool bypass;260	struct device_node *parent_np;261 262	of_property_read_string(np, "clock-output-names", &name);263	bypass = of_property_read_bool(np, "atmel,osc-bypass");264	parent_name = of_clk_get_parent_name(np, 0);265 266	parent_np = of_get_parent(np);267	regmap = syscon_node_to_regmap(parent_np);268	of_node_put(parent_np);269	if (IS_ERR(regmap))270		return;271 272	hw = at91_clk_register_main_osc(regmap, name, parent_name, NULL, bypass);273	if (IS_ERR(hw))274		return;275 276	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);277}278CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",279	       of_at91rm9200_clk_main_osc_setup);280 281static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)282{283	struct clk_hw *hw;284	u32 frequency = 0;285	u32 accuracy = 0;286	const char *name = np->name;287	struct regmap *regmap;288	struct device_node *parent_np;289 290	of_property_read_string(np, "clock-output-names", &name);291	of_property_read_u32(np, "clock-frequency", &frequency);292	of_property_read_u32(np, "clock-accuracy", &accuracy);293 294	parent_np = of_get_parent(np);295	regmap = syscon_node_to_regmap(parent_np);296	of_node_put(parent_np);297	if (IS_ERR(regmap))298		return;299 300	hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);301	if (IS_ERR(hw))302		return;303 304	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);305}306CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",307	       of_at91sam9x5_clk_main_rc_osc_setup);308 309static void __init of_at91rm9200_clk_main_setup(struct device_node *np)310{311	struct clk_hw *hw;312	const char *parent_name;313	const char *name = np->name;314	struct regmap *regmap;315	struct device_node *parent_np;316 317	parent_name = of_clk_get_parent_name(np, 0);318	of_property_read_string(np, "clock-output-names", &name);319 320	parent_np = of_get_parent(np);321	regmap = syscon_node_to_regmap(parent_np);322	of_node_put(parent_np);323	if (IS_ERR(regmap))324		return;325 326	hw = at91_clk_register_rm9200_main(regmap, name, parent_name, NULL);327	if (IS_ERR(hw))328		return;329 330	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);331}332CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",333	       of_at91rm9200_clk_main_setup);334 335static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)336{337	struct clk_hw *hw;338	const char *parent_names[2];339	unsigned int num_parents;340	const char *name = np->name;341	struct regmap *regmap;342	struct device_node *parent_np;343 344	num_parents = of_clk_get_parent_count(np);345	if (num_parents == 0 || num_parents > 2)346		return;347 348	of_clk_parent_fill(np, parent_names, num_parents);349	parent_np = of_get_parent(np);350	regmap = syscon_node_to_regmap(parent_np);351	of_node_put(parent_np);352	if (IS_ERR(regmap))353		return;354 355	of_property_read_string(np, "clock-output-names", &name);356 357	hw = at91_clk_register_sam9x5_main(regmap, name, parent_names, NULL,358					   num_parents);359	if (IS_ERR(hw))360		return;361 362	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);363}364CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",365	       of_at91sam9x5_clk_main_setup);366 367static struct clk_master_characteristics * __init368of_at91_clk_master_get_characteristics(struct device_node *np)369{370	struct clk_master_characteristics *characteristics;371 372	characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);373	if (!characteristics)374		return NULL;375 376	if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))377		goto out_free_characteristics;378 379	of_property_read_u32_array(np, "atmel,clk-divisors",380				   characteristics->divisors, 4);381 382	characteristics->have_div3_pres =383		of_property_read_bool(np, "atmel,master-clk-have-div3-pres");384 385	return characteristics;386 387out_free_characteristics:388	kfree(characteristics);389	return NULL;390}391 392static void __init393of_at91_clk_master_setup(struct device_node *np,394			 const struct clk_master_layout *layout)395{396	struct clk_hw *hw;397	unsigned int num_parents;398	const char *parent_names[MASTER_SOURCE_MAX];399	const char *name = np->name;400	struct clk_master_characteristics *characteristics;401	struct regmap *regmap;402	struct device_node *parent_np;403 404	num_parents = of_clk_get_parent_count(np);405	if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)406		return;407 408	of_clk_parent_fill(np, parent_names, num_parents);409 410	of_property_read_string(np, "clock-output-names", &name);411 412	characteristics = of_at91_clk_master_get_characteristics(np);413	if (!characteristics)414		return;415 416	parent_np = of_get_parent(np);417	regmap = syscon_node_to_regmap(parent_np);418	of_node_put(parent_np);419	if (IS_ERR(regmap))420		return;421 422	hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents,423					   parent_names, NULL, layout,424					   characteristics, &mck_lock);425	if (IS_ERR(hw))426		goto out_free_characteristics;427 428	hw = at91_clk_register_master_div(regmap, name, "masterck_pres", NULL,429					  layout, characteristics,430					  &mck_lock, CLK_SET_RATE_GATE, 0);431	if (IS_ERR(hw))432		goto out_free_characteristics;433 434	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);435	return;436 437out_free_characteristics:438	kfree(characteristics);439}440 441static void __init of_at91rm9200_clk_master_setup(struct device_node *np)442{443	of_at91_clk_master_setup(np, &at91rm9200_master_layout);444}445CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",446	       of_at91rm9200_clk_master_setup);447 448static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)449{450	of_at91_clk_master_setup(np, &at91sam9x5_master_layout);451}452CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",453	       of_at91sam9x5_clk_master_setup);454 455static void __init456of_at91_clk_periph_setup(struct device_node *np, u8 type)457{458	int num;459	u32 id;460	struct clk_hw *hw;461	const char *parent_name;462	const char *name;463	struct device_node *periphclknp;464	struct regmap *regmap;465	struct device_node *parent_np;466 467	parent_name = of_clk_get_parent_name(np, 0);468	if (!parent_name)469		return;470 471	num = of_get_child_count(np);472	if (!num || num > PERIPHERAL_MAX)473		return;474 475	parent_np = of_get_parent(np);476	regmap = syscon_node_to_regmap(parent_np);477	of_node_put(parent_np);478	if (IS_ERR(regmap))479		return;480 481	for_each_child_of_node(np, periphclknp) {482		if (of_property_read_u32(periphclknp, "reg", &id))483			continue;484 485		if (id >= PERIPHERAL_MAX)486			continue;487 488		if (of_property_read_string(np, "clock-output-names", &name))489			name = periphclknp->name;490 491		if (type == PERIPHERAL_AT91RM9200) {492			hw = at91_clk_register_peripheral(regmap, name,493							  parent_name, NULL, id);494		} else {495			struct clk_range range = CLK_RANGE(0, 0);496			unsigned long flags = 0;497 498			of_at91_get_clk_range(periphclknp,499					      "atmel,clk-output-range",500					      &range);501 502			/*503			 * mpddr_clk feed DDR controller and is enabled by504			 * bootloader thus we need to keep it enabled in case505			 * there is no Linux consumer for it.506			 */507			if (!strcmp(periphclknp->name, "mpddr_clk"))508				flags = CLK_IS_CRITICAL;509 510			hw = at91_clk_register_sam9x5_peripheral(regmap,511								 &pmc_pcr_lock,512								 &dt_pcr_layout,513								 name,514								 parent_name,515								 NULL,516								 id, &range,517								 INT_MIN,518								 flags);519		}520 521		if (IS_ERR(hw))522			continue;523 524		of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);525	}526}527 528static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)529{530	of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);531}532CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",533	       of_at91rm9200_clk_periph_setup);534 535static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)536{537	of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);538}539CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",540	       of_at91sam9x5_clk_periph_setup);541 542static struct clk_pll_characteristics * __init543of_at91_clk_pll_get_characteristics(struct device_node *np)544{545	int i;546	int offset;547	u32 tmp;548	int num_output;549	u32 num_cells;550	struct clk_range input;551	struct clk_range *output;552	u8 *out = NULL;553	u16 *icpll = NULL;554	struct clk_pll_characteristics *characteristics;555 556	if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))557		return NULL;558 559	if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",560				 &num_cells))561		return NULL;562 563	if (num_cells < 2 || num_cells > 4)564		return NULL;565 566	num_output = of_property_count_u32_elems(np, "atmel,pll-clk-output-ranges");567	if (num_output <= 0)568		return NULL;569	num_output /= num_cells;570 571	characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);572	if (!characteristics)573		return NULL;574 575	output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);576	if (!output)577		goto out_free_characteristics;578 579	if (num_cells > 2) {580		out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);581		if (!out)582			goto out_free_output;583	}584 585	if (num_cells > 3) {586		icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);587		if (!icpll)588			goto out_free_output;589	}590 591	for (i = 0; i < num_output; i++) {592		offset = i * num_cells;593		if (of_property_read_u32_index(np,594					       "atmel,pll-clk-output-ranges",595					       offset, &tmp))596			goto out_free_output;597		output[i].min = tmp;598		if (of_property_read_u32_index(np,599					       "atmel,pll-clk-output-ranges",600					       offset + 1, &tmp))601			goto out_free_output;602		output[i].max = tmp;603 604		if (num_cells == 2)605			continue;606 607		if (of_property_read_u32_index(np,608					       "atmel,pll-clk-output-ranges",609					       offset + 2, &tmp))610			goto out_free_output;611		out[i] = tmp;612 613		if (num_cells == 3)614			continue;615 616		if (of_property_read_u32_index(np,617					       "atmel,pll-clk-output-ranges",618					       offset + 3, &tmp))619			goto out_free_output;620		icpll[i] = tmp;621	}622 623	characteristics->input = input;624	characteristics->num_output = num_output;625	characteristics->output = output;626	characteristics->out = out;627	characteristics->icpll = icpll;628	return characteristics;629 630out_free_output:631	kfree(icpll);632	kfree(out);633	kfree(output);634out_free_characteristics:635	kfree(characteristics);636	return NULL;637}638 639static void __init640of_at91_clk_pll_setup(struct device_node *np,641		      const struct clk_pll_layout *layout)642{643	u32 id;644	struct clk_hw *hw;645	struct regmap *regmap;646	const char *parent_name;647	const char *name = np->name;648	struct device_node *parent_np;649	struct clk_pll_characteristics *characteristics;650 651	if (of_property_read_u32(np, "reg", &id))652		return;653 654	parent_name = of_clk_get_parent_name(np, 0);655 656	of_property_read_string(np, "clock-output-names", &name);657 658	parent_np = of_get_parent(np);659	regmap = syscon_node_to_regmap(parent_np);660	of_node_put(parent_np);661	if (IS_ERR(regmap))662		return;663 664	characteristics = of_at91_clk_pll_get_characteristics(np);665	if (!characteristics)666		return;667 668	hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,669				   characteristics);670	if (IS_ERR(hw))671		goto out_free_characteristics;672 673	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);674	return;675 676out_free_characteristics:677	kfree(characteristics);678}679 680static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)681{682	of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);683}684CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",685	       of_at91rm9200_clk_pll_setup);686 687static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)688{689	of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);690}691CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",692	       of_at91sam9g45_clk_pll_setup);693 694static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)695{696	of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);697}698CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",699	       of_at91sam9g20_clk_pllb_setup);700 701static void __init of_sama5d3_clk_pll_setup(struct device_node *np)702{703	of_at91_clk_pll_setup(np, &sama5d3_pll_layout);704}705CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",706	       of_sama5d3_clk_pll_setup);707 708static void __init709of_at91sam9x5_clk_plldiv_setup(struct device_node *np)710{711	struct clk_hw *hw;712	const char *parent_name;713	const char *name = np->name;714	struct regmap *regmap;715	struct device_node *parent_np;716 717	parent_name = of_clk_get_parent_name(np, 0);718 719	of_property_read_string(np, "clock-output-names", &name);720 721	parent_np = of_get_parent(np);722	regmap = syscon_node_to_regmap(parent_np);723	of_node_put(parent_np);724	if (IS_ERR(regmap))725		return;726 727	hw = at91_clk_register_plldiv(regmap, name, parent_name);728	if (IS_ERR(hw))729		return;730 731	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);732}733CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",734	       of_at91sam9x5_clk_plldiv_setup);735 736static void __init737of_at91_clk_prog_setup(struct device_node *np,738		       const struct clk_programmable_layout *layout,739		       u32 *mux_table)740{741	int num;742	u32 id;743	struct clk_hw *hw;744	unsigned int num_parents;745	const char *parent_names[PROG_SOURCE_MAX];746	const char *name;747	struct device_node *progclknp, *parent_np;748	struct regmap *regmap;749 750	num_parents = of_clk_get_parent_count(np);751	if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)752		return;753 754	of_clk_parent_fill(np, parent_names, num_parents);755 756	num = of_get_child_count(np);757	if (!num || num > (PROG_ID_MAX + 1))758		return;759 760	parent_np = of_get_parent(np);761	regmap = syscon_node_to_regmap(parent_np);762	of_node_put(parent_np);763	if (IS_ERR(regmap))764		return;765 766	for_each_child_of_node(np, progclknp) {767		if (of_property_read_u32(progclknp, "reg", &id))768			continue;769 770		if (of_property_read_string(np, "clock-output-names", &name))771			name = progclknp->name;772 773		hw = at91_clk_register_programmable(regmap, name,774						    parent_names, NULL, num_parents,775						    id, layout, mux_table);776		if (IS_ERR(hw))777			continue;778 779		of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);780	}781}782 783static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)784{785	of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout, NULL);786}787CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",788	       of_at91rm9200_clk_prog_setup);789 790static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)791{792	of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout, NULL);793}794CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",795	       of_at91sam9g45_clk_prog_setup);796 797static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)798{799	of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout, NULL);800}801CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",802	       of_at91sam9x5_clk_prog_setup);803 804static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)805{806	struct clk_hw *hw;807	const char *parent_names[2];808	unsigned int num_parents;809	const char *name = np->name;810	struct regmap *regmap;811	struct device_node *parent_np;812 813	num_parents = of_clk_get_parent_count(np);814	if (num_parents != 2)815		return;816 817	of_clk_parent_fill(np, parent_names, num_parents);818	parent_np = of_get_parent(np);819	regmap = syscon_node_to_regmap(parent_np);820	of_node_put(parent_np);821	if (IS_ERR(regmap))822		return;823 824	of_property_read_string(np, "clock-output-names", &name);825 826	hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,827					    num_parents);828	if (IS_ERR(hw))829		return;830 831	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);832}833CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",834	       of_at91sam9260_clk_slow_setup);835 836#ifdef CONFIG_HAVE_AT91_SMD837#define SMD_SOURCE_MAX		2838 839static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)840{841	struct clk_hw *hw;842	unsigned int num_parents;843	const char *parent_names[SMD_SOURCE_MAX];844	const char *name = np->name;845	struct regmap *regmap;846	struct device_node *parent_np;847 848	num_parents = of_clk_get_parent_count(np);849	if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)850		return;851 852	of_clk_parent_fill(np, parent_names, num_parents);853 854	of_property_read_string(np, "clock-output-names", &name);855 856	parent_np = of_get_parent(np);857	regmap = syscon_node_to_regmap(parent_np);858	of_node_put(parent_np);859	if (IS_ERR(regmap))860		return;861 862	hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,863					 num_parents);864	if (IS_ERR(hw))865		return;866 867	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);868}869CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",870	       of_at91sam9x5_clk_smd_setup);871#endif /* CONFIG_HAVE_AT91_SMD */872 873static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)874{875	int num;876	u32 id;877	struct clk_hw *hw;878	const char *name;879	struct device_node *sysclknp, *parent_np;880	const char *parent_name;881	struct regmap *regmap;882 883	num = of_get_child_count(np);884	if (num > (SYSTEM_MAX_ID + 1))885		return;886 887	parent_np = of_get_parent(np);888	regmap = syscon_node_to_regmap(parent_np);889	of_node_put(parent_np);890	if (IS_ERR(regmap))891		return;892 893	for_each_child_of_node(np, sysclknp) {894		unsigned long flags = 0;895 896		if (of_property_read_u32(sysclknp, "reg", &id))897			continue;898 899		if (of_property_read_string(np, "clock-output-names", &name))900			name = sysclknp->name;901 902		parent_name = of_clk_get_parent_name(sysclknp, 0);903 904		/*905		 * ddrck feeds DDR controller and is enabled by bootloader thus906		 * we need to keep it enabled in case there is no Linux consumer907		 * for it.908		 */909		if (!strcmp(sysclknp->name, "ddrck"))910			flags = CLK_IS_CRITICAL;911 912		hw = at91_clk_register_system(regmap, name, parent_name, NULL,913					      id, flags);914		if (IS_ERR(hw))915			continue;916 917		of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);918	}919}920CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",921	       of_at91rm9200_clk_sys_setup);922 923#ifdef CONFIG_HAVE_AT91_USB_CLK924#define USB_SOURCE_MAX		2925 926static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)927{928	struct clk_hw *hw;929	unsigned int num_parents;930	const char *parent_names[USB_SOURCE_MAX];931	const char *name = np->name;932	struct regmap *regmap;933	struct device_node *parent_np;934 935	num_parents = of_clk_get_parent_count(np);936	if (num_parents == 0 || num_parents > USB_SOURCE_MAX)937		return;938 939	of_clk_parent_fill(np, parent_names, num_parents);940 941	of_property_read_string(np, "clock-output-names", &name);942 943	parent_np = of_get_parent(np);944	regmap = syscon_node_to_regmap(parent_np);945	of_node_put(parent_np);946	if (IS_ERR(regmap))947		return;948 949	hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,950					 num_parents);951	if (IS_ERR(hw))952		return;953 954	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);955}956CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",957	       of_at91sam9x5_clk_usb_setup);958 959static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)960{961	struct clk_hw *hw;962	const char *parent_name;963	const char *name = np->name;964	struct regmap *regmap;965	struct device_node *parent_np;966 967	parent_name = of_clk_get_parent_name(np, 0);968	if (!parent_name)969		return;970 971	of_property_read_string(np, "clock-output-names", &name);972 973	parent_np = of_get_parent(np);974	regmap = syscon_node_to_regmap(parent_np);975	of_node_put(parent_np);976	if (IS_ERR(regmap))977		return;978 979	hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);980	if (IS_ERR(hw))981		return;982 983	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);984}985CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",986	       of_at91sam9n12_clk_usb_setup);987 988static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)989{990	struct clk_hw *hw;991	const char *parent_name;992	const char *name = np->name;993	u32 divisors[4] = {0, 0, 0, 0};994	struct regmap *regmap;995	struct device_node *parent_np;996 997	parent_name = of_clk_get_parent_name(np, 0);998	if (!parent_name)999		return;1000 1001	of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);1002	if (!divisors[0])1003		return;1004 1005	of_property_read_string(np, "clock-output-names", &name);1006 1007	parent_np = of_get_parent(np);1008	regmap = syscon_node_to_regmap(parent_np);1009	of_node_put(parent_np);1010	if (IS_ERR(regmap))1011		return;1012	hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);1013	if (IS_ERR(hw))1014		return;1015 1016	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);1017}1018CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",1019	       of_at91rm9200_clk_usb_setup);1020#endif /* CONFIG_HAVE_AT91_USB_CLK */1021 1022#ifdef CONFIG_HAVE_AT91_UTMI1023static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)1024{1025	struct clk_hw *hw;1026	const char *parent_name;1027	const char *name = np->name;1028	struct regmap *regmap_pmc, *regmap_sfr;1029	struct device_node *parent_np;1030 1031	parent_name = of_clk_get_parent_name(np, 0);1032 1033	of_property_read_string(np, "clock-output-names", &name);1034 1035	parent_np = of_get_parent(np);1036	regmap_pmc = syscon_node_to_regmap(parent_np);1037	of_node_put(parent_np);1038	if (IS_ERR(regmap_pmc))1039		return;1040 1041	/*1042	 * If the device supports different mainck rates, this value has to be1043	 * set in the UTMI Clock Trimming register.1044	 * - 9x5: mainck supports several rates but it is indicated that a1045	 *   12 MHz is needed in case of USB.1046	 * - sama5d3 and sama5d2: mainck supports several rates. Configuring1047	 *   the FREQ field of the UTMI Clock Trimming register is mandatory.1048	 * - sama5d4: mainck is at 12 MHz.1049	 *1050	 * We only need to retrieve sama5d3 or sama5d2 sfr regmap.1051	 */1052	regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");1053	if (IS_ERR(regmap_sfr)) {1054		regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");1055		if (IS_ERR(regmap_sfr))1056			regmap_sfr = NULL;1057	}1058 1059	hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name, NULL);1060	if (IS_ERR(hw))1061		return;1062 1063	of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);1064}1065CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",1066	       of_at91sam9x5_clk_utmi_setup);1067#endif /* CONFIG_HAVE_AT91_UTMI */1068