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