1 /* 2 * IMX6UL Clock Control Module 3 * 4 * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net> 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 * 9 * To get the timer frequencies right, we need to emulate at least part of 10 * the CCM. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "hw/registerfields.h" 15 #include "migration/vmstate.h" 16 #include "hw/misc/imx6ul_ccm.h" 17 #include "qemu/log.h" 18 #include "qemu/module.h" 19 20 #include "trace.h" 21 22 static const char *imx6ul_ccm_reg_name(uint32_t reg) 23 { 24 static char unknown[20]; 25 26 switch (reg) { 27 case CCM_CCR: 28 return "CCR"; 29 case CCM_CCDR: 30 return "CCDR"; 31 case CCM_CSR: 32 return "CSR"; 33 case CCM_CCSR: 34 return "CCSR"; 35 case CCM_CACRR: 36 return "CACRR"; 37 case CCM_CBCDR: 38 return "CBCDR"; 39 case CCM_CBCMR: 40 return "CBCMR"; 41 case CCM_CSCMR1: 42 return "CSCMR1"; 43 case CCM_CSCMR2: 44 return "CSCMR2"; 45 case CCM_CSCDR1: 46 return "CSCDR1"; 47 case CCM_CS1CDR: 48 return "CS1CDR"; 49 case CCM_CS2CDR: 50 return "CS2CDR"; 51 case CCM_CDCDR: 52 return "CDCDR"; 53 case CCM_CHSCCDR: 54 return "CHSCCDR"; 55 case CCM_CSCDR2: 56 return "CSCDR2"; 57 case CCM_CSCDR3: 58 return "CSCDR3"; 59 case CCM_CDHIPR: 60 return "CDHIPR"; 61 case CCM_CTOR: 62 return "CTOR"; 63 case CCM_CLPCR: 64 return "CLPCR"; 65 case CCM_CISR: 66 return "CISR"; 67 case CCM_CIMR: 68 return "CIMR"; 69 case CCM_CCOSR: 70 return "CCOSR"; 71 case CCM_CGPR: 72 return "CGPR"; 73 case CCM_CCGR0: 74 return "CCGR0"; 75 case CCM_CCGR1: 76 return "CCGR1"; 77 case CCM_CCGR2: 78 return "CCGR2"; 79 case CCM_CCGR3: 80 return "CCGR3"; 81 case CCM_CCGR4: 82 return "CCGR4"; 83 case CCM_CCGR5: 84 return "CCGR5"; 85 case CCM_CCGR6: 86 return "CCGR6"; 87 case CCM_CMEOR: 88 return "CMEOR"; 89 default: 90 sprintf(unknown, "%d ?", reg); 91 return unknown; 92 } 93 } 94 95 static const char *imx6ul_analog_reg_name(uint32_t reg) 96 { 97 static char unknown[20]; 98 99 switch (reg) { 100 case CCM_ANALOG_PLL_ARM: 101 return "PLL_ARM"; 102 case CCM_ANALOG_PLL_ARM_SET: 103 return "PLL_ARM_SET"; 104 case CCM_ANALOG_PLL_ARM_CLR: 105 return "PLL_ARM_CLR"; 106 case CCM_ANALOG_PLL_ARM_TOG: 107 return "PLL_ARM_TOG"; 108 case CCM_ANALOG_PLL_USB1: 109 return "PLL_USB1"; 110 case CCM_ANALOG_PLL_USB1_SET: 111 return "PLL_USB1_SET"; 112 case CCM_ANALOG_PLL_USB1_CLR: 113 return "PLL_USB1_CLR"; 114 case CCM_ANALOG_PLL_USB1_TOG: 115 return "PLL_USB1_TOG"; 116 case CCM_ANALOG_PLL_USB2: 117 return "PLL_USB2"; 118 case CCM_ANALOG_PLL_USB2_SET: 119 return "PLL_USB2_SET"; 120 case CCM_ANALOG_PLL_USB2_CLR: 121 return "PLL_USB2_CLR"; 122 case CCM_ANALOG_PLL_USB2_TOG: 123 return "PLL_USB2_TOG"; 124 case CCM_ANALOG_PLL_SYS: 125 return "PLL_SYS"; 126 case CCM_ANALOG_PLL_SYS_SET: 127 return "PLL_SYS_SET"; 128 case CCM_ANALOG_PLL_SYS_CLR: 129 return "PLL_SYS_CLR"; 130 case CCM_ANALOG_PLL_SYS_TOG: 131 return "PLL_SYS_TOG"; 132 case CCM_ANALOG_PLL_SYS_SS: 133 return "PLL_SYS_SS"; 134 case CCM_ANALOG_PLL_SYS_NUM: 135 return "PLL_SYS_NUM"; 136 case CCM_ANALOG_PLL_SYS_DENOM: 137 return "PLL_SYS_DENOM"; 138 case CCM_ANALOG_PLL_AUDIO: 139 return "PLL_AUDIO"; 140 case CCM_ANALOG_PLL_AUDIO_SET: 141 return "PLL_AUDIO_SET"; 142 case CCM_ANALOG_PLL_AUDIO_CLR: 143 return "PLL_AUDIO_CLR"; 144 case CCM_ANALOG_PLL_AUDIO_TOG: 145 return "PLL_AUDIO_TOG"; 146 case CCM_ANALOG_PLL_AUDIO_NUM: 147 return "PLL_AUDIO_NUM"; 148 case CCM_ANALOG_PLL_AUDIO_DENOM: 149 return "PLL_AUDIO_DENOM"; 150 case CCM_ANALOG_PLL_VIDEO: 151 return "PLL_VIDEO"; 152 case CCM_ANALOG_PLL_VIDEO_SET: 153 return "PLL_VIDEO_SET"; 154 case CCM_ANALOG_PLL_VIDEO_CLR: 155 return "PLL_VIDEO_CLR"; 156 case CCM_ANALOG_PLL_VIDEO_TOG: 157 return "PLL_VIDEO_TOG"; 158 case CCM_ANALOG_PLL_VIDEO_NUM: 159 return "PLL_VIDEO_NUM"; 160 case CCM_ANALOG_PLL_VIDEO_DENOM: 161 return "PLL_VIDEO_DENOM"; 162 case CCM_ANALOG_PLL_ENET: 163 return "PLL_ENET"; 164 case CCM_ANALOG_PLL_ENET_SET: 165 return "PLL_ENET_SET"; 166 case CCM_ANALOG_PLL_ENET_CLR: 167 return "PLL_ENET_CLR"; 168 case CCM_ANALOG_PLL_ENET_TOG: 169 return "PLL_ENET_TOG"; 170 case CCM_ANALOG_PFD_480: 171 return "PFD_480"; 172 case CCM_ANALOG_PFD_480_SET: 173 return "PFD_480_SET"; 174 case CCM_ANALOG_PFD_480_CLR: 175 return "PFD_480_CLR"; 176 case CCM_ANALOG_PFD_480_TOG: 177 return "PFD_480_TOG"; 178 case CCM_ANALOG_PFD_528: 179 return "PFD_528"; 180 case CCM_ANALOG_PFD_528_SET: 181 return "PFD_528_SET"; 182 case CCM_ANALOG_PFD_528_CLR: 183 return "PFD_528_CLR"; 184 case CCM_ANALOG_PFD_528_TOG: 185 return "PFD_528_TOG"; 186 case CCM_ANALOG_MISC0: 187 return "MISC0"; 188 case CCM_ANALOG_MISC0_SET: 189 return "MISC0_SET"; 190 case CCM_ANALOG_MISC0_CLR: 191 return "MISC0_CLR"; 192 case CCM_ANALOG_MISC0_TOG: 193 return "MISC0_TOG"; 194 case CCM_ANALOG_MISC2: 195 return "MISC2"; 196 case CCM_ANALOG_MISC2_SET: 197 return "MISC2_SET"; 198 case CCM_ANALOG_MISC2_CLR: 199 return "MISC2_CLR"; 200 case CCM_ANALOG_MISC2_TOG: 201 return "MISC2_TOG"; 202 case PMU_REG_1P1: 203 return "PMU_REG_1P1"; 204 case PMU_REG_3P0: 205 return "PMU_REG_3P0"; 206 case PMU_REG_2P5: 207 return "PMU_REG_2P5"; 208 case PMU_REG_CORE: 209 return "PMU_REG_CORE"; 210 case PMU_MISC1: 211 return "PMU_MISC1"; 212 case PMU_MISC1_SET: 213 return "PMU_MISC1_SET"; 214 case PMU_MISC1_CLR: 215 return "PMU_MISC1_CLR"; 216 case PMU_MISC1_TOG: 217 return "PMU_MISC1_TOG"; 218 case USB_ANALOG_DIGPROG: 219 return "USB_ANALOG_DIGPROG"; 220 default: 221 sprintf(unknown, "%d ?", reg); 222 return unknown; 223 } 224 } 225 226 #define CKIH_FREQ 24000000 /* 24MHz crystal input */ 227 228 static const VMStateDescription vmstate_imx6ul_ccm = { 229 .name = TYPE_IMX6UL_CCM, 230 .version_id = 1, 231 .minimum_version_id = 1, 232 .fields = (VMStateField[]) { 233 VMSTATE_UINT32_ARRAY(ccm, IMX6ULCCMState, CCM_MAX), 234 VMSTATE_UINT32_ARRAY(analog, IMX6ULCCMState, CCM_ANALOG_MAX), 235 VMSTATE_END_OF_LIST() 236 }, 237 }; 238 239 static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState *dev) 240 { 241 uint64_t freq = CKIH_FREQ; 242 243 trace_ccm_freq((uint32_t)freq); 244 245 return freq; 246 } 247 248 static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState *dev) 249 { 250 uint64_t freq = imx6ul_analog_get_osc_clk(dev); 251 252 if (FIELD_EX32(dev->analog[CCM_ANALOG_PLL_SYS], 253 ANALOG_PLL_SYS, DIV_SELECT)) { 254 freq *= 22; 255 } else { 256 freq *= 20; 257 } 258 259 trace_ccm_freq((uint32_t)freq); 260 261 return freq; 262 } 263 264 static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState *dev) 265 { 266 uint64_t freq = imx6ul_analog_get_osc_clk(dev) * 20; 267 268 trace_ccm_freq((uint32_t)freq); 269 270 return freq; 271 } 272 273 static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState *dev) 274 { 275 uint64_t freq = 0; 276 277 freq = imx6ul_analog_get_pll2_clk(dev) * 18 278 / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528], 279 ANALOG_PFD_528, PFD0_FRAC); 280 281 trace_ccm_freq((uint32_t)freq); 282 283 return freq; 284 } 285 286 static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState *dev) 287 { 288 uint64_t freq = 0; 289 290 freq = imx6ul_analog_get_pll2_clk(dev) * 18 291 / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528], 292 ANALOG_PFD_528, PFD2_FRAC); 293 294 trace_ccm_freq((uint32_t)freq); 295 296 return freq; 297 } 298 299 static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState *dev) 300 { 301 uint64_t freq = 0; 302 303 trace_ccm_freq((uint32_t)freq); 304 305 return freq; 306 } 307 308 static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState *dev) 309 { 310 uint64_t freq = 0; 311 312 switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PERIPH_CLK2_SEL)) { 313 case 0: 314 freq = imx6ul_analog_get_pll3_clk(dev); 315 break; 316 case 1: 317 freq = imx6ul_analog_get_osc_clk(dev); 318 break; 319 case 2: 320 freq = imx6ul_analog_pll2_bypass_clk(dev); 321 break; 322 case 3: 323 /* We should never get there as 3 is a reserved value */ 324 qemu_log_mask(LOG_GUEST_ERROR, 325 "[%s]%s: unsupported PERIPH_CLK2_SEL value 3\n", 326 TYPE_IMX6UL_CCM, __func__); 327 /* freq is set to 0 as we don't know what it should be */ 328 break; 329 default: 330 g_assert_not_reached(); 331 } 332 333 trace_ccm_freq((uint32_t)freq); 334 335 return freq; 336 } 337 338 static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState *dev) 339 { 340 uint64_t freq = 0; 341 342 switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PRE_PERIPH_CLK_SEL)) { 343 case 0: 344 freq = imx6ul_analog_get_pll2_clk(dev); 345 break; 346 case 1: 347 freq = imx6ul_analog_get_pll2_pfd2_clk(dev); 348 break; 349 case 2: 350 freq = imx6ul_analog_get_pll2_pfd0_clk(dev); 351 break; 352 case 3: 353 freq = imx6ul_analog_get_pll2_pfd2_clk(dev) / 2; 354 break; 355 default: 356 g_assert_not_reached(); 357 } 358 359 trace_ccm_freq((uint32_t)freq); 360 361 return freq; 362 } 363 364 static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState *dev) 365 { 366 uint64_t freq = 0; 367 368 freq = imx6ul_ccm_get_periph_clk2_sel_clk(dev) 369 / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK2_PODF)); 370 371 trace_ccm_freq((uint32_t)freq); 372 373 return freq; 374 } 375 376 static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState *dev) 377 { 378 uint64_t freq = 0; 379 380 switch (FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK_SEL)) { 381 case 0: 382 freq = imx6ul_ccm_get_periph_clk_sel_clk(dev); 383 break; 384 case 1: 385 freq = imx6ul_ccm_get_periph_clk2_clk(dev); 386 break; 387 default: 388 g_assert_not_reached(); 389 } 390 391 trace_ccm_freq((uint32_t)freq); 392 393 return freq; 394 } 395 396 static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState *dev) 397 { 398 uint64_t freq = 0; 399 400 freq = imx6ul_ccm_get_periph_sel_clk(dev) 401 / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, AHB_PODF)); 402 403 trace_ccm_freq((uint32_t)freq); 404 405 return freq; 406 } 407 408 static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState *dev) 409 { 410 uint64_t freq = 0; 411 412 freq = imx6ul_ccm_get_ahb_clk(dev) 413 / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, IPG_PODF)); 414 415 trace_ccm_freq((uint32_t)freq); 416 417 return freq; 418 } 419 420 static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState *dev) 421 { 422 uint64_t freq = 0; 423 424 switch (FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_CLK_SEL)) { 425 case 0: 426 freq = imx6ul_ccm_get_ipg_clk(dev); 427 break; 428 case 1: 429 freq = imx6ul_analog_get_osc_clk(dev); 430 break; 431 default: 432 g_assert_not_reached(); 433 } 434 435 trace_ccm_freq((uint32_t)freq); 436 437 return freq; 438 } 439 440 static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState *dev) 441 { 442 uint64_t freq = 0; 443 444 freq = imx6ul_ccm_get_per_sel_clk(dev) 445 / (1 + FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_PODF)); 446 447 trace_ccm_freq((uint32_t)freq); 448 449 return freq; 450 } 451 452 static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) 453 { 454 uint32_t freq = 0; 455 IMX6ULCCMState *s = IMX6UL_CCM(dev); 456 457 switch (clock) { 458 case CLK_NONE: 459 break; 460 case CLK_IPG: 461 freq = imx6ul_ccm_get_ipg_clk(s); 462 break; 463 case CLK_IPG_HIGH: 464 freq = imx6ul_ccm_get_per_clk(s); 465 break; 466 case CLK_32k: 467 freq = CKIL_FREQ; 468 break; 469 case CLK_HIGH: 470 freq = CKIH_FREQ; 471 break; 472 case CLK_HIGH_DIV: 473 freq = CKIH_FREQ / 8; 474 break; 475 default: 476 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", 477 TYPE_IMX6UL_CCM, __func__, clock); 478 break; 479 } 480 481 trace_ccm_clock_freq(clock, freq); 482 483 return freq; 484 } 485 486 static void imx6ul_ccm_reset(DeviceState *dev) 487 { 488 IMX6ULCCMState *s = IMX6UL_CCM(dev); 489 490 trace_ccm_entry(); 491 492 s->ccm[CCM_CCR] = 0x0401167F; 493 s->ccm[CCM_CCDR] = 0x00000000; 494 s->ccm[CCM_CSR] = 0x00000010; 495 s->ccm[CCM_CCSR] = 0x00000100; 496 s->ccm[CCM_CACRR] = 0x00000000; 497 s->ccm[CCM_CBCDR] = 0x00018D00; 498 s->ccm[CCM_CBCMR] = 0x24860324; 499 s->ccm[CCM_CSCMR1] = 0x04900080; 500 s->ccm[CCM_CSCMR2] = 0x03192F06; 501 s->ccm[CCM_CSCDR1] = 0x00490B00; 502 s->ccm[CCM_CS1CDR] = 0x0EC102C1; 503 s->ccm[CCM_CS2CDR] = 0x000336C1; 504 s->ccm[CCM_CDCDR] = 0x33F71F92; 505 s->ccm[CCM_CHSCCDR] = 0x000248A4; 506 s->ccm[CCM_CSCDR2] = 0x00029B48; 507 s->ccm[CCM_CSCDR3] = 0x00014841; 508 s->ccm[CCM_CDHIPR] = 0x00000000; 509 s->ccm[CCM_CTOR] = 0x00000000; 510 s->ccm[CCM_CLPCR] = 0x00000079; 511 s->ccm[CCM_CISR] = 0x00000000; 512 s->ccm[CCM_CIMR] = 0xFFFFFFFF; 513 s->ccm[CCM_CCOSR] = 0x000A0001; 514 s->ccm[CCM_CGPR] = 0x0000FE62; 515 s->ccm[CCM_CCGR0] = 0xFFFFFFFF; 516 s->ccm[CCM_CCGR1] = 0xFFFFFFFF; 517 s->ccm[CCM_CCGR2] = 0xFC3FFFFF; 518 s->ccm[CCM_CCGR3] = 0xFFFFFFFF; 519 s->ccm[CCM_CCGR4] = 0xFFFFFFFF; 520 s->ccm[CCM_CCGR5] = 0xFFFFFFFF; 521 s->ccm[CCM_CCGR6] = 0xFFFFFFFF; 522 s->ccm[CCM_CMEOR] = 0xFFFFFFFF; 523 524 s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063; 525 s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000; 526 s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000; 527 s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001; 528 s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000; 529 s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000; 530 s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012; 531 s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006; 532 s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100; 533 s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C; 534 s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C; 535 s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100; 536 s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447; 537 s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001; 538 s->analog[CCM_ANALOG_PFD_480] = 0x1311100C; 539 s->analog[CCM_ANALOG_PFD_528] = 0x1018101B; 540 541 s->analog[PMU_REG_1P1] = 0x00001073; 542 s->analog[PMU_REG_3P0] = 0x00000F74; 543 s->analog[PMU_REG_2P5] = 0x00001073; 544 s->analog[PMU_REG_CORE] = 0x00482012; 545 s->analog[PMU_MISC0] = 0x04000000; 546 s->analog[PMU_MISC1] = 0x00000000; 547 s->analog[PMU_MISC2] = 0x00272727; 548 s->analog[PMU_LOWPWR_CTRL] = 0x00004009; 549 550 s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004; 551 s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000; 552 s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000; 553 s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000; 554 s->analog[USB_ANALOG_USB1_MISC] = 0x00000002; 555 s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004; 556 s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000; 557 s->analog[USB_ANALOG_USB2_MISC] = 0x00000002; 558 s->analog[USB_ANALOG_DIGPROG] = 0x00640000; 559 560 /* all PLLs need to be locked */ 561 s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK; 562 s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK; 563 s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK; 564 s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK; 565 s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK; 566 s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK; 567 s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK; 568 569 s->analog[TEMPMON_TEMPSENSE0] = 0x00000001; 570 s->analog[TEMPMON_TEMPSENSE1] = 0x00000001; 571 s->analog[TEMPMON_TEMPSENSE2] = 0x00000000; 572 } 573 574 static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size) 575 { 576 uint32_t value = 0; 577 uint32_t index = offset >> 2; 578 IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 579 580 assert(index < CCM_MAX); 581 582 value = s->ccm[index]; 583 584 trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value); 585 586 return (uint64_t)value; 587 } 588 589 static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value, 590 unsigned size) 591 { 592 uint32_t index = offset >> 2; 593 IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 594 595 assert(index < CCM_MAX); 596 597 trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value); 598 599 /* 600 * We will do a better implementation later. In particular some bits 601 * cannot be written to. 602 */ 603 s->ccm[index] = (uint32_t)value; 604 } 605 606 static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size) 607 { 608 uint32_t value; 609 uint32_t index = offset >> 2; 610 IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 611 612 assert(index < CCM_ANALOG_MAX); 613 614 switch (index) { 615 case CCM_ANALOG_PLL_ARM_SET: 616 case CCM_ANALOG_PLL_USB1_SET: 617 case CCM_ANALOG_PLL_USB2_SET: 618 case CCM_ANALOG_PLL_SYS_SET: 619 case CCM_ANALOG_PLL_AUDIO_SET: 620 case CCM_ANALOG_PLL_VIDEO_SET: 621 case CCM_ANALOG_PLL_ENET_SET: 622 case CCM_ANALOG_PFD_480_SET: 623 case CCM_ANALOG_PFD_528_SET: 624 case CCM_ANALOG_MISC0_SET: 625 case PMU_MISC1_SET: 626 case CCM_ANALOG_MISC2_SET: 627 case USB_ANALOG_USB1_VBUS_DETECT_SET: 628 case USB_ANALOG_USB1_CHRG_DETECT_SET: 629 case USB_ANALOG_USB1_MISC_SET: 630 case USB_ANALOG_USB2_VBUS_DETECT_SET: 631 case USB_ANALOG_USB2_CHRG_DETECT_SET: 632 case USB_ANALOG_USB2_MISC_SET: 633 case TEMPMON_TEMPSENSE0_SET: 634 case TEMPMON_TEMPSENSE1_SET: 635 case TEMPMON_TEMPSENSE2_SET: 636 /* 637 * All REG_NAME_SET register access are in fact targeting 638 * the REG_NAME register. 639 */ 640 value = s->analog[index - 1]; 641 break; 642 case CCM_ANALOG_PLL_ARM_CLR: 643 case CCM_ANALOG_PLL_USB1_CLR: 644 case CCM_ANALOG_PLL_USB2_CLR: 645 case CCM_ANALOG_PLL_SYS_CLR: 646 case CCM_ANALOG_PLL_AUDIO_CLR: 647 case CCM_ANALOG_PLL_VIDEO_CLR: 648 case CCM_ANALOG_PLL_ENET_CLR: 649 case CCM_ANALOG_PFD_480_CLR: 650 case CCM_ANALOG_PFD_528_CLR: 651 case CCM_ANALOG_MISC0_CLR: 652 case PMU_MISC1_CLR: 653 case CCM_ANALOG_MISC2_CLR: 654 case USB_ANALOG_USB1_VBUS_DETECT_CLR: 655 case USB_ANALOG_USB1_CHRG_DETECT_CLR: 656 case USB_ANALOG_USB1_MISC_CLR: 657 case USB_ANALOG_USB2_VBUS_DETECT_CLR: 658 case USB_ANALOG_USB2_CHRG_DETECT_CLR: 659 case USB_ANALOG_USB2_MISC_CLR: 660 case TEMPMON_TEMPSENSE0_CLR: 661 case TEMPMON_TEMPSENSE1_CLR: 662 case TEMPMON_TEMPSENSE2_CLR: 663 /* 664 * All REG_NAME_CLR register access are in fact targeting 665 * the REG_NAME register. 666 */ 667 value = s->analog[index - 2]; 668 break; 669 case CCM_ANALOG_PLL_ARM_TOG: 670 case CCM_ANALOG_PLL_USB1_TOG: 671 case CCM_ANALOG_PLL_USB2_TOG: 672 case CCM_ANALOG_PLL_SYS_TOG: 673 case CCM_ANALOG_PLL_AUDIO_TOG: 674 case CCM_ANALOG_PLL_VIDEO_TOG: 675 case CCM_ANALOG_PLL_ENET_TOG: 676 case CCM_ANALOG_PFD_480_TOG: 677 case CCM_ANALOG_PFD_528_TOG: 678 case CCM_ANALOG_MISC0_TOG: 679 case PMU_MISC1_TOG: 680 case CCM_ANALOG_MISC2_TOG: 681 case USB_ANALOG_USB1_VBUS_DETECT_TOG: 682 case USB_ANALOG_USB1_CHRG_DETECT_TOG: 683 case USB_ANALOG_USB1_MISC_TOG: 684 case USB_ANALOG_USB2_VBUS_DETECT_TOG: 685 case USB_ANALOG_USB2_CHRG_DETECT_TOG: 686 case USB_ANALOG_USB2_MISC_TOG: 687 case TEMPMON_TEMPSENSE0_TOG: 688 case TEMPMON_TEMPSENSE1_TOG: 689 case TEMPMON_TEMPSENSE2_TOG: 690 /* 691 * All REG_NAME_TOG register access are in fact targeting 692 * the REG_NAME register. 693 */ 694 value = s->analog[index - 3]; 695 break; 696 default: 697 value = s->analog[index]; 698 break; 699 } 700 701 trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value); 702 703 return (uint64_t)value; 704 } 705 706 static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value, 707 unsigned size) 708 { 709 uint32_t index = offset >> 2; 710 IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 711 712 assert(index < CCM_ANALOG_MAX); 713 714 trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value); 715 716 switch (index) { 717 case CCM_ANALOG_PLL_ARM_SET: 718 case CCM_ANALOG_PLL_USB1_SET: 719 case CCM_ANALOG_PLL_USB2_SET: 720 case CCM_ANALOG_PLL_SYS_SET: 721 case CCM_ANALOG_PLL_AUDIO_SET: 722 case CCM_ANALOG_PLL_VIDEO_SET: 723 case CCM_ANALOG_PLL_ENET_SET: 724 case CCM_ANALOG_PFD_480_SET: 725 case CCM_ANALOG_PFD_528_SET: 726 case CCM_ANALOG_MISC0_SET: 727 case PMU_MISC1_SET: 728 case CCM_ANALOG_MISC2_SET: 729 case USB_ANALOG_USB1_VBUS_DETECT_SET: 730 case USB_ANALOG_USB1_CHRG_DETECT_SET: 731 case USB_ANALOG_USB1_MISC_SET: 732 case USB_ANALOG_USB2_VBUS_DETECT_SET: 733 case USB_ANALOG_USB2_CHRG_DETECT_SET: 734 case USB_ANALOG_USB2_MISC_SET: 735 /* 736 * All REG_NAME_SET register access are in fact targeting 737 * the REG_NAME register. So we change the value of the 738 * REG_NAME register, setting bits passed in the value. 739 */ 740 s->analog[index - 1] |= value; 741 break; 742 case CCM_ANALOG_PLL_ARM_CLR: 743 case CCM_ANALOG_PLL_USB1_CLR: 744 case CCM_ANALOG_PLL_USB2_CLR: 745 case CCM_ANALOG_PLL_SYS_CLR: 746 case CCM_ANALOG_PLL_AUDIO_CLR: 747 case CCM_ANALOG_PLL_VIDEO_CLR: 748 case CCM_ANALOG_PLL_ENET_CLR: 749 case CCM_ANALOG_PFD_480_CLR: 750 case CCM_ANALOG_PFD_528_CLR: 751 case CCM_ANALOG_MISC0_CLR: 752 case PMU_MISC1_CLR: 753 case CCM_ANALOG_MISC2_CLR: 754 case USB_ANALOG_USB1_VBUS_DETECT_CLR: 755 case USB_ANALOG_USB1_CHRG_DETECT_CLR: 756 case USB_ANALOG_USB1_MISC_CLR: 757 case USB_ANALOG_USB2_VBUS_DETECT_CLR: 758 case USB_ANALOG_USB2_CHRG_DETECT_CLR: 759 case USB_ANALOG_USB2_MISC_CLR: 760 /* 761 * All REG_NAME_CLR register access are in fact targeting 762 * the REG_NAME register. So we change the value of the 763 * REG_NAME register, unsetting bits passed in the value. 764 */ 765 s->analog[index - 2] &= ~value; 766 break; 767 case CCM_ANALOG_PLL_ARM_TOG: 768 case CCM_ANALOG_PLL_USB1_TOG: 769 case CCM_ANALOG_PLL_USB2_TOG: 770 case CCM_ANALOG_PLL_SYS_TOG: 771 case CCM_ANALOG_PLL_AUDIO_TOG: 772 case CCM_ANALOG_PLL_VIDEO_TOG: 773 case CCM_ANALOG_PLL_ENET_TOG: 774 case CCM_ANALOG_PFD_480_TOG: 775 case CCM_ANALOG_PFD_528_TOG: 776 case CCM_ANALOG_MISC0_TOG: 777 case PMU_MISC1_TOG: 778 case CCM_ANALOG_MISC2_TOG: 779 case USB_ANALOG_USB1_VBUS_DETECT_TOG: 780 case USB_ANALOG_USB1_CHRG_DETECT_TOG: 781 case USB_ANALOG_USB1_MISC_TOG: 782 case USB_ANALOG_USB2_VBUS_DETECT_TOG: 783 case USB_ANALOG_USB2_CHRG_DETECT_TOG: 784 case USB_ANALOG_USB2_MISC_TOG: 785 /* 786 * All REG_NAME_TOG register access are in fact targeting 787 * the REG_NAME register. So we change the value of the 788 * REG_NAME register, toggling bits passed in the value. 789 */ 790 s->analog[index - 3] ^= value; 791 break; 792 default: 793 /* 794 * We will do a better implementation later. In particular some bits 795 * cannot be written to. 796 */ 797 s->analog[index] = value; 798 break; 799 } 800 } 801 802 static const struct MemoryRegionOps imx6ul_ccm_ops = { 803 .read = imx6ul_ccm_read, 804 .write = imx6ul_ccm_write, 805 .endianness = DEVICE_NATIVE_ENDIAN, 806 .valid = { 807 /* 808 * Our device would not work correctly if the guest was doing 809 * unaligned access. This might not be a limitation on the real 810 * device but in practice there is no reason for a guest to access 811 * this device unaligned. 812 */ 813 .min_access_size = 4, 814 .max_access_size = 4, 815 .unaligned = false, 816 }, 817 }; 818 819 static const struct MemoryRegionOps imx6ul_analog_ops = { 820 .read = imx6ul_analog_read, 821 .write = imx6ul_analog_write, 822 .endianness = DEVICE_NATIVE_ENDIAN, 823 .valid = { 824 /* 825 * Our device would not work correctly if the guest was doing 826 * unaligned access. This might not be a limitation on the real 827 * device but in practice there is no reason for a guest to access 828 * this device unaligned. 829 */ 830 .min_access_size = 4, 831 .max_access_size = 4, 832 .unaligned = false, 833 }, 834 }; 835 836 static void imx6ul_ccm_init(Object *obj) 837 { 838 DeviceState *dev = DEVICE(obj); 839 SysBusDevice *sd = SYS_BUS_DEVICE(obj); 840 IMX6ULCCMState *s = IMX6UL_CCM(obj); 841 842 /* initialize a container for the all memory range */ 843 memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000); 844 845 /* We initialize an IO memory region for the CCM part */ 846 memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s, 847 TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t)); 848 849 /* Add the CCM as a subregion at offset 0 */ 850 memory_region_add_subregion(&s->container, 0, &s->ioccm); 851 852 /* We initialize an IO memory region for the ANALOG part */ 853 memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s, 854 TYPE_IMX6UL_CCM ".analog", 855 CCM_ANALOG_MAX * sizeof(uint32_t)); 856 857 /* Add the ANALOG as a subregion at offset 0x4000 */ 858 memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog); 859 860 sysbus_init_mmio(sd, &s->container); 861 } 862 863 static void imx6ul_ccm_class_init(ObjectClass *klass, void *data) 864 { 865 DeviceClass *dc = DEVICE_CLASS(klass); 866 IMXCCMClass *ccm = IMX_CCM_CLASS(klass); 867 868 dc->reset = imx6ul_ccm_reset; 869 dc->vmsd = &vmstate_imx6ul_ccm; 870 dc->desc = "i.MX6UL Clock Control Module"; 871 872 ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency; 873 } 874 875 static const TypeInfo imx6ul_ccm_info = { 876 .name = TYPE_IMX6UL_CCM, 877 .parent = TYPE_IMX_CCM, 878 .instance_size = sizeof(IMX6ULCCMState), 879 .instance_init = imx6ul_ccm_init, 880 .class_init = imx6ul_ccm_class_init, 881 }; 882 883 static void imx6ul_ccm_register_types(void) 884 { 885 type_register_static(&imx6ul_ccm_info); 886 } 887 888 type_init(imx6ul_ccm_register_types) 889