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