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 #if defined(CONFIG_CPU_SUBTYPE_SH7724) 134 #define STCPLL(frqcr) ((((frqcr >> 24) & 0x3f) + 1) * 2) 135 #else 136 #define STCPLL(frqcr) (((frqcr >> 24) & 0x1f) + 1) 137 #endif 138 139 /* 140 * Instead of having two separate multipliers/divisors set, like this: 141 * 142 * static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 143 * static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; 144 * 145 * I created the divisors2 array, which is used to calculate rate like 146 * rate = parent * 2 / divisors2[ divisor ]; 147 */ 148 #if defined(CONFIG_CPU_SUBTYPE_SH7724) 149 static int divisors2[] = { 4, 1, 8, 12, 16, 24, 32, 1, 48, 64, 72, 96, 1, 144 }; 150 #else 151 static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 }; 152 #endif 153 154 static void master_clk_recalc(struct clk *clk) 155 { 156 unsigned frqcr = ctrl_inl(FRQCR); 157 158 clk->rate = CONFIG_SH_PCLK_FREQ * STCPLL(frqcr); 159 } 160 161 static void master_clk_init(struct clk *clk) 162 { 163 clk->parent = NULL; 164 clk->flags |= CLK_RATE_PROPAGATES; 165 clk->rate = CONFIG_SH_PCLK_FREQ; 166 master_clk_recalc(clk); 167 } 168 169 170 static void module_clk_recalc(struct clk *clk) 171 { 172 unsigned long frqcr = ctrl_inl(FRQCR); 173 174 clk->rate = clk->parent->rate / STCPLL(frqcr); 175 } 176 177 #if defined(CONFIG_CPU_SUBTYPE_SH7724) 178 #define MASTERDIVS { 12, 16, 24, 30, 32, 36, 48 } 179 #define STCMASK 0x3f 180 #define DIVCALC(div) (div/2-1) 181 #define FRQCRKICK 0x80000000 182 #elif defined(CONFIG_CPU_SUBTYPE_SH7723) 183 #define MASTERDIVS { 6, 8, 12, 16 } 184 #define STCMASK 0x1f 185 #define DIVCALC(div) (div-1) 186 #define FRQCRKICK 0x00000000 187 #else 188 #define MASTERDIVS { 2, 3, 4, 6, 8, 16 } 189 #define STCMASK 0x1f 190 #define DIVCALC(div) (div-1) 191 #define FRQCRKICK 0x00000000 192 #endif 193 194 static int master_clk_setrate(struct clk *clk, unsigned long rate, int id) 195 { 196 int div = rate / clk->rate; 197 int master_divs[] = MASTERDIVS; 198 int index; 199 unsigned long frqcr; 200 201 for (index = 1; index < ARRAY_SIZE(master_divs); index++) 202 if (div >= master_divs[index - 1] && div < master_divs[index]) 203 break; 204 205 if (index >= ARRAY_SIZE(master_divs)) 206 index = ARRAY_SIZE(master_divs); 207 div = master_divs[index - 1]; 208 209 frqcr = ctrl_inl(FRQCR); 210 frqcr &= ~(STCMASK << 24); 211 frqcr |= (DIVCALC(div) << 24); 212 frqcr |= FRQCRKICK; 213 ctrl_outl(frqcr, FRQCR); 214 215 return 0; 216 } 217 218 static struct clk_ops sh7722_master_clk_ops = { 219 .init = master_clk_init, 220 .recalc = master_clk_recalc, 221 .set_rate = master_clk_setrate, 222 }; 223 224 static struct clk_ops sh7722_module_clk_ops = { 225 .recalc = module_clk_recalc, 226 }; 227 228 struct frqcr_context { 229 unsigned mask; 230 unsigned shift; 231 }; 232 233 struct frqcr_context sh7722_get_clk_context(const char *name) 234 { 235 struct frqcr_context ctx = { 0, }; 236 237 if (!strcmp(name, "peripheral_clk")) { 238 ctx.shift = 0; 239 ctx.mask = 0xF; 240 } else if (!strcmp(name, "sdram_clk")) { 241 ctx.shift = 4; 242 ctx.mask = 0xF; 243 } else if (!strcmp(name, "bus_clk")) { 244 ctx.shift = 8; 245 ctx.mask = 0xF; 246 } else if (!strcmp(name, "sh_clk")) { 247 ctx.shift = 12; 248 ctx.mask = 0xF; 249 } else if (!strcmp(name, "umem_clk")) { 250 ctx.shift = 16; 251 ctx.mask = 0xF; 252 } else if (!strcmp(name, "cpu_clk")) { 253 ctx.shift = 20; 254 ctx.mask = 7; 255 } 256 return ctx; 257 } 258 259 /** 260 * sh7722_find_div_index - find divisor for setting rate 261 * 262 * All sh7722 clocks use the same set of multipliers/divisors. This function 263 * chooses correct divisor to set the rate of clock with parent clock that 264 * generates frequency of 'parent_rate' 265 * 266 * @parent_rate: rate of parent clock 267 * @rate: requested rate to be set 268 */ 269 static int sh7722_find_div_index(unsigned long parent_rate, unsigned rate) 270 { 271 unsigned div2 = parent_rate * 2 / rate; 272 int index; 273 274 if (rate > parent_rate) 275 return -EINVAL; 276 277 for (index = 1; index < ARRAY_SIZE(divisors2); index++) { 278 if (div2 > divisors2[index - 1] && div2 <= divisors2[index]) 279 break; 280 } 281 if (index >= ARRAY_SIZE(divisors2)) 282 index = ARRAY_SIZE(divisors2) - 1; 283 return index; 284 } 285 286 static void sh7722_frqcr_recalc(struct clk *clk) 287 { 288 struct frqcr_context ctx = sh7722_get_clk_context(clk->name); 289 unsigned long frqcr = ctrl_inl(FRQCR); 290 int index; 291 292 index = (frqcr >> ctx.shift) & ctx.mask; 293 clk->rate = clk->parent->rate * 2 / divisors2[index]; 294 } 295 296 static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate, 297 int algo_id) 298 { 299 struct frqcr_context ctx = sh7722_get_clk_context(clk->name); 300 unsigned long parent_rate = clk->parent->rate; 301 int div; 302 unsigned long frqcr; 303 int err = 0; 304 305 /* pretty invalid */ 306 if (parent_rate < rate) 307 return -EINVAL; 308 309 /* look for multiplier/divisor pair */ 310 div = sh7722_find_div_index(parent_rate, rate); 311 if (div<0) 312 return div; 313 314 /* calculate new value of clock rate */ 315 clk->rate = parent_rate * 2 / divisors2[div]; 316 frqcr = ctrl_inl(FRQCR); 317 318 /* FIXME: adjust as algo_id specifies */ 319 if (algo_id != NO_CHANGE) { 320 int originator; 321 char *algo_group_1[] = { "cpu_clk", "umem_clk", "sh_clk" }; 322 char *algo_group_2[] = { "sh_clk", "bus_clk" }; 323 char *algo_group_3[] = { "sh_clk", "sdram_clk" }; 324 char *algo_group_4[] = { "bus_clk", "peripheral_clk" }; 325 char *algo_group_5[] = { "cpu_clk", "peripheral_clk" }; 326 char **algo_current = NULL; 327 /* 3 is the maximum number of clocks in relation */ 328 struct clk *ck[3]; 329 unsigned long values[3]; /* the same comment as above */ 330 int part_length = -1; 331 int i; 332 333 /* 334 * all the steps below only required if adjustion was 335 * requested 336 */ 337 if (algo_id == IUS_N1_N1 || 338 algo_id == IUS_322 || 339 algo_id == IUS_522 || 340 algo_id == IUS_N11) { 341 algo_current = algo_group_1; 342 part_length = 3; 343 } 344 if (algo_id == SB_N1) { 345 algo_current = algo_group_2; 346 part_length = 2; 347 } 348 if (algo_id == SB3_N1 || 349 algo_id == SB3_32 || 350 algo_id == SB3_43 || 351 algo_id == SB3_54) { 352 algo_current = algo_group_3; 353 part_length = 2; 354 } 355 if (algo_id == BP_N1) { 356 algo_current = algo_group_4; 357 part_length = 2; 358 } 359 if (algo_id == IP_N1) { 360 algo_current = algo_group_5; 361 part_length = 2; 362 } 363 if (!algo_current) 364 goto incorrect_algo_id; 365 366 originator = -1; 367 for (i = 0; i < part_length; i ++ ) { 368 if (originator >= 0 && !strcmp(clk->name, 369 algo_current[i])) 370 originator = i; 371 ck[i] = clk_get(NULL, algo_current[i]); 372 values[i] = clk_get_rate(ck[i]); 373 } 374 375 if (originator >= 0) 376 adjust_clocks(originator, adjust_algos[algo_id], 377 values, part_length); 378 379 for (i = 0; i < part_length; i ++ ) { 380 struct frqcr_context part_ctx; 381 int part_div; 382 383 if (likely(!err)) { 384 part_div = sh7722_find_div_index(parent_rate, 385 rate); 386 if (part_div > 0) { 387 part_ctx = sh7722_get_clk_context( 388 ck[i]->name); 389 frqcr &= ~(part_ctx.mask << 390 part_ctx.shift); 391 frqcr |= part_div << part_ctx.shift; 392 } else 393 err = part_div; 394 } 395 396 ck[i]->ops->recalc(ck[i]); 397 clk_put(ck[i]); 398 } 399 } 400 401 /* was there any error during recalculation ? If so, bail out.. */ 402 if (unlikely(err!=0)) 403 goto out_err; 404 405 /* clear FRQCR bits */ 406 frqcr &= ~(ctx.mask << ctx.shift); 407 frqcr |= div << ctx.shift; 408 frqcr |= FRQCRKICK; 409 410 /* ...and perform actual change */ 411 ctrl_outl(frqcr, FRQCR); 412 return 0; 413 414 incorrect_algo_id: 415 return -EINVAL; 416 out_err: 417 return err; 418 } 419 420 static long sh7722_frqcr_round_rate(struct clk *clk, unsigned long rate) 421 { 422 unsigned long parent_rate = clk->parent->rate; 423 int div; 424 425 /* look for multiplier/divisor pair */ 426 div = sh7722_find_div_index(parent_rate, rate); 427 if (div < 0) 428 return clk->rate; 429 430 /* calculate new value of clock rate */ 431 return parent_rate * 2 / divisors2[div]; 432 } 433 434 static struct clk_ops sh7722_frqcr_clk_ops = { 435 .recalc = sh7722_frqcr_recalc, 436 .set_rate = sh7722_frqcr_set_rate, 437 .round_rate = sh7722_frqcr_round_rate, 438 }; 439 440 /* 441 * clock ops methods for SIU A/B and IrDA clock 442 * 443 */ 444 445 #ifndef CONFIG_CPU_SUBTYPE_SH7343 446 447 static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id) 448 { 449 unsigned long r; 450 int div; 451 452 r = ctrl_inl(clk->arch_flags); 453 div = sh7722_find_div_index(clk->parent->rate, rate); 454 if (div < 0) 455 return div; 456 r = (r & ~0xF) | div; 457 ctrl_outl(r, clk->arch_flags); 458 return 0; 459 } 460 461 static void sh7722_siu_recalc(struct clk *clk) 462 { 463 unsigned long r; 464 465 r = ctrl_inl(clk->arch_flags); 466 clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF]; 467 } 468 469 static int sh7722_siu_start_stop(struct clk *clk, int enable) 470 { 471 unsigned long r; 472 473 r = ctrl_inl(clk->arch_flags); 474 if (enable) 475 ctrl_outl(r & ~(1 << 8), clk->arch_flags); 476 else 477 ctrl_outl(r | (1 << 8), clk->arch_flags); 478 return 0; 479 } 480 481 static void sh7722_siu_enable(struct clk *clk) 482 { 483 sh7722_siu_start_stop(clk, 1); 484 } 485 486 static void sh7722_siu_disable(struct clk *clk) 487 { 488 sh7722_siu_start_stop(clk, 0); 489 } 490 491 static struct clk_ops sh7722_siu_clk_ops = { 492 .recalc = sh7722_siu_recalc, 493 .set_rate = sh7722_siu_set_rate, 494 .enable = sh7722_siu_enable, 495 .disable = sh7722_siu_disable, 496 }; 497 498 #endif /* CONFIG_CPU_SUBTYPE_SH7343 */ 499 500 static void sh7722_video_enable(struct clk *clk) 501 { 502 unsigned long r; 503 504 r = ctrl_inl(VCLKCR); 505 ctrl_outl( r & ~(1<<8), VCLKCR); 506 } 507 508 static void sh7722_video_disable(struct clk *clk) 509 { 510 unsigned long r; 511 512 r = ctrl_inl(VCLKCR); 513 ctrl_outl( r | (1<<8), VCLKCR); 514 } 515 516 static int sh7722_video_set_rate(struct clk *clk, unsigned long rate, 517 int algo_id) 518 { 519 unsigned long r; 520 521 r = ctrl_inl(VCLKCR); 522 r &= ~0x3F; 523 r |= ((clk->parent->rate / rate - 1) & 0x3F); 524 ctrl_outl(r, VCLKCR); 525 return 0; 526 } 527 528 static void sh7722_video_recalc(struct clk *clk) 529 { 530 unsigned long r; 531 532 r = ctrl_inl(VCLKCR); 533 clk->rate = clk->parent->rate / ((r & 0x3F) + 1); 534 } 535 536 static struct clk_ops sh7722_video_clk_ops = { 537 .recalc = sh7722_video_recalc, 538 .set_rate = sh7722_video_set_rate, 539 .enable = sh7722_video_enable, 540 .disable = sh7722_video_disable, 541 }; 542 /* 543 * and at last, clock definitions themselves 544 */ 545 static struct clk sh7722_umem_clock = { 546 .name = "umem_clk", 547 .ops = &sh7722_frqcr_clk_ops, 548 .flags = CLK_RATE_PROPAGATES, 549 }; 550 551 static struct clk sh7722_sh_clock = { 552 .name = "sh_clk", 553 .ops = &sh7722_frqcr_clk_ops, 554 .flags = CLK_RATE_PROPAGATES, 555 }; 556 557 static struct clk sh7722_peripheral_clock = { 558 .name = "peripheral_clk", 559 .ops = &sh7722_frqcr_clk_ops, 560 .flags = CLK_RATE_PROPAGATES, 561 }; 562 563 static struct clk sh7722_sdram_clock = { 564 .name = "sdram_clk", 565 .ops = &sh7722_frqcr_clk_ops, 566 }; 567 568 static struct clk sh7722_r_clock = { 569 .name = "r_clk", 570 .rate = 32768, 571 .flags = CLK_RATE_PROPAGATES, 572 }; 573 574 #if !defined(CONFIG_CPU_SUBTYPE_SH7343) &&\ 575 !defined(CONFIG_CPU_SUBTYPE_SH7724) 576 /* 577 * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops 578 * methods of clk_ops determine which register they should access by 579 * examining clk->name field 580 */ 581 static struct clk sh7722_siu_a_clock = { 582 .name = "siu_a_clk", 583 .arch_flags = SCLKACR, 584 .ops = &sh7722_siu_clk_ops, 585 }; 586 587 static struct clk sh7722_siu_b_clock = { 588 .name = "siu_b_clk", 589 .arch_flags = SCLKBCR, 590 .ops = &sh7722_siu_clk_ops, 591 }; 592 #endif /* CONFIG_CPU_SUBTYPE_SH7343, SH7724 */ 593 594 #if defined(CONFIG_CPU_SUBTYPE_SH7722) ||\ 595 defined(CONFIG_CPU_SUBTYPE_SH7724) 596 static struct clk sh7722_irda_clock = { 597 .name = "irda_clk", 598 .arch_flags = IrDACLKCR, 599 .ops = &sh7722_siu_clk_ops, 600 }; 601 #endif 602 603 static struct clk sh7722_video_clock = { 604 .name = "video_clk", 605 .ops = &sh7722_video_clk_ops, 606 }; 607 608 #define MSTPCR_ARCH_FLAGS(reg, bit) (((reg) << 8) | (bit)) 609 #define MSTPCR_ARCH_FLAGS_REG(value) ((value) >> 8) 610 #define MSTPCR_ARCH_FLAGS_BIT(value) ((value) & 0xff) 611 612 static int sh7722_mstpcr_start_stop(struct clk *clk, int enable) 613 { 614 unsigned long bit = MSTPCR_ARCH_FLAGS_BIT(clk->arch_flags); 615 unsigned long reg; 616 unsigned long r; 617 618 switch(MSTPCR_ARCH_FLAGS_REG(clk->arch_flags)) { 619 case 0: 620 reg = MSTPCR0; 621 break; 622 case 1: 623 reg = MSTPCR1; 624 break; 625 case 2: 626 reg = MSTPCR2; 627 break; 628 default: 629 return -EINVAL; 630 } 631 632 r = ctrl_inl(reg); 633 634 if (enable) 635 r &= ~(1 << bit); 636 else 637 r |= (1 << bit); 638 639 ctrl_outl(r, reg); 640 return 0; 641 } 642 643 static void sh7722_mstpcr_enable(struct clk *clk) 644 { 645 sh7722_mstpcr_start_stop(clk, 1); 646 } 647 648 static void sh7722_mstpcr_disable(struct clk *clk) 649 { 650 sh7722_mstpcr_start_stop(clk, 0); 651 } 652 653 static void sh7722_mstpcr_recalc(struct clk *clk) 654 { 655 if (clk->parent) 656 clk->rate = clk->parent->rate; 657 } 658 659 static struct clk_ops sh7722_mstpcr_clk_ops = { 660 .enable = sh7722_mstpcr_enable, 661 .disable = sh7722_mstpcr_disable, 662 .recalc = sh7722_mstpcr_recalc, 663 }; 664 665 #define MSTPCR(_name, _parent, regnr, bitnr) \ 666 { \ 667 .name = _name, \ 668 .arch_flags = MSTPCR_ARCH_FLAGS(regnr, bitnr), \ 669 .ops = (void *)_parent, \ 670 } 671 672 static struct clk sh7722_mstpcr_clocks[] = { 673 #if defined(CONFIG_CPU_SUBTYPE_SH7722) 674 MSTPCR("uram0", "umem_clk", 0, 28), 675 MSTPCR("xymem0", "bus_clk", 0, 26), 676 MSTPCR("tmu0", "peripheral_clk", 0, 15), 677 MSTPCR("cmt0", "r_clk", 0, 14), 678 MSTPCR("rwdt0", "r_clk", 0, 13), 679 MSTPCR("flctl0", "peripheral_clk", 0, 10), 680 MSTPCR("scif0", "peripheral_clk", 0, 7), 681 MSTPCR("scif1", "peripheral_clk", 0, 6), 682 MSTPCR("scif2", "peripheral_clk", 0, 5), 683 MSTPCR("i2c0", "peripheral_clk", 1, 9), 684 MSTPCR("rtc0", "r_clk", 1, 8), 685 MSTPCR("sdhi0", "peripheral_clk", 2, 18), 686 MSTPCR("keysc0", "r_clk", 2, 14), 687 MSTPCR("usbf0", "peripheral_clk", 2, 11), 688 MSTPCR("2dg0", "bus_clk", 2, 9), 689 MSTPCR("siu0", "bus_clk", 2, 8), 690 MSTPCR("vou0", "bus_clk", 2, 5), 691 MSTPCR("jpu0", "bus_clk", 2, 6), 692 MSTPCR("beu0", "bus_clk", 2, 4), 693 MSTPCR("ceu0", "bus_clk", 2, 3), 694 MSTPCR("veu0", "bus_clk", 2, 2), 695 MSTPCR("vpu0", "bus_clk", 2, 1), 696 MSTPCR("lcdc0", "bus_clk", 2, 0), 697 #endif 698 #if defined(CONFIG_CPU_SUBTYPE_SH7723) 699 /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ 700 MSTPCR("tlb0", "cpu_clk", 0, 31), 701 MSTPCR("ic0", "cpu_clk", 0, 30), 702 MSTPCR("oc0", "cpu_clk", 0, 29), 703 MSTPCR("l2c0", "sh_clk", 0, 28), 704 MSTPCR("ilmem0", "cpu_clk", 0, 27), 705 MSTPCR("fpu0", "cpu_clk", 0, 24), 706 MSTPCR("intc0", "cpu_clk", 0, 22), 707 MSTPCR("dmac0", "bus_clk", 0, 21), 708 MSTPCR("sh0", "sh_clk", 0, 20), 709 MSTPCR("hudi0", "peripheral_clk", 0, 19), 710 MSTPCR("ubc0", "cpu_clk", 0, 17), 711 MSTPCR("tmu0", "peripheral_clk", 0, 15), 712 MSTPCR("cmt0", "r_clk", 0, 14), 713 MSTPCR("rwdt0", "r_clk", 0, 13), 714 MSTPCR("dmac1", "bus_clk", 0, 12), 715 MSTPCR("tmu1", "peripheral_clk", 0, 11), 716 MSTPCR("flctl0", "peripheral_clk", 0, 10), 717 MSTPCR("scif0", "peripheral_clk", 0, 9), 718 MSTPCR("scif1", "peripheral_clk", 0, 8), 719 MSTPCR("scif2", "peripheral_clk", 0, 7), 720 MSTPCR("scif3", "bus_clk", 0, 6), 721 MSTPCR("scif4", "bus_clk", 0, 5), 722 MSTPCR("scif5", "bus_clk", 0, 4), 723 MSTPCR("msiof0", "bus_clk", 0, 2), 724 MSTPCR("msiof1", "bus_clk", 0, 1), 725 MSTPCR("meram0", "sh_clk", 0, 0), 726 MSTPCR("i2c0", "peripheral_clk", 1, 9), 727 MSTPCR("rtc0", "r_clk", 1, 8), 728 MSTPCR("atapi0", "sh_clk", 2, 28), 729 MSTPCR("adc0", "peripheral_clk", 2, 28), 730 MSTPCR("tpu0", "bus_clk", 2, 25), 731 MSTPCR("irda0", "peripheral_clk", 2, 24), 732 MSTPCR("tsif0", "bus_clk", 2, 22), 733 MSTPCR("icb0", "bus_clk", 2, 21), 734 MSTPCR("sdhi0", "bus_clk", 2, 18), 735 MSTPCR("sdhi1", "bus_clk", 2, 17), 736 MSTPCR("keysc0", "r_clk", 2, 14), 737 MSTPCR("usb0", "bus_clk", 2, 11), 738 MSTPCR("2dg0", "bus_clk", 2, 10), 739 MSTPCR("siu0", "bus_clk", 2, 8), 740 MSTPCR("veu1", "bus_clk", 2, 6), 741 MSTPCR("vou0", "bus_clk", 2, 5), 742 MSTPCR("beu0", "bus_clk", 2, 4), 743 MSTPCR("ceu0", "bus_clk", 2, 3), 744 MSTPCR("veu0", "bus_clk", 2, 2), 745 MSTPCR("vpu0", "bus_clk", 2, 1), 746 MSTPCR("lcdc0", "bus_clk", 2, 0), 747 #endif 748 #if defined(CONFIG_CPU_SUBTYPE_SH7724) 749 /* See Datasheet : Overview -> Block Diagram */ 750 MSTPCR("tlb0", "cpu_clk", 0, 31), 751 MSTPCR("ic0", "cpu_clk", 0, 30), 752 MSTPCR("oc0", "cpu_clk", 0, 29), 753 MSTPCR("rs0", "bus_clk", 0, 28), 754 MSTPCR("ilmem0", "cpu_clk", 0, 27), 755 MSTPCR("l2c0", "sh_clk", 0, 26), 756 MSTPCR("fpu0", "cpu_clk", 0, 24), 757 MSTPCR("intc0", "peripheral_clk", 0, 22), 758 MSTPCR("dmac0", "bus_clk", 0, 21), 759 MSTPCR("sh0", "sh_clk", 0, 20), 760 MSTPCR("hudi0", "peripheral_clk", 0, 19), 761 MSTPCR("ubc0", "cpu_clk", 0, 17), 762 MSTPCR("tmu0", "peripheral_clk", 0, 15), 763 MSTPCR("cmt0", "r_clk", 0, 14), 764 MSTPCR("rwdt0", "r_clk", 0, 13), 765 MSTPCR("dmac1", "bus_clk", 0, 12), 766 MSTPCR("tmu1", "peripheral_clk", 0, 10), 767 MSTPCR("scif0", "peripheral_clk", 0, 9), 768 MSTPCR("scif1", "peripheral_clk", 0, 8), 769 MSTPCR("scif2", "peripheral_clk", 0, 7), 770 MSTPCR("scif3", "bus_clk", 0, 6), 771 MSTPCR("scif4", "bus_clk", 0, 5), 772 MSTPCR("scif5", "bus_clk", 0, 4), 773 MSTPCR("msiof0", "bus_clk", 0, 2), 774 MSTPCR("msiof1", "bus_clk", 0, 1), 775 MSTPCR("keysc0", "r_clk", 1, 12), 776 MSTPCR("rtc0", "r_clk", 1, 11), 777 MSTPCR("i2c0", "peripheral_clk", 1, 9), 778 MSTPCR("i2c1", "peripheral_clk", 1, 8), 779 MSTPCR("mmc0", "bus_clk", 2, 29), 780 MSTPCR("eth0", "bus_clk", 2, 28), 781 MSTPCR("atapi0", "bus_clk", 2, 26), 782 MSTPCR("tpu0", "bus_clk", 2, 25), 783 MSTPCR("irda0", "peripheral_clk", 2, 24), 784 MSTPCR("tsif0", "bus_clk", 2, 22), 785 MSTPCR("usb1", "bus_clk", 2, 21), 786 MSTPCR("usb0", "bus_clk", 2, 20), 787 MSTPCR("2dg0", "bus_clk", 2, 19), 788 MSTPCR("sdhi0", "bus_clk", 2, 18), 789 MSTPCR("sdhi1", "bus_clk", 2, 17), 790 MSTPCR("veu1", "bus_clk", 2, 15), 791 MSTPCR("ceu1", "bus_clk", 2, 13), 792 MSTPCR("beu1", "bus_clk", 2, 12), 793 MSTPCR("2ddmac0", "sh_clk", 2, 10), 794 MSTPCR("spu0", "bus_clk", 2, 9), 795 MSTPCR("jpu0", "bus_clk", 2, 6), 796 MSTPCR("vou0", "bus_clk", 2, 5), 797 MSTPCR("beu0", "bus_clk", 2, 4), 798 MSTPCR("ceu0", "bus_clk", 2, 3), 799 MSTPCR("veu0", "bus_clk", 2, 2), 800 MSTPCR("vpu0", "bus_clk", 2, 1), 801 MSTPCR("lcdc0", "bus_clk", 2, 0), 802 #endif 803 #if defined(CONFIG_CPU_SUBTYPE_SH7343) 804 MSTPCR("uram0", "umem_clk", 0, 28), 805 MSTPCR("xymem0", "bus_clk", 0, 26), 806 MSTPCR("tmu0", "peripheral_clk", 0, 15), 807 MSTPCR("cmt0", "r_clk", 0, 14), 808 MSTPCR("rwdt0", "r_clk", 0, 13), 809 MSTPCR("scif0", "peripheral_clk", 0, 7), 810 MSTPCR("scif1", "peripheral_clk", 0, 6), 811 MSTPCR("scif2", "peripheral_clk", 0, 5), 812 MSTPCR("scif3", "peripheral_clk", 0, 4), 813 MSTPCR("i2c0", "peripheral_clk", 1, 9), 814 MSTPCR("i2c1", "peripheral_clk", 1, 8), 815 MSTPCR("sdhi0", "peripheral_clk", 2, 18), 816 MSTPCR("keysc0", "r_clk", 2, 14), 817 MSTPCR("usbf0", "peripheral_clk", 2, 11), 818 MSTPCR("siu0", "bus_clk", 2, 8), 819 MSTPCR("jpu0", "bus_clk", 2, 6), 820 MSTPCR("vou0", "bus_clk", 2, 5), 821 MSTPCR("beu0", "bus_clk", 2, 4), 822 MSTPCR("ceu0", "bus_clk", 2, 3), 823 MSTPCR("veu0", "bus_clk", 2, 2), 824 MSTPCR("vpu0", "bus_clk", 2, 1), 825 MSTPCR("lcdc0", "bus_clk", 2, 0), 826 #endif 827 #if defined(CONFIG_CPU_SUBTYPE_SH7366) 828 /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */ 829 MSTPCR("tlb0", "cpu_clk", 0, 31), 830 MSTPCR("ic0", "cpu_clk", 0, 30), 831 MSTPCR("oc0", "cpu_clk", 0, 29), 832 MSTPCR("rsmem0", "sh_clk", 0, 28), 833 MSTPCR("xymem0", "cpu_clk", 0, 26), 834 MSTPCR("intc30", "peripheral_clk", 0, 23), 835 MSTPCR("intc0", "peripheral_clk", 0, 22), 836 MSTPCR("dmac0", "bus_clk", 0, 21), 837 MSTPCR("sh0", "sh_clk", 0, 20), 838 MSTPCR("hudi0", "peripheral_clk", 0, 19), 839 MSTPCR("ubc0", "cpu_clk", 0, 17), 840 MSTPCR("tmu0", "peripheral_clk", 0, 15), 841 MSTPCR("cmt0", "r_clk", 0, 14), 842 MSTPCR("rwdt0", "r_clk", 0, 13), 843 MSTPCR("flctl0", "peripheral_clk", 0, 10), 844 MSTPCR("scif0", "peripheral_clk", 0, 7), 845 MSTPCR("scif1", "bus_clk", 0, 6), 846 MSTPCR("scif2", "bus_clk", 0, 5), 847 MSTPCR("msiof0", "peripheral_clk", 0, 2), 848 MSTPCR("sbr0", "peripheral_clk", 0, 1), 849 MSTPCR("i2c0", "peripheral_clk", 1, 9), 850 MSTPCR("icb0", "bus_clk", 2, 27), 851 MSTPCR("meram0", "sh_clk", 2, 26), 852 MSTPCR("dacc0", "peripheral_clk", 2, 24), 853 MSTPCR("dacy0", "peripheral_clk", 2, 23), 854 MSTPCR("tsif0", "bus_clk", 2, 22), 855 MSTPCR("sdhi0", "bus_clk", 2, 18), 856 MSTPCR("mmcif0", "bus_clk", 2, 17), 857 MSTPCR("usb0", "bus_clk", 2, 11), 858 MSTPCR("siu0", "bus_clk", 2, 8), 859 MSTPCR("veu1", "bus_clk", 2, 7), 860 MSTPCR("vou0", "bus_clk", 2, 5), 861 MSTPCR("beu0", "bus_clk", 2, 4), 862 MSTPCR("ceu0", "bus_clk", 2, 3), 863 MSTPCR("veu0", "bus_clk", 2, 2), 864 MSTPCR("vpu0", "bus_clk", 2, 1), 865 MSTPCR("lcdc0", "bus_clk", 2, 0), 866 #endif 867 }; 868 869 static struct clk *sh7722_clocks[] = { 870 &sh7722_umem_clock, 871 &sh7722_sh_clock, 872 &sh7722_peripheral_clock, 873 &sh7722_sdram_clock, 874 #if !defined(CONFIG_CPU_SUBTYPE_SH7343) &&\ 875 !defined(CONFIG_CPU_SUBTYPE_SH7724) 876 &sh7722_siu_a_clock, 877 &sh7722_siu_b_clock, 878 #endif 879 /* 7724 should support FSI clock */ 880 #if defined(CONFIG_CPU_SUBTYPE_SH7722) || \ 881 defined(CONFIG_CPU_SUBTYPE_SH7724) 882 &sh7722_irda_clock, 883 #endif 884 &sh7722_video_clock, 885 }; 886 887 /* 888 * init in order: master, module, bus, cpu 889 */ 890 struct clk_ops *onchip_ops[] = { 891 &sh7722_master_clk_ops, 892 &sh7722_module_clk_ops, 893 &sh7722_frqcr_clk_ops, 894 &sh7722_frqcr_clk_ops, 895 }; 896 897 void __init 898 arch_init_clk_ops(struct clk_ops **ops, int type) 899 { 900 BUG_ON(type < 0 || type > ARRAY_SIZE(onchip_ops)); 901 *ops = onchip_ops[type]; 902 } 903 904 int __init arch_clk_init(void) 905 { 906 struct clk *clk; 907 int i; 908 909 clk = clk_get(NULL, "master_clk"); 910 for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) { 911 pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name); 912 sh7722_clocks[i]->parent = clk; 913 clk_register(sh7722_clocks[i]); 914 } 915 clk_put(clk); 916 917 clk_register(&sh7722_r_clock); 918 919 for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr_clocks); i++) { 920 pr_debug( "Registering mstpcr clock '%s'\n", 921 sh7722_mstpcr_clocks[i].name); 922 clk = clk_get(NULL, (void *) sh7722_mstpcr_clocks[i].ops); 923 sh7722_mstpcr_clocks[i].parent = clk; 924 sh7722_mstpcr_clocks[i].ops = &sh7722_mstpcr_clk_ops; 925 clk_register(&sh7722_mstpcr_clocks[i]); 926 clk_put(clk); 927 } 928 929 clk_recalc_rate(&sh7722_r_clock); /* make sure rate gets propagated */ 930 931 return 0; 932 } 933