1 /* 2 * arch/sh/kernel/cpu/sh4a/clock-sh7722.c 3 * 4 * SH7343, SH7722, SH7723 & SH7366 support for the clock framework 5 * 6 * Copyright (c) 2006-2007 Nomad Global Solutions Inc 7 * Based on code for sh7343 by Paul Mundt 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file "COPYING" in the main directory of this archive 11 * for more details. 12 */ 13 #include <linux/init.h> 14 #include <linux/kernel.h> 15 #include <linux/io.h> 16 #include <linux/errno.h> 17 #include <linux/stringify.h> 18 #include <asm/clock.h> 19 #include <asm/freq.h> 20 21 #define N (-1) 22 #define NM (-2) 23 #define ROUND_NEAREST 0 24 #define ROUND_DOWN -1 25 #define ROUND_UP +1 26 27 static int adjust_algos[][3] = { 28 {}, /* NO_CHANGE */ 29 { NM, N, 1 }, /* N:1, N:1 */ 30 { 3, 2, 2 }, /* 3:2:2 */ 31 { 5, 2, 2 }, /* 5:2:2 */ 32 { N, 1, 1 }, /* N:1:1 */ 33 34 { N, 1 }, /* N:1 */ 35 36 { N, 1 }, /* N:1 */ 37 { 3, 2 }, 38 { 4, 3 }, 39 { 5, 4 }, 40 41 { N, 1 } 42 }; 43 44 static unsigned long adjust_pair_of_clocks(unsigned long r1, unsigned long r2, 45 int m1, int m2, int round_flag) 46 { 47 unsigned long rem, div; 48 int the_one = 0; 49 50 pr_debug( "Actual values: r1 = %ld\n", r1); 51 pr_debug( "...............r2 = %ld\n", r2); 52 53 if (m1 == m2) { 54 r2 = r1; 55 pr_debug( "setting equal rates: r2 now %ld\n", r2); 56 } else if ((m2 == N && m1 == 1) || 57 (m2 == NM && m1 == N)) { /* N:1 or NM:N */ 58 pr_debug( "Setting rates as 1:N (N:N*M)\n"); 59 rem = r2 % r1; 60 pr_debug( "...remainder = %ld\n", rem); 61 if (rem) { 62 div = r2 / r1; 63 pr_debug( "...div = %ld\n", div); 64 switch (round_flag) { 65 case ROUND_NEAREST: 66 the_one = rem >= r1/2 ? 1 : 0; break; 67 case ROUND_UP: 68 the_one = 1; break; 69 case ROUND_DOWN: 70 the_one = 0; break; 71 } 72 73 r2 = r1 * (div + the_one); 74 pr_debug( "...setting r2 to %ld\n", r2); 75 } 76 } else if ((m2 == 1 && m1 == N) || 77 (m2 == N && m1 == NM)) { /* 1:N or N:NM */ 78 pr_debug( "Setting rates as N:1 (N*M:N)\n"); 79 rem = r1 % r2; 80 pr_debug( "...remainder = %ld\n", rem); 81 if (rem) { 82 div = r1 / r2; 83 pr_debug( "...div = %ld\n", div); 84 switch (round_flag) { 85 case ROUND_NEAREST: 86 the_one = rem > r2/2 ? 1 : 0; break; 87 case ROUND_UP: 88 the_one = 0; break; 89 case ROUND_DOWN: 90 the_one = 1; break; 91 } 92 93 r2 = r1 / (div + the_one); 94 pr_debug( "...setting r2 to %ld\n", r2); 95 } 96 } else { /* value:value */ 97 pr_debug( "Setting rates as %d:%d\n", m1, m2); 98 div = r1 / m1; 99 r2 = div * m2; 100 pr_debug( "...div = %ld\n", div); 101 pr_debug( "...setting r2 to %ld\n", r2); 102 } 103 104 return r2; 105 } 106 107 static void adjust_clocks(int originate, int *l, unsigned long v[], 108 int n_in_line) 109 { 110 int x; 111 112 pr_debug( "Go down from %d...\n", originate); 113 /* go up recalculation clocks */ 114 for (x = originate; x>0; x -- ) 115 v[x-1] = adjust_pair_of_clocks(v[x], v[x-1], 116 l[x], l[x-1], 117 ROUND_UP); 118 119 pr_debug( "Go up from %d...\n", originate); 120 /* go down recalculation clocks */ 121 for (x = originate; x<n_in_line - 1; x ++ ) 122 v[x+1] = adjust_pair_of_clocks(v[x], v[x+1], 123 l[x], l[x+1], 124 ROUND_UP); 125 } 126 127 128 /* 129 * SH7722 uses a common set of multipliers and divisors, so this 130 * is quite simple.. 131 */ 132 133 /* 134 * Instead of having two separate multipliers/divisors set, like this: 135 * 136 * static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 137 * static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; 138 * 139 * I created the divisors2 array, which is used to calculate rate like 140 * rate = parent * 2 / divisors2[ divisor ]; 141 */ 142 static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 }; 143 144 static void master_clk_recalc(struct clk *clk) 145 { 146 unsigned frqcr = ctrl_inl(FRQCR); 147 148 clk->rate = CONFIG_SH_PCLK_FREQ * (((frqcr >> 24) & 0x1f) + 1); 149 } 150 151 static void master_clk_init(struct clk *clk) 152 { 153 clk->parent = NULL; 154 clk->flags |= CLK_RATE_PROPAGATES; 155 clk->rate = CONFIG_SH_PCLK_FREQ; 156 master_clk_recalc(clk); 157 } 158 159 160 static void module_clk_recalc(struct clk *clk) 161 { 162 unsigned long frqcr = ctrl_inl(FRQCR); 163 164 clk->rate = clk->parent->rate / (((frqcr >> 24) & 0x1f) + 1); 165 } 166 167 static int master_clk_setrate(struct clk *clk, unsigned long rate, int id) 168 { 169 int div = rate / clk->rate; 170 int master_divs[] = { 2, 3, 4, 6, 8, 16 }; 171 int index; 172 unsigned long frqcr; 173 174 for (index = 1; index < ARRAY_SIZE(master_divs); index++) 175 if (div >= master_divs[index - 1] && div < master_divs[index]) 176 break; 177 178 if (index >= ARRAY_SIZE(master_divs)) 179 index = ARRAY_SIZE(master_divs); 180 div = master_divs[index - 1]; 181 182 frqcr = ctrl_inl(FRQCR); 183 frqcr &= ~(0xF << 24); 184 frqcr |= ( (div-1) << 24); 185 ctrl_outl(frqcr, FRQCR); 186 187 return 0; 188 } 189 190 static struct clk_ops sh7722_master_clk_ops = { 191 .init = master_clk_init, 192 .recalc = master_clk_recalc, 193 .set_rate = master_clk_setrate, 194 }; 195 196 static struct clk_ops sh7722_module_clk_ops = { 197 .recalc = module_clk_recalc, 198 }; 199 200 struct frqcr_context { 201 unsigned mask; 202 unsigned shift; 203 }; 204 205 struct frqcr_context sh7722_get_clk_context(const char *name) 206 { 207 struct frqcr_context ctx = { 0, }; 208 209 if (!strcmp(name, "peripheral_clk")) { 210 ctx.shift = 0; 211 ctx.mask = 0xF; 212 } else if (!strcmp(name, "sdram_clk")) { 213 ctx.shift = 4; 214 ctx.mask = 0xF; 215 } else if (!strcmp(name, "bus_clk")) { 216 ctx.shift = 8; 217 ctx.mask = 0xF; 218 } else if (!strcmp(name, "sh_clk")) { 219 ctx.shift = 12; 220 ctx.mask = 0xF; 221 } else if (!strcmp(name, "umem_clk")) { 222 ctx.shift = 16; 223 ctx.mask = 0xF; 224 } else if (!strcmp(name, "cpu_clk")) { 225 ctx.shift = 20; 226 ctx.mask = 7; 227 } 228 return ctx; 229 } 230 231 /** 232 * sh7722_find_divisors - find divisor for setting rate 233 * 234 * All sh7722 clocks use the same set of multipliers/divisors. This function 235 * chooses correct divisor to set the rate of clock with parent clock that 236 * generates frequency of 'parent_rate' 237 * 238 * @parent_rate: rate of parent clock 239 * @rate: requested rate to be set 240 */ 241 static int sh7722_find_divisors(unsigned long parent_rate, unsigned rate) 242 { 243 unsigned div2 = parent_rate * 2 / rate; 244 int index; 245 246 if (rate > parent_rate) 247 return -EINVAL; 248 249 for (index = 1; index < ARRAY_SIZE(divisors2); index++) { 250 if (div2 > divisors2[index] && div2 <= divisors2[index]) 251 break; 252 } 253 if (index >= ARRAY_SIZE(divisors2)) 254 index = ARRAY_SIZE(divisors2) - 1; 255 return divisors2[index]; 256 } 257 258 static void sh7722_frqcr_recalc(struct clk *clk) 259 { 260 struct frqcr_context ctx = sh7722_get_clk_context(clk->name); 261 unsigned long frqcr = ctrl_inl(FRQCR); 262 int index; 263 264 index = (frqcr >> ctx.shift) & ctx.mask; 265 clk->rate = clk->parent->rate * 2 / divisors2[index]; 266 } 267 268 static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate, 269 int algo_id) 270 { 271 struct frqcr_context ctx = sh7722_get_clk_context(clk->name); 272 unsigned long parent_rate = clk->parent->rate; 273 int div; 274 unsigned long frqcr; 275 int err = 0; 276 277 /* pretty invalid */ 278 if (parent_rate < rate) 279 return -EINVAL; 280 281 /* look for multiplier/divisor pair */ 282 div = sh7722_find_divisors(parent_rate, rate); 283 if (div<0) 284 return div; 285 286 /* calculate new value of clock rate */ 287 clk->rate = parent_rate * 2 / div; 288 frqcr = ctrl_inl(FRQCR); 289 290 /* FIXME: adjust as algo_id specifies */ 291 if (algo_id != NO_CHANGE) { 292 int originator; 293 char *algo_group_1[] = { "cpu_clk", "umem_clk", "sh_clk" }; 294 char *algo_group_2[] = { "sh_clk", "bus_clk" }; 295 char *algo_group_3[] = { "sh_clk", "sdram_clk" }; 296 char *algo_group_4[] = { "bus_clk", "peripheral_clk" }; 297 char *algo_group_5[] = { "cpu_clk", "peripheral_clk" }; 298 char **algo_current = NULL; 299 /* 3 is the maximum number of clocks in relation */ 300 struct clk *ck[3]; 301 unsigned long values[3]; /* the same comment as above */ 302 int part_length = -1; 303 int i; 304 305 /* 306 * all the steps below only required if adjustion was 307 * requested 308 */ 309 if (algo_id == IUS_N1_N1 || 310 algo_id == IUS_322 || 311 algo_id == IUS_522 || 312 algo_id == IUS_N11) { 313 algo_current = algo_group_1; 314 part_length = 3; 315 } 316 if (algo_id == SB_N1) { 317 algo_current = algo_group_2; 318 part_length = 2; 319 } 320 if (algo_id == SB3_N1 || 321 algo_id == SB3_32 || 322 algo_id == SB3_43 || 323 algo_id == SB3_54) { 324 algo_current = algo_group_3; 325 part_length = 2; 326 } 327 if (algo_id == BP_N1) { 328 algo_current = algo_group_4; 329 part_length = 2; 330 } 331 if (algo_id == IP_N1) { 332 algo_current = algo_group_5; 333 part_length = 2; 334 } 335 if (!algo_current) 336 goto incorrect_algo_id; 337 338 originator = -1; 339 for (i = 0; i < part_length; i ++ ) { 340 if (originator >= 0 && !strcmp(clk->name, 341 algo_current[i])) 342 originator = i; 343 ck[i] = clk_get(NULL, algo_current[i]); 344 values[i] = clk_get_rate(ck[i]); 345 } 346 347 if (originator >= 0) 348 adjust_clocks(originator, adjust_algos[algo_id], 349 values, part_length); 350 351 for (i = 0; i < part_length; i ++ ) { 352 struct frqcr_context part_ctx; 353 int part_div; 354 355 if (likely(!err)) { 356 part_div = sh7722_find_divisors(parent_rate, 357 rate); 358 if (part_div > 0) { 359 part_ctx = sh7722_get_clk_context( 360 ck[i]->name); 361 frqcr &= ~(part_ctx.mask << 362 part_ctx.shift); 363 frqcr |= part_div << part_ctx.shift; 364 } else 365 err = part_div; 366 } 367 368 ck[i]->ops->recalc(ck[i]); 369 clk_put(ck[i]); 370 } 371 } 372 373 /* was there any error during recalculation ? If so, bail out.. */ 374 if (unlikely(err!=0)) 375 goto out_err; 376 377 /* clear FRQCR bits */ 378 frqcr &= ~(ctx.mask << ctx.shift); 379 frqcr |= div << ctx.shift; 380 381 /* ...and perform actual change */ 382 ctrl_outl(frqcr, FRQCR); 383 return 0; 384 385 incorrect_algo_id: 386 return -EINVAL; 387 out_err: 388 return err; 389 } 390 391 static long sh7722_frqcr_round_rate(struct clk *clk, unsigned long rate) 392 { 393 unsigned long parent_rate = clk->parent->rate; 394 int div; 395 396 /* look for multiplier/divisor pair */ 397 div = sh7722_find_divisors(parent_rate, rate); 398 if (div < 0) 399 return clk->rate; 400 401 /* calculate new value of clock rate */ 402 return parent_rate * 2 / div; 403 } 404 405 static struct clk_ops sh7722_frqcr_clk_ops = { 406 .recalc = sh7722_frqcr_recalc, 407 .set_rate = sh7722_frqcr_set_rate, 408 .round_rate = sh7722_frqcr_round_rate, 409 }; 410 411 /* 412 * clock ops methods for SIU A/B and IrDA clock 413 * 414 */ 415 416 #ifndef CONFIG_CPU_SUBTYPE_SH7343 417 418 static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id) 419 { 420 unsigned long r; 421 int div; 422 423 r = ctrl_inl(clk->arch_flags); 424 div = sh7722_find_divisors(clk->parent->rate, rate); 425 if (div < 0) 426 return div; 427 r = (r & ~0xF) | div; 428 ctrl_outl(r, clk->arch_flags); 429 return 0; 430 } 431 432 static void sh7722_siu_recalc(struct clk *clk) 433 { 434 unsigned long r; 435 436 r = ctrl_inl(clk->arch_flags); 437 clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF]; 438 } 439 440 static int sh7722_siu_start_stop(struct clk *clk, int enable) 441 { 442 unsigned long r; 443 444 r = ctrl_inl(clk->arch_flags); 445 if (enable) 446 ctrl_outl(r & ~(1 << 8), clk->arch_flags); 447 else 448 ctrl_outl(r | (1 << 8), clk->arch_flags); 449 return 0; 450 } 451 452 static void sh7722_siu_enable(struct clk *clk) 453 { 454 sh7722_siu_start_stop(clk, 1); 455 } 456 457 static void sh7722_siu_disable(struct clk *clk) 458 { 459 sh7722_siu_start_stop(clk, 0); 460 } 461 462 static struct clk_ops sh7722_siu_clk_ops = { 463 .recalc = sh7722_siu_recalc, 464 .set_rate = sh7722_siu_set_rate, 465 .enable = sh7722_siu_enable, 466 .disable = sh7722_siu_disable, 467 }; 468 469 #endif /* CONFIG_CPU_SUBTYPE_SH7343 */ 470 471 static void sh7722_video_enable(struct clk *clk) 472 { 473 unsigned long r; 474 475 r = ctrl_inl(VCLKCR); 476 ctrl_outl( r & ~(1<<8), VCLKCR); 477 } 478 479 static void sh7722_video_disable(struct clk *clk) 480 { 481 unsigned long r; 482 483 r = ctrl_inl(VCLKCR); 484 ctrl_outl( r | (1<<8), VCLKCR); 485 } 486 487 static int sh7722_video_set_rate(struct clk *clk, unsigned long rate, 488 int algo_id) 489 { 490 unsigned long r; 491 492 r = ctrl_inl(VCLKCR); 493 r &= ~0x3F; 494 r |= ((clk->parent->rate / rate - 1) & 0x3F); 495 ctrl_outl(r, VCLKCR); 496 return 0; 497 } 498 499 static void sh7722_video_recalc(struct clk *clk) 500 { 501 unsigned long r; 502 503 r = ctrl_inl(VCLKCR); 504 clk->rate = clk->parent->rate / ((r & 0x3F) + 1); 505 } 506 507 static struct clk_ops sh7722_video_clk_ops = { 508 .recalc = sh7722_video_recalc, 509 .set_rate = sh7722_video_set_rate, 510 .enable = sh7722_video_enable, 511 .disable = sh7722_video_disable, 512 }; 513 /* 514 * and at last, clock definitions themselves 515 */ 516 static struct clk sh7722_umem_clock = { 517 .name = "umem_clk", 518 .ops = &sh7722_frqcr_clk_ops, 519 }; 520 521 static struct clk sh7722_sh_clock = { 522 .name = "sh_clk", 523 .ops = &sh7722_frqcr_clk_ops, 524 }; 525 526 static struct clk sh7722_peripheral_clock = { 527 .name = "peripheral_clk", 528 .ops = &sh7722_frqcr_clk_ops, 529 }; 530 531 static struct clk sh7722_sdram_clock = { 532 .name = "sdram_clk", 533 .ops = &sh7722_frqcr_clk_ops, 534 }; 535 536 537 #ifndef CONFIG_CPU_SUBTYPE_SH7343 538 539 /* 540 * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops 541 * methods of clk_ops determine which register they should access by 542 * examining clk->name field 543 */ 544 static struct clk sh7722_siu_a_clock = { 545 .name = "siu_a_clk", 546 .arch_flags = SCLKACR, 547 .ops = &sh7722_siu_clk_ops, 548 }; 549 550 static struct clk sh7722_siu_b_clock = { 551 .name = "siu_b_clk", 552 .arch_flags = SCLKBCR, 553 .ops = &sh7722_siu_clk_ops, 554 }; 555 556 #if defined(CONFIG_CPU_SUBTYPE_SH7722) 557 static struct clk sh7722_irda_clock = { 558 .name = "irda_clk", 559 .arch_flags = IrDACLKCR, 560 .ops = &sh7722_siu_clk_ops, 561 }; 562 #endif 563 #endif /* CONFIG_CPU_SUBTYPE_SH7343 */ 564 565 static struct clk sh7722_video_clock = { 566 .name = "video_clk", 567 .ops = &sh7722_video_clk_ops, 568 }; 569 570 static int sh7722_mstpcr_start_stop(struct clk *clk, unsigned long reg, 571 int enable) 572 { 573 unsigned long bit = clk->arch_flags; 574 unsigned long r; 575 576 r = ctrl_inl(reg); 577 578 if (enable) 579 r &= ~(1 << bit); 580 else 581 r |= (1 << bit); 582 583 ctrl_outl(r, reg); 584 return 0; 585 } 586 587 static void sh7722_mstpcr0_enable(struct clk *clk) 588 { 589 sh7722_mstpcr_start_stop(clk, MSTPCR0, 1); 590 } 591 592 static void sh7722_mstpcr0_disable(struct clk *clk) 593 { 594 sh7722_mstpcr_start_stop(clk, MSTPCR0, 0); 595 } 596 597 static void sh7722_mstpcr1_enable(struct clk *clk) 598 { 599 sh7722_mstpcr_start_stop(clk, MSTPCR1, 1); 600 } 601 602 static void sh7722_mstpcr1_disable(struct clk *clk) 603 { 604 sh7722_mstpcr_start_stop(clk, MSTPCR1, 0); 605 } 606 607 static void sh7722_mstpcr2_enable(struct clk *clk) 608 { 609 sh7722_mstpcr_start_stop(clk, MSTPCR2, 1); 610 } 611 612 static void sh7722_mstpcr2_disable(struct clk *clk) 613 { 614 sh7722_mstpcr_start_stop(clk, MSTPCR2, 0); 615 } 616 617 static struct clk_ops sh7722_mstpcr0_clk_ops = { 618 .enable = sh7722_mstpcr0_enable, 619 .disable = sh7722_mstpcr0_disable, 620 }; 621 622 static struct clk_ops sh7722_mstpcr1_clk_ops = { 623 .enable = sh7722_mstpcr1_enable, 624 .disable = sh7722_mstpcr1_disable, 625 }; 626 627 static struct clk_ops sh7722_mstpcr2_clk_ops = { 628 .enable = sh7722_mstpcr2_enable, 629 .disable = sh7722_mstpcr2_disable, 630 }; 631 632 #define DECLARE_MSTPCRN(regnr, bitnr, bitstr) \ 633 { \ 634 .name = "mstp" __stringify(regnr) bitstr, \ 635 .arch_flags = bitnr, \ 636 .ops = &sh7722_mstpcr ## regnr ## _clk_ops, \ 637 } 638 639 #define DECLARE_MSTPCR(regnr) \ 640 DECLARE_MSTPCRN(regnr, 31, "31"), \ 641 DECLARE_MSTPCRN(regnr, 30, "30"), \ 642 DECLARE_MSTPCRN(regnr, 29, "29"), \ 643 DECLARE_MSTPCRN(regnr, 28, "28"), \ 644 DECLARE_MSTPCRN(regnr, 27, "27"), \ 645 DECLARE_MSTPCRN(regnr, 26, "26"), \ 646 DECLARE_MSTPCRN(regnr, 25, "25"), \ 647 DECLARE_MSTPCRN(regnr, 24, "24"), \ 648 DECLARE_MSTPCRN(regnr, 23, "23"), \ 649 DECLARE_MSTPCRN(regnr, 22, "22"), \ 650 DECLARE_MSTPCRN(regnr, 21, "21"), \ 651 DECLARE_MSTPCRN(regnr, 20, "20"), \ 652 DECLARE_MSTPCRN(regnr, 19, "19"), \ 653 DECLARE_MSTPCRN(regnr, 18, "18"), \ 654 DECLARE_MSTPCRN(regnr, 17, "17"), \ 655 DECLARE_MSTPCRN(regnr, 16, "16"), \ 656 DECLARE_MSTPCRN(regnr, 15, "15"), \ 657 DECLARE_MSTPCRN(regnr, 14, "14"), \ 658 DECLARE_MSTPCRN(regnr, 13, "13"), \ 659 DECLARE_MSTPCRN(regnr, 12, "12"), \ 660 DECLARE_MSTPCRN(regnr, 11, "11"), \ 661 DECLARE_MSTPCRN(regnr, 10, "10"), \ 662 DECLARE_MSTPCRN(regnr, 9, "09"), \ 663 DECLARE_MSTPCRN(regnr, 8, "08"), \ 664 DECLARE_MSTPCRN(regnr, 7, "07"), \ 665 DECLARE_MSTPCRN(regnr, 6, "06"), \ 666 DECLARE_MSTPCRN(regnr, 5, "05"), \ 667 DECLARE_MSTPCRN(regnr, 4, "04"), \ 668 DECLARE_MSTPCRN(regnr, 3, "03"), \ 669 DECLARE_MSTPCRN(regnr, 2, "02"), \ 670 DECLARE_MSTPCRN(regnr, 1, "01"), \ 671 DECLARE_MSTPCRN(regnr, 0, "00") 672 673 static struct clk sh7722_mstpcr[] = { 674 DECLARE_MSTPCR(0), 675 DECLARE_MSTPCR(1), 676 DECLARE_MSTPCR(2), 677 }; 678 679 static struct clk *sh7722_clocks[] = { 680 &sh7722_umem_clock, 681 &sh7722_sh_clock, 682 &sh7722_peripheral_clock, 683 &sh7722_sdram_clock, 684 #ifndef CONFIG_CPU_SUBTYPE_SH7343 685 &sh7722_siu_a_clock, 686 &sh7722_siu_b_clock, 687 #if defined(CONFIG_CPU_SUBTYPE_SH7722) 688 &sh7722_irda_clock, 689 #endif 690 #endif 691 &sh7722_video_clock, 692 }; 693 694 /* 695 * init in order: master, module, bus, cpu 696 */ 697 struct clk_ops *onchip_ops[] = { 698 &sh7722_master_clk_ops, 699 &sh7722_module_clk_ops, 700 &sh7722_frqcr_clk_ops, 701 &sh7722_frqcr_clk_ops, 702 }; 703 704 void __init 705 arch_init_clk_ops(struct clk_ops **ops, int type) 706 { 707 BUG_ON(type < 0 || type > ARRAY_SIZE(onchip_ops)); 708 *ops = onchip_ops[type]; 709 } 710 711 int __init arch_clk_init(void) 712 { 713 struct clk *master; 714 int i; 715 716 master = clk_get(NULL, "master_clk"); 717 for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) { 718 pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name); 719 sh7722_clocks[i]->parent = master; 720 clk_register(sh7722_clocks[i]); 721 } 722 clk_put(master); 723 724 for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr); i++) { 725 pr_debug( "Registering mstpcr '%s'\n", sh7722_mstpcr[i].name); 726 clk_register(&sh7722_mstpcr[i]); 727 } 728 729 return 0; 730 } 731