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