qemu

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

imx31_ccm.c (9227B)


      1 /*
      2  * IMX31 Clock Control Module
      3  *
      4  * Copyright (C) 2012 NICTA
      5  * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
      6  *
      7  * This work is licensed under the terms of the GNU GPL, version 2 or later.
      8  * See the COPYING file in the top-level directory.
      9  *
     10  * To get the timer frequencies right, we need to emulate at least part of
     11  * the i.MX31 CCM.
     12  */
     13 
     14 #include "qemu/osdep.h"
     15 #include "hw/misc/imx31_ccm.h"
     16 #include "migration/vmstate.h"
     17 #include "qemu/log.h"
     18 #include "qemu/module.h"
     19 
     20 #define CKIH_FREQ 26000000 /* 26MHz crystal input */
     21 
     22 #ifndef DEBUG_IMX31_CCM
     23 #define DEBUG_IMX31_CCM 0
     24 #endif
     25 
     26 #define DPRINTF(fmt, args...) \
     27     do { \
     28         if (DEBUG_IMX31_CCM) { \
     29             fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX31_CCM, \
     30                                              __func__, ##args); \
     31         } \
     32     } while (0)
     33 
     34 static const char *imx31_ccm_reg_name(uint32_t reg)
     35 {
     36     static char unknown[20];
     37 
     38     switch (reg) {
     39     case IMX31_CCM_CCMR_REG:
     40         return "CCMR";
     41     case IMX31_CCM_PDR0_REG:
     42         return "PDR0";
     43     case IMX31_CCM_PDR1_REG:
     44         return "PDR1";
     45     case IMX31_CCM_RCSR_REG:
     46         return "RCSR";
     47     case IMX31_CCM_MPCTL_REG:
     48         return "MPCTL";
     49     case IMX31_CCM_UPCTL_REG:
     50         return "UPCTL";
     51     case IMX31_CCM_SPCTL_REG:
     52         return "SPCTL";
     53     case IMX31_CCM_COSR_REG:
     54         return "COSR";
     55     case IMX31_CCM_CGR0_REG:
     56         return "CGR0";
     57     case IMX31_CCM_CGR1_REG:
     58         return "CGR1";
     59     case IMX31_CCM_CGR2_REG:
     60         return "CGR2";
     61     case IMX31_CCM_WIMR_REG:
     62         return "WIMR";
     63     case IMX31_CCM_LDC_REG:
     64         return "LDC";
     65     case IMX31_CCM_DCVR0_REG:
     66         return "DCVR0";
     67     case IMX31_CCM_DCVR1_REG:
     68         return "DCVR1";
     69     case IMX31_CCM_DCVR2_REG:
     70         return "DCVR2";
     71     case IMX31_CCM_DCVR3_REG:
     72         return "DCVR3";
     73     case IMX31_CCM_LTR0_REG:
     74         return "LTR0";
     75     case IMX31_CCM_LTR1_REG:
     76         return "LTR1";
     77     case IMX31_CCM_LTR2_REG:
     78         return "LTR2";
     79     case IMX31_CCM_LTR3_REG:
     80         return "LTR3";
     81     case IMX31_CCM_LTBR0_REG:
     82         return "LTBR0";
     83     case IMX31_CCM_LTBR1_REG:
     84         return "LTBR1";
     85     case IMX31_CCM_PMCR0_REG:
     86         return "PMCR0";
     87     case IMX31_CCM_PMCR1_REG:
     88         return "PMCR1";
     89     case IMX31_CCM_PDR2_REG:
     90         return "PDR2";
     91     default:
     92         sprintf(unknown, "[%u ?]", reg);
     93         return unknown;
     94     }
     95 }
     96 
     97 static const VMStateDescription vmstate_imx31_ccm = {
     98     .name = TYPE_IMX31_CCM,
     99     .version_id = 2,
    100     .minimum_version_id = 2,
    101     .fields = (VMStateField[]) {
    102         VMSTATE_UINT32_ARRAY(reg, IMX31CCMState, IMX31_CCM_MAX_REG),
    103         VMSTATE_END_OF_LIST()
    104     },
    105 };
    106 
    107 static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
    108 {
    109     uint32_t freq = 0;
    110     IMX31CCMState *s = IMX31_CCM(dev);
    111 
    112     if ((s->reg[IMX31_CCM_CCMR_REG] & CCMR_PRCS) == 2) {
    113         if (s->reg[IMX31_CCM_CCMR_REG] & CCMR_FPME) {
    114             freq = CKIL_FREQ;
    115             if (s->reg[IMX31_CCM_CCMR_REG] & CCMR_FPMF) {
    116                 freq *= 1024;
    117             }
    118         } 
    119     } else {
    120         freq = CKIH_FREQ;
    121     }
    122 
    123     DPRINTF("freq = %u\n", freq);
    124 
    125     return freq;
    126 }
    127 
    128 static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
    129 {
    130     uint32_t freq;
    131     IMX31CCMState *s = IMX31_CCM(dev);
    132 
    133     freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
    134                             imx31_ccm_get_pll_ref_clk(dev));
    135 
    136     DPRINTF("freq = %u\n", freq);
    137 
    138     return freq;
    139 }
    140 
    141 static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
    142 {
    143     uint32_t freq;
    144     IMX31CCMState *s = IMX31_CCM(dev);
    145 
    146     if ((s->reg[IMX31_CCM_CCMR_REG] & CCMR_MDS) ||
    147         !(s->reg[IMX31_CCM_CCMR_REG] & CCMR_MPE)) {
    148         freq = imx31_ccm_get_pll_ref_clk(dev);
    149     } else {
    150         freq = imx31_ccm_get_mpll_clk(dev);
    151     }
    152 
    153     DPRINTF("freq = %u\n", freq);
    154 
    155     return freq;
    156 }
    157 
    158 static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
    159 {
    160     uint32_t freq;
    161     IMX31CCMState *s = IMX31_CCM(dev);
    162 
    163     freq = imx31_ccm_get_mcu_main_clk(dev)
    164            / (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
    165 
    166     DPRINTF("freq = %u\n", freq);
    167 
    168     return freq;
    169 }
    170 
    171 static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
    172 {
    173     uint32_t freq;
    174     IMX31CCMState *s = IMX31_CCM(dev);
    175 
    176     freq = imx31_ccm_get_hclk_clk(dev)
    177            / (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
    178 
    179     DPRINTF("freq = %u\n", freq);
    180 
    181     return freq;
    182 }
    183 
    184 static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
    185 {
    186     uint32_t freq = 0;
    187 
    188     switch (clock) {
    189     case CLK_NONE:
    190         break;
    191     case CLK_IPG:
    192     case CLK_IPG_HIGH:
    193         freq = imx31_ccm_get_ipg_clk(dev);
    194         break;
    195     case CLK_32k:
    196         freq = CKIL_FREQ;
    197         break;
    198     default:
    199         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
    200                       TYPE_IMX31_CCM, __func__, clock);
    201         break;
    202     }
    203 
    204     DPRINTF("Clock = %d) = %u\n", clock, freq);
    205 
    206     return freq;
    207 }
    208 
    209 static void imx31_ccm_reset(DeviceState *dev)
    210 {
    211     IMX31CCMState *s = IMX31_CCM(dev);
    212 
    213     DPRINTF("()\n");
    214 
    215     memset(s->reg, 0, sizeof(uint32_t) * IMX31_CCM_MAX_REG);
    216 
    217     s->reg[IMX31_CCM_CCMR_REG]   = 0x074b0b7d;
    218     s->reg[IMX31_CCM_PDR0_REG]   = 0xff870b48;
    219     s->reg[IMX31_CCM_PDR1_REG]   = 0x49fcfe7f;
    220     s->reg[IMX31_CCM_RCSR_REG]   = 0x007f0000;
    221     s->reg[IMX31_CCM_MPCTL_REG]  = 0x04001800;
    222     s->reg[IMX31_CCM_UPCTL_REG]  = 0x04051c03;
    223     s->reg[IMX31_CCM_SPCTL_REG]  = 0x04043001;
    224     s->reg[IMX31_CCM_COSR_REG]   = 0x00000280;
    225     s->reg[IMX31_CCM_CGR0_REG]   = 0xffffffff;
    226     s->reg[IMX31_CCM_CGR1_REG]   = 0xffffffff;
    227     s->reg[IMX31_CCM_CGR2_REG]   = 0xffffffff;
    228     s->reg[IMX31_CCM_WIMR_REG]   = 0xffffffff;
    229     s->reg[IMX31_CCM_LTR1_REG]   = 0x00004040;
    230     s->reg[IMX31_CCM_PMCR0_REG]  = 0x80209828;
    231     s->reg[IMX31_CCM_PMCR1_REG]  = 0x00aa0000;
    232     s->reg[IMX31_CCM_PDR2_REG]   = 0x00000285;
    233 }
    234 
    235 static uint64_t imx31_ccm_read(void *opaque, hwaddr offset, unsigned size)
    236 {
    237     uint32_t value = 0;
    238     IMX31CCMState *s = (IMX31CCMState *)opaque;
    239 
    240     if ((offset >> 2) < IMX31_CCM_MAX_REG) {
    241         value = s->reg[offset >> 2];
    242     } else {
    243         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
    244                       HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset);
    245     }
    246 
    247     DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2),
    248             value);
    249 
    250     return (uint64_t)value;
    251 }
    252 
    253 static void imx31_ccm_write(void *opaque, hwaddr offset, uint64_t value,
    254                             unsigned size)
    255 {
    256     IMX31CCMState *s = (IMX31CCMState *)opaque;
    257 
    258     DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2),
    259             (uint32_t)value);
    260 
    261     switch (offset >> 2) {
    262     case IMX31_CCM_CCMR_REG:
    263         s->reg[IMX31_CCM_CCMR_REG] = CCMR_FPMF | (value & 0x3b6fdfff);
    264         break;
    265     case IMX31_CCM_PDR0_REG:
    266         s->reg[IMX31_CCM_PDR0_REG] = value & 0xff9f3fff;
    267         break;
    268     case IMX31_CCM_PDR1_REG:
    269         s->reg[IMX31_CCM_PDR1_REG] = value;
    270         break;
    271     case IMX31_CCM_MPCTL_REG:
    272         s->reg[IMX31_CCM_MPCTL_REG] = value & 0xbfff3fff;
    273         break;
    274     case IMX31_CCM_SPCTL_REG:
    275         s->reg[IMX31_CCM_SPCTL_REG] = value & 0xbfff3fff;
    276         break;
    277     case IMX31_CCM_CGR0_REG:
    278         s->reg[IMX31_CCM_CGR0_REG] = value;
    279         break;
    280     case IMX31_CCM_CGR1_REG:
    281         s->reg[IMX31_CCM_CGR1_REG] = value;
    282         break;
    283     case IMX31_CCM_CGR2_REG:
    284         s->reg[IMX31_CCM_CGR2_REG] = value;
    285         break;
    286     default:
    287         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
    288                       HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset);
    289         break;
    290     }
    291 }
    292 
    293 static const struct MemoryRegionOps imx31_ccm_ops = {
    294     .read = imx31_ccm_read,
    295     .write = imx31_ccm_write,
    296     .endianness = DEVICE_NATIVE_ENDIAN,
    297     .valid = {
    298         /*
    299          * Our device would not work correctly if the guest was doing
    300          * unaligned access. This might not be a limitation on the real
    301          * device but in practice there is no reason for a guest to access
    302          * this device unaligned.
    303          */
    304         .min_access_size = 4,
    305         .max_access_size = 4,
    306         .unaligned = false,
    307     },
    308 
    309 };
    310 
    311 static void imx31_ccm_init(Object *obj)
    312 {
    313     DeviceState *dev = DEVICE(obj);
    314     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
    315     IMX31CCMState *s = IMX31_CCM(obj);
    316 
    317     memory_region_init_io(&s->iomem, OBJECT(dev), &imx31_ccm_ops, s,
    318                           TYPE_IMX31_CCM, 0x1000);
    319     sysbus_init_mmio(sd, &s->iomem);
    320 }
    321 
    322 static void imx31_ccm_class_init(ObjectClass *klass, void *data)
    323 {
    324     DeviceClass *dc  = DEVICE_CLASS(klass);
    325     IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
    326 
    327     dc->reset = imx31_ccm_reset;
    328     dc->vmsd  = &vmstate_imx31_ccm;
    329     dc->desc  = "i.MX31 Clock Control Module";
    330 
    331     ccm->get_clock_frequency = imx31_ccm_get_clock_frequency;
    332 }
    333 
    334 static const TypeInfo imx31_ccm_info = {
    335     .name          = TYPE_IMX31_CCM,
    336     .parent        = TYPE_IMX_CCM,
    337     .instance_size = sizeof(IMX31CCMState),
    338     .instance_init = imx31_ccm_init,
    339     .class_init    = imx31_ccm_class_init,
    340 };
    341 
    342 static void imx31_ccm_register_types(void)
    343 {
    344     type_register_static(&imx31_ccm_info);
    345 }
    346 
    347 type_init(imx31_ccm_register_types)