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_div_index - 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_div_index(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 - 1] && div2 <= divisors2[index]) 251 break; 252 } 253 if (index >= ARRAY_SIZE(divisors2)) 254 index = ARRAY_SIZE(divisors2) - 1; 255 return 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_div_index(parent_rate, rate); 283 if (div<0) 284 return div; 285 286 /* calculate new value of clock rate */ 287 clk->rate = parent_rate * 2 / divisors2[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_div_index(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_div_index(parent_rate, rate); 398 if (div < 0) 399 return clk->rate; 400 401 /* calculate new value of clock rate */ 402 return parent_rate * 2 / divisors2[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_div_index(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 .flags = CLK_RATE_PROPAGATES, 520 }; 521 522 static struct clk sh7722_sh_clock = { 523 .name = "sh_clk", 524 .ops = &sh7722_frqcr_clk_ops, 525 .flags = CLK_RATE_PROPAGATES, 526 }; 527 528 static struct clk sh7722_peripheral_clock = { 529 .name = "peripheral_clk", 530 .ops = &sh7722_frqcr_clk_ops, 531 .flags = CLK_RATE_PROPAGATES, 532 }; 533 534 static struct clk sh7722_sdram_clock = { 535 .name = "sdram_clk", 536 .ops = &sh7722_frqcr_clk_ops, 537 }; 538 539 static struct clk sh7722_r_clock = { 540 .name = "r_clk", 541 .rate = 32768, 542 .flags = CLK_RATE_PROPAGATES, 543 }; 544 545 #ifndef CONFIG_CPU_SUBTYPE_SH7343 546 547 /* 548 * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops 549 * methods of clk_ops determine which register they should access by 550 * examining clk->name field 551 */ 552 static struct clk sh7722_siu_a_clock = { 553 .name = "siu_a_clk", 554 .arch_flags = SCLKACR, 555 .ops = &sh7722_siu_clk_ops, 556 }; 557 558 static struct clk sh7722_siu_b_clock = { 559 .name = "siu_b_clk", 560 .arch_flags = SCLKBCR, 561 .ops = &sh7722_siu_clk_ops, 562 }; 563 564 #if defined(CONFIG_CPU_SUBTYPE_SH7722) 565 static struct clk sh7722_irda_clock = { 566 .name = "irda_clk", 567 .arch_flags = IrDACLKCR, 568 .ops = &sh7722_siu_clk_ops, 569 }; 570 #endif 571 #endif /* CONFIG_CPU_SUBTYPE_SH7343 */ 572 573 static struct clk sh7722_video_clock = { 574 .name = "video_clk", 575 .ops = &sh7722_video_clk_ops, 576 }; 577 578 #define MSTPCR_ARCH_FLAGS(reg, bit) (((reg) << 8) | (bit)) 579 #define MSTPCR_ARCH_FLAGS_REG(value) ((value) >> 8) 580 #define MSTPCR_ARCH_FLAGS_BIT(value) ((value) & 0xff) 581 582 static int sh7722_mstpcr_start_stop(struct clk *clk, int enable) 583 { 584 unsigned long bit = MSTPCR_ARCH_FLAGS_BIT(clk->arch_flags); 585 unsigned long reg; 586 unsigned long r; 587 588 switch(MSTPCR_ARCH_FLAGS_REG(clk->arch_flags)) { 589 case 0: 590 reg = MSTPCR0; 591 break; 592 case 1: 593 reg = MSTPCR1; 594 break; 595 case 2: 596 reg = MSTPCR2; 597 break; 598 default: 599 return -EINVAL; 600 } 601 602 r = ctrl_inl(reg); 603 604 if (enable) 605 r &= ~(1 << bit); 606 else 607 r |= (1 << bit); 608 609 ctrl_outl(r, reg); 610 return 0; 611 } 612 613 static void sh7722_mstpcr_enable(struct clk *clk) 614 { 615 sh7722_mstpcr_start_stop(clk, 1); 616 } 617 618 static void sh7722_mstpcr_disable(struct clk *clk) 619 { 620 sh7722_mstpcr_start_stop(clk, 0); 621 } 622 623 static void sh7722_mstpcr_recalc(struct clk *clk) 624 { 625 if (clk->parent) 626 clk->rate = clk->parent->rate; 627 } 628 629 static struct clk_ops sh7722_mstpcr_clk_ops = { 630 .enable = sh7722_mstpcr_enable, 631 .disable = sh7722_mstpcr_disable, 632 .recalc = sh7722_mstpcr_recalc, 633 }; 634 635 #define MSTPCR(_name, _parent, regnr, bitnr) \ 636 { \ 637 .name = _name, \ 638 .arch_flags = MSTPCR_ARCH_FLAGS(regnr, bitnr), \ 639 .ops = (void *)_parent, \ 640 } 641 642 static struct clk sh7722_mstpcr_clocks[] = { 643 #if defined(CONFIG_CPU_SUBTYPE_SH7722) 644 MSTPCR("uram0", "umem_clk", 0, 28), 645 MSTPCR("xymem0", "bus_clk", 0, 26), 646 MSTPCR("tmu0", "peripheral_clk", 0, 15), 647 MSTPCR("cmt0", "r_clk", 0, 14), 648 MSTPCR("rwdt0", "r_clk", 0, 13), 649 MSTPCR("flctl0", "peripheral_clk", 0, 10), 650 MSTPCR("scif0", "peripheral_clk", 0, 7), 651 MSTPCR("scif1", "peripheral_clk", 0, 6), 652 MSTPCR("scif2", "peripheral_clk", 0, 5), 653 MSTPCR("i2c0", "peripheral_clk", 1, 9), 654 MSTPCR("rtc0", "r_clk", 1, 8), 655 MSTPCR("sdhi0", "peripheral_clk", 2, 18), 656 MSTPCR("keysc0", "r_clk", 2, 14), 657 MSTPCR("usbf0", "peripheral_clk", 2, 11), 658 MSTPCR("2dg0", "bus_clk", 2, 9), 659 MSTPCR("siu0", "bus_clk", 2, 8), 660 MSTPCR("vou0", "bus_clk", 2, 5), 661 MSTPCR("jpu0", "bus_clk", 2, 6), 662 MSTPCR("beu0", "bus_clk", 2, 4), 663 MSTPCR("ceu0", "bus_clk", 2, 3), 664 MSTPCR("veu0", "bus_clk", 2, 2), 665 MSTPCR("vpu0", "bus_clk", 2, 1), 666 MSTPCR("lcdc0", "bus_clk", 2, 0), 667 #endif 668 #if defined(CONFIG_CPU_SUBTYPE_SH7723) 669 /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ 670 MSTPCR("tlb0", "cpu_clk", 0, 31), 671 MSTPCR("ic0", "cpu_clk", 0, 30), 672 MSTPCR("oc0", "cpu_clk", 0, 29), 673 MSTPCR("l2c0", "sh_clk", 0, 28), 674 MSTPCR("ilmem0", "cpu_clk", 0, 27), 675 MSTPCR("fpu0", "cpu_clk", 0, 24), 676 MSTPCR("intc0", "cpu_clk", 0, 22), 677 MSTPCR("dmac0", "bus_clk", 0, 21), 678 MSTPCR("sh0", "sh_clk", 0, 20), 679 MSTPCR("hudi0", "peripheral_clk", 0, 19), 680 MSTPCR("ubc0", "cpu_clk", 0, 17), 681 MSTPCR("tmu0", "peripheral_clk", 0, 15), 682 MSTPCR("cmt0", "r_clk", 0, 14), 683 MSTPCR("rwdt0", "r_clk", 0, 13), 684 MSTPCR("dmac1", "bus_clk", 0, 12), 685 MSTPCR("tmu1", "peripheral_clk", 0, 11), 686 MSTPCR("flctl0", "peripheral_clk", 0, 10), 687 MSTPCR("scif0", "peripheral_clk", 0, 9), 688 MSTPCR("scif1", "peripheral_clk", 0, 8), 689 MSTPCR("scif2", "peripheral_clk", 0, 7), 690 MSTPCR("scif3", "bus_clk", 0, 6), 691 MSTPCR("scif4", "bus_clk", 0, 5), 692 MSTPCR("scif5", "bus_clk", 0, 4), 693 MSTPCR("msiof0", "bus_clk", 0, 2), 694 MSTPCR("msiof1", "bus_clk", 0, 1), 695 MSTPCR("meram0", "sh_clk", 0, 0), 696 MSTPCR("i2c0", "peripheral_clk", 1, 9), 697 MSTPCR("rtc0", "r_clk", 1, 8), 698 MSTPCR("atapi0", "sh_clk", 2, 28), 699 MSTPCR("adc0", "peripheral_clk", 2, 28), 700 MSTPCR("tpu0", "bus_clk", 2, 25), 701 MSTPCR("irda0", "peripheral_clk", 2, 24), 702 MSTPCR("tsif0", "bus_clk", 2, 22), 703 MSTPCR("icb0", "bus_clk", 2, 21), 704 MSTPCR("sdhi0", "bus_clk", 2, 18), 705 MSTPCR("sdhi1", "bus_clk", 2, 17), 706 MSTPCR("keysc0", "r_clk", 2, 14), 707 MSTPCR("usb0", "bus_clk", 2, 11), 708 MSTPCR("2dg0", "bus_clk", 2, 10), 709 MSTPCR("siu0", "bus_clk", 2, 8), 710 MSTPCR("veu1", "bus_clk", 2, 6), 711 MSTPCR("vou0", "bus_clk", 2, 5), 712 MSTPCR("beu0", "bus_clk", 2, 4), 713 MSTPCR("ceu0", "bus_clk", 2, 3), 714 MSTPCR("veu0", "bus_clk", 2, 2), 715 MSTPCR("vpu0", "bus_clk", 2, 1), 716 MSTPCR("lcdc0", "bus_clk", 2, 0), 717 #endif 718 #if defined(CONFIG_CPU_SUBTYPE_SH7343) 719 MSTPCR("uram0", "umem_clk", 0, 28), 720 MSTPCR("xymem0", "bus_clk", 0, 26), 721 MSTPCR("tmu0", "peripheral_clk", 0, 15), 722 MSTPCR("cmt0", "r_clk", 0, 14), 723 MSTPCR("rwdt0", "r_clk", 0, 13), 724 MSTPCR("scif0", "peripheral_clk", 0, 7), 725 MSTPCR("scif1", "peripheral_clk", 0, 6), 726 MSTPCR("scif2", "peripheral_clk", 0, 5), 727 MSTPCR("scif3", "peripheral_clk", 0, 4), 728 MSTPCR("i2c0", "peripheral_clk", 1, 9), 729 MSTPCR("i2c1", "peripheral_clk", 1, 8), 730 MSTPCR("sdhi0", "peripheral_clk", 2, 18), 731 MSTPCR("keysc0", "r_clk", 2, 14), 732 MSTPCR("usbf0", "peripheral_clk", 2, 11), 733 MSTPCR("siu0", "bus_clk", 2, 8), 734 MSTPCR("jpu0", "bus_clk", 2, 6), 735 MSTPCR("vou0", "bus_clk", 2, 5), 736 MSTPCR("beu0", "bus_clk", 2, 4), 737 MSTPCR("ceu0", "bus_clk", 2, 3), 738 MSTPCR("veu0", "bus_clk", 2, 2), 739 MSTPCR("vpu0", "bus_clk", 2, 1), 740 MSTPCR("lcdc0", "bus_clk", 2, 0), 741 #endif 742 #if defined(CONFIG_CPU_SUBTYPE_SH7366) 743 /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */ 744 MSTPCR("tlb0", "cpu_clk", 0, 31), 745 MSTPCR("ic0", "cpu_clk", 0, 30), 746 MSTPCR("oc0", "cpu_clk", 0, 29), 747 MSTPCR("rsmem0", "sh_clk", 0, 28), 748 MSTPCR("xymem0", "cpu_clk", 0, 26), 749 MSTPCR("intc30", "peripheral_clk", 0, 23), 750 MSTPCR("intc0", "peripheral_clk", 0, 22), 751 MSTPCR("dmac0", "bus_clk", 0, 21), 752 MSTPCR("sh0", "sh_clk", 0, 20), 753 MSTPCR("hudi0", "peripheral_clk", 0, 19), 754 MSTPCR("ubc0", "cpu_clk", 0, 17), 755 MSTPCR("tmu0", "peripheral_clk", 0, 15), 756 MSTPCR("cmt0", "r_clk", 0, 14), 757 MSTPCR("rwdt0", "r_clk", 0, 13), 758 MSTPCR("flctl0", "peripheral_clk", 0, 10), 759 MSTPCR("scif0", "peripheral_clk", 0, 7), 760 MSTPCR("scif1", "bus_clk", 0, 6), 761 MSTPCR("scif2", "bus_clk", 0, 5), 762 MSTPCR("msiof0", "peripheral_clk", 0, 2), 763 MSTPCR("sbr0", "peripheral_clk", 0, 1), 764 MSTPCR("i2c0", "peripheral_clk", 1, 9), 765 MSTPCR("icb0", "bus_clk", 2, 27), 766 MSTPCR("meram0", "sh_clk", 2, 26), 767 MSTPCR("dacc0", "peripheral_clk", 2, 24), 768 MSTPCR("dacy0", "peripheral_clk", 2, 23), 769 MSTPCR("tsif0", "bus_clk", 2, 22), 770 MSTPCR("sdhi0", "bus_clk", 2, 18), 771 MSTPCR("mmcif0", "bus_clk", 2, 17), 772 MSTPCR("usb0", "bus_clk", 2, 11), 773 MSTPCR("siu0", "bus_clk", 2, 8), 774 MSTPCR("veu1", "bus_clk", 2, 7), 775 MSTPCR("vou0", "bus_clk", 2, 5), 776 MSTPCR("beu0", "bus_clk", 2, 4), 777 MSTPCR("ceu0", "bus_clk", 2, 3), 778 MSTPCR("veu0", "bus_clk", 2, 2), 779 MSTPCR("vpu0", "bus_clk", 2, 1), 780 MSTPCR("lcdc0", "bus_clk", 2, 0), 781 #endif 782 }; 783 784 static struct clk *sh7722_clocks[] = { 785 &sh7722_umem_clock, 786 &sh7722_sh_clock, 787 &sh7722_peripheral_clock, 788 &sh7722_sdram_clock, 789 #ifndef CONFIG_CPU_SUBTYPE_SH7343 790 &sh7722_siu_a_clock, 791 &sh7722_siu_b_clock, 792 #if defined(CONFIG_CPU_SUBTYPE_SH7722) 793 &sh7722_irda_clock, 794 #endif 795 #endif 796 &sh7722_video_clock, 797 }; 798 799 /* 800 * init in order: master, module, bus, cpu 801 */ 802 struct clk_ops *onchip_ops[] = { 803 &sh7722_master_clk_ops, 804 &sh7722_module_clk_ops, 805 &sh7722_frqcr_clk_ops, 806 &sh7722_frqcr_clk_ops, 807 }; 808 809 void __init 810 arch_init_clk_ops(struct clk_ops **ops, int type) 811 { 812 BUG_ON(type < 0 || type > ARRAY_SIZE(onchip_ops)); 813 *ops = onchip_ops[type]; 814 } 815 816 int __init arch_clk_init(void) 817 { 818 struct clk *clk; 819 int i; 820 821 clk = clk_get(NULL, "master_clk"); 822 for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) { 823 pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name); 824 sh7722_clocks[i]->parent = clk; 825 clk_register(sh7722_clocks[i]); 826 } 827 clk_put(clk); 828 829 clk_register(&sh7722_r_clock); 830 831 for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr_clocks); i++) { 832 pr_debug( "Registering mstpcr clock '%s'\n", 833 sh7722_mstpcr_clocks[i].name); 834 clk = clk_get(NULL, (void *) sh7722_mstpcr_clocks[i].ops); 835 sh7722_mstpcr_clocks[i].parent = clk; 836 sh7722_mstpcr_clocks[i].ops = &sh7722_mstpcr_clk_ops; 837 clk_register(&sh7722_mstpcr_clocks[i]); 838 clk_put(clk); 839 } 840 841 clk_recalc_rate(&sh7722_r_clock); /* make sure rate gets propagated */ 842 843 return 0; 844 } 845