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 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)
 939