aboutsummaryrefslogtreecommitdiffstats
path: root/hw/misc/imx_ccm.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/misc/imx_ccm.c')
-rw-r--r--hw/misc/imx_ccm.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
new file mode 100644
index 000000000..9403c5daa
--- /dev/null
+++ b/hw/misc/imx_ccm.c
@@ -0,0 +1,86 @@
+/*
+ * 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)