cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dt-compat.c (25666B)


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