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 CCM. 12 */ 13 14 #include "hw/misc/imx_ccm.h" 15 16 #define CKIH_FREQ 26000000 /* 26MHz crystal input */ 17 #define CKIL_FREQ 32768 /* nominal 32khz clock */ 18 19 #ifndef DEBUG_IMX_CCM 20 #define DEBUG_IMX_CCM 0 21 #endif 22 23 #define DPRINTF(fmt, args...) \ 24 do { \ 25 if (DEBUG_IMX_CCM) { \ 26 fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_CCM, \ 27 __func__, ##args); \ 28 } \ 29 } while (0) 30 31 static int imx_ccm_post_load(void *opaque, int version_id); 32 33 static const VMStateDescription vmstate_imx_ccm = { 34 .name = TYPE_IMX_CCM, 35 .version_id = 1, 36 .minimum_version_id = 1, 37 .fields = (VMStateField[]) { 38 VMSTATE_UINT32(ccmr, IMXCCMState), 39 VMSTATE_UINT32(pdr0, IMXCCMState), 40 VMSTATE_UINT32(pdr1, IMXCCMState), 41 VMSTATE_UINT32(mpctl, IMXCCMState), 42 VMSTATE_UINT32(spctl, IMXCCMState), 43 VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3), 44 VMSTATE_UINT32(pmcr0, IMXCCMState), 45 VMSTATE_UINT32(pmcr1, IMXCCMState), 46 VMSTATE_UINT32(pll_refclk_freq, IMXCCMState), 47 VMSTATE_END_OF_LIST() 48 }, 49 .post_load = imx_ccm_post_load, 50 }; 51 52 uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock) 53 { 54 IMXCCMState *s = IMX_CCM(dev); 55 56 switch (clock) { 57 case NOCLK: 58 return 0; 59 case MCU: 60 return s->mcu_clk_freq; 61 case HSP: 62 return s->hsp_clk_freq; 63 case IPG: 64 return s->ipg_clk_freq; 65 case CLK_32k: 66 return CKIL_FREQ; 67 } 68 return 0; 69 } 70 71 /* 72 * Calculate PLL output frequency 73 */ 74 static uint32_t calc_pll(uint32_t pllreg, uint32_t base_freq) 75 { 76 int32_t mfn = MFN(pllreg); /* Numerator */ 77 uint32_t mfi = MFI(pllreg); /* Integer part */ 78 uint32_t mfd = 1 + MFD(pllreg); /* Denominator */ 79 uint32_t pd = 1 + PD(pllreg); /* Pre-divider */ 80 81 if (mfi < 5) { 82 mfi = 5; 83 } 84 /* mfn is 10-bit signed twos-complement */ 85 mfn <<= 32 - 10; 86 mfn >>= 32 - 10; 87 88 return ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) / 89 (mfd * pd)) << 10; 90 } 91 92 static void update_clocks(IMXCCMState *s) 93 { 94 /* 95 * If we ever emulate more clocks, this should switch to a data-driven 96 * approach 97 */ 98 99 if ((s->ccmr & CCMR_PRCS) == 2) { 100 s->pll_refclk_freq = CKIL_FREQ * 1024; 101 } else { 102 s->pll_refclk_freq = CKIH_FREQ; 103 } 104 105 /* ipg_clk_arm aka MCU clock */ 106 if ((s->ccmr & CCMR_MDS) || !(s->ccmr & CCMR_MPE)) { 107 s->mcu_clk_freq = s->pll_refclk_freq; 108 } else { 109 s->mcu_clk_freq = calc_pll(s->mpctl, s->pll_refclk_freq); 110 } 111 112 /* High-speed clock */ 113 s->hsp_clk_freq = s->mcu_clk_freq / (1 + EXTRACT(s->pdr0, HSP)); 114 s->ipg_clk_freq = s->hsp_clk_freq / (1 + EXTRACT(s->pdr0, IPG)); 115 116 DPRINTF("mcu %uMHz, HSP %uMHz, IPG %uHz\n", 117 s->mcu_clk_freq / 1000000, 118 s->hsp_clk_freq / 1000000, 119 s->ipg_clk_freq); 120 } 121 122 static void imx_ccm_reset(DeviceState *dev) 123 { 124 IMXCCMState *s = IMX_CCM(dev); 125 126 s->ccmr = 0x074b0b7b; 127 s->pdr0 = 0xff870b48; 128 s->pdr1 = 0x49fcfe7f; 129 s->mpctl = PLL_PD(1) | PLL_MFD(0) | PLL_MFI(6) | PLL_MFN(0); 130 s->cgr[0] = s->cgr[1] = s->cgr[2] = 0xffffffff; 131 s->spctl = PLL_PD(1) | PLL_MFD(4) | PLL_MFI(0xc) | PLL_MFN(1); 132 s->pmcr0 = 0x80209828; 133 134 update_clocks(s); 135 } 136 137 static uint64_t imx_ccm_read(void *opaque, hwaddr offset, 138 unsigned size) 139 { 140 IMXCCMState *s = (IMXCCMState *)opaque; 141 142 DPRINTF("(offset=0x%" HWADDR_PRIx ")\n", offset); 143 144 switch (offset >> 2) { 145 case 0: /* CCMR */ 146 DPRINTF(" ccmr = 0x%x\n", s->ccmr); 147 return s->ccmr; 148 case 1: 149 DPRINTF(" pdr0 = 0x%x\n", s->pdr0); 150 return s->pdr0; 151 case 2: 152 DPRINTF(" pdr1 = 0x%x\n", s->pdr1); 153 return s->pdr1; 154 case 4: 155 DPRINTF(" mpctl = 0x%x\n", s->mpctl); 156 return s->mpctl; 157 case 6: 158 DPRINTF(" spctl = 0x%x\n", s->spctl); 159 return s->spctl; 160 case 8: 161 DPRINTF(" cgr0 = 0x%x\n", s->cgr[0]); 162 return s->cgr[0]; 163 case 9: 164 DPRINTF(" cgr1 = 0x%x\n", s->cgr[1]); 165 return s->cgr[1]; 166 case 10: 167 DPRINTF(" cgr2 = 0x%x\n", s->cgr[2]); 168 return s->cgr[2]; 169 case 18: /* LTR1 */ 170 return 0x00004040; 171 case 23: 172 DPRINTF(" pcmr0 = 0x%x\n", s->pmcr0); 173 return s->pmcr0; 174 default: 175 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" 176 HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset); 177 return 0; 178 } 179 } 180 181 static void imx_ccm_write(void *opaque, hwaddr offset, 182 uint64_t value, unsigned size) 183 { 184 IMXCCMState *s = (IMXCCMState *)opaque; 185 186 DPRINTF("(offset=0x%" HWADDR_PRIx ", value = 0x%x)\n", 187 offset, (unsigned int)value); 188 189 switch (offset >> 2) { 190 case 0: 191 s->ccmr = CCMR_FPMF | (value & 0x3b6fdfff); 192 break; 193 case 1: 194 s->pdr0 = value & 0xff9f3fff; 195 break; 196 case 2: 197 s->pdr1 = value; 198 break; 199 case 4: 200 s->mpctl = value & 0xbfff3fff; 201 break; 202 case 6: 203 s->spctl = value & 0xbfff3fff; 204 break; 205 case 8: 206 s->cgr[0] = value; 207 return; 208 case 9: 209 s->cgr[1] = value; 210 return; 211 case 10: 212 s->cgr[2] = value; 213 return; 214 215 default: 216 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" 217 HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset); 218 return; 219 } 220 update_clocks(s); 221 } 222 223 static const struct MemoryRegionOps imx_ccm_ops = { 224 .read = imx_ccm_read, 225 .write = imx_ccm_write, 226 .endianness = DEVICE_NATIVE_ENDIAN, 227 }; 228 229 static int imx_ccm_init(SysBusDevice *dev) 230 { 231 IMXCCMState *s = IMX_CCM(dev); 232 233 memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s, 234 TYPE_IMX_CCM, 0x1000); 235 sysbus_init_mmio(dev, &s->iomem); 236 237 return 0; 238 } 239 240 static int imx_ccm_post_load(void *opaque, int version_id) 241 { 242 IMXCCMState *s = (IMXCCMState *)opaque; 243 244 update_clocks(s); 245 return 0; 246 } 247 248 static void imx_ccm_class_init(ObjectClass *klass, void *data) 249 { 250 DeviceClass *dc = DEVICE_CLASS(klass); 251 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 252 253 sbc->init = imx_ccm_init; 254 dc->reset = imx_ccm_reset; 255 dc->vmsd = &vmstate_imx_ccm; 256 dc->desc = "i.MX Clock Control Module"; 257 } 258 259 static const TypeInfo imx_ccm_info = { 260 .name = TYPE_IMX_CCM, 261 .parent = TYPE_SYS_BUS_DEVICE, 262 .instance_size = sizeof(IMXCCMState), 263 .class_init = imx_ccm_class_init, 264 }; 265 266 static void imx_ccm_register_types(void) 267 { 268 type_register_static(&imx_ccm_info); 269 } 270 271 type_init(imx_ccm_register_types) 272