1 /* 2 * OMAP clocks. 3 * 4 * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org> 5 * 6 * Clocks data comes in part from arch/arm/mach-omap1/clock.h in Linux. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License along 19 * with this program; if not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "qemu/osdep.h" 23 #include "hw/hw.h" 24 #include "hw/irq.h" 25 #include "hw/arm/omap.h" 26 27 struct clk { 28 const char *name; 29 const char *alias; 30 struct clk *parent; 31 struct clk *child1; 32 struct clk *sibling; 33 #define ALWAYS_ENABLED (1 << 0) 34 #define CLOCK_IN_OMAP310 (1 << 10) 35 #define CLOCK_IN_OMAP730 (1 << 11) 36 #define CLOCK_IN_OMAP1510 (1 << 12) 37 #define CLOCK_IN_OMAP16XX (1 << 13) 38 uint32_t flags; 39 int id; 40 41 int running; /* Is currently ticking */ 42 int enabled; /* Is enabled, regardless of its input clk */ 43 unsigned long rate; /* Current rate (if .running) */ 44 unsigned int divisor; /* Rate relative to input (if .enabled) */ 45 unsigned int multiplier; /* Rate relative to input (if .enabled) */ 46 qemu_irq users[16]; /* Who to notify on change */ 47 int usecount; /* Automatically idle when unused */ 48 }; 49 50 static struct clk xtal_osc12m = { 51 .name = "xtal_osc_12m", 52 .rate = 12000000, 53 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 54 }; 55 56 static struct clk xtal_osc32k = { 57 .name = "xtal_osc_32k", 58 .rate = 32768, 59 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 60 }; 61 62 static struct clk ck_ref = { 63 .name = "ck_ref", 64 .alias = "clkin", 65 .parent = &xtal_osc12m, 66 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 67 ALWAYS_ENABLED, 68 }; 69 70 /* If a dpll is disabled it becomes a bypass, child clocks don't stop */ 71 static struct clk dpll1 = { 72 .name = "dpll1", 73 .parent = &ck_ref, 74 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 75 ALWAYS_ENABLED, 76 }; 77 78 static struct clk dpll2 = { 79 .name = "dpll2", 80 .parent = &ck_ref, 81 .flags = CLOCK_IN_OMAP310 | ALWAYS_ENABLED, 82 }; 83 84 static struct clk dpll3 = { 85 .name = "dpll3", 86 .parent = &ck_ref, 87 .flags = CLOCK_IN_OMAP310 | ALWAYS_ENABLED, 88 }; 89 90 static struct clk dpll4 = { 91 .name = "dpll4", 92 .parent = &ck_ref, 93 .multiplier = 4, 94 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 95 }; 96 97 static struct clk apll = { 98 .name = "apll", 99 .parent = &ck_ref, 100 .multiplier = 48, 101 .divisor = 12, 102 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 103 }; 104 105 static struct clk ck_48m = { 106 .name = "ck_48m", 107 .parent = &dpll4, /* either dpll4 or apll */ 108 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 109 }; 110 111 static struct clk ck_dpll1out = { 112 .name = "ck_dpll1out", 113 .parent = &dpll1, 114 .flags = CLOCK_IN_OMAP16XX, 115 }; 116 117 static struct clk sossi_ck = { 118 .name = "ck_sossi", 119 .parent = &ck_dpll1out, 120 .flags = CLOCK_IN_OMAP16XX, 121 }; 122 123 static struct clk clkm1 = { 124 .name = "clkm1", 125 .alias = "ck_gen1", 126 .parent = &dpll1, 127 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 128 ALWAYS_ENABLED, 129 }; 130 131 static struct clk clkm2 = { 132 .name = "clkm2", 133 .alias = "ck_gen2", 134 .parent = &dpll1, 135 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 136 ALWAYS_ENABLED, 137 }; 138 139 static struct clk clkm3 = { 140 .name = "clkm3", 141 .alias = "ck_gen3", 142 .parent = &dpll1, /* either dpll1 or ck_ref */ 143 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 144 ALWAYS_ENABLED, 145 }; 146 147 static struct clk arm_ck = { 148 .name = "arm_ck", 149 .alias = "mpu_ck", 150 .parent = &clkm1, 151 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 152 ALWAYS_ENABLED, 153 }; 154 155 static struct clk armper_ck = { 156 .name = "armper_ck", 157 .alias = "mpuper_ck", 158 .parent = &clkm1, 159 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 160 }; 161 162 static struct clk arm_gpio_ck = { 163 .name = "arm_gpio_ck", 164 .alias = "mpu_gpio_ck", 165 .parent = &clkm1, 166 .divisor = 1, 167 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, 168 }; 169 170 static struct clk armxor_ck = { 171 .name = "armxor_ck", 172 .alias = "mpuxor_ck", 173 .parent = &ck_ref, 174 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 175 }; 176 177 static struct clk armtim_ck = { 178 .name = "armtim_ck", 179 .alias = "mputim_ck", 180 .parent = &ck_ref, /* either CLKIN or DPLL1 */ 181 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 182 }; 183 184 static struct clk armwdt_ck = { 185 .name = "armwdt_ck", 186 .alias = "mpuwd_ck", 187 .parent = &clkm1, 188 .divisor = 14, 189 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 190 ALWAYS_ENABLED, 191 }; 192 193 static struct clk arminth_ck16xx = { 194 .name = "arminth_ck", 195 .parent = &arm_ck, 196 .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, 197 /* Note: On 16xx the frequency can be divided by 2 by programming 198 * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 199 * 200 * 1510 version is in TC clocks. 201 */ 202 }; 203 204 static struct clk dsp_ck = { 205 .name = "dsp_ck", 206 .parent = &clkm2, 207 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, 208 }; 209 210 static struct clk dspmmu_ck = { 211 .name = "dspmmu_ck", 212 .parent = &clkm2, 213 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | 214 ALWAYS_ENABLED, 215 }; 216 217 static struct clk dspper_ck = { 218 .name = "dspper_ck", 219 .parent = &clkm2, 220 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, 221 }; 222 223 static struct clk dspxor_ck = { 224 .name = "dspxor_ck", 225 .parent = &ck_ref, 226 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, 227 }; 228 229 static struct clk dsptim_ck = { 230 .name = "dsptim_ck", 231 .parent = &ck_ref, 232 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, 233 }; 234 235 static struct clk tc_ck = { 236 .name = "tc_ck", 237 .parent = &clkm3, 238 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | 239 CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 | 240 ALWAYS_ENABLED, 241 }; 242 243 static struct clk arminth_ck15xx = { 244 .name = "arminth_ck", 245 .parent = &tc_ck, 246 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, 247 /* Note: On 1510 the frequency follows TC_CK 248 * 249 * 16xx version is in MPU clocks. 250 */ 251 }; 252 253 static struct clk tipb_ck = { 254 /* No-idle controlled by "tc_ck" */ 255 .name = "tipb_ck", 256 .parent = &tc_ck, 257 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, 258 }; 259 260 static struct clk l3_ocpi_ck = { 261 /* No-idle controlled by "tc_ck" */ 262 .name = "l3_ocpi_ck", 263 .parent = &tc_ck, 264 .flags = CLOCK_IN_OMAP16XX, 265 }; 266 267 static struct clk tc1_ck = { 268 .name = "tc1_ck", 269 .parent = &tc_ck, 270 .flags = CLOCK_IN_OMAP16XX, 271 }; 272 273 static struct clk tc2_ck = { 274 .name = "tc2_ck", 275 .parent = &tc_ck, 276 .flags = CLOCK_IN_OMAP16XX, 277 }; 278 279 static struct clk dma_ck = { 280 /* No-idle controlled by "tc_ck" */ 281 .name = "dma_ck", 282 .parent = &tc_ck, 283 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 284 ALWAYS_ENABLED, 285 }; 286 287 static struct clk dma_lcdfree_ck = { 288 .name = "dma_lcdfree_ck", 289 .parent = &tc_ck, 290 .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, 291 }; 292 293 static struct clk api_ck = { 294 .name = "api_ck", 295 .alias = "mpui_ck", 296 .parent = &tc_ck, 297 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 298 }; 299 300 static struct clk lb_ck = { 301 .name = "lb_ck", 302 .parent = &tc_ck, 303 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, 304 }; 305 306 static struct clk lbfree_ck = { 307 .name = "lbfree_ck", 308 .parent = &tc_ck, 309 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, 310 }; 311 312 static struct clk hsab_ck = { 313 .name = "hsab_ck", 314 .parent = &tc_ck, 315 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, 316 }; 317 318 static struct clk rhea1_ck = { 319 .name = "rhea1_ck", 320 .parent = &tc_ck, 321 .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, 322 }; 323 324 static struct clk rhea2_ck = { 325 .name = "rhea2_ck", 326 .parent = &tc_ck, 327 .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, 328 }; 329 330 static struct clk lcd_ck_16xx = { 331 .name = "lcd_ck", 332 .parent = &clkm3, 333 .flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730, 334 }; 335 336 static struct clk lcd_ck_1510 = { 337 .name = "lcd_ck", 338 .parent = &clkm3, 339 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, 340 }; 341 342 static struct clk uart1_1510 = { 343 .name = "uart1_ck", 344 /* Direct from ULPD, no real parent */ 345 .parent = &armper_ck, /* either armper_ck or dpll4 */ 346 .rate = 12000000, 347 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, 348 }; 349 350 static struct clk uart1_16xx = { 351 .name = "uart1_ck", 352 /* Direct from ULPD, no real parent */ 353 .parent = &armper_ck, 354 .rate = 48000000, 355 .flags = CLOCK_IN_OMAP16XX, 356 }; 357 358 static struct clk uart2_ck = { 359 .name = "uart2_ck", 360 /* Direct from ULPD, no real parent */ 361 .parent = &armper_ck, /* either armper_ck or dpll4 */ 362 .rate = 12000000, 363 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | 364 ALWAYS_ENABLED, 365 }; 366 367 static struct clk uart3_1510 = { 368 .name = "uart3_ck", 369 /* Direct from ULPD, no real parent */ 370 .parent = &armper_ck, /* either armper_ck or dpll4 */ 371 .rate = 12000000, 372 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, 373 }; 374 375 static struct clk uart3_16xx = { 376 .name = "uart3_ck", 377 /* Direct from ULPD, no real parent */ 378 .parent = &armper_ck, 379 .rate = 48000000, 380 .flags = CLOCK_IN_OMAP16XX, 381 }; 382 383 static struct clk usb_clk0 = { /* 6 MHz output on W4_USB_CLK0 */ 384 .name = "usb_clk0", 385 .alias = "usb.clko", 386 /* Direct from ULPD, no parent */ 387 .rate = 6000000, 388 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 389 }; 390 391 static struct clk usb_hhc_ck1510 = { 392 .name = "usb_hhc_ck", 393 /* Direct from ULPD, no parent */ 394 .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ 395 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, 396 }; 397 398 static struct clk usb_hhc_ck16xx = { 399 .name = "usb_hhc_ck", 400 /* Direct from ULPD, no parent */ 401 .rate = 48000000, 402 /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ 403 .flags = CLOCK_IN_OMAP16XX, 404 }; 405 406 static struct clk usb_w2fc_mclk = { 407 .name = "usb_w2fc_mclk", 408 .alias = "usb_w2fc_ck", 409 .parent = &ck_48m, 410 .rate = 48000000, 411 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, 412 }; 413 414 static struct clk mclk_1510 = { 415 .name = "mclk", 416 /* Direct from ULPD, no parent. May be enabled by ext hardware. */ 417 .rate = 12000000, 418 .flags = CLOCK_IN_OMAP1510, 419 }; 420 421 static struct clk bclk_310 = { 422 .name = "bt_mclk_out", /* Alias midi_mclk_out? */ 423 .parent = &armper_ck, 424 .flags = CLOCK_IN_OMAP310, 425 }; 426 427 static struct clk mclk_310 = { 428 .name = "com_mclk_out", 429 .parent = &armper_ck, 430 .flags = CLOCK_IN_OMAP310, 431 }; 432 433 static struct clk mclk_16xx = { 434 .name = "mclk", 435 /* Direct from ULPD, no parent. May be enabled by ext hardware. */ 436 .flags = CLOCK_IN_OMAP16XX, 437 }; 438 439 static struct clk bclk_1510 = { 440 .name = "bclk", 441 /* Direct from ULPD, no parent. May be enabled by ext hardware. */ 442 .rate = 12000000, 443 .flags = CLOCK_IN_OMAP1510, 444 }; 445 446 static struct clk bclk_16xx = { 447 .name = "bclk", 448 /* Direct from ULPD, no parent. May be enabled by ext hardware. */ 449 .flags = CLOCK_IN_OMAP16XX, 450 }; 451 452 static struct clk mmc1_ck = { 453 .name = "mmc_ck", 454 .id = 1, 455 /* Functional clock is direct from ULPD, interface clock is ARMPER */ 456 .parent = &armper_ck, /* either armper_ck or dpll4 */ 457 .rate = 48000000, 458 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310, 459 }; 460 461 static struct clk mmc2_ck = { 462 .name = "mmc_ck", 463 .id = 2, 464 /* Functional clock is direct from ULPD, interface clock is ARMPER */ 465 .parent = &armper_ck, 466 .rate = 48000000, 467 .flags = CLOCK_IN_OMAP16XX, 468 }; 469 470 static struct clk cam_mclk = { 471 .name = "cam.mclk", 472 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, 473 .rate = 12000000, 474 }; 475 476 static struct clk cam_exclk = { 477 .name = "cam.exclk", 478 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, 479 /* Either 12M from cam.mclk or 48M from dpll4 */ 480 .parent = &cam_mclk, 481 }; 482 483 static struct clk cam_lclk = { 484 .name = "cam.lclk", 485 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, 486 }; 487 488 static struct clk i2c_fck = { 489 .name = "i2c_fck", 490 .id = 1, 491 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | 492 ALWAYS_ENABLED, 493 .parent = &armxor_ck, 494 }; 495 496 static struct clk i2c_ick = { 497 .name = "i2c_ick", 498 .id = 1, 499 .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, 500 .parent = &armper_ck, 501 }; 502 503 static struct clk clk32k = { 504 .name = "clk32-kHz", 505 .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | 506 ALWAYS_ENABLED, 507 .parent = &xtal_osc32k, 508 }; 509 510 static struct clk *onchip_clks[] = { 511 /* OMAP 1 */ 512 513 /* non-ULPD clocks */ 514 &xtal_osc12m, 515 &xtal_osc32k, 516 &ck_ref, 517 &dpll1, 518 &dpll2, 519 &dpll3, 520 &dpll4, 521 &apll, 522 &ck_48m, 523 /* CK_GEN1 clocks */ 524 &clkm1, 525 &ck_dpll1out, 526 &sossi_ck, 527 &arm_ck, 528 &armper_ck, 529 &arm_gpio_ck, 530 &armxor_ck, 531 &armtim_ck, 532 &armwdt_ck, 533 &arminth_ck15xx, &arminth_ck16xx, 534 /* CK_GEN2 clocks */ 535 &clkm2, 536 &dsp_ck, 537 &dspmmu_ck, 538 &dspper_ck, 539 &dspxor_ck, 540 &dsptim_ck, 541 /* CK_GEN3 clocks */ 542 &clkm3, 543 &tc_ck, 544 &tipb_ck, 545 &l3_ocpi_ck, 546 &tc1_ck, 547 &tc2_ck, 548 &dma_ck, 549 &dma_lcdfree_ck, 550 &api_ck, 551 &lb_ck, 552 &lbfree_ck, 553 &hsab_ck, 554 &rhea1_ck, 555 &rhea2_ck, 556 &lcd_ck_16xx, 557 &lcd_ck_1510, 558 /* ULPD clocks */ 559 &uart1_1510, 560 &uart1_16xx, 561 &uart2_ck, 562 &uart3_1510, 563 &uart3_16xx, 564 &usb_clk0, 565 &usb_hhc_ck1510, &usb_hhc_ck16xx, 566 &mclk_1510, &mclk_16xx, &mclk_310, 567 &bclk_1510, &bclk_16xx, &bclk_310, 568 &mmc1_ck, 569 &mmc2_ck, 570 &cam_mclk, 571 &cam_exclk, 572 &cam_lclk, 573 &clk32k, 574 &usb_w2fc_mclk, 575 /* Virtual clocks */ 576 &i2c_fck, 577 &i2c_ick, 578 579 NULL 580 }; 581 582 void omap_clk_adduser(struct clk *clk, qemu_irq user) 583 { 584 qemu_irq *i; 585 586 for (i = clk->users; *i; i ++); 587 *i = user; 588 } 589 590 struct clk *omap_findclk(struct omap_mpu_state_s *mpu, const char *name) 591 { 592 struct clk *i; 593 594 for (i = mpu->clks; i->name; i ++) 595 if (!strcmp(i->name, name) || (i->alias && !strcmp(i->alias, name))) 596 return i; 597 hw_error("%s: %s not found\n", __func__, name); 598 } 599 600 void omap_clk_get(struct clk *clk) 601 { 602 clk->usecount ++; 603 } 604 605 void omap_clk_put(struct clk *clk) 606 { 607 if (!(clk->usecount --)) 608 hw_error("%s: %s is not in use\n", __func__, clk->name); 609 } 610 611 static void omap_clk_update(struct clk *clk) 612 { 613 int parent, running; 614 qemu_irq *user; 615 struct clk *i; 616 617 if (clk->parent) 618 parent = clk->parent->running; 619 else 620 parent = 1; 621 622 running = parent && (clk->enabled || 623 ((clk->flags & ALWAYS_ENABLED) && clk->usecount)); 624 if (clk->running != running) { 625 clk->running = running; 626 for (user = clk->users; *user; user ++) 627 qemu_set_irq(*user, running); 628 for (i = clk->child1; i; i = i->sibling) 629 omap_clk_update(i); 630 } 631 } 632 633 static void omap_clk_rate_update_full(struct clk *clk, unsigned long int rate, 634 unsigned long int div, unsigned long int mult) 635 { 636 struct clk *i; 637 qemu_irq *user; 638 639 clk->rate = muldiv64(rate, mult, div); 640 if (clk->running) 641 for (user = clk->users; *user; user ++) 642 qemu_irq_raise(*user); 643 for (i = clk->child1; i; i = i->sibling) 644 omap_clk_rate_update_full(i, rate, 645 div * i->divisor, mult * i->multiplier); 646 } 647 648 static void omap_clk_rate_update(struct clk *clk) 649 { 650 struct clk *i; 651 unsigned long int div, mult = div = 1; 652 653 for (i = clk; i->parent; i = i->parent) { 654 div *= i->divisor; 655 mult *= i->multiplier; 656 } 657 658 omap_clk_rate_update_full(clk, i->rate, div, mult); 659 } 660 661 void omap_clk_reparent(struct clk *clk, struct clk *parent) 662 { 663 struct clk **p; 664 665 if (clk->parent) { 666 for (p = &clk->parent->child1; *p != clk; p = &(*p)->sibling); 667 *p = clk->sibling; 668 } 669 670 clk->parent = parent; 671 if (parent) { 672 clk->sibling = parent->child1; 673 parent->child1 = clk; 674 omap_clk_update(clk); 675 omap_clk_rate_update(clk); 676 } else 677 clk->sibling = NULL; 678 } 679 680 void omap_clk_onoff(struct clk *clk, int on) 681 { 682 clk->enabled = on; 683 omap_clk_update(clk); 684 } 685 686 void omap_clk_canidle(struct clk *clk, int can) 687 { 688 if (can) 689 omap_clk_put(clk); 690 else 691 omap_clk_get(clk); 692 } 693 694 void omap_clk_setrate(struct clk *clk, int divide, int multiply) 695 { 696 clk->divisor = divide; 697 clk->multiplier = multiply; 698 omap_clk_rate_update(clk); 699 } 700 701 int64_t omap_clk_getrate(omap_clk clk) 702 { 703 return clk->rate; 704 } 705 706 void omap_clk_init(struct omap_mpu_state_s *mpu) 707 { 708 struct clk **i, *j, *k; 709 int count; 710 int flag; 711 712 if (cpu_is_omap310(mpu)) 713 flag = CLOCK_IN_OMAP310; 714 else if (cpu_is_omap1510(mpu)) 715 flag = CLOCK_IN_OMAP1510; 716 else 717 return; 718 719 for (i = onchip_clks, count = 0; *i; i ++) 720 if ((*i)->flags & flag) 721 count ++; 722 mpu->clks = g_new0(struct clk, count + 1); 723 for (i = onchip_clks, j = mpu->clks; *i; i ++) 724 if ((*i)->flags & flag) { 725 memcpy(j, *i, sizeof(struct clk)); 726 for (k = mpu->clks; k < j; k ++) 727 if (j->parent && !strcmp(j->parent->name, k->name)) { 728 j->parent = k; 729 j->sibling = k->child1; 730 k->child1 = j; 731 } else if (k->parent && !strcmp(k->parent->name, j->name)) { 732 k->parent = j; 733 k->sibling = j->child1; 734 j->child1 = k; 735 } 736 j->divisor = j->divisor ?: 1; 737 j->multiplier = j->multiplier ?: 1; 738 j ++; 739 } 740 for (j = mpu->clks; count --; j ++) { 741 omap_clk_update(j); 742 omap_clk_rate_update(j); 743 } 744 } 745