Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 596 lines 14 kB view raw
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 struct clk_parent_data *parent_data, 156 bool bypass) 157{ 158 struct clk_main_osc *osc; 159 struct clk_init_data init = {}; 160 struct clk_hw *hw; 161 int ret; 162 163 if (!name || !(parent_name || parent_data)) 164 return ERR_PTR(-EINVAL); 165 166 osc = kzalloc_obj(*osc); 167 if (!osc) 168 return ERR_PTR(-ENOMEM); 169 170 init.name = name; 171 init.ops = &main_osc_ops; 172 if (parent_data) 173 init.parent_data = (const struct clk_parent_data *)parent_data; 174 else 175 init.parent_names = &parent_name; 176 init.num_parents = 1; 177 init.flags = CLK_IGNORE_UNUSED; 178 179 osc->hw.init = &init; 180 osc->regmap = regmap; 181 182 if (bypass) 183 regmap_update_bits(regmap, 184 AT91_CKGR_MOR, MOR_KEY_MASK | 185 AT91_PMC_OSCBYPASS, 186 AT91_PMC_OSCBYPASS | AT91_PMC_KEY); 187 188 hw = &osc->hw; 189 ret = clk_hw_register(NULL, &osc->hw); 190 if (ret) { 191 kfree(osc); 192 hw = ERR_PTR(ret); 193 } 194 195 return hw; 196} 197 198static bool clk_main_rc_osc_ready(struct regmap *regmap) 199{ 200 unsigned int status; 201 202 regmap_read(regmap, AT91_PMC_SR, &status); 203 204 return !!(status & AT91_PMC_MOSCRCS); 205} 206 207static int clk_main_rc_osc_prepare(struct clk_hw *hw) 208{ 209 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 210 struct regmap *regmap = osc->regmap; 211 unsigned int mor; 212 213 regmap_read(regmap, AT91_CKGR_MOR, &mor); 214 215 if (!(mor & AT91_PMC_MOSCRCEN)) 216 regmap_update_bits(regmap, AT91_CKGR_MOR, 217 MOR_KEY_MASK | AT91_PMC_MOSCRCEN, 218 AT91_PMC_MOSCRCEN | AT91_PMC_KEY); 219 220 while (!clk_main_rc_osc_ready(regmap)) 221 cpu_relax(); 222 223 return 0; 224} 225 226static void clk_main_rc_osc_unprepare(struct clk_hw *hw) 227{ 228 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 229 struct regmap *regmap = osc->regmap; 230 unsigned int mor; 231 232 regmap_read(regmap, AT91_CKGR_MOR, &mor); 233 234 if (!(mor & AT91_PMC_MOSCRCEN)) 235 return; 236 237 regmap_update_bits(regmap, AT91_CKGR_MOR, 238 MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY); 239} 240 241static int clk_main_rc_osc_is_prepared(struct clk_hw *hw) 242{ 243 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 244 struct regmap *regmap = osc->regmap; 245 unsigned int mor, status; 246 247 regmap_read(regmap, AT91_CKGR_MOR, &mor); 248 regmap_read(regmap, AT91_PMC_SR, &status); 249 250 return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS); 251} 252 253static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw, 254 unsigned long parent_rate) 255{ 256 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 257 258 return osc->frequency; 259} 260 261static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw, 262 unsigned long parent_acc) 263{ 264 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 265 266 return osc->accuracy; 267} 268 269static int clk_main_rc_osc_save_context(struct clk_hw *hw) 270{ 271 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 272 273 osc->pms.status = clk_main_rc_osc_is_prepared(hw); 274 275 return 0; 276} 277 278static void clk_main_rc_osc_restore_context(struct clk_hw *hw) 279{ 280 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); 281 282 if (osc->pms.status) 283 clk_main_rc_osc_prepare(hw); 284} 285 286static const struct clk_ops main_rc_osc_ops = { 287 .prepare = clk_main_rc_osc_prepare, 288 .unprepare = clk_main_rc_osc_unprepare, 289 .is_prepared = clk_main_rc_osc_is_prepared, 290 .recalc_rate = clk_main_rc_osc_recalc_rate, 291 .recalc_accuracy = clk_main_rc_osc_recalc_accuracy, 292 .save_context = clk_main_rc_osc_save_context, 293 .restore_context = clk_main_rc_osc_restore_context, 294}; 295 296struct clk_hw * __init 297at91_clk_register_main_rc_osc(struct regmap *regmap, 298 const char *name, 299 u32 frequency, u32 accuracy) 300{ 301 struct clk_main_rc_osc *osc; 302 struct clk_init_data init; 303 struct clk_hw *hw; 304 int ret; 305 306 if (!name || !frequency) 307 return ERR_PTR(-EINVAL); 308 309 osc = kzalloc_obj(*osc); 310 if (!osc) 311 return ERR_PTR(-ENOMEM); 312 313 init.name = name; 314 init.ops = &main_rc_osc_ops; 315 init.parent_names = NULL; 316 init.num_parents = 0; 317 init.flags = CLK_IGNORE_UNUSED; 318 319 osc->hw.init = &init; 320 osc->regmap = regmap; 321 osc->frequency = frequency; 322 osc->accuracy = accuracy; 323 324 hw = &osc->hw; 325 ret = clk_hw_register(NULL, hw); 326 if (ret) { 327 kfree(osc); 328 hw = ERR_PTR(ret); 329 } 330 331 return hw; 332} 333 334static int clk_main_probe_frequency(struct regmap *regmap) 335{ 336 unsigned long prep_time, timeout; 337 unsigned int mcfr; 338 339 timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); 340 do { 341 prep_time = jiffies; 342 regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); 343 if (mcfr & AT91_PMC_MAINRDY) 344 return 0; 345 if (system_state < SYSTEM_RUNNING) 346 udelay(MAINF_LOOP_MIN_WAIT); 347 else 348 usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); 349 } while (time_before(prep_time, timeout)); 350 351 return -ETIMEDOUT; 352} 353 354static unsigned long clk_main_recalc_rate(struct regmap *regmap, 355 unsigned long parent_rate) 356{ 357 unsigned int mcfr; 358 359 if (parent_rate) 360 return parent_rate; 361 362 pr_warn("Main crystal frequency not set, using approximate value\n"); 363 regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); 364 if (!(mcfr & AT91_PMC_MAINRDY)) 365 return 0; 366 367 return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; 368} 369 370static int clk_rm9200_main_prepare(struct clk_hw *hw) 371{ 372 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); 373 374 return clk_main_probe_frequency(clkmain->regmap); 375} 376 377static int clk_rm9200_main_is_prepared(struct clk_hw *hw) 378{ 379 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); 380 unsigned int status; 381 382 regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status); 383 384 return !!(status & AT91_PMC_MAINRDY); 385} 386 387static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw, 388 unsigned long parent_rate) 389{ 390 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); 391 392 return clk_main_recalc_rate(clkmain->regmap, parent_rate); 393} 394 395static const struct clk_ops rm9200_main_ops = { 396 .prepare = clk_rm9200_main_prepare, 397 .is_prepared = clk_rm9200_main_is_prepared, 398 .recalc_rate = clk_rm9200_main_recalc_rate, 399}; 400 401struct clk_hw * __init 402at91_clk_register_rm9200_main(struct regmap *regmap, 403 const char *name, 404 const char *parent_name, 405 struct clk_hw *parent_hw) 406{ 407 struct clk_rm9200_main *clkmain; 408 struct clk_init_data init = {}; 409 struct clk_hw *hw; 410 int ret; 411 412 if (!name) 413 return ERR_PTR(-EINVAL); 414 415 if (!(parent_name || parent_hw)) 416 return ERR_PTR(-EINVAL); 417 418 clkmain = kzalloc_obj(*clkmain); 419 if (!clkmain) 420 return ERR_PTR(-ENOMEM); 421 422 init.name = name; 423 init.ops = &rm9200_main_ops; 424 if (parent_hw) 425 init.parent_hws = (const struct clk_hw **)&parent_hw; 426 else 427 init.parent_names = &parent_name; 428 init.num_parents = 1; 429 init.flags = 0; 430 431 clkmain->hw.init = &init; 432 clkmain->regmap = regmap; 433 434 hw = &clkmain->hw; 435 ret = clk_hw_register(NULL, &clkmain->hw); 436 if (ret) { 437 kfree(clkmain); 438 hw = ERR_PTR(ret); 439 } 440 441 return hw; 442} 443 444static inline bool clk_sam9x5_main_ready(struct regmap *regmap) 445{ 446 unsigned int status; 447 448 regmap_read(regmap, AT91_PMC_SR, &status); 449 450 return !!(status & AT91_PMC_MOSCSELS); 451} 452 453static int clk_sam9x5_main_prepare(struct clk_hw *hw) 454{ 455 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 456 struct regmap *regmap = clkmain->regmap; 457 458 while (!clk_sam9x5_main_ready(regmap)) 459 cpu_relax(); 460 461 return clk_main_probe_frequency(regmap); 462} 463 464static int clk_sam9x5_main_is_prepared(struct clk_hw *hw) 465{ 466 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 467 468 return clk_sam9x5_main_ready(clkmain->regmap); 469} 470 471static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw, 472 unsigned long parent_rate) 473{ 474 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 475 476 return clk_main_recalc_rate(clkmain->regmap, parent_rate); 477} 478 479static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) 480{ 481 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 482 struct regmap *regmap = clkmain->regmap; 483 unsigned int tmp; 484 485 if (index > 1) 486 return -EINVAL; 487 488 regmap_read(regmap, AT91_CKGR_MOR, &tmp); 489 490 if (index && !(tmp & AT91_PMC_MOSCSEL)) 491 tmp = AT91_PMC_MOSCSEL; 492 else if (!index && (tmp & AT91_PMC_MOSCSEL)) 493 tmp = 0; 494 else 495 return 0; 496 497 regmap_update_bits(regmap, AT91_CKGR_MOR, 498 AT91_PMC_MOSCSEL | MOR_KEY_MASK, 499 tmp | AT91_PMC_KEY); 500 501 while (!clk_sam9x5_main_ready(regmap)) 502 cpu_relax(); 503 504 return 0; 505} 506 507static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw) 508{ 509 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 510 unsigned int status; 511 512 regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); 513 514 return clk_main_parent_select(status); 515} 516 517static int clk_sam9x5_main_save_context(struct clk_hw *hw) 518{ 519 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 520 521 clkmain->pms.status = clk_main_rc_osc_is_prepared(&clkmain->hw); 522 clkmain->pms.parent = clk_sam9x5_main_get_parent(&clkmain->hw); 523 524 return 0; 525} 526 527static void clk_sam9x5_main_restore_context(struct clk_hw *hw) 528{ 529 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); 530 int ret; 531 532 ret = clk_sam9x5_main_set_parent(hw, clkmain->pms.parent); 533 if (ret) 534 return; 535 536 if (clkmain->pms.status) 537 clk_sam9x5_main_prepare(hw); 538} 539 540static const struct clk_ops sam9x5_main_ops = { 541 .prepare = clk_sam9x5_main_prepare, 542 .is_prepared = clk_sam9x5_main_is_prepared, 543 .recalc_rate = clk_sam9x5_main_recalc_rate, 544 .determine_rate = clk_hw_determine_rate_no_reparent, 545 .set_parent = clk_sam9x5_main_set_parent, 546 .get_parent = clk_sam9x5_main_get_parent, 547 .save_context = clk_sam9x5_main_save_context, 548 .restore_context = clk_sam9x5_main_restore_context, 549}; 550 551struct clk_hw * __init 552at91_clk_register_sam9x5_main(struct regmap *regmap, 553 const char *name, 554 const char **parent_names, 555 struct clk_hw **parent_hws, 556 int num_parents) 557{ 558 struct clk_sam9x5_main *clkmain; 559 struct clk_init_data init = {}; 560 unsigned int status; 561 struct clk_hw *hw; 562 int ret; 563 564 if (!name) 565 return ERR_PTR(-EINVAL); 566 567 if (!(parent_hws || parent_names) || !num_parents) 568 return ERR_PTR(-EINVAL); 569 570 clkmain = kzalloc_obj(*clkmain); 571 if (!clkmain) 572 return ERR_PTR(-ENOMEM); 573 574 init.name = name; 575 init.ops = &sam9x5_main_ops; 576 if (parent_hws) 577 init.parent_hws = (const struct clk_hw **)parent_hws; 578 else 579 init.parent_names = parent_names; 580 init.num_parents = num_parents; 581 init.flags = CLK_SET_PARENT_GATE; 582 583 clkmain->hw.init = &init; 584 clkmain->regmap = regmap; 585 regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); 586 clkmain->parent = clk_main_parent_select(status); 587 588 hw = &clkmain->hw; 589 ret = clk_hw_register(NULL, &clkmain->hw); 590 if (ret) { 591 kfree(clkmain); 592 hw = ERR_PTR(ret); 593 } 594 595 return hw; 596}