|
@@ -0,0 +1,99 @@
|
|
|
+/*
|
|
|
+ * OMAP2/3/4 DPLL clock functions
|
|
|
+ *
|
|
|
+ * Copyright (C) 2005-2008 Texas Instruments, Inc.
|
|
|
+ * Copyright (C) 2004-2010 Nokia Corporation
|
|
|
+ *
|
|
|
+ * Contacts:
|
|
|
+ * Richard Woodruff <r-woodruff2@ti.com>
|
|
|
+ * Paul Walmsley
|
|
|
+ *
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU General Public License version 2 as
|
|
|
+ * published by the Free Software Foundation.
|
|
|
+ */
|
|
|
+#undef DEBUG
|
|
|
+
|
|
|
+#include <linux/kernel.h>
|
|
|
+#include <linux/errno.h>
|
|
|
+#include <linux/clk-provider.h>
|
|
|
+#include <linux/io.h>
|
|
|
+
|
|
|
+#include <asm/div64.h>
|
|
|
+
|
|
|
+#include "soc.h"
|
|
|
+#include "clock.h"
|
|
|
+#include "cm-regbits-24xx.h"
|
|
|
+#include "cm-regbits-34xx.h"
|
|
|
+
|
|
|
+/* DPLL rate rounding: minimum DPLL multiplier, divider values */
|
|
|
+#define DPLL_MIN_MULTIPLIER 2
|
|
|
+#define DPLL_MIN_DIVIDER 1
|
|
|
+
|
|
|
+/* Possible error results from _dpll_test_mult */
|
|
|
+#define DPLL_MULT_UNDERFLOW -1
|
|
|
+
|
|
|
+/*
|
|
|
+ * Scale factor to mitigate roundoff errors in DPLL rate rounding.
|
|
|
+ * The higher the scale factor, the greater the risk of arithmetic overflow,
|
|
|
+ * but the closer the rounded rate to the target rate. DPLL_SCALE_FACTOR
|
|
|
+ * must be a power of DPLL_SCALE_BASE.
|
|
|
+ */
|
|
|
+#define DPLL_SCALE_FACTOR 64
|
|
|
+#define DPLL_SCALE_BASE 2
|
|
|
+#define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \
|
|
|
+ (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
|
|
|
+
|
|
|
+/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
|
|
|
+#define OMAP3430_DPLL_FINT_BAND1_MIN 750000
|
|
|
+#define OMAP3430_DPLL_FINT_BAND1_MAX 2100000
|
|
|
+#define OMAP3430_DPLL_FINT_BAND2_MIN 7500000
|
|
|
+#define OMAP3430_DPLL_FINT_BAND2_MAX 21000000
|
|
|
+
|
|
|
+/*
|
|
|
+ * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
|
|
|
+ * From device data manual section 4.3 "DPLL and DLL Specifications".
|
|
|
+ */
|
|
|
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN 500000
|
|
|
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX 2500000
|
|
|
+#define OMAP3PLUS_DPLL_FINT_MIN 32000
|
|
|
+#define OMAP3PLUS_DPLL_FINT_MAX 52000000
|
|
|
+
|
|
|
+/* _dpll_test_fint() return codes */
|
|
|
+#define DPLL_FINT_UNDERFLOW -1
|
|
|
+#define DPLL_FINT_INVALID -2
|
|
|
+
|
|
|
+/* Private functions */
|
|
|
+
|
|
|
+/*
|
|
|
+ * _dpll_test_fint - test whether an Fint value is valid for the DPLL
|
|
|
+ * @clk: DPLL struct clk to test
|
|
|
+ * @n: divider value (N) to test
|
|
|
+ *
|
|
|
+ * Tests whether a particular divider @n will result in a valid DPLL
|
|
|
+ * internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter
|
|
|
+ * Correction". Returns 0 if OK, -1 if the enclosing loop can terminate
|
|
|
+ * (assuming that it is counting N upwards), or -2 if the enclosing loop
|
|
|
+ * should skip to the next iteration (again assuming N is increasing).
|
|
|
+ */
|
|
|
+static int _dpll_test_fint(struct clk_hw_omap *clk, u8 n)
|
|
|
+{
|
|
|
+ struct dpll_data *dd;
|
|
|
+ long fint, fint_min, fint_max;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ dd = clk->dpll_data;
|
|
|
+
|
|
|
+ /* DPLL divider must result in a valid jitter correction val */
|
|
|
+ fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
|
|
|
+
|
|
|
+ if (cpu_is_omap24xx()) {
|
|
|
+ /* Should not be called for OMAP2, so warn if it is called */
|
|
|
+ WARN(1, "No fint limits available for OMAP2!\n");
|
|
|
+ return DPLL_FINT_INVALID;
|
|
|
+ } else if (cpu_is_omap3430()) {
|
|
|
+ fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
|
|
|
+ fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
|
|
|
+ } else if (dd->flags & DPLL_J_TYPE) {
|
|
|
+ fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
|
|
|
+ fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
|