qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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 
     31 static 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 
    104 static 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 
    245 static 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 
    256 static 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 
    271 static 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 
    283 static 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 
    295 static 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 
    323 static 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 
    335 static 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 
    347 static 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 
    359 static 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 
    393 static 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 
    478 static 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 
    491 static 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 
    507 static 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 
    599 static 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 
    697 static 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 
    714 static 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 
    731 static 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 
    758 static 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 
    770 static 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 
    778 static void imx6_ccm_register_types(void)
    779 {
    780     type_register_static(&imx6_ccm_info);
    781 }
    782 
    783 type_init(imx6_ccm_register_types)