qemu/hw/misc/imx6ul_ccm.c
<<
>>
Prefs
   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
  21static 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
  94static 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
 227static 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
 238static 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
 247static 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
 263static 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
 272static 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
 285static 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
 298static 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
 307static 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
 337static 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
 363static 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
 375static 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
 395static 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
 407static 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
 419static 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
 439static 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
 451static 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
 485static 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
 573static 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
 588static 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
 605static 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
 705static 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
 801static 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
 818static 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
 835static 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
 862static 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
 874static 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
 882static void imx6ul_ccm_register_types(void)
 883{
 884    type_register_static(&imx6ul_ccm_info);
 885}
 886
 887type_init(imx6ul_ccm_register_types)
 888