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 | * This is an abstract base class used to get a common interface to |
11 | * retrieve the CCM frequencies from the various i.MX SOC. |
12 | */ |
13 | |
14 | #include "qemu/osdep.h" |
15 | #include "hw/misc/imx_ccm.h" |
16 | #include "qemu/log.h" |
17 | #include "qemu/module.h" |
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 | |
32 | uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) |
33 | { |
34 | uint32_t freq = 0; |
35 | IMXCCMClass *klass = IMX_GET_CLASS(dev); |
36 | |
37 | if (klass->get_clock_frequency) { |
38 | freq = klass->get_clock_frequency(dev, clock); |
39 | } |
40 | |
41 | DPRINTF("(clock = %d) = %d\n" , clock, freq); |
42 | |
43 | return freq; |
44 | } |
45 | |
46 | /* |
47 | * Calculate PLL output frequency |
48 | */ |
49 | uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq) |
50 | { |
51 | int32_t freq; |
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 | } |
60 | |
61 | /* mfn is 10-bit signed twos-complement */ |
62 | mfn <<= 32 - 10; |
63 | mfn >>= 32 - 10; |
64 | |
65 | freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) / |
66 | (mfd * pd)) << 10; |
67 | |
68 | DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n" , pllreg, base_freq, |
69 | freq); |
70 | |
71 | return freq; |
72 | } |
73 | |
74 | static const TypeInfo imx_ccm_info = { |
75 | .name = TYPE_IMX_CCM, |
76 | .parent = TYPE_SYS_BUS_DEVICE, |
77 | .instance_size = sizeof(IMXCCMState), |
78 | .class_size = sizeof(IMXCCMClass), |
79 | .abstract = true, |
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) |
88 | |