Selaa lähdekoodia

efHotAgingTrendMining environmentalTemperatureAnalysis.c 宁志军 commit at 2020-09-18

宁志军 4 vuotta sitten
vanhempi
commit
81c67c75ff

+ 109 - 0
efHotAgingTrendMining/analysisOfEnvironmentalFactors/environmentalTemperatureAnalysis.c

@@ -90,3 +90,112 @@ static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
  * will ensure that the write to the clksel_reg reaches its
  * destination before returning -- important since PRM and CM register
  * accesses can be quite slow compared to ARM cycles -- but does not
+ * take into account any time the hardware might take to switch the
+ * clock source.
+ */
+static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
+{
+	u32 v;
+
+	v = __raw_readl(clk->clksel_reg);
+	v &= ~clk->clksel_mask;
+	v |= field_val << __ffs(clk->clksel_mask);
+	__raw_writel(v, clk->clksel_reg);
+
+	v = __raw_readl(clk->clksel_reg); /* OCP barrier */
+}
+
+/**
+ * _clksel_to_divisor() - turn clksel field value into integer divider
+ * @clk: OMAP struct clk to use
+ * @field_val: register field value to find
+ *
+ * Given a struct clk of a rate-selectable clksel clock, and a register field
+ * value to search for, find the corresponding clock divisor.  The register
+ * field value should be pre-masked and shifted down so the LSB is at bit 0
+ * before calling.  Returns 0 on error or returns the actual integer divisor
+ * upon success.
+ */
+static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
+{
+	const struct clksel *clks;
+	const struct clksel_rate *clkr;
+	struct clk *parent;
+
+	parent = __clk_get_parent(clk->hw.clk);
+
+	clks = _get_clksel_by_parent(clk, parent);
+	if (!clks)
+		return 0;
+
+	for (clkr = clks->rates; clkr->div; clkr++) {
+		if (!(clkr->flags & cpu_mask))
+			continue;
+
+		if (clkr->val == field_val)
+			break;
+	}
+
+	if (!clkr->div) {
+		/* This indicates a data error */
+		WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
+		     __clk_get_name(clk->hw.clk), field_val,
+		     __clk_get_name(parent));
+		return 0;
+	}
+
+	return clkr->div;
+}
+
+/**
+ * _divisor_to_clksel() - turn clksel integer divisor into a field value
+ * @clk: OMAP struct clk to use
+ * @div: integer divisor to search for
+ *
+ * Given a struct clk of a rate-selectable clksel clock, and a clock
+ * divisor, find the corresponding register field value.  Returns the
+ * register field value _before_ left-shifting (i.e., LSB is at bit
+ * 0); or returns 0xFFFFFFFF (~0) upon error.
+ */
+static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
+{
+	const struct clksel *clks;
+	const struct clksel_rate *clkr;
+	struct clk *parent;
+
+	/* should never happen */
+	WARN_ON(div == 0);
+
+	parent = __clk_get_parent(clk->hw.clk);
+	clks = _get_clksel_by_parent(clk, parent);
+	if (!clks)
+		return ~0;
+
+	for (clkr = clks->rates; clkr->div; clkr++) {
+		if (!(clkr->flags & cpu_mask))
+			continue;
+
+		if (clkr->div == div)
+			break;
+	}
+
+	if (!clkr->div) {
+		pr_err("clock: %s: could not find divisor %d for parent %s\n",
+		       __clk_get_name(clk->hw.clk), div,
+		       __clk_get_name(parent));
+		return ~0;
+	}
+
+	return clkr->val;
+}
+
+/**
+ * _read_divisor() - get current divisor applied to parent clock (from hdwr)
+ * @clk: OMAP struct clk to use.
+ *
+ * Read the current divisor register value for @clk that is programmed
+ * into the hardware, convert it into the actual divisor value, and
+ * return it; or return 0 on error.
+ */
+static u32 _read_divisor(struct clk_hw_omap *clk)
+{