cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

imx6_ccm.c (22963B)


      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)