0001
0002 #include <linux/clk-provider.h>
0003 #include <linux/clk/at91_pmc.h>
0004 #include <linux/of.h>
0005 #include <linux/mfd/syscon.h>
0006 #include <linux/regmap.h>
0007 #include <linux/slab.h>
0008
0009 #include "pmc.h"
0010
0011 #define MASTER_SOURCE_MAX 4
0012
0013 #define PERIPHERAL_AT91RM9200 0
0014 #define PERIPHERAL_AT91SAM9X5 1
0015
0016 #define PERIPHERAL_MAX 64
0017
0018 #define PERIPHERAL_ID_MIN 2
0019
0020 #define PROG_SOURCE_MAX 5
0021 #define PROG_ID_MAX 7
0022
0023 #define SYSTEM_MAX_ID 31
0024
0025 #define GCK_INDEX_DT_AUDIO_PLL 5
0026
0027 static DEFINE_SPINLOCK(mck_lock);
0028
0029 #ifdef CONFIG_HAVE_AT91_AUDIO_PLL
0030 static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
0031 {
0032 struct clk_hw *hw;
0033 const char *name = np->name;
0034 const char *parent_name;
0035 struct regmap *regmap;
0036
0037 regmap = syscon_node_to_regmap(of_get_parent(np));
0038 if (IS_ERR(regmap))
0039 return;
0040
0041 parent_name = of_clk_get_parent_name(np, 0);
0042
0043 hw = at91_clk_register_audio_pll_frac(regmap, name, parent_name);
0044 if (IS_ERR(hw))
0045 return;
0046
0047 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0048 }
0049 CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
0050 "atmel,sama5d2-clk-audio-pll-frac",
0051 of_sama5d2_clk_audio_pll_frac_setup);
0052
0053 static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
0054 {
0055 struct clk_hw *hw;
0056 const char *name = np->name;
0057 const char *parent_name;
0058 struct regmap *regmap;
0059
0060 regmap = syscon_node_to_regmap(of_get_parent(np));
0061 if (IS_ERR(regmap))
0062 return;
0063
0064 parent_name = of_clk_get_parent_name(np, 0);
0065
0066 hw = at91_clk_register_audio_pll_pad(regmap, name, parent_name);
0067 if (IS_ERR(hw))
0068 return;
0069
0070 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0071 }
0072 CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
0073 "atmel,sama5d2-clk-audio-pll-pad",
0074 of_sama5d2_clk_audio_pll_pad_setup);
0075
0076 static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
0077 {
0078 struct clk_hw *hw;
0079 const char *name = np->name;
0080 const char *parent_name;
0081 struct regmap *regmap;
0082
0083 regmap = syscon_node_to_regmap(of_get_parent(np));
0084 if (IS_ERR(regmap))
0085 return;
0086
0087 parent_name = of_clk_get_parent_name(np, 0);
0088
0089 hw = at91_clk_register_audio_pll_pmc(regmap, name, parent_name);
0090 if (IS_ERR(hw))
0091 return;
0092
0093 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0094 }
0095 CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
0096 "atmel,sama5d2-clk-audio-pll-pmc",
0097 of_sama5d2_clk_audio_pll_pmc_setup);
0098 #endif
0099
0100 static const struct clk_pcr_layout dt_pcr_layout = {
0101 .offset = 0x10c,
0102 .cmd = BIT(12),
0103 .pid_mask = GENMASK(5, 0),
0104 .div_mask = GENMASK(17, 16),
0105 .gckcss_mask = GENMASK(10, 8),
0106 };
0107
0108 #ifdef CONFIG_HAVE_AT91_GENERATED_CLK
0109 #define GENERATED_SOURCE_MAX 6
0110
0111 #define GCK_ID_I2S0 54
0112 #define GCK_ID_I2S1 55
0113 #define GCK_ID_CLASSD 59
0114
0115 static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
0116 {
0117 int num;
0118 u32 id;
0119 const char *name;
0120 struct clk_hw *hw;
0121 unsigned int num_parents;
0122 const char *parent_names[GENERATED_SOURCE_MAX];
0123 struct device_node *gcknp;
0124 struct clk_range range = CLK_RANGE(0, 0);
0125 struct regmap *regmap;
0126
0127 num_parents = of_clk_get_parent_count(np);
0128 if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
0129 return;
0130
0131 of_clk_parent_fill(np, parent_names, num_parents);
0132
0133 num = of_get_child_count(np);
0134 if (!num || num > PERIPHERAL_MAX)
0135 return;
0136
0137 regmap = syscon_node_to_regmap(of_get_parent(np));
0138 if (IS_ERR(regmap))
0139 return;
0140
0141 for_each_child_of_node(np, gcknp) {
0142 int chg_pid = INT_MIN;
0143
0144 if (of_property_read_u32(gcknp, "reg", &id))
0145 continue;
0146
0147 if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
0148 continue;
0149
0150 if (of_property_read_string(np, "clock-output-names", &name))
0151 name = gcknp->name;
0152
0153 of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
0154 &range);
0155
0156 if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&
0157 (id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||
0158 id == GCK_ID_CLASSD))
0159 chg_pid = GCK_INDEX_DT_AUDIO_PLL;
0160
0161 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
0162 &dt_pcr_layout, name,
0163 parent_names, NULL,
0164 num_parents, id, &range,
0165 chg_pid);
0166 if (IS_ERR(hw))
0167 continue;
0168
0169 of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
0170 }
0171 }
0172 CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
0173 of_sama5d2_clk_generated_setup);
0174 #endif
0175
0176 #ifdef CONFIG_HAVE_AT91_H32MX
0177 static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
0178 {
0179 struct clk_hw *hw;
0180 const char *name = np->name;
0181 const char *parent_name;
0182 struct regmap *regmap;
0183
0184 regmap = syscon_node_to_regmap(of_get_parent(np));
0185 if (IS_ERR(regmap))
0186 return;
0187
0188 parent_name = of_clk_get_parent_name(np, 0);
0189
0190 hw = at91_clk_register_h32mx(regmap, name, parent_name);
0191 if (IS_ERR(hw))
0192 return;
0193
0194 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0195 }
0196 CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
0197 of_sama5d4_clk_h32mx_setup);
0198 #endif
0199
0200 #ifdef CONFIG_HAVE_AT91_I2S_MUX_CLK
0201 #define I2S_BUS_NR 2
0202
0203 static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
0204 {
0205 struct regmap *regmap_sfr;
0206 u8 bus_id;
0207 const char *parent_names[2];
0208 struct device_node *i2s_mux_np;
0209 struct clk_hw *hw;
0210 int ret;
0211
0212 regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
0213 if (IS_ERR(regmap_sfr))
0214 return;
0215
0216 for_each_child_of_node(np, i2s_mux_np) {
0217 if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
0218 continue;
0219
0220 if (bus_id > I2S_BUS_NR)
0221 continue;
0222
0223 ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
0224 if (ret != 2)
0225 continue;
0226
0227 hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
0228 parent_names, 2, bus_id);
0229 if (IS_ERR(hw))
0230 continue;
0231
0232 of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
0233 }
0234 }
0235 CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
0236 of_sama5d2_clk_i2s_mux_setup);
0237 #endif
0238
0239 static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
0240 {
0241 struct clk_hw *hw;
0242 const char *name = np->name;
0243 const char *parent_name;
0244 struct regmap *regmap;
0245 bool bypass;
0246
0247 of_property_read_string(np, "clock-output-names", &name);
0248 bypass = of_property_read_bool(np, "atmel,osc-bypass");
0249 parent_name = of_clk_get_parent_name(np, 0);
0250
0251 regmap = syscon_node_to_regmap(of_get_parent(np));
0252 if (IS_ERR(regmap))
0253 return;
0254
0255 hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
0256 if (IS_ERR(hw))
0257 return;
0258
0259 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0260 }
0261 CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
0262 of_at91rm9200_clk_main_osc_setup);
0263
0264 static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
0265 {
0266 struct clk_hw *hw;
0267 u32 frequency = 0;
0268 u32 accuracy = 0;
0269 const char *name = np->name;
0270 struct regmap *regmap;
0271
0272 of_property_read_string(np, "clock-output-names", &name);
0273 of_property_read_u32(np, "clock-frequency", &frequency);
0274 of_property_read_u32(np, "clock-accuracy", &accuracy);
0275
0276 regmap = syscon_node_to_regmap(of_get_parent(np));
0277 if (IS_ERR(regmap))
0278 return;
0279
0280 hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
0281 if (IS_ERR(hw))
0282 return;
0283
0284 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0285 }
0286 CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
0287 of_at91sam9x5_clk_main_rc_osc_setup);
0288
0289 static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
0290 {
0291 struct clk_hw *hw;
0292 const char *parent_name;
0293 const char *name = np->name;
0294 struct regmap *regmap;
0295
0296 parent_name = of_clk_get_parent_name(np, 0);
0297 of_property_read_string(np, "clock-output-names", &name);
0298
0299 regmap = syscon_node_to_regmap(of_get_parent(np));
0300 if (IS_ERR(regmap))
0301 return;
0302
0303 hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
0304 if (IS_ERR(hw))
0305 return;
0306
0307 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0308 }
0309 CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
0310 of_at91rm9200_clk_main_setup);
0311
0312 static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
0313 {
0314 struct clk_hw *hw;
0315 const char *parent_names[2];
0316 unsigned int num_parents;
0317 const char *name = np->name;
0318 struct regmap *regmap;
0319
0320 num_parents = of_clk_get_parent_count(np);
0321 if (num_parents == 0 || num_parents > 2)
0322 return;
0323
0324 of_clk_parent_fill(np, parent_names, num_parents);
0325 regmap = syscon_node_to_regmap(of_get_parent(np));
0326 if (IS_ERR(regmap))
0327 return;
0328
0329 of_property_read_string(np, "clock-output-names", &name);
0330
0331 hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
0332 num_parents);
0333 if (IS_ERR(hw))
0334 return;
0335
0336 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0337 }
0338 CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
0339 of_at91sam9x5_clk_main_setup);
0340
0341 static struct clk_master_characteristics * __init
0342 of_at91_clk_master_get_characteristics(struct device_node *np)
0343 {
0344 struct clk_master_characteristics *characteristics;
0345
0346 characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
0347 if (!characteristics)
0348 return NULL;
0349
0350 if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
0351 goto out_free_characteristics;
0352
0353 of_property_read_u32_array(np, "atmel,clk-divisors",
0354 characteristics->divisors, 4);
0355
0356 characteristics->have_div3_pres =
0357 of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
0358
0359 return characteristics;
0360
0361 out_free_characteristics:
0362 kfree(characteristics);
0363 return NULL;
0364 }
0365
0366 static void __init
0367 of_at91_clk_master_setup(struct device_node *np,
0368 const struct clk_master_layout *layout)
0369 {
0370 struct clk_hw *hw;
0371 unsigned int num_parents;
0372 const char *parent_names[MASTER_SOURCE_MAX];
0373 const char *name = np->name;
0374 struct clk_master_characteristics *characteristics;
0375 struct regmap *regmap;
0376
0377 num_parents = of_clk_get_parent_count(np);
0378 if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
0379 return;
0380
0381 of_clk_parent_fill(np, parent_names, num_parents);
0382
0383 of_property_read_string(np, "clock-output-names", &name);
0384
0385 characteristics = of_at91_clk_master_get_characteristics(np);
0386 if (!characteristics)
0387 return;
0388
0389 regmap = syscon_node_to_regmap(of_get_parent(np));
0390 if (IS_ERR(regmap))
0391 return;
0392
0393 hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents,
0394 parent_names, layout,
0395 characteristics, &mck_lock);
0396 if (IS_ERR(hw))
0397 goto out_free_characteristics;
0398
0399 hw = at91_clk_register_master_div(regmap, name, "masterck_pres",
0400 layout, characteristics,
0401 &mck_lock, CLK_SET_RATE_GATE, 0);
0402 if (IS_ERR(hw))
0403 goto out_free_characteristics;
0404
0405 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0406 return;
0407
0408 out_free_characteristics:
0409 kfree(characteristics);
0410 }
0411
0412 static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
0413 {
0414 of_at91_clk_master_setup(np, &at91rm9200_master_layout);
0415 }
0416 CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
0417 of_at91rm9200_clk_master_setup);
0418
0419 static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
0420 {
0421 of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
0422 }
0423 CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
0424 of_at91sam9x5_clk_master_setup);
0425
0426 static void __init
0427 of_at91_clk_periph_setup(struct device_node *np, u8 type)
0428 {
0429 int num;
0430 u32 id;
0431 struct clk_hw *hw;
0432 const char *parent_name;
0433 const char *name;
0434 struct device_node *periphclknp;
0435 struct regmap *regmap;
0436
0437 parent_name = of_clk_get_parent_name(np, 0);
0438 if (!parent_name)
0439 return;
0440
0441 num = of_get_child_count(np);
0442 if (!num || num > PERIPHERAL_MAX)
0443 return;
0444
0445 regmap = syscon_node_to_regmap(of_get_parent(np));
0446 if (IS_ERR(regmap))
0447 return;
0448
0449 for_each_child_of_node(np, periphclknp) {
0450 if (of_property_read_u32(periphclknp, "reg", &id))
0451 continue;
0452
0453 if (id >= PERIPHERAL_MAX)
0454 continue;
0455
0456 if (of_property_read_string(np, "clock-output-names", &name))
0457 name = periphclknp->name;
0458
0459 if (type == PERIPHERAL_AT91RM9200) {
0460 hw = at91_clk_register_peripheral(regmap, name,
0461 parent_name, id);
0462 } else {
0463 struct clk_range range = CLK_RANGE(0, 0);
0464
0465 of_at91_get_clk_range(periphclknp,
0466 "atmel,clk-output-range",
0467 &range);
0468
0469 hw = at91_clk_register_sam9x5_peripheral(regmap,
0470 &pmc_pcr_lock,
0471 &dt_pcr_layout,
0472 name,
0473 parent_name,
0474 id, &range,
0475 INT_MIN);
0476 }
0477
0478 if (IS_ERR(hw))
0479 continue;
0480
0481 of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
0482 }
0483 }
0484
0485 static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
0486 {
0487 of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
0488 }
0489 CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
0490 of_at91rm9200_clk_periph_setup);
0491
0492 static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
0493 {
0494 of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
0495 }
0496 CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
0497 of_at91sam9x5_clk_periph_setup);
0498
0499 static struct clk_pll_characteristics * __init
0500 of_at91_clk_pll_get_characteristics(struct device_node *np)
0501 {
0502 int i;
0503 int offset;
0504 u32 tmp;
0505 int num_output;
0506 u32 num_cells;
0507 struct clk_range input;
0508 struct clk_range *output;
0509 u8 *out = NULL;
0510 u16 *icpll = NULL;
0511 struct clk_pll_characteristics *characteristics;
0512
0513 if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
0514 return NULL;
0515
0516 if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
0517 &num_cells))
0518 return NULL;
0519
0520 if (num_cells < 2 || num_cells > 4)
0521 return NULL;
0522
0523 if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
0524 return NULL;
0525 num_output = tmp / (sizeof(u32) * num_cells);
0526
0527 characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
0528 if (!characteristics)
0529 return NULL;
0530
0531 output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
0532 if (!output)
0533 goto out_free_characteristics;
0534
0535 if (num_cells > 2) {
0536 out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
0537 if (!out)
0538 goto out_free_output;
0539 }
0540
0541 if (num_cells > 3) {
0542 icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
0543 if (!icpll)
0544 goto out_free_output;
0545 }
0546
0547 for (i = 0; i < num_output; i++) {
0548 offset = i * num_cells;
0549 if (of_property_read_u32_index(np,
0550 "atmel,pll-clk-output-ranges",
0551 offset, &tmp))
0552 goto out_free_output;
0553 output[i].min = tmp;
0554 if (of_property_read_u32_index(np,
0555 "atmel,pll-clk-output-ranges",
0556 offset + 1, &tmp))
0557 goto out_free_output;
0558 output[i].max = tmp;
0559
0560 if (num_cells == 2)
0561 continue;
0562
0563 if (of_property_read_u32_index(np,
0564 "atmel,pll-clk-output-ranges",
0565 offset + 2, &tmp))
0566 goto out_free_output;
0567 out[i] = tmp;
0568
0569 if (num_cells == 3)
0570 continue;
0571
0572 if (of_property_read_u32_index(np,
0573 "atmel,pll-clk-output-ranges",
0574 offset + 3, &tmp))
0575 goto out_free_output;
0576 icpll[i] = tmp;
0577 }
0578
0579 characteristics->input = input;
0580 characteristics->num_output = num_output;
0581 characteristics->output = output;
0582 characteristics->out = out;
0583 characteristics->icpll = icpll;
0584 return characteristics;
0585
0586 out_free_output:
0587 kfree(icpll);
0588 kfree(out);
0589 kfree(output);
0590 out_free_characteristics:
0591 kfree(characteristics);
0592 return NULL;
0593 }
0594
0595 static void __init
0596 of_at91_clk_pll_setup(struct device_node *np,
0597 const struct clk_pll_layout *layout)
0598 {
0599 u32 id;
0600 struct clk_hw *hw;
0601 struct regmap *regmap;
0602 const char *parent_name;
0603 const char *name = np->name;
0604 struct clk_pll_characteristics *characteristics;
0605
0606 if (of_property_read_u32(np, "reg", &id))
0607 return;
0608
0609 parent_name = of_clk_get_parent_name(np, 0);
0610
0611 of_property_read_string(np, "clock-output-names", &name);
0612
0613 regmap = syscon_node_to_regmap(of_get_parent(np));
0614 if (IS_ERR(regmap))
0615 return;
0616
0617 characteristics = of_at91_clk_pll_get_characteristics(np);
0618 if (!characteristics)
0619 return;
0620
0621 hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
0622 characteristics);
0623 if (IS_ERR(hw))
0624 goto out_free_characteristics;
0625
0626 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0627 return;
0628
0629 out_free_characteristics:
0630 kfree(characteristics);
0631 }
0632
0633 static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
0634 {
0635 of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
0636 }
0637 CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
0638 of_at91rm9200_clk_pll_setup);
0639
0640 static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
0641 {
0642 of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
0643 }
0644 CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
0645 of_at91sam9g45_clk_pll_setup);
0646
0647 static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
0648 {
0649 of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
0650 }
0651 CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
0652 of_at91sam9g20_clk_pllb_setup);
0653
0654 static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
0655 {
0656 of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
0657 }
0658 CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
0659 of_sama5d3_clk_pll_setup);
0660
0661 static void __init
0662 of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
0663 {
0664 struct clk_hw *hw;
0665 const char *parent_name;
0666 const char *name = np->name;
0667 struct regmap *regmap;
0668
0669 parent_name = of_clk_get_parent_name(np, 0);
0670
0671 of_property_read_string(np, "clock-output-names", &name);
0672
0673 regmap = syscon_node_to_regmap(of_get_parent(np));
0674 if (IS_ERR(regmap))
0675 return;
0676
0677 hw = at91_clk_register_plldiv(regmap, name, parent_name);
0678 if (IS_ERR(hw))
0679 return;
0680
0681 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0682 }
0683 CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
0684 of_at91sam9x5_clk_plldiv_setup);
0685
0686 static void __init
0687 of_at91_clk_prog_setup(struct device_node *np,
0688 const struct clk_programmable_layout *layout,
0689 u32 *mux_table)
0690 {
0691 int num;
0692 u32 id;
0693 struct clk_hw *hw;
0694 unsigned int num_parents;
0695 const char *parent_names[PROG_SOURCE_MAX];
0696 const char *name;
0697 struct device_node *progclknp;
0698 struct regmap *regmap;
0699
0700 num_parents = of_clk_get_parent_count(np);
0701 if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
0702 return;
0703
0704 of_clk_parent_fill(np, parent_names, num_parents);
0705
0706 num = of_get_child_count(np);
0707 if (!num || num > (PROG_ID_MAX + 1))
0708 return;
0709
0710 regmap = syscon_node_to_regmap(of_get_parent(np));
0711 if (IS_ERR(regmap))
0712 return;
0713
0714 for_each_child_of_node(np, progclknp) {
0715 if (of_property_read_u32(progclknp, "reg", &id))
0716 continue;
0717
0718 if (of_property_read_string(np, "clock-output-names", &name))
0719 name = progclknp->name;
0720
0721 hw = at91_clk_register_programmable(regmap, name,
0722 parent_names, num_parents,
0723 id, layout, mux_table);
0724 if (IS_ERR(hw))
0725 continue;
0726
0727 of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
0728 }
0729 }
0730
0731 static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
0732 {
0733 of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout, NULL);
0734 }
0735 CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
0736 of_at91rm9200_clk_prog_setup);
0737
0738 static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
0739 {
0740 of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout, NULL);
0741 }
0742 CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
0743 of_at91sam9g45_clk_prog_setup);
0744
0745 static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
0746 {
0747 of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout, NULL);
0748 }
0749 CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
0750 of_at91sam9x5_clk_prog_setup);
0751
0752 static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
0753 {
0754 struct clk_hw *hw;
0755 const char *parent_names[2];
0756 unsigned int num_parents;
0757 const char *name = np->name;
0758 struct regmap *regmap;
0759
0760 num_parents = of_clk_get_parent_count(np);
0761 if (num_parents != 2)
0762 return;
0763
0764 of_clk_parent_fill(np, parent_names, num_parents);
0765 regmap = syscon_node_to_regmap(of_get_parent(np));
0766 if (IS_ERR(regmap))
0767 return;
0768
0769 of_property_read_string(np, "clock-output-names", &name);
0770
0771 hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
0772 num_parents);
0773 if (IS_ERR(hw))
0774 return;
0775
0776 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0777 }
0778 CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
0779 of_at91sam9260_clk_slow_setup);
0780
0781 #ifdef CONFIG_HAVE_AT91_SMD
0782 #define SMD_SOURCE_MAX 2
0783
0784 static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
0785 {
0786 struct clk_hw *hw;
0787 unsigned int num_parents;
0788 const char *parent_names[SMD_SOURCE_MAX];
0789 const char *name = np->name;
0790 struct regmap *regmap;
0791
0792 num_parents = of_clk_get_parent_count(np);
0793 if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
0794 return;
0795
0796 of_clk_parent_fill(np, parent_names, num_parents);
0797
0798 of_property_read_string(np, "clock-output-names", &name);
0799
0800 regmap = syscon_node_to_regmap(of_get_parent(np));
0801 if (IS_ERR(regmap))
0802 return;
0803
0804 hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
0805 num_parents);
0806 if (IS_ERR(hw))
0807 return;
0808
0809 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0810 }
0811 CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
0812 of_at91sam9x5_clk_smd_setup);
0813 #endif
0814
0815 static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
0816 {
0817 int num;
0818 u32 id;
0819 struct clk_hw *hw;
0820 const char *name;
0821 struct device_node *sysclknp;
0822 const char *parent_name;
0823 struct regmap *regmap;
0824
0825 num = of_get_child_count(np);
0826 if (num > (SYSTEM_MAX_ID + 1))
0827 return;
0828
0829 regmap = syscon_node_to_regmap(of_get_parent(np));
0830 if (IS_ERR(regmap))
0831 return;
0832
0833 for_each_child_of_node(np, sysclknp) {
0834 if (of_property_read_u32(sysclknp, "reg", &id))
0835 continue;
0836
0837 if (of_property_read_string(np, "clock-output-names", &name))
0838 name = sysclknp->name;
0839
0840 parent_name = of_clk_get_parent_name(sysclknp, 0);
0841
0842 hw = at91_clk_register_system(regmap, name, parent_name, id);
0843 if (IS_ERR(hw))
0844 continue;
0845
0846 of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
0847 }
0848 }
0849 CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
0850 of_at91rm9200_clk_sys_setup);
0851
0852 #ifdef CONFIG_HAVE_AT91_USB_CLK
0853 #define USB_SOURCE_MAX 2
0854
0855 static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
0856 {
0857 struct clk_hw *hw;
0858 unsigned int num_parents;
0859 const char *parent_names[USB_SOURCE_MAX];
0860 const char *name = np->name;
0861 struct regmap *regmap;
0862
0863 num_parents = of_clk_get_parent_count(np);
0864 if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
0865 return;
0866
0867 of_clk_parent_fill(np, parent_names, num_parents);
0868
0869 of_property_read_string(np, "clock-output-names", &name);
0870
0871 regmap = syscon_node_to_regmap(of_get_parent(np));
0872 if (IS_ERR(regmap))
0873 return;
0874
0875 hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
0876 num_parents);
0877 if (IS_ERR(hw))
0878 return;
0879
0880 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0881 }
0882 CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
0883 of_at91sam9x5_clk_usb_setup);
0884
0885 static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
0886 {
0887 struct clk_hw *hw;
0888 const char *parent_name;
0889 const char *name = np->name;
0890 struct regmap *regmap;
0891
0892 parent_name = of_clk_get_parent_name(np, 0);
0893 if (!parent_name)
0894 return;
0895
0896 of_property_read_string(np, "clock-output-names", &name);
0897
0898 regmap = syscon_node_to_regmap(of_get_parent(np));
0899 if (IS_ERR(regmap))
0900 return;
0901
0902 hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
0903 if (IS_ERR(hw))
0904 return;
0905
0906 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0907 }
0908 CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
0909 of_at91sam9n12_clk_usb_setup);
0910
0911 static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
0912 {
0913 struct clk_hw *hw;
0914 const char *parent_name;
0915 const char *name = np->name;
0916 u32 divisors[4] = {0, 0, 0, 0};
0917 struct regmap *regmap;
0918
0919 parent_name = of_clk_get_parent_name(np, 0);
0920 if (!parent_name)
0921 return;
0922
0923 of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
0924 if (!divisors[0])
0925 return;
0926
0927 of_property_read_string(np, "clock-output-names", &name);
0928
0929 regmap = syscon_node_to_regmap(of_get_parent(np));
0930 if (IS_ERR(regmap))
0931 return;
0932 hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
0933 if (IS_ERR(hw))
0934 return;
0935
0936 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0937 }
0938 CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
0939 of_at91rm9200_clk_usb_setup);
0940 #endif
0941
0942 #ifdef CONFIG_HAVE_AT91_UTMI
0943 static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
0944 {
0945 struct clk_hw *hw;
0946 const char *parent_name;
0947 const char *name = np->name;
0948 struct regmap *regmap_pmc, *regmap_sfr;
0949
0950 parent_name = of_clk_get_parent_name(np, 0);
0951
0952 of_property_read_string(np, "clock-output-names", &name);
0953
0954 regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
0955 if (IS_ERR(regmap_pmc))
0956 return;
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969 regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
0970 if (IS_ERR(regmap_sfr)) {
0971 regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
0972 if (IS_ERR(regmap_sfr))
0973 regmap_sfr = NULL;
0974 }
0975
0976 hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
0977 if (IS_ERR(hw))
0978 return;
0979
0980 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0981 }
0982 CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
0983 of_at91sam9x5_clk_utmi_setup);
0984 #endif