]>
Commit | Line | Data |
---|---|---|
bcc181b0 PC |
1 | /* |
2 | * IMX31 Clock Control Module | |
3 | * | |
4 | * Copyright (C) 2012 NICTA | |
282e74c8 | 5 | * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> |
bcc181b0 PC |
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 | * | |
cb54d868 JCD |
10 | * This is an abstract base class used to get a common interface to |
11 | * retrieve the CCM frequencies from the various i.MX SOC. | |
bcc181b0 PC |
12 | */ |
13 | ||
8ef94f0b | 14 | #include "qemu/osdep.h" |
282e74c8 | 15 | #include "hw/misc/imx_ccm.h" |
03dd024f | 16 | #include "qemu/log.h" |
0b8fa32f | 17 | #include "qemu/module.h" |
bcc181b0 | 18 | |
4a6aa0af JCD |
19 | #ifndef DEBUG_IMX_CCM |
20 | #define DEBUG_IMX_CCM 0 | |
bcc181b0 PC |
21 | #endif |
22 | ||
4a6aa0af JCD |
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 | ||
bcc181b0 | 31 | |
cb54d868 | 32 | uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) |
bcc181b0 | 33 | { |
cb54d868 JCD |
34 | uint32_t freq = 0; |
35 | IMXCCMClass *klass = IMX_GET_CLASS(dev); | |
bcc181b0 | 36 | |
cb54d868 JCD |
37 | if (klass->get_clock_frequency) { |
38 | freq = klass->get_clock_frequency(dev, clock); | |
bcc181b0 | 39 | } |
cb54d868 JCD |
40 | |
41 | DPRINTF("(clock = %d) = %d\n", clock, freq); | |
42 | ||
43 | return freq; | |
bcc181b0 PC |
44 | } |
45 | ||
46 | /* | |
47 | * Calculate PLL output frequency | |
48 | */ | |
cb54d868 | 49 | uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq) |
bcc181b0 | 50 | { |
cb54d868 | 51 | int32_t freq; |
bcc181b0 PC |
52 | int32_t mfn = MFN(pllreg); /* Numerator */ |
53 | uint32_t mfi = MFI(pllreg); /* Integer part */ | |
54 | uint32_t mfd = 1 + MFD(pllreg); /* Denominator */ | |
55 | uint32_t pd = 1 + PD(pllreg); /* Pre-divider */ | |
56 | ||
57 | if (mfi < 5) { | |
58 | mfi = 5; | |
59 | } | |
cb54d868 | 60 | |
bcc181b0 PC |
61 | /* mfn is 10-bit signed twos-complement */ |
62 | mfn <<= 32 - 10; | |
63 | mfn >>= 32 - 10; | |
64 | ||
cb54d868 | 65 | freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) / |
bcc181b0 | 66 | (mfd * pd)) << 10; |
bcc181b0 | 67 | |
cb54d868 JCD |
68 | DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq, |
69 | freq); | |
bcc181b0 | 70 | |
cb54d868 | 71 | return freq; |
bcc181b0 PC |
72 | } |
73 | ||
8c43a6f0 | 74 | static const TypeInfo imx_ccm_info = { |
cb54d868 JCD |
75 | .name = TYPE_IMX_CCM, |
76 | .parent = TYPE_SYS_BUS_DEVICE, | |
bcc181b0 | 77 | .instance_size = sizeof(IMXCCMState), |
cb54d868 JCD |
78 | .class_size = sizeof(IMXCCMClass), |
79 | .abstract = true, | |
bcc181b0 PC |
80 | }; |
81 | ||
82 | static void imx_ccm_register_types(void) | |
83 | { | |
84 | type_register_static(&imx_ccm_info); | |
85 | } | |
86 | ||
87 | type_init(imx_ccm_register_types) |