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