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 "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 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
  95static 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
 228static 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
 239static 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
 248static 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
 264static 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
 273static 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
 286static 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
 299static 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
 308static 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
 338static 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
 364static 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
 376static 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
 396static 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
 408static 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
 420static 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
 440static 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
 452static 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
 486static 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
 574static 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
 589static 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
 606static 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
 706static 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
 802static 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
 819static 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
 836static 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
 863static 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
 875static 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
 883static void imx6ul_ccm_register_types(void)
 884{
 885    type_register_static(&imx6ul_ccm_info);
 886}
 887
 888type_init(imx6ul_ccm_register_types)
 889