clk-main.c (13289B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 4 */ 5 6#include <linux/clk-provider.h> 7#include <linux/clkdev.h> 8#include <linux/clk/at91_pmc.h> 9#include <linux/delay.h> 10#include <linux/mfd/syscon.h> 11#include <linux/regmap.h> 12 13#include "pmc.h" 14 15#define SLOW_CLOCK_FREQ 32768 16#define MAINF_DIV 16 17#define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \ 18 SLOW_CLOCK_FREQ) 19#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ) 20#define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT 21 22#define MOR_KEY_MASK (0xff << 16) 23 24#define clk_main_parent_select(s) (((s) & \ 25 (AT91_PMC_MOSCEN | \ 26 AT91_PMC_OSCBYPASS)) ? 1 : 0) 27 28struct clk_main_osc { 29 struct clk_hw hw; 30 struct regmap *regmap; 31 struct at91_clk_pms pms; 32}; 33 34#define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw) 35 36struct clk_main_rc_osc { 37 struct clk_hw hw; 38 struct regmap *regmap; 39 unsigned long frequency; 40 unsigned long accuracy; 41 struct at91_clk_pms pms; 42}; 43 44#define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw) 45 46struct clk_rm9200_main { 47 struct clk_hw hw; 48 struct regmap *regmap; 49}; 50 51#define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw) 52 53struct clk_sam9x5_main { 54 struct clk_hw hw; 55 struct regmap *regmap; 56 struct at91_clk_pms pms; 57 u8 parent; 58}; 59 60#define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw) 61 62static inline bool clk_main_osc_ready(struct regmap *regmap) 63{ 64 unsigned int status; 65 66 regmap_read(regmap, AT91_PMC_SR, &status); 67 68 return status & AT91_PMC_MOSCS; 69} 70 71static int clk_main_osc_prepare(struct clk_hw *hw) 72{ 73 struct clk_main_osc *osc = to_clk_main_osc(hw); 74 struct regmap *regmap = osc->regmap; 75 u32 tmp; 76 77 regmap_read(regmap, AT91_CKGR_MOR, &tmp); 78 tmp &= ~MOR_KEY_MASK; 79 80 if (tmp & AT91_PMC_OSCBYPASS) 81 return 0; 82 83 if (!(tmp & AT91_PMC_MOSCEN)) { 84 tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY; 85 regmap_write(regmap, AT91_CKGR_MOR, tmp); 86 } 87 88 while (!clk_main_osc_ready(regmap)) 89 cpu_relax(); 90 91 return 0; 92} 93 94static void clk_main_osc_unprepare(struct clk_hw *hw) 95{ 96 struct clk_main_osc *osc = to_clk_main_osc(hw); 97 struct regmap *regmap = osc->regmap; 98 u32 tmp; 99 100 regmap_read(regmap, AT91_CKGR_MOR, &tmp); 101 if (tmp & AT91_PMC_OSCBYPASS) 102 return; 103 104 if (!(tmp & AT91_PMC_MOSCEN)) 105 return; 106 107 tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN); 108 regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); 109} 110 111static int clk_main_osc_is_prepared(struct clk_hw *hw) 112{ 113 struct clk_main_osc *osc = to_clk_main_osc(hw); 114 struct regmap *regmap = osc->regmap; 115 u32 tmp, status; 116 117 regmap_read(regmap, AT91_CKGR_MOR, &tmp); 118 if (tmp & AT91_PMC_OSCBYPASS) 119 return 1; 120 121 regmap_read(regmap, AT91_PMC_SR, &status); 122 123 return (status & AT91_PMC_MOSCS) && clk_main_parent_select(tmp); 124} 125 126static int clk_main_osc_save_context(struct clk_hw *hw) 127{ 128 struct clk_main_osc *osc = to_clk_main_osc(hw); 129 130 osc->pms.status = clk_main_osc_is_prepared(hw); 131 132 return 0; 133} 134 135static void clk_main_osc_restore_context(struct clk_hw *hw) 136{ 137 struct clk_main_osc *osc = to_clk_main_osc(hw); 138 139 if (osc->pms.status) 140 clk_main_osc_prepare(hw); 141} 142 143static const struct clk_ops main_osc_ops = { 144 .prepare = clk_main_osc_prepare, 145 .unprepare = clk_main_osc_unprepare, 146 .is_prepared = clk_main_osc_is_prepared, 147 .save_context = clk_main_osc_save_context, 148 .restore_context = clk_main_osc_restore_context, 149}; 150 151struct clk_hw * __init 152at91_clk_register_main_osc(struct regmap *regmap, 153 const char *name, 154 const char *parent_name, 155 bool bypass) 156{ 157 struct clk_main_osc *osc; 158 struct clk_init_data init; 159 struct clk_hw *hw; 160 int ret; 161 162 if (!name || !parent_name) 163 return ERR_PTR(-EINVAL); 164 165 osc = kzalloc(sizeof(*osc), GFP_KERNEL); 166 if (!osc) 167 return ERR_PTR(-ENOMEM); 168 169 init.name = name; 170 init.ops = &main_osc_ops; 171 init.parent_names = &parent_name; 172 init.num_parents = 1; 173 init.flags = CLK_IGNORE_UNUSED; 174 175 osc->hw.init = &init; 176 osc->regmap = regmap; 177 178 if (bypass) 179 regmap_update_bits(regmap, 180 AT91_CKGR_MOR, MOR_KEY_MASK | 181 AT91_PMC_OSCBYPASS, 182 AT91_PMC_OSCBYPASS | AT91_PMC_KEY); 183 184 hw = &osc->hw; 185 ret = clk_hw_register(NULL, &osc->hw); 186 if (ret) { 187 kfree(osc); 188 hw = ERR_PTR(ret); 189 } 190 191 return hw; 192} 193 194static bool clk_main_rc_osc_ready(struct regmap *regmap) 195{ 196 unsigned int status; 197 198 regmap_read(regmap, AT91_PMC_SR, &status); 199 200 return !!(status & AT91_PMC_MOSCRCS); 201} 202 203static int clk_main_rc_osc_prepare(struct clk_hw *hw) 204{ 205 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 206 struct regmap *regmap = osc->regmap; 207 unsigned int mor; 208 209 regmap_read(regmap, AT91_CKGR_MOR, &mor); 210 211 if (!(mor & AT91_PMC_MOSCRCEN)) 212 regmap_update_bits(regmap, AT91_CKGR_MOR, 213 MOR_KEY_MASK | AT91_PMC_MOSCRCEN, 214 AT91_PMC_MOSCRCEN | AT91_PMC_KEY); 215 216 while (!clk_main_rc_osc_ready(regmap)) 217 cpu_relax(); 218 219 return 0; 220} 221 222static void clk_main_rc_osc_unprepare(struct clk_hw *hw) 223{ 224 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 225 struct regmap *regmap = osc->regmap; 226 unsigned int mor; 227 228 regmap_read(regmap, AT91_CKGR_MOR, &mor); 229 230 if (!(mor & AT91_PMC_MOSCRCEN)) 231 return; 232 233 regmap_update_bits(regmap, AT91_CKGR_MOR, 234 MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY); 235} 236 237static int clk_main_rc_osc_is_prepared(struct clk_hw *hw) 238{ 239 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 240 struct regmap *regmap = osc->regmap; 241 unsigned int mor, status; 242 243 regmap_read(regmap, AT91_CKGR_MOR, &mor); 244 regmap_read(regmap, AT91_PMC_SR, &status); 245 246 return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS); 247} 248 249static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw, 250 unsigned long parent_rate) 251{ 252 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 253 254 return osc->frequency; 255} 256 257static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw, 258 unsigned long parent_acc) 259{ 260 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 261 262 return osc->accuracy; 263} 264 265static int clk_main_rc_osc_save_context(struct clk_hw *hw) 266{ 267 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 268 269 osc->pms.status = clk_main_rc_osc_is_prepared(hw); 270 271 return 0; 272} 273 274static void clk_main_rc_osc_restore_context(struct clk_hw *hw) 275{ 276 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 277 278 if (osc->pms.status) 279 clk_main_rc_osc_prepare(hw); 280} 281 282static const struct clk_ops main_rc_osc_ops = { 283 .prepare = clk_main_rc_osc_prepare, 284 .unprepare = clk_main_rc_osc_unprepare, 285 .is_prepared = clk_main_rc_osc_is_prepared, 286 .recalc_rate = clk_main_rc_osc_recalc_rate, 287 .recalc_accuracy = clk_main_rc_osc_recalc_accuracy, 288 .save_context = clk_main_rc_osc_save_context, 289 .restore_context = clk_main_rc_osc_restore_context, 290}; 291 292struct clk_hw * __init 293at91_clk_register_main_rc_osc(struct regmap *regmap, 294 const char *name, 295 u32 frequency, u32 accuracy) 296{ 297 struct clk_main_rc_osc *osc; 298 struct clk_init_data init; 299 struct clk_hw *hw; 300 int ret; 301 302 if (!name || !frequency) 303 return ERR_PTR(-EINVAL); 304 305 osc = kzalloc(sizeof(*osc), GFP_KERNEL); 306 if (!osc) 307 return ERR_PTR(-ENOMEM); 308 309 init.name = name; 310 init.ops = &main_rc_osc_ops; 311 init.parent_names = NULL; 312 init.num_parents = 0; 313 init.flags = CLK_IGNORE_UNUSED; 314 315 osc->hw.init = &init; 316 osc->regmap = regmap; 317 osc->frequency = frequency; 318 osc->accuracy = accuracy; 319 320 hw = &osc->hw; 321 ret = clk_hw_register(NULL, hw); 322 if (ret) { 323 kfree(osc); 324 hw = ERR_PTR(ret); 325 } 326 327 return hw; 328} 329 330static int clk_main_probe_frequency(struct regmap *regmap) 331{ 332 unsigned long prep_time, timeout; 333 unsigned int mcfr; 334 335 timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); 336 do { 337 prep_time = jiffies; 338 regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); 339 if (mcfr & AT91_PMC_MAINRDY) 340 return 0; 341 if (system_state < SYSTEM_RUNNING) 342 udelay(MAINF_LOOP_MIN_WAIT); 343 else 344 usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); 345 } while (time_before(prep_time, timeout)); 346 347 return -ETIMEDOUT; 348} 349 350static unsigned long clk_main_recalc_rate(struct regmap *regmap, 351 unsigned long parent_rate) 352{ 353 unsigned int mcfr; 354 355 if (parent_rate) 356 return parent_rate; 357 358 pr_warn("Main crystal frequency not set, using approximate value\n"); 359 regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); 360 if (!(mcfr & AT91_PMC_MAINRDY)) 361 return 0; 362 363 return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; 364} 365 366static int clk_rm9200_main_prepare(struct clk_hw *hw) 367{ 368 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); 369 370 return clk_main_probe_frequency(clkmain->regmap); 371} 372 373static int clk_rm9200_main_is_prepared(struct clk_hw *hw) 374{ 375 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); 376 unsigned int status; 377 378 regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status); 379 380 return !!(status & AT91_PMC_MAINRDY); 381} 382 383static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw, 384 unsigned long parent_rate) 385{ 386 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); 387 388 return clk_main_recalc_rate(clkmain->regmap, parent_rate); 389} 390 391static const struct clk_ops rm9200_main_ops = { 392 .prepare = clk_rm9200_main_prepare, 393 .is_prepared = clk_rm9200_main_is_prepared, 394 .recalc_rate = clk_rm9200_main_recalc_rate, 395}; 396 397struct clk_hw * __init 398at91_clk_register_rm9200_main(struct regmap *regmap, 399 const char *name, 400 const char *parent_name) 401{ 402 struct clk_rm9200_main *clkmain; 403 struct clk_init_data init; 404 struct clk_hw *hw; 405 int ret; 406 407 if (!name) 408 return ERR_PTR(-EINVAL); 409 410 if (!parent_name) 411 return ERR_PTR(-EINVAL); 412 413 clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); 414 if (!clkmain) 415 return ERR_PTR(-ENOMEM); 416 417 init.name = name; 418 init.ops = &rm9200_main_ops; 419 init.parent_names = &parent_name; 420 init.num_parents = 1; 421 init.flags = 0; 422 423 clkmain->hw.init = &init; 424 clkmain->regmap = regmap; 425 426 hw = &clkmain->hw; 427 ret = clk_hw_register(NULL, &clkmain->hw); 428 if (ret) { 429 kfree(clkmain); 430 hw = ERR_PTR(ret); 431 } 432 433 return hw; 434} 435 436static inline bool clk_sam9x5_main_ready(struct regmap *regmap) 437{ 438 unsigned int status; 439 440 regmap_read(regmap, AT91_PMC_SR, &status); 441 442 return !!(status & AT91_PMC_MOSCSELS); 443} 444 445static int clk_sam9x5_main_prepare(struct clk_hw *hw) 446{ 447 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 448 struct regmap *regmap = clkmain->regmap; 449 450 while (!clk_sam9x5_main_ready(regmap)) 451 cpu_relax(); 452 453 return clk_main_probe_frequency(regmap); 454} 455 456static int clk_sam9x5_main_is_prepared(struct clk_hw *hw) 457{ 458 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 459 460 return clk_sam9x5_main_ready(clkmain->regmap); 461} 462 463static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw, 464 unsigned long parent_rate) 465{ 466 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 467 468 return clk_main_recalc_rate(clkmain->regmap, parent_rate); 469} 470 471static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) 472{ 473 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 474 struct regmap *regmap = clkmain->regmap; 475 unsigned int tmp; 476 477 if (index > 1) 478 return -EINVAL; 479 480 regmap_read(regmap, AT91_CKGR_MOR, &tmp); 481 482 if (index && !(tmp & AT91_PMC_MOSCSEL)) 483 tmp = AT91_PMC_MOSCSEL; 484 else if (!index && (tmp & AT91_PMC_MOSCSEL)) 485 tmp = 0; 486 else 487 return 0; 488 489 regmap_update_bits(regmap, AT91_CKGR_MOR, 490 AT91_PMC_MOSCSEL | MOR_KEY_MASK, 491 tmp | AT91_PMC_KEY); 492 493 while (!clk_sam9x5_main_ready(regmap)) 494 cpu_relax(); 495 496 return 0; 497} 498 499static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw) 500{ 501 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 502 unsigned int status; 503 504 regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); 505 506 return clk_main_parent_select(status); 507} 508 509static int clk_sam9x5_main_save_context(struct clk_hw *hw) 510{ 511 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 512 513 clkmain->pms.status = clk_main_rc_osc_is_prepared(&clkmain->hw); 514 clkmain->pms.parent = clk_sam9x5_main_get_parent(&clkmain->hw); 515 516 return 0; 517} 518 519static void clk_sam9x5_main_restore_context(struct clk_hw *hw) 520{ 521 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 522 int ret; 523 524 ret = clk_sam9x5_main_set_parent(hw, clkmain->pms.parent); 525 if (ret) 526 return; 527 528 if (clkmain->pms.status) 529 clk_sam9x5_main_prepare(hw); 530} 531 532static const struct clk_ops sam9x5_main_ops = { 533 .prepare = clk_sam9x5_main_prepare, 534 .is_prepared = clk_sam9x5_main_is_prepared, 535 .recalc_rate = clk_sam9x5_main_recalc_rate, 536 .set_parent = clk_sam9x5_main_set_parent, 537 .get_parent = clk_sam9x5_main_get_parent, 538 .save_context = clk_sam9x5_main_save_context, 539 .restore_context = clk_sam9x5_main_restore_context, 540}; 541 542struct clk_hw * __init 543at91_clk_register_sam9x5_main(struct regmap *regmap, 544 const char *name, 545 const char **parent_names, 546 int num_parents) 547{ 548 struct clk_sam9x5_main *clkmain; 549 struct clk_init_data init; 550 unsigned int status; 551 struct clk_hw *hw; 552 int ret; 553 554 if (!name) 555 return ERR_PTR(-EINVAL); 556 557 if (!parent_names || !num_parents) 558 return ERR_PTR(-EINVAL); 559 560 clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); 561 if (!clkmain) 562 return ERR_PTR(-ENOMEM); 563 564 init.name = name; 565 init.ops = &sam9x5_main_ops; 566 init.parent_names = parent_names; 567 init.num_parents = num_parents; 568 init.flags = CLK_SET_PARENT_GATE; 569 570 clkmain->hw.init = &init; 571 clkmain->regmap = regmap; 572 regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); 573 clkmain->parent = clk_main_parent_select(status); 574 575 hw = &clkmain->hw; 576 ret = clk_hw_register(NULL, &clkmain->hw); 577 if (ret) { 578 kfree(clkmain); 579 hw = ERR_PTR(ret); 580 } 581 582 return hw; 583}