Browse Source

efHotAgingTrendMining influenceAnalysisOfCableAging.c 韩正义 commit at 2021-04-19

韩正义 4 years ago
parent
commit
2470829e70

+ 77 - 0
efHotAgingTrendMining/analysisOfEnvironmentalFactors/influenceAnalysisOfCableAging.c

@@ -285,3 +285,80 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
  * possible, programmable rate for this DPLL.  Attempts to select the
  * possible, programmable rate for this DPLL.  Attempts to select the
  * minimum possible n.  Stores the computed (m, n) in the DPLL's
  * minimum possible n.  Stores the computed (m, n) in the DPLL's
  * dpll_data structure so set_rate() will not need to call this
  * dpll_data structure so set_rate() will not need to call this
+ * (expensive) function again.  Returns ~0 if the target rate cannot
+ * be rounded, or the rounded rate upon success.
+ */
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+		unsigned long *parent_rate)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	int m, n, r, scaled_max_m;
+	unsigned long scaled_rt_rp;
+	unsigned long new_rate = 0;
+	struct dpll_data *dd;
+	unsigned long ref_rate;
+	const char *clk_name;
+
+	if (!clk || !clk->dpll_data)
+		return ~0;
+
+	dd = clk->dpll_data;
+
+	ref_rate = __clk_get_rate(dd->clk_ref);
+	clk_name = __clk_get_name(hw->clk);
+	pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
+		 clk_name, target_rate);
+
+	scaled_rt_rp = target_rate / (ref_rate / DPLL_SCALE_FACTOR);
+	scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
+
+	dd->last_rounded_rate = 0;
+
+	for (n = dd->min_divider; n <= dd->max_divider; n++) {
+
+		/* Is the (input clk, divider) pair valid for the DPLL? */
+		r = _dpll_test_fint(clk, n);
+		if (r == DPLL_FINT_UNDERFLOW)
+			break;
+		else if (r == DPLL_FINT_INVALID)
+			continue;
+
+		/* Compute the scaled DPLL multiplier, based on the divider */
+		m = scaled_rt_rp * n;
+
+		/*
+		 * Since we're counting n up, a m overflow means we
+		 * can bail out completely (since as n increases in
+		 * the next iteration, there's no way that m can
+		 * increase beyond the current m)
+		 */
+		if (m > scaled_max_m)
+			break;
+
+		r = _dpll_test_mult(&m, n, &new_rate, target_rate,
+				    ref_rate);
+
+		/* m can't be set low enough for this n - try with a larger n */
+		if (r == DPLL_MULT_UNDERFLOW)
+			continue;
+
+		pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n",
+			 clk_name, m, n, new_rate);
+
+		if (target_rate == new_rate) {
+			dd->last_rounded_m = m;
+			dd->last_rounded_n = n;
+			dd->last_rounded_rate = target_rate;
+			break;
+		}
+	}
+
+	if (target_rate != new_rate) {
+		pr_debug("clock: %s: cannot round to rate %ld\n",
+			 clk_name, target_rate);
+		return ~0;
+	}
+
+	return target_rate;
+}
+