qemu

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

imx6ul_ccm.c (27190B)


      1 /*
      2  * IMX6UL Clock Control Module
      3  *
      4  * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
      5  *
      6  * This work is licensed under the terms of the GNU GPL, version 2 or later.
      7  * See the COPYING file in the top-level directory.
      8  *
      9  * To get the timer frequencies right, we need to emulate at least part of
     10  * the CCM.
     11  */
     12 
     13 #include "qemu/osdep.h"
     14 #include "hw/registerfields.h"
     15 #include "migration/vmstate.h"
     16 #include "hw/misc/imx6ul_ccm.h"
     17 #include "qemu/log.h"
     18 #include "qemu/module.h"
     19 
     20 #include "trace.h"
     21 
     22 static const uint32_t ccm_mask[CCM_MAX] = {
     23     [CCM_CCR] = 0xf01fef80,
     24     [CCM_CCDR] = 0xfffeffff,
     25     [CCM_CSR] = 0xffffffff,
     26     [CCM_CCSR] = 0xfffffef2,
     27     [CCM_CACRR] = 0xfffffff8,
     28     [CCM_CBCDR] = 0xc1f8e000,
     29     [CCM_CBCMR] = 0xfc03cfff,
     30     [CCM_CSCMR1] = 0x80700000,
     31     [CCM_CSCMR2] = 0xe01ff003,
     32     [CCM_CSCDR1] = 0xfe00c780,
     33     [CCM_CS1CDR] = 0xfe00fe00,
     34     [CCM_CS2CDR] = 0xf8007000,
     35     [CCM_CDCDR] = 0xf00fffff,
     36     [CCM_CHSCCDR] = 0xfffc01ff,
     37     [CCM_CSCDR2] = 0xfe0001ff,
     38     [CCM_CSCDR3] = 0xffffc1ff,
     39     [CCM_CDHIPR] = 0xffffffff,
     40     [CCM_CTOR] = 0x00000000,
     41     [CCM_CLPCR] = 0xf39ff01c,
     42     [CCM_CISR] = 0xfb85ffbe,
     43     [CCM_CIMR] = 0xfb85ffbf,
     44     [CCM_CCOSR] = 0xfe00fe00,
     45     [CCM_CGPR] = 0xfffc3fea,
     46     [CCM_CCGR0] = 0x00000000,
     47     [CCM_CCGR1] = 0x00000000,
     48     [CCM_CCGR2] = 0x00000000,
     49     [CCM_CCGR3] = 0x00000000,
     50     [CCM_CCGR4] = 0x00000000,
     51     [CCM_CCGR5] = 0x00000000,
     52     [CCM_CCGR6] = 0x00000000,
     53     [CCM_CMEOR] = 0xafffff1f,
     54 };
     55 
     56 static const uint32_t analog_mask[CCM_ANALOG_MAX] = {
     57     [CCM_ANALOG_PLL_ARM] = 0xfff60f80,
     58     [CCM_ANALOG_PLL_USB1] = 0xfffe0fbc,
     59     [CCM_ANALOG_PLL_USB2] = 0xfffe0fbc,
     60     [CCM_ANALOG_PLL_SYS] = 0xfffa0ffe,
     61     [CCM_ANALOG_PLL_SYS_SS] = 0x00000000,
     62     [CCM_ANALOG_PLL_SYS_NUM] = 0xc0000000,
     63     [CCM_ANALOG_PLL_SYS_DENOM] = 0xc0000000,
     64     [CCM_ANALOG_PLL_AUDIO] = 0xffe20f80,
     65     [CCM_ANALOG_PLL_AUDIO_NUM] = 0xc0000000,
     66     [CCM_ANALOG_PLL_AUDIO_DENOM] = 0xc0000000,
     67     [CCM_ANALOG_PLL_VIDEO] = 0xffe20f80,
     68     [CCM_ANALOG_PLL_VIDEO_NUM] = 0xc0000000,
     69     [CCM_ANALOG_PLL_VIDEO_DENOM] = 0xc0000000,
     70     [CCM_ANALOG_PLL_ENET] = 0xffc20ff0,
     71     [CCM_ANALOG_PFD_480] = 0x40404040,
     72     [CCM_ANALOG_PFD_528] = 0x40404040,
     73     [PMU_MISC0] = 0x01fe8306,
     74     [PMU_MISC1] = 0x07fcede0,
     75     [PMU_MISC2] = 0x005f5f5f,
     76 };
     77 
     78 static const char *imx6ul_ccm_reg_name(uint32_t reg)
     79 {
     80     static char unknown[20];
     81 
     82     switch (reg) {
     83     case CCM_CCR:
     84         return "CCR";
     85     case CCM_CCDR:
     86         return "CCDR";
     87     case CCM_CSR:
     88         return "CSR";
     89     case CCM_CCSR:
     90         return "CCSR";
     91     case CCM_CACRR:
     92         return "CACRR";
     93     case CCM_CBCDR:
     94         return "CBCDR";
     95     case CCM_CBCMR:
     96         return "CBCMR";
     97     case CCM_CSCMR1:
     98         return "CSCMR1";
     99     case CCM_CSCMR2:
    100         return "CSCMR2";
    101     case CCM_CSCDR1:
    102         return "CSCDR1";
    103     case CCM_CS1CDR:
    104         return "CS1CDR";
    105     case CCM_CS2CDR:
    106         return "CS2CDR";
    107     case CCM_CDCDR:
    108         return "CDCDR";
    109     case CCM_CHSCCDR:
    110         return "CHSCCDR";
    111     case CCM_CSCDR2:
    112         return "CSCDR2";
    113     case CCM_CSCDR3:
    114         return "CSCDR3";
    115     case CCM_CDHIPR:
    116         return "CDHIPR";
    117     case CCM_CTOR:
    118         return "CTOR";
    119     case CCM_CLPCR:
    120         return "CLPCR";
    121     case CCM_CISR:
    122         return "CISR";
    123     case CCM_CIMR:
    124         return "CIMR";
    125     case CCM_CCOSR:
    126         return "CCOSR";
    127     case CCM_CGPR:
    128         return "CGPR";
    129     case CCM_CCGR0:
    130         return "CCGR0";
    131     case CCM_CCGR1:
    132         return "CCGR1";
    133     case CCM_CCGR2:
    134         return "CCGR2";
    135     case CCM_CCGR3:
    136         return "CCGR3";
    137     case CCM_CCGR4:
    138         return "CCGR4";
    139     case CCM_CCGR5:
    140         return "CCGR5";
    141     case CCM_CCGR6:
    142         return "CCGR6";
    143     case CCM_CMEOR:
    144         return "CMEOR";
    145     default:
    146         sprintf(unknown, "%u ?", reg);
    147         return unknown;
    148     }
    149 }
    150 
    151 static const char *imx6ul_analog_reg_name(uint32_t reg)
    152 {
    153     static char unknown[20];
    154 
    155     switch (reg) {
    156     case CCM_ANALOG_PLL_ARM:
    157         return "PLL_ARM";
    158     case CCM_ANALOG_PLL_ARM_SET:
    159         return "PLL_ARM_SET";
    160     case CCM_ANALOG_PLL_ARM_CLR:
    161         return "PLL_ARM_CLR";
    162     case CCM_ANALOG_PLL_ARM_TOG:
    163         return "PLL_ARM_TOG";
    164     case CCM_ANALOG_PLL_USB1:
    165         return "PLL_USB1";
    166     case CCM_ANALOG_PLL_USB1_SET:
    167         return "PLL_USB1_SET";
    168     case CCM_ANALOG_PLL_USB1_CLR:
    169         return "PLL_USB1_CLR";
    170     case CCM_ANALOG_PLL_USB1_TOG:
    171         return "PLL_USB1_TOG";
    172     case CCM_ANALOG_PLL_USB2:
    173         return "PLL_USB2";
    174     case CCM_ANALOG_PLL_USB2_SET:
    175         return "PLL_USB2_SET";
    176     case CCM_ANALOG_PLL_USB2_CLR:
    177         return "PLL_USB2_CLR";
    178     case CCM_ANALOG_PLL_USB2_TOG:
    179         return "PLL_USB2_TOG";
    180     case CCM_ANALOG_PLL_SYS:
    181         return "PLL_SYS";
    182     case CCM_ANALOG_PLL_SYS_SET:
    183         return "PLL_SYS_SET";
    184     case CCM_ANALOG_PLL_SYS_CLR:
    185         return "PLL_SYS_CLR";
    186     case CCM_ANALOG_PLL_SYS_TOG:
    187         return "PLL_SYS_TOG";
    188     case CCM_ANALOG_PLL_SYS_SS:
    189         return "PLL_SYS_SS";
    190     case CCM_ANALOG_PLL_SYS_NUM:
    191         return "PLL_SYS_NUM";
    192     case CCM_ANALOG_PLL_SYS_DENOM:
    193         return "PLL_SYS_DENOM";
    194     case CCM_ANALOG_PLL_AUDIO:
    195         return "PLL_AUDIO";
    196     case CCM_ANALOG_PLL_AUDIO_SET:
    197         return "PLL_AUDIO_SET";
    198     case CCM_ANALOG_PLL_AUDIO_CLR:
    199         return "PLL_AUDIO_CLR";
    200     case CCM_ANALOG_PLL_AUDIO_TOG:
    201         return "PLL_AUDIO_TOG";
    202     case CCM_ANALOG_PLL_AUDIO_NUM:
    203         return "PLL_AUDIO_NUM";
    204     case CCM_ANALOG_PLL_AUDIO_DENOM:
    205         return "PLL_AUDIO_DENOM";
    206     case CCM_ANALOG_PLL_VIDEO:
    207         return "PLL_VIDEO";
    208     case CCM_ANALOG_PLL_VIDEO_SET:
    209         return "PLL_VIDEO_SET";
    210     case CCM_ANALOG_PLL_VIDEO_CLR:
    211         return "PLL_VIDEO_CLR";
    212     case CCM_ANALOG_PLL_VIDEO_TOG:
    213         return "PLL_VIDEO_TOG";
    214     case CCM_ANALOG_PLL_VIDEO_NUM:
    215         return "PLL_VIDEO_NUM";
    216     case CCM_ANALOG_PLL_VIDEO_DENOM:
    217         return "PLL_VIDEO_DENOM";
    218     case CCM_ANALOG_PLL_ENET:
    219         return "PLL_ENET";
    220     case CCM_ANALOG_PLL_ENET_SET:
    221         return "PLL_ENET_SET";
    222     case CCM_ANALOG_PLL_ENET_CLR:
    223         return "PLL_ENET_CLR";
    224     case CCM_ANALOG_PLL_ENET_TOG:
    225         return "PLL_ENET_TOG";
    226     case CCM_ANALOG_PFD_480:
    227         return "PFD_480";
    228     case CCM_ANALOG_PFD_480_SET:
    229         return "PFD_480_SET";
    230     case CCM_ANALOG_PFD_480_CLR:
    231         return "PFD_480_CLR";
    232     case CCM_ANALOG_PFD_480_TOG:
    233         return "PFD_480_TOG";
    234     case CCM_ANALOG_PFD_528:
    235         return "PFD_528";
    236     case CCM_ANALOG_PFD_528_SET:
    237         return "PFD_528_SET";
    238     case CCM_ANALOG_PFD_528_CLR:
    239         return "PFD_528_CLR";
    240     case CCM_ANALOG_PFD_528_TOG:
    241         return "PFD_528_TOG";
    242     case CCM_ANALOG_MISC0:
    243         return "MISC0";
    244     case CCM_ANALOG_MISC0_SET:
    245         return "MISC0_SET";
    246     case CCM_ANALOG_MISC0_CLR:
    247         return "MISC0_CLR";
    248     case CCM_ANALOG_MISC0_TOG:
    249         return "MISC0_TOG";
    250     case CCM_ANALOG_MISC2:
    251         return "MISC2";
    252     case CCM_ANALOG_MISC2_SET:
    253         return "MISC2_SET";
    254     case CCM_ANALOG_MISC2_CLR:
    255         return "MISC2_CLR";
    256     case CCM_ANALOG_MISC2_TOG:
    257         return "MISC2_TOG";
    258     case PMU_REG_1P1:
    259         return "PMU_REG_1P1";
    260     case PMU_REG_3P0:
    261         return "PMU_REG_3P0";
    262     case PMU_REG_2P5:
    263         return "PMU_REG_2P5";
    264     case PMU_REG_CORE:
    265         return "PMU_REG_CORE";
    266     case PMU_MISC1:
    267         return "PMU_MISC1";
    268     case PMU_MISC1_SET:
    269         return "PMU_MISC1_SET";
    270     case PMU_MISC1_CLR:
    271         return "PMU_MISC1_CLR";
    272     case PMU_MISC1_TOG:
    273         return "PMU_MISC1_TOG";
    274     case USB_ANALOG_DIGPROG:
    275         return "USB_ANALOG_DIGPROG";
    276     default:
    277         sprintf(unknown, "%u ?", reg);
    278         return unknown;
    279     }
    280 }
    281 
    282 #define CKIH_FREQ 24000000 /* 24MHz crystal input */
    283 
    284 static const VMStateDescription vmstate_imx6ul_ccm = {
    285     .name = TYPE_IMX6UL_CCM,
    286     .version_id = 1,
    287     .minimum_version_id = 1,
    288     .fields = (VMStateField[]) {
    289         VMSTATE_UINT32_ARRAY(ccm, IMX6ULCCMState, CCM_MAX),
    290         VMSTATE_UINT32_ARRAY(analog, IMX6ULCCMState, CCM_ANALOG_MAX),
    291         VMSTATE_END_OF_LIST()
    292     },
    293 };
    294 
    295 static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState *dev)
    296 {
    297     uint64_t freq = CKIH_FREQ;
    298 
    299     trace_ccm_freq((uint32_t)freq);
    300 
    301     return freq;
    302 }
    303 
    304 static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState *dev)
    305 {
    306     uint64_t freq = imx6ul_analog_get_osc_clk(dev);
    307 
    308     if (FIELD_EX32(dev->analog[CCM_ANALOG_PLL_SYS],
    309                    ANALOG_PLL_SYS, DIV_SELECT)) {
    310         freq *= 22;
    311     } else {
    312         freq *= 20;
    313     }
    314 
    315     trace_ccm_freq((uint32_t)freq);
    316 
    317     return freq;
    318 }
    319 
    320 static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState *dev)
    321 {
    322     uint64_t freq = imx6ul_analog_get_osc_clk(dev) * 20;
    323 
    324     trace_ccm_freq((uint32_t)freq);
    325 
    326     return freq;
    327 }
    328 
    329 static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState *dev)
    330 {
    331     uint64_t freq = 0;
    332 
    333     freq = imx6ul_analog_get_pll2_clk(dev) * 18
    334            / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
    335                         ANALOG_PFD_528, PFD0_FRAC);
    336 
    337     trace_ccm_freq((uint32_t)freq);
    338 
    339     return freq;
    340 }
    341 
    342 static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState *dev)
    343 {
    344     uint64_t freq = 0;
    345 
    346     freq = imx6ul_analog_get_pll2_clk(dev) * 18
    347            / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
    348                         ANALOG_PFD_528, PFD2_FRAC);
    349 
    350     trace_ccm_freq((uint32_t)freq);
    351 
    352     return freq;
    353 }
    354 
    355 static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState *dev)
    356 {
    357     uint64_t freq = 0;
    358 
    359     trace_ccm_freq((uint32_t)freq);
    360 
    361     return freq;
    362 }
    363 
    364 static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState *dev)
    365 {
    366     uint64_t freq = 0;
    367 
    368     switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PERIPH_CLK2_SEL)) {
    369     case 0:
    370         freq = imx6ul_analog_get_pll3_clk(dev);
    371         break;
    372     case 1:
    373         freq = imx6ul_analog_get_osc_clk(dev);
    374         break;
    375     case 2:
    376         freq = imx6ul_analog_pll2_bypass_clk(dev);
    377         break;
    378     case 3:
    379         /* We should never get there as 3 is a reserved value */
    380         qemu_log_mask(LOG_GUEST_ERROR,
    381                       "[%s]%s: unsupported PERIPH_CLK2_SEL value 3\n",
    382                       TYPE_IMX6UL_CCM, __func__);
    383         /* freq is set to 0 as we don't know what it should be */
    384         break;
    385     default:
    386         g_assert_not_reached();
    387     }
    388 
    389     trace_ccm_freq((uint32_t)freq);
    390 
    391     return freq;
    392 }
    393 
    394 static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState *dev)
    395 {
    396     uint64_t freq = 0;
    397 
    398     switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PRE_PERIPH_CLK_SEL)) {
    399     case 0:
    400         freq = imx6ul_analog_get_pll2_clk(dev);
    401         break;
    402     case 1:
    403         freq = imx6ul_analog_get_pll2_pfd2_clk(dev);
    404         break;
    405     case 2:
    406         freq = imx6ul_analog_get_pll2_pfd0_clk(dev);
    407         break;
    408     case 3:
    409         freq = imx6ul_analog_get_pll2_pfd2_clk(dev) / 2;
    410         break;
    411     default:
    412         g_assert_not_reached();
    413     }
    414 
    415     trace_ccm_freq((uint32_t)freq);
    416 
    417     return freq;
    418 }
    419 
    420 static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState *dev)
    421 {
    422     uint64_t freq = 0;
    423 
    424     freq = imx6ul_ccm_get_periph_clk2_sel_clk(dev)
    425            / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK2_PODF));
    426 
    427     trace_ccm_freq((uint32_t)freq);
    428 
    429     return freq;
    430 }
    431 
    432 static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState *dev)
    433 {
    434     uint64_t freq = 0;
    435 
    436     switch (FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK_SEL)) {
    437     case 0:
    438         freq = imx6ul_ccm_get_periph_clk_sel_clk(dev);
    439         break;
    440     case 1:
    441         freq = imx6ul_ccm_get_periph_clk2_clk(dev);
    442         break;
    443     default:
    444         g_assert_not_reached();
    445     }
    446 
    447     trace_ccm_freq((uint32_t)freq);
    448 
    449     return freq;
    450 }
    451 
    452 static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState *dev)
    453 {
    454     uint64_t freq = 0;
    455 
    456     freq = imx6ul_ccm_get_periph_sel_clk(dev)
    457            / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, AHB_PODF));
    458 
    459     trace_ccm_freq((uint32_t)freq);
    460 
    461     return freq;
    462 }
    463 
    464 static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState *dev)
    465 {
    466     uint64_t freq = 0;
    467 
    468     freq = imx6ul_ccm_get_ahb_clk(dev)
    469            / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, IPG_PODF));
    470 
    471     trace_ccm_freq((uint32_t)freq);
    472 
    473     return freq;
    474 }
    475 
    476 static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState *dev)
    477 {
    478     uint64_t freq = 0;
    479 
    480     switch (FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_CLK_SEL)) {
    481     case 0:
    482         freq = imx6ul_ccm_get_ipg_clk(dev);
    483         break;
    484     case 1:
    485         freq = imx6ul_analog_get_osc_clk(dev);
    486         break;
    487     default:
    488         g_assert_not_reached();
    489     }
    490 
    491     trace_ccm_freq((uint32_t)freq);
    492 
    493     return freq;
    494 }
    495 
    496 static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState *dev)
    497 {
    498     uint64_t freq = 0;
    499 
    500     freq = imx6ul_ccm_get_per_sel_clk(dev)
    501            / (1 + FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_PODF));
    502 
    503     trace_ccm_freq((uint32_t)freq);
    504 
    505     return freq;
    506 }
    507 
    508 static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
    509 {
    510     uint32_t freq = 0;
    511     IMX6ULCCMState *s = IMX6UL_CCM(dev);
    512 
    513     switch (clock) {
    514     case CLK_NONE:
    515         break;
    516     case CLK_IPG:
    517         freq = imx6ul_ccm_get_ipg_clk(s);
    518         break;
    519     case CLK_IPG_HIGH:
    520         freq = imx6ul_ccm_get_per_clk(s);
    521         break;
    522     case CLK_32k:
    523         freq = CKIL_FREQ;
    524         break;
    525     case CLK_HIGH:
    526         freq = CKIH_FREQ;
    527         break;
    528     case CLK_HIGH_DIV:
    529         freq = CKIH_FREQ / 8;
    530         break;
    531     default:
    532         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
    533                       TYPE_IMX6UL_CCM, __func__, clock);
    534         break;
    535     }
    536 
    537     trace_ccm_clock_freq(clock, freq);
    538 
    539     return freq;
    540 }
    541 
    542 static void imx6ul_ccm_reset(DeviceState *dev)
    543 {
    544     IMX6ULCCMState *s = IMX6UL_CCM(dev);
    545 
    546     trace_ccm_entry();
    547 
    548     s->ccm[CCM_CCR] = 0x0401167F;
    549     s->ccm[CCM_CCDR] = 0x00000000;
    550     s->ccm[CCM_CSR] = 0x00000010;
    551     s->ccm[CCM_CCSR] = 0x00000100;
    552     s->ccm[CCM_CACRR] = 0x00000000;
    553     s->ccm[CCM_CBCDR] = 0x00018D00;
    554     s->ccm[CCM_CBCMR] = 0x24860324;
    555     s->ccm[CCM_CSCMR1] = 0x04900080;
    556     s->ccm[CCM_CSCMR2] = 0x03192F06;
    557     s->ccm[CCM_CSCDR1] = 0x00490B00;
    558     s->ccm[CCM_CS1CDR] = 0x0EC102C1;
    559     s->ccm[CCM_CS2CDR] = 0x000336C1;
    560     s->ccm[CCM_CDCDR] = 0x33F71F92;
    561     s->ccm[CCM_CHSCCDR] = 0x000248A4;
    562     s->ccm[CCM_CSCDR2] = 0x00029B48;
    563     s->ccm[CCM_CSCDR3] = 0x00014841;
    564     s->ccm[CCM_CDHIPR] = 0x00000000;
    565     s->ccm[CCM_CTOR] = 0x00000000;
    566     s->ccm[CCM_CLPCR] = 0x00000079;
    567     s->ccm[CCM_CISR] = 0x00000000;
    568     s->ccm[CCM_CIMR] = 0xFFFFFFFF;
    569     s->ccm[CCM_CCOSR] = 0x000A0001;
    570     s->ccm[CCM_CGPR] = 0x0000FE62;
    571     s->ccm[CCM_CCGR0] = 0xFFFFFFFF;
    572     s->ccm[CCM_CCGR1] = 0xFFFFFFFF;
    573     s->ccm[CCM_CCGR2] = 0xFC3FFFFF;
    574     s->ccm[CCM_CCGR3] = 0xFFFFFFFF;
    575     s->ccm[CCM_CCGR4] = 0xFFFFFFFF;
    576     s->ccm[CCM_CCGR5] = 0xFFFFFFFF;
    577     s->ccm[CCM_CCGR6] = 0xFFFFFFFF;
    578     s->ccm[CCM_CMEOR] = 0xFFFFFFFF;
    579 
    580     s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063;
    581     s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000;
    582     s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000;
    583     s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001;
    584     s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000;
    585     s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000;
    586     s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012;
    587     s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006;
    588     s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100;
    589     s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C;
    590     s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C;
    591     s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100;
    592     s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447;
    593     s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001;
    594     s->analog[CCM_ANALOG_PFD_480] = 0x1311100C;
    595     s->analog[CCM_ANALOG_PFD_528] = 0x1018101B;
    596 
    597     s->analog[PMU_REG_1P1] = 0x00001073;
    598     s->analog[PMU_REG_3P0] = 0x00000F74;
    599     s->analog[PMU_REG_2P5] = 0x00001073;
    600     s->analog[PMU_REG_CORE] = 0x00482012;
    601     s->analog[PMU_MISC0] = 0x04000000;
    602     s->analog[PMU_MISC1] = 0x00000000;
    603     s->analog[PMU_MISC2] = 0x00272727;
    604     s->analog[PMU_LOWPWR_CTRL] = 0x00004009;
    605 
    606     s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004;
    607     s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000;
    608     s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000;
    609     s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000;
    610     s->analog[USB_ANALOG_USB1_MISC] = 0x00000002;
    611     s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004;
    612     s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000;
    613     s->analog[USB_ANALOG_USB2_MISC] = 0x00000002;
    614     s->analog[USB_ANALOG_DIGPROG] = 0x00640000;
    615 
    616     /* all PLLs need to be locked */
    617     s->analog[CCM_ANALOG_PLL_ARM]   |= CCM_ANALOG_PLL_LOCK;
    618     s->analog[CCM_ANALOG_PLL_USB1]  |= CCM_ANALOG_PLL_LOCK;
    619     s->analog[CCM_ANALOG_PLL_USB2]  |= CCM_ANALOG_PLL_LOCK;
    620     s->analog[CCM_ANALOG_PLL_SYS]   |= CCM_ANALOG_PLL_LOCK;
    621     s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
    622     s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
    623     s->analog[CCM_ANALOG_PLL_ENET]  |= CCM_ANALOG_PLL_LOCK;
    624 
    625     s->analog[TEMPMON_TEMPSENSE0] = 0x00000001;
    626     s->analog[TEMPMON_TEMPSENSE1] = 0x00000001;
    627     s->analog[TEMPMON_TEMPSENSE2] = 0x00000000;
    628 }
    629 
    630 static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size)
    631 {
    632     uint32_t value = 0;
    633     uint32_t index = offset >> 2;
    634     IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
    635 
    636     assert(index < CCM_MAX);
    637 
    638     value = s->ccm[index];
    639 
    640     trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
    641 
    642     return (uint64_t)value;
    643 }
    644 
    645 static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value,
    646                            unsigned size)
    647 {
    648     uint32_t index = offset >> 2;
    649     IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
    650 
    651     assert(index < CCM_MAX);
    652 
    653     trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
    654 
    655     s->ccm[index] = (s->ccm[index] & ccm_mask[index]) |
    656                            ((uint32_t)value & ~ccm_mask[index]);
    657 }
    658 
    659 static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size)
    660 {
    661     uint32_t value;
    662     uint32_t index = offset >> 2;
    663     IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
    664 
    665     assert(index < CCM_ANALOG_MAX);
    666 
    667     switch (index) {
    668     case CCM_ANALOG_PLL_ARM_SET:
    669     case CCM_ANALOG_PLL_USB1_SET:
    670     case CCM_ANALOG_PLL_USB2_SET:
    671     case CCM_ANALOG_PLL_SYS_SET:
    672     case CCM_ANALOG_PLL_AUDIO_SET:
    673     case CCM_ANALOG_PLL_VIDEO_SET:
    674     case CCM_ANALOG_PLL_ENET_SET:
    675     case CCM_ANALOG_PFD_480_SET:
    676     case CCM_ANALOG_PFD_528_SET:
    677     case CCM_ANALOG_MISC0_SET:
    678     case PMU_MISC1_SET:
    679     case CCM_ANALOG_MISC2_SET:
    680     case USB_ANALOG_USB1_VBUS_DETECT_SET:
    681     case USB_ANALOG_USB1_CHRG_DETECT_SET:
    682     case USB_ANALOG_USB1_MISC_SET:
    683     case USB_ANALOG_USB2_VBUS_DETECT_SET:
    684     case USB_ANALOG_USB2_CHRG_DETECT_SET:
    685     case USB_ANALOG_USB2_MISC_SET:
    686     case TEMPMON_TEMPSENSE0_SET:
    687     case TEMPMON_TEMPSENSE1_SET:
    688     case TEMPMON_TEMPSENSE2_SET:
    689         /*
    690          * All REG_NAME_SET register access are in fact targeting
    691          * the REG_NAME register.
    692          */
    693         value = s->analog[index - 1];
    694         break;
    695     case CCM_ANALOG_PLL_ARM_CLR:
    696     case CCM_ANALOG_PLL_USB1_CLR:
    697     case CCM_ANALOG_PLL_USB2_CLR:
    698     case CCM_ANALOG_PLL_SYS_CLR:
    699     case CCM_ANALOG_PLL_AUDIO_CLR:
    700     case CCM_ANALOG_PLL_VIDEO_CLR:
    701     case CCM_ANALOG_PLL_ENET_CLR:
    702     case CCM_ANALOG_PFD_480_CLR:
    703     case CCM_ANALOG_PFD_528_CLR:
    704     case CCM_ANALOG_MISC0_CLR:
    705     case PMU_MISC1_CLR:
    706     case CCM_ANALOG_MISC2_CLR:
    707     case USB_ANALOG_USB1_VBUS_DETECT_CLR:
    708     case USB_ANALOG_USB1_CHRG_DETECT_CLR:
    709     case USB_ANALOG_USB1_MISC_CLR:
    710     case USB_ANALOG_USB2_VBUS_DETECT_CLR:
    711     case USB_ANALOG_USB2_CHRG_DETECT_CLR:
    712     case USB_ANALOG_USB2_MISC_CLR:
    713     case TEMPMON_TEMPSENSE0_CLR:
    714     case TEMPMON_TEMPSENSE1_CLR:
    715     case TEMPMON_TEMPSENSE2_CLR:
    716         /*
    717          * All REG_NAME_CLR register access are in fact targeting
    718          * the REG_NAME register.
    719          */
    720         value = s->analog[index - 2];
    721         break;
    722     case CCM_ANALOG_PLL_ARM_TOG:
    723     case CCM_ANALOG_PLL_USB1_TOG:
    724     case CCM_ANALOG_PLL_USB2_TOG:
    725     case CCM_ANALOG_PLL_SYS_TOG:
    726     case CCM_ANALOG_PLL_AUDIO_TOG:
    727     case CCM_ANALOG_PLL_VIDEO_TOG:
    728     case CCM_ANALOG_PLL_ENET_TOG:
    729     case CCM_ANALOG_PFD_480_TOG:
    730     case CCM_ANALOG_PFD_528_TOG:
    731     case CCM_ANALOG_MISC0_TOG:
    732     case PMU_MISC1_TOG:
    733     case CCM_ANALOG_MISC2_TOG:
    734     case USB_ANALOG_USB1_VBUS_DETECT_TOG:
    735     case USB_ANALOG_USB1_CHRG_DETECT_TOG:
    736     case USB_ANALOG_USB1_MISC_TOG:
    737     case USB_ANALOG_USB2_VBUS_DETECT_TOG:
    738     case USB_ANALOG_USB2_CHRG_DETECT_TOG:
    739     case USB_ANALOG_USB2_MISC_TOG:
    740     case TEMPMON_TEMPSENSE0_TOG:
    741     case TEMPMON_TEMPSENSE1_TOG:
    742     case TEMPMON_TEMPSENSE2_TOG:
    743         /*
    744          * All REG_NAME_TOG register access are in fact targeting
    745          * the REG_NAME register.
    746          */
    747         value = s->analog[index - 3];
    748         break;
    749     default:
    750         value = s->analog[index];
    751         break;
    752     }
    753 
    754     trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
    755 
    756     return (uint64_t)value;
    757 }
    758 
    759 static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
    760                               unsigned size)
    761 {
    762     uint32_t index = offset >> 2;
    763     IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
    764 
    765     assert(index < CCM_ANALOG_MAX);
    766 
    767     trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
    768 
    769     switch (index) {
    770     case CCM_ANALOG_PLL_ARM_SET:
    771     case CCM_ANALOG_PLL_USB1_SET:
    772     case CCM_ANALOG_PLL_USB2_SET:
    773     case CCM_ANALOG_PLL_SYS_SET:
    774     case CCM_ANALOG_PLL_AUDIO_SET:
    775     case CCM_ANALOG_PLL_VIDEO_SET:
    776     case CCM_ANALOG_PLL_ENET_SET:
    777     case CCM_ANALOG_PFD_480_SET:
    778     case CCM_ANALOG_PFD_528_SET:
    779     case CCM_ANALOG_MISC0_SET:
    780     case PMU_MISC1_SET:
    781     case CCM_ANALOG_MISC2_SET:
    782     case USB_ANALOG_USB1_VBUS_DETECT_SET:
    783     case USB_ANALOG_USB1_CHRG_DETECT_SET:
    784     case USB_ANALOG_USB1_MISC_SET:
    785     case USB_ANALOG_USB2_VBUS_DETECT_SET:
    786     case USB_ANALOG_USB2_CHRG_DETECT_SET:
    787     case USB_ANALOG_USB2_MISC_SET:
    788         /*
    789          * All REG_NAME_SET register access are in fact targeting
    790          * the REG_NAME register. So we change the value of the
    791          * REG_NAME register, setting bits passed in the value.
    792          */
    793         s->analog[index - 1] |= (value & ~analog_mask[index - 1]);
    794         break;
    795     case CCM_ANALOG_PLL_ARM_CLR:
    796     case CCM_ANALOG_PLL_USB1_CLR:
    797     case CCM_ANALOG_PLL_USB2_CLR:
    798     case CCM_ANALOG_PLL_SYS_CLR:
    799     case CCM_ANALOG_PLL_AUDIO_CLR:
    800     case CCM_ANALOG_PLL_VIDEO_CLR:
    801     case CCM_ANALOG_PLL_ENET_CLR:
    802     case CCM_ANALOG_PFD_480_CLR:
    803     case CCM_ANALOG_PFD_528_CLR:
    804     case CCM_ANALOG_MISC0_CLR:
    805     case PMU_MISC1_CLR:
    806     case CCM_ANALOG_MISC2_CLR:
    807     case USB_ANALOG_USB1_VBUS_DETECT_CLR:
    808     case USB_ANALOG_USB1_CHRG_DETECT_CLR:
    809     case USB_ANALOG_USB1_MISC_CLR:
    810     case USB_ANALOG_USB2_VBUS_DETECT_CLR:
    811     case USB_ANALOG_USB2_CHRG_DETECT_CLR:
    812     case USB_ANALOG_USB2_MISC_CLR:
    813         /*
    814          * All REG_NAME_CLR register access are in fact targeting
    815          * the REG_NAME register. So we change the value of the
    816          * REG_NAME register, unsetting bits passed in the value.
    817          */
    818         s->analog[index - 2] &= ~(value & ~analog_mask[index - 2]);
    819         break;
    820     case CCM_ANALOG_PLL_ARM_TOG:
    821     case CCM_ANALOG_PLL_USB1_TOG:
    822     case CCM_ANALOG_PLL_USB2_TOG:
    823     case CCM_ANALOG_PLL_SYS_TOG:
    824     case CCM_ANALOG_PLL_AUDIO_TOG:
    825     case CCM_ANALOG_PLL_VIDEO_TOG:
    826     case CCM_ANALOG_PLL_ENET_TOG:
    827     case CCM_ANALOG_PFD_480_TOG:
    828     case CCM_ANALOG_PFD_528_TOG:
    829     case CCM_ANALOG_MISC0_TOG:
    830     case PMU_MISC1_TOG:
    831     case CCM_ANALOG_MISC2_TOG:
    832     case USB_ANALOG_USB1_VBUS_DETECT_TOG:
    833     case USB_ANALOG_USB1_CHRG_DETECT_TOG:
    834     case USB_ANALOG_USB1_MISC_TOG:
    835     case USB_ANALOG_USB2_VBUS_DETECT_TOG:
    836     case USB_ANALOG_USB2_CHRG_DETECT_TOG:
    837     case USB_ANALOG_USB2_MISC_TOG:
    838         /*
    839          * All REG_NAME_TOG register access are in fact targeting
    840          * the REG_NAME register. So we change the value of the
    841          * REG_NAME register, toggling bits passed in the value.
    842          */
    843         s->analog[index - 3] ^= (value & ~analog_mask[index - 3]);
    844         break;
    845     default:
    846         s->analog[index] = (s->analog[index] & analog_mask[index]) |
    847                            (value & ~analog_mask[index]);
    848         break;
    849     }
    850 }
    851 
    852 static const struct MemoryRegionOps imx6ul_ccm_ops = {
    853     .read = imx6ul_ccm_read,
    854     .write = imx6ul_ccm_write,
    855     .endianness = DEVICE_NATIVE_ENDIAN,
    856     .valid = {
    857         /*
    858          * Our device would not work correctly if the guest was doing
    859          * unaligned access. This might not be a limitation on the real
    860          * device but in practice there is no reason for a guest to access
    861          * this device unaligned.
    862          */
    863         .min_access_size = 4,
    864         .max_access_size = 4,
    865         .unaligned = false,
    866     },
    867 };
    868 
    869 static const struct MemoryRegionOps imx6ul_analog_ops = {
    870     .read = imx6ul_analog_read,
    871     .write = imx6ul_analog_write,
    872     .endianness = DEVICE_NATIVE_ENDIAN,
    873     .valid = {
    874         /*
    875          * Our device would not work correctly if the guest was doing
    876          * unaligned access. This might not be a limitation on the real
    877          * device but in practice there is no reason for a guest to access
    878          * this device unaligned.
    879          */
    880         .min_access_size = 4,
    881         .max_access_size = 4,
    882         .unaligned = false,
    883     },
    884 };
    885 
    886 static void imx6ul_ccm_init(Object *obj)
    887 {
    888     DeviceState *dev = DEVICE(obj);
    889     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
    890     IMX6ULCCMState *s = IMX6UL_CCM(obj);
    891 
    892     /* initialize a container for the all memory range */
    893     memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000);
    894 
    895     /* We initialize an IO memory region for the CCM part */
    896     memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s,
    897                           TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t));
    898 
    899     /* Add the CCM as a subregion at offset 0 */
    900     memory_region_add_subregion(&s->container, 0, &s->ioccm);
    901 
    902     /* We initialize an IO memory region for the ANALOG part */
    903     memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s,
    904                           TYPE_IMX6UL_CCM ".analog",
    905                           CCM_ANALOG_MAX * sizeof(uint32_t));
    906 
    907     /* Add the ANALOG as a subregion at offset 0x4000 */
    908     memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog);
    909 
    910     sysbus_init_mmio(sd, &s->container);
    911 }
    912 
    913 static void imx6ul_ccm_class_init(ObjectClass *klass, void *data)
    914 {
    915     DeviceClass *dc = DEVICE_CLASS(klass);
    916     IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
    917 
    918     dc->reset = imx6ul_ccm_reset;
    919     dc->vmsd = &vmstate_imx6ul_ccm;
    920     dc->desc = "i.MX6UL Clock Control Module";
    921 
    922     ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency;
    923 }
    924 
    925 static const TypeInfo imx6ul_ccm_info = {
    926     .name          = TYPE_IMX6UL_CCM,
    927     .parent        = TYPE_IMX_CCM,
    928     .instance_size = sizeof(IMX6ULCCMState),
    929     .instance_init = imx6ul_ccm_init,
    930     .class_init    = imx6ul_ccm_class_init,
    931 };
    932 
    933 static void imx6ul_ccm_register_types(void)
    934 {
    935     type_register_static(&imx6ul_ccm_info);
    936 }
    937 
    938 type_init(imx6ul_ccm_register_types)