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