| /* |
| * IMX31 Clock Control Module |
| * |
| * Copyright (C) 2012 NICTA |
| * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> |
| * |
| * This work is licensed under the terms of the GNU GPL, version 2 or later. |
| * See the COPYING file in the top-level directory. |
| * |
| * This is an abstract base class used to get a common interface to |
| * retrieve the CCM frequencies from the various i.MX SOC. |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "hw/misc/imx_ccm.h" |
| #include "qemu/module.h" |
| |
| #ifndef DEBUG_IMX_CCM |
| #define DEBUG_IMX_CCM 0 |
| #endif |
| |
| #define DPRINTF(fmt, args...) \ |
| do { \ |
| if (DEBUG_IMX_CCM) { \ |
| fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_CCM, \ |
| __func__, ##args); \ |
| } \ |
| } while (0) |
| |
| |
| uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) |
| { |
| uint32_t freq = 0; |
| IMXCCMClass *klass = IMX_CCM_GET_CLASS(dev); |
| |
| if (klass->get_clock_frequency) { |
| freq = klass->get_clock_frequency(dev, clock); |
| } |
| |
| DPRINTF("(clock = %d) = %u\n", clock, freq); |
| |
| return freq; |
| } |
| |
| /* |
| * Calculate PLL output frequency |
| */ |
| uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq) |
| { |
| int32_t freq; |
| int32_t mfn = MFN(pllreg); /* Numerator */ |
| uint32_t mfi = MFI(pllreg); /* Integer part */ |
| uint32_t mfd = 1 + MFD(pllreg); /* Denominator */ |
| uint32_t pd = 1 + PD(pllreg); /* Pre-divider */ |
| |
| if (mfi < 5) { |
| mfi = 5; |
| } |
| |
| /* mfn is 10-bit signed twos-complement */ |
| mfn <<= 32 - 10; |
| mfn >>= 32 - 10; |
| |
| freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) / |
| (mfd * pd)) << 10; |
| |
| DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq, |
| freq); |
| |
| return freq; |
| } |
| |
| static const TypeInfo imx_ccm_info = { |
| .name = TYPE_IMX_CCM, |
| .parent = TYPE_SYS_BUS_DEVICE, |
| .instance_size = sizeof(IMXCCMState), |
| .class_size = sizeof(IMXCCMClass), |
| .abstract = true, |
| }; |
| |
| static void imx_ccm_register_types(void) |
| { |
| type_register_static(&imx_ccm_info); |
| } |
| |
| type_init(imx_ccm_register_types) |