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