0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk-provider.h>
0009 #include <linux/clkdev.h>
0010 #include <linux/delay.h>
0011 #include <linux/of.h>
0012 #include <linux/of_address.h>
0013 #include <linux/io.h>
0014
0015 #define SLOW_CLOCK_FREQ 32768
0016 #define SLOWCK_SW_CYCLES 5
0017 #define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
0018 SLOW_CLOCK_FREQ)
0019
0020 #define AT91_SCKC_CR 0x00
0021
0022 struct clk_slow_bits {
0023 u32 cr_rcen;
0024 u32 cr_osc32en;
0025 u32 cr_osc32byp;
0026 u32 cr_oscsel;
0027 };
0028
0029 struct clk_slow_osc {
0030 struct clk_hw hw;
0031 void __iomem *sckcr;
0032 const struct clk_slow_bits *bits;
0033 unsigned long startup_usec;
0034 };
0035
0036 #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
0037
0038 struct clk_sama5d4_slow_osc {
0039 struct clk_hw hw;
0040 void __iomem *sckcr;
0041 const struct clk_slow_bits *bits;
0042 unsigned long startup_usec;
0043 bool prepared;
0044 };
0045
0046 #define to_clk_sama5d4_slow_osc(hw) container_of(hw, struct clk_sama5d4_slow_osc, hw)
0047
0048 struct clk_slow_rc_osc {
0049 struct clk_hw hw;
0050 void __iomem *sckcr;
0051 const struct clk_slow_bits *bits;
0052 unsigned long frequency;
0053 unsigned long accuracy;
0054 unsigned long startup_usec;
0055 };
0056
0057 #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
0058
0059 struct clk_sam9x5_slow {
0060 struct clk_hw hw;
0061 void __iomem *sckcr;
0062 const struct clk_slow_bits *bits;
0063 u8 parent;
0064 };
0065
0066 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
0067
0068 static int clk_slow_osc_prepare(struct clk_hw *hw)
0069 {
0070 struct clk_slow_osc *osc = to_clk_slow_osc(hw);
0071 void __iomem *sckcr = osc->sckcr;
0072 u32 tmp = readl(sckcr);
0073
0074 if (tmp & (osc->bits->cr_osc32byp | osc->bits->cr_osc32en))
0075 return 0;
0076
0077 writel(tmp | osc->bits->cr_osc32en, sckcr);
0078
0079 if (system_state < SYSTEM_RUNNING)
0080 udelay(osc->startup_usec);
0081 else
0082 usleep_range(osc->startup_usec, osc->startup_usec + 1);
0083
0084 return 0;
0085 }
0086
0087 static void clk_slow_osc_unprepare(struct clk_hw *hw)
0088 {
0089 struct clk_slow_osc *osc = to_clk_slow_osc(hw);
0090 void __iomem *sckcr = osc->sckcr;
0091 u32 tmp = readl(sckcr);
0092
0093 if (tmp & osc->bits->cr_osc32byp)
0094 return;
0095
0096 writel(tmp & ~osc->bits->cr_osc32en, sckcr);
0097 }
0098
0099 static int clk_slow_osc_is_prepared(struct clk_hw *hw)
0100 {
0101 struct clk_slow_osc *osc = to_clk_slow_osc(hw);
0102 void __iomem *sckcr = osc->sckcr;
0103 u32 tmp = readl(sckcr);
0104
0105 if (tmp & osc->bits->cr_osc32byp)
0106 return 1;
0107
0108 return !!(tmp & osc->bits->cr_osc32en);
0109 }
0110
0111 static const struct clk_ops slow_osc_ops = {
0112 .prepare = clk_slow_osc_prepare,
0113 .unprepare = clk_slow_osc_unprepare,
0114 .is_prepared = clk_slow_osc_is_prepared,
0115 };
0116
0117 static struct clk_hw * __init
0118 at91_clk_register_slow_osc(void __iomem *sckcr,
0119 const char *name,
0120 const char *parent_name,
0121 unsigned long startup,
0122 bool bypass,
0123 const struct clk_slow_bits *bits)
0124 {
0125 struct clk_slow_osc *osc;
0126 struct clk_hw *hw;
0127 struct clk_init_data init;
0128 int ret;
0129
0130 if (!sckcr || !name || !parent_name)
0131 return ERR_PTR(-EINVAL);
0132
0133 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
0134 if (!osc)
0135 return ERR_PTR(-ENOMEM);
0136
0137 init.name = name;
0138 init.ops = &slow_osc_ops;
0139 init.parent_names = &parent_name;
0140 init.num_parents = 1;
0141 init.flags = CLK_IGNORE_UNUSED;
0142
0143 osc->hw.init = &init;
0144 osc->sckcr = sckcr;
0145 osc->startup_usec = startup;
0146 osc->bits = bits;
0147
0148 if (bypass)
0149 writel((readl(sckcr) & ~osc->bits->cr_osc32en) |
0150 osc->bits->cr_osc32byp, sckcr);
0151
0152 hw = &osc->hw;
0153 ret = clk_hw_register(NULL, &osc->hw);
0154 if (ret) {
0155 kfree(osc);
0156 hw = ERR_PTR(ret);
0157 }
0158
0159 return hw;
0160 }
0161
0162 static void at91_clk_unregister_slow_osc(struct clk_hw *hw)
0163 {
0164 struct clk_slow_osc *osc = to_clk_slow_osc(hw);
0165
0166 clk_hw_unregister(hw);
0167 kfree(osc);
0168 }
0169
0170 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
0171 unsigned long parent_rate)
0172 {
0173 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
0174
0175 return osc->frequency;
0176 }
0177
0178 static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw,
0179 unsigned long parent_acc)
0180 {
0181 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
0182
0183 return osc->accuracy;
0184 }
0185
0186 static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
0187 {
0188 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
0189 void __iomem *sckcr = osc->sckcr;
0190
0191 writel(readl(sckcr) | osc->bits->cr_rcen, sckcr);
0192
0193 if (system_state < SYSTEM_RUNNING)
0194 udelay(osc->startup_usec);
0195 else
0196 usleep_range(osc->startup_usec, osc->startup_usec + 1);
0197
0198 return 0;
0199 }
0200
0201 static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
0202 {
0203 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
0204 void __iomem *sckcr = osc->sckcr;
0205
0206 writel(readl(sckcr) & ~osc->bits->cr_rcen, sckcr);
0207 }
0208
0209 static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
0210 {
0211 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
0212
0213 return !!(readl(osc->sckcr) & osc->bits->cr_rcen);
0214 }
0215
0216 static const struct clk_ops slow_rc_osc_ops = {
0217 .prepare = clk_slow_rc_osc_prepare,
0218 .unprepare = clk_slow_rc_osc_unprepare,
0219 .is_prepared = clk_slow_rc_osc_is_prepared,
0220 .recalc_rate = clk_slow_rc_osc_recalc_rate,
0221 .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy,
0222 };
0223
0224 static struct clk_hw * __init
0225 at91_clk_register_slow_rc_osc(void __iomem *sckcr,
0226 const char *name,
0227 unsigned long frequency,
0228 unsigned long accuracy,
0229 unsigned long startup,
0230 const struct clk_slow_bits *bits)
0231 {
0232 struct clk_slow_rc_osc *osc;
0233 struct clk_hw *hw;
0234 struct clk_init_data init;
0235 int ret;
0236
0237 if (!sckcr || !name)
0238 return ERR_PTR(-EINVAL);
0239
0240 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
0241 if (!osc)
0242 return ERR_PTR(-ENOMEM);
0243
0244 init.name = name;
0245 init.ops = &slow_rc_osc_ops;
0246 init.parent_names = NULL;
0247 init.num_parents = 0;
0248 init.flags = CLK_IGNORE_UNUSED;
0249
0250 osc->hw.init = &init;
0251 osc->sckcr = sckcr;
0252 osc->bits = bits;
0253 osc->frequency = frequency;
0254 osc->accuracy = accuracy;
0255 osc->startup_usec = startup;
0256
0257 hw = &osc->hw;
0258 ret = clk_hw_register(NULL, &osc->hw);
0259 if (ret) {
0260 kfree(osc);
0261 hw = ERR_PTR(ret);
0262 }
0263
0264 return hw;
0265 }
0266
0267 static void at91_clk_unregister_slow_rc_osc(struct clk_hw *hw)
0268 {
0269 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
0270
0271 clk_hw_unregister(hw);
0272 kfree(osc);
0273 }
0274
0275 static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
0276 {
0277 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
0278 void __iomem *sckcr = slowck->sckcr;
0279 u32 tmp;
0280
0281 if (index > 1)
0282 return -EINVAL;
0283
0284 tmp = readl(sckcr);
0285
0286 if ((!index && !(tmp & slowck->bits->cr_oscsel)) ||
0287 (index && (tmp & slowck->bits->cr_oscsel)))
0288 return 0;
0289
0290 if (index)
0291 tmp |= slowck->bits->cr_oscsel;
0292 else
0293 tmp &= ~slowck->bits->cr_oscsel;
0294
0295 writel(tmp, sckcr);
0296
0297 if (system_state < SYSTEM_RUNNING)
0298 udelay(SLOWCK_SW_TIME_USEC);
0299 else
0300 usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
0301
0302 return 0;
0303 }
0304
0305 static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
0306 {
0307 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
0308
0309 return !!(readl(slowck->sckcr) & slowck->bits->cr_oscsel);
0310 }
0311
0312 static const struct clk_ops sam9x5_slow_ops = {
0313 .set_parent = clk_sam9x5_slow_set_parent,
0314 .get_parent = clk_sam9x5_slow_get_parent,
0315 };
0316
0317 static struct clk_hw * __init
0318 at91_clk_register_sam9x5_slow(void __iomem *sckcr,
0319 const char *name,
0320 const char **parent_names,
0321 int num_parents,
0322 const struct clk_slow_bits *bits)
0323 {
0324 struct clk_sam9x5_slow *slowck;
0325 struct clk_hw *hw;
0326 struct clk_init_data init;
0327 int ret;
0328
0329 if (!sckcr || !name || !parent_names || !num_parents)
0330 return ERR_PTR(-EINVAL);
0331
0332 slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
0333 if (!slowck)
0334 return ERR_PTR(-ENOMEM);
0335
0336 init.name = name;
0337 init.ops = &sam9x5_slow_ops;
0338 init.parent_names = parent_names;
0339 init.num_parents = num_parents;
0340 init.flags = 0;
0341
0342 slowck->hw.init = &init;
0343 slowck->sckcr = sckcr;
0344 slowck->bits = bits;
0345 slowck->parent = !!(readl(sckcr) & slowck->bits->cr_oscsel);
0346
0347 hw = &slowck->hw;
0348 ret = clk_hw_register(NULL, &slowck->hw);
0349 if (ret) {
0350 kfree(slowck);
0351 hw = ERR_PTR(ret);
0352 }
0353
0354 return hw;
0355 }
0356
0357 static void at91_clk_unregister_sam9x5_slow(struct clk_hw *hw)
0358 {
0359 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
0360
0361 clk_hw_unregister(hw);
0362 kfree(slowck);
0363 }
0364
0365 static void __init at91sam9x5_sckc_register(struct device_node *np,
0366 unsigned int rc_osc_startup_us,
0367 const struct clk_slow_bits *bits)
0368 {
0369 const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
0370 void __iomem *regbase = of_iomap(np, 0);
0371 struct device_node *child = NULL;
0372 const char *xtal_name;
0373 struct clk_hw *slow_rc, *slow_osc, *slowck;
0374 bool bypass;
0375 int ret;
0376
0377 if (!regbase)
0378 return;
0379
0380 slow_rc = at91_clk_register_slow_rc_osc(regbase, parent_names[0],
0381 32768, 50000000,
0382 rc_osc_startup_us, bits);
0383 if (IS_ERR(slow_rc))
0384 return;
0385
0386 xtal_name = of_clk_get_parent_name(np, 0);
0387 if (!xtal_name) {
0388
0389 child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow-osc");
0390 if (!child)
0391 goto unregister_slow_rc;
0392
0393 xtal_name = of_clk_get_parent_name(child, 0);
0394 bypass = of_property_read_bool(child, "atmel,osc-bypass");
0395
0396 child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow");
0397 } else {
0398 bypass = of_property_read_bool(np, "atmel,osc-bypass");
0399 }
0400
0401 if (!xtal_name)
0402 goto unregister_slow_rc;
0403
0404 slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1],
0405 xtal_name, 1200000, bypass, bits);
0406 if (IS_ERR(slow_osc))
0407 goto unregister_slow_rc;
0408
0409 slowck = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names,
0410 2, bits);
0411 if (IS_ERR(slowck))
0412 goto unregister_slow_osc;
0413
0414
0415 if (child)
0416 ret = of_clk_add_hw_provider(child, of_clk_hw_simple_get,
0417 slowck);
0418 else
0419 ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, slowck);
0420
0421 if (WARN_ON(ret))
0422 goto unregister_slowck;
0423
0424 return;
0425
0426 unregister_slowck:
0427 at91_clk_unregister_sam9x5_slow(slowck);
0428 unregister_slow_osc:
0429 at91_clk_unregister_slow_osc(slow_osc);
0430 unregister_slow_rc:
0431 at91_clk_unregister_slow_rc_osc(slow_rc);
0432 }
0433
0434 static const struct clk_slow_bits at91sam9x5_bits = {
0435 .cr_rcen = BIT(0),
0436 .cr_osc32en = BIT(1),
0437 .cr_osc32byp = BIT(2),
0438 .cr_oscsel = BIT(3),
0439 };
0440
0441 static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
0442 {
0443 at91sam9x5_sckc_register(np, 75, &at91sam9x5_bits);
0444 }
0445 CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
0446 of_at91sam9x5_sckc_setup);
0447
0448 static void __init of_sama5d3_sckc_setup(struct device_node *np)
0449 {
0450 at91sam9x5_sckc_register(np, 500, &at91sam9x5_bits);
0451 }
0452 CLK_OF_DECLARE(sama5d3_clk_sckc, "atmel,sama5d3-sckc",
0453 of_sama5d3_sckc_setup);
0454
0455 static const struct clk_slow_bits at91sam9x60_bits = {
0456 .cr_osc32en = BIT(1),
0457 .cr_osc32byp = BIT(2),
0458 .cr_oscsel = BIT(24),
0459 };
0460
0461 static void __init of_sam9x60_sckc_setup(struct device_node *np)
0462 {
0463 void __iomem *regbase = of_iomap(np, 0);
0464 struct clk_hw_onecell_data *clk_data;
0465 struct clk_hw *slow_rc, *slow_osc;
0466 const char *xtal_name;
0467 const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
0468 bool bypass;
0469 int ret;
0470
0471 if (!regbase)
0472 return;
0473
0474 slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0],
0475 NULL, 0, 32768,
0476 93750000);
0477 if (IS_ERR(slow_rc))
0478 return;
0479
0480 xtal_name = of_clk_get_parent_name(np, 0);
0481 if (!xtal_name)
0482 goto unregister_slow_rc;
0483
0484 bypass = of_property_read_bool(np, "atmel,osc-bypass");
0485 slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1],
0486 xtal_name, 5000000, bypass,
0487 &at91sam9x60_bits);
0488 if (IS_ERR(slow_osc))
0489 goto unregister_slow_rc;
0490
0491 clk_data = kzalloc(struct_size(clk_data, hws, 2), GFP_KERNEL);
0492 if (!clk_data)
0493 goto unregister_slow_osc;
0494
0495
0496 clk_data->num = 2;
0497 clk_data->hws[0] = clk_hw_register_fixed_rate(NULL, "md_slck",
0498 parent_names[0],
0499 0, 32768);
0500 if (IS_ERR(clk_data->hws[0]))
0501 goto clk_data_free;
0502
0503 clk_data->hws[1] = at91_clk_register_sam9x5_slow(regbase, "td_slck",
0504 parent_names, 2,
0505 &at91sam9x60_bits);
0506 if (IS_ERR(clk_data->hws[1]))
0507 goto unregister_md_slck;
0508
0509 ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
0510 if (WARN_ON(ret))
0511 goto unregister_td_slck;
0512
0513 return;
0514
0515 unregister_td_slck:
0516 at91_clk_unregister_sam9x5_slow(clk_data->hws[1]);
0517 unregister_md_slck:
0518 clk_hw_unregister(clk_data->hws[0]);
0519 clk_data_free:
0520 kfree(clk_data);
0521 unregister_slow_osc:
0522 at91_clk_unregister_slow_osc(slow_osc);
0523 unregister_slow_rc:
0524 clk_hw_unregister(slow_rc);
0525 }
0526 CLK_OF_DECLARE(sam9x60_clk_sckc, "microchip,sam9x60-sckc",
0527 of_sam9x60_sckc_setup);
0528
0529 static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
0530 {
0531 struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
0532
0533 if (osc->prepared)
0534 return 0;
0535
0536
0537
0538
0539
0540 if ((readl(osc->sckcr) & osc->bits->cr_oscsel)) {
0541 osc->prepared = true;
0542 return 0;
0543 }
0544
0545 if (system_state < SYSTEM_RUNNING)
0546 udelay(osc->startup_usec);
0547 else
0548 usleep_range(osc->startup_usec, osc->startup_usec + 1);
0549 osc->prepared = true;
0550
0551 return 0;
0552 }
0553
0554 static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw *hw)
0555 {
0556 struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
0557
0558 return osc->prepared;
0559 }
0560
0561 static const struct clk_ops sama5d4_slow_osc_ops = {
0562 .prepare = clk_sama5d4_slow_osc_prepare,
0563 .is_prepared = clk_sama5d4_slow_osc_is_prepared,
0564 };
0565
0566 static const struct clk_slow_bits at91sama5d4_bits = {
0567 .cr_oscsel = BIT(3),
0568 };
0569
0570 static void __init of_sama5d4_sckc_setup(struct device_node *np)
0571 {
0572 void __iomem *regbase = of_iomap(np, 0);
0573 struct clk_hw *slow_rc, *slowck;
0574 struct clk_sama5d4_slow_osc *osc;
0575 struct clk_init_data init;
0576 const char *xtal_name;
0577 const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
0578 int ret;
0579
0580 if (!regbase)
0581 return;
0582
0583 slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL,
0584 parent_names[0],
0585 NULL, 0, 32768,
0586 250000000);
0587 if (IS_ERR(slow_rc))
0588 return;
0589
0590 xtal_name = of_clk_get_parent_name(np, 0);
0591
0592 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
0593 if (!osc)
0594 goto unregister_slow_rc;
0595
0596 init.name = parent_names[1];
0597 init.ops = &sama5d4_slow_osc_ops;
0598 init.parent_names = &xtal_name;
0599 init.num_parents = 1;
0600 init.flags = CLK_IGNORE_UNUSED;
0601
0602 osc->hw.init = &init;
0603 osc->sckcr = regbase;
0604 osc->startup_usec = 1200000;
0605 osc->bits = &at91sama5d4_bits;
0606
0607 ret = clk_hw_register(NULL, &osc->hw);
0608 if (ret)
0609 goto free_slow_osc_data;
0610
0611 slowck = at91_clk_register_sam9x5_slow(regbase, "slowck",
0612 parent_names, 2,
0613 &at91sama5d4_bits);
0614 if (IS_ERR(slowck))
0615 goto unregister_slow_osc;
0616
0617 ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, slowck);
0618 if (WARN_ON(ret))
0619 goto unregister_slowck;
0620
0621 return;
0622
0623 unregister_slowck:
0624 at91_clk_unregister_sam9x5_slow(slowck);
0625 unregister_slow_osc:
0626 clk_hw_unregister(&osc->hw);
0627 free_slow_osc_data:
0628 kfree(osc);
0629 unregister_slow_rc:
0630 clk_hw_unregister(slow_rc);
0631 }
0632 CLK_OF_DECLARE(sama5d4_clk_sckc, "atmel,sama5d4-sckc",
0633 of_sama5d4_sckc_setup);