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 "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
  34static 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
  97static 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
 107static 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
 128static 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
 141static 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
 158static 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
 171static 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
 184static 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
 209static 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
 235static 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
 253static 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
 293static 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
 311static 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
 322static 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
 334static 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
 342static void imx31_ccm_register_types(void)
 343{
 344    type_register_static(&imx31_ccm_info);
 345}
 346
 347type_init(imx31_ccm_register_types)
 348