svn commit: r350846 - head/sys/arm/allwinner/clkng

Emmanuel Vadot manu at FreeBSD.org
Sat Aug 10 19:02:51 UTC 2019


Author: manu
Date: Sat Aug 10 19:02:50 2019
New Revision: 350846
URL: https://svnweb.freebsd.org/changeset/base/350846

Log:
  allwinner: Add support to min/max in aw_clk_frac
  
  The Fractionals clock in Allwinner device have some min/max frequencies
  that they can do.
  Add support for it.

Modified:
  head/sys/arm/allwinner/clkng/aw_clk.h
  head/sys/arm/allwinner/clkng/aw_clk_frac.c
  head/sys/arm/allwinner/clkng/aw_clk_frac.h
  head/sys/arm/allwinner/clkng/ccu_a10.c
  head/sys/arm/allwinner/clkng/ccu_a31.c
  head/sys/arm/allwinner/clkng/ccu_a64.c
  head/sys/arm/allwinner/clkng/ccu_h3.c

Modified: head/sys/arm/allwinner/clkng/aw_clk.h
==============================================================================
--- head/sys/arm/allwinner/clkng/aw_clk.h	Sat Aug 10 18:58:25 2019	(r350845)
+++ head/sys/arm/allwinner/clkng/aw_clk.h	Sat Aug 10 19:02:50 2019	(r350846)
@@ -314,13 +314,15 @@ aw_clk_factor_get_value(struct aw_clk_factor *factor, 
      _nshift, _nwidth, _nvalue, _nflags,		\
      _mshift, _mwidth, _mvalue, _mflags,		\
      _gate_shift, _lock_shift,_lock_retries,		\
-    _flags, _freq0, _freq1, _mode_sel, _freq_sel)	\
+    _flags, _freq0, _freq1, _mode_sel, _freq_sel,	\
+    _min_freq, _max_freq)				\
 	static struct aw_clk_frac_def _clkname = {	\
 		.clkdef = {				\
 			.id = _id,			\
 			.name = _name,			\
 			.parent_names = _pnames,	\
 			.parent_cnt = nitems(_pnames),	\
+			.flags = CLK_NODE_GLITCH_FREE,	\
 		},					\
 		.offset = _offset,			\
 		.n.shift = _nshift,			\
@@ -339,6 +341,8 @@ aw_clk_factor_get_value(struct aw_clk_factor *factor, 
 		.frac.freq1 = _freq1,			\
 		.frac.mode_sel = _mode_sel,		\
 		.frac.freq_sel = _freq_sel,		\
+		.min_freq = _min_freq,			\
+		.max_freq = _max_freq,			\
 	}
 
 #define M_CLK(_clkname, _id, _name, _pnames,		\

Modified: head/sys/arm/allwinner/clkng/aw_clk_frac.c
==============================================================================
--- head/sys/arm/allwinner/clkng/aw_clk_frac.c	Sat Aug 10 18:58:25 2019	(r350845)
+++ head/sys/arm/allwinner/clkng/aw_clk_frac.c	Sat Aug 10 19:02:50 2019	(r350846)
@@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$");
 
 #include "clkdev_if.h"
 
+/* #define	dprintf(format, arg...)	printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg) */
+#define	dprintf(format, arg...)
+
 /*
  * clknode for clocks matching the formula :
  *
@@ -54,6 +57,9 @@ struct aw_clk_frac_sc {
 	struct aw_clk_factor	n;
 	struct aw_clk_frac	frac;
 
+	uint64_t		min_freq;
+	uint64_t		max_freq;
+
 	uint32_t	mux_shift;
 	uint32_t	mux_mask;
 	uint32_t	gate_shift;
@@ -89,6 +95,7 @@ aw_clk_frac_init(struct clknode *clk, device_t dev)
 		idx = (val & sc->mux_mask) >> sc->mux_shift;
 	}
 
+	dprintf("init parent idx %d\n", idx);
 	clknode_init_parent_idx(clk, idx);
 	return (0);
 }
@@ -104,6 +111,7 @@ aw_clk_frac_set_gate(struct clknode *clk, bool enable)
 	if ((sc->flags & AW_CLK_HAS_GATE) == 0)
 		return (0);
 
+	dprintf("%sabling gate\n", enable ? "En" : "Dis");
 	DEVICE_LOCK(clk);
 	READ4(clk, sc->offset, &val);
 	if (enable)
@@ -127,6 +135,7 @@ aw_clk_frac_set_mux(struct clknode *clk, int index)
 	if ((sc->flags & AW_CLK_HAS_MUX) == 0)
 		return (0);
 
+	dprintf("Set mux to %d\n", index);
 	DEVICE_LOCK(clk);
 	READ4(clk, sc->offset, &val);
 	val &= ~sc->mux_mask;
@@ -138,7 +147,7 @@ aw_clk_frac_set_mux(struct clknode *clk, int index)
 }
 
 static uint64_t
-aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint64_t fparent, uint64_t *fout,
+aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint64_t fparent, uint64_t fout,
     uint32_t *factor_n, uint32_t *factor_m)
 {
 	uint64_t cur, best;
@@ -150,18 +159,27 @@ aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint6
 	max_m = aw_clk_factor_get_max(&sc->m);
 	max_n = aw_clk_factor_get_max(&sc->n);
 	min_m = aw_clk_factor_get_min(&sc->m);
-	min_n = aw_clk_factor_get_min(&sc->n);
+	min_n = sc->min_freq / fparent;
 
 	for (n = min_n; n <= max_n; n++) {
 		for (m = min_m; m <= max_m; m++) {
 			cur = fparent * n / m;
-			if ((*fout - cur) < (*fout - best)) {
+			if (cur < sc->min_freq) {
+				continue;
+			}
+			if (cur > sc->max_freq) {
+				continue;
+			}
+			if (cur == fout) {
+				*factor_n = n;
+				*factor_m = m;
+				return (cur);
+			}
+			if (abs((fout - cur)) < abs((fout - best))) {
 				best = cur;
 				*factor_n = n;
 				*factor_m = m;
 			}
-			if (best == *fout)
-				return (best);
 		}
 	}
 
@@ -175,32 +193,73 @@ aw_clk_frac_set_freq(struct clknode *clk, uint64_t fpa
 	struct aw_clk_frac_sc *sc;
 	uint64_t cur, best, best_frac;
 	uint32_t val, m, n, best_m, best_n;
-	int retry;
+	int retry, multiple, max_mult, best_mult;
 
 	sc = clknode_get_softc(clk);
 
 	best = best_frac = cur = 0;
+	best_mult = 0;
+	max_mult = 1;
 
-	if (*fout == sc->frac.freq0)
-		best = best_frac = sc->frac.freq0;
-	else if (*fout == sc->frac.freq1)
-		best = best_frac = sc->frac.freq1;
-	else
-		best = aw_clk_frac_find_best(sc, fparent, fout,
-		    &best_n, &best_m);
+	dprintf("Trying to find freq %ju with parent %ju\n", *fout, fparent);
+	if ((flags & CLK_SET_ROUND_MULTIPLE) != 0)
+		max_mult = 10;
+	for (multiple = 1; multiple <= max_mult; multiple++) {
+		/* First test the fractional frequencies */
+		dprintf("Testing with multiple %d\n", multiple);
+		if (*fout * multiple == sc->frac.freq0) {
+			best = best_frac = sc->frac.freq0;
+			best_mult = multiple;
+			dprintf("Found with using frac.freq0 and multiple %d\n", multiple);
+			break;
+		}
+		else if (*fout * multiple == sc->frac.freq1) {
+			best = best_frac = sc->frac.freq1;
+			best_mult = multiple;
+			dprintf("Found with using frac.freq1 and multiple %d\n", multiple);
+			break;
+		}
+		else {
+			cur = aw_clk_frac_find_best(sc, fparent, *fout * multiple,
+			  &n, &m);
+			dprintf("Got %ju with n=%d, m=%d\n", cur, n, m);
+			if (cur == (*fout * multiple)) {
+				best = cur;
+				best_mult = multiple;
+				best_n = n;
+				best_m = m;
+				dprintf("This is the one: n=%d m=%d mult=%d\n", best_n, best_m, best_mult);
+				break;
+			}
+			if (abs(((*fout * multiple) - cur)) < abs(((*fout * multiple) - best))) {
+				best = cur;
+				best_mult = multiple;
+				best_n = n;
+				best_m = m;
+				dprintf("This is the best for now: n=%d m=%d mult=%d\n", best_n, best_m, best_mult);
+			}
+		}
+	}
 
+	if (best < sc->min_freq ||
+	    best > sc->max_freq) {
+		printf("%s: Cannot set %ju for %s (min=%ju max=%ju)\n",
+		    __func__, best, clknode_get_name(clk),
+		    sc->min_freq, sc->max_freq);
+		return (ERANGE);
+	}
 	if ((flags & CLK_SET_DRYRUN) != 0) {
 		*fout = best;
 		*stop = 1;
 		return (0);
 	}
 
-	if ((best < *fout) &&
+	if ((best < (*fout * best_mult)) &&
 	  ((flags & CLK_SET_ROUND_DOWN) == 0)) {
 		*stop = 1;
 		return (ERANGE);
 	}
-	if ((best > *fout) &&
+	if ((best > *fout * best_mult) &&
 	  ((flags & CLK_SET_ROUND_UP) == 0)) {
 		*stop = 1;
 		return (ERANGE);
@@ -271,7 +330,6 @@ aw_clk_frac_recalc(struct clknode *clk, uint64_t *freq
 	} else {
 		m = aw_clk_get_factor(val, &sc->m);
 		n = aw_clk_get_factor(val, &sc->n);
-
 		*freq = *freq * n / m;
 	}
 
@@ -321,6 +379,9 @@ aw_clk_frac_register(struct clkdom *clkdom, struct aw_
 	sc->frac.freq1 = clkdef->frac.freq1;
 	sc->frac.mode_sel = 1 << clkdef->frac.mode_sel;
 	sc->frac.freq_sel = 1 << clkdef->frac.freq_sel;
+
+	sc->min_freq = clkdef->min_freq;
+	sc->max_freq = clkdef->max_freq;
 
 	sc->mux_shift = clkdef->mux_shift;
 	sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;

Modified: head/sys/arm/allwinner/clkng/aw_clk_frac.h
==============================================================================
--- head/sys/arm/allwinner/clkng/aw_clk_frac.h	Sat Aug 10 18:58:25 2019	(r350845)
+++ head/sys/arm/allwinner/clkng/aw_clk_frac.h	Sat Aug 10 19:02:50 2019	(r350846)
@@ -38,6 +38,9 @@ struct aw_clk_frac_def {
 	struct aw_clk_factor	n;
 	struct aw_clk_frac	frac;
 
+	uint64_t		min_freq;
+	uint64_t		max_freq;
+
 	uint32_t		mux_shift;
 	uint32_t		mux_width;
 	uint32_t		gate_shift;

Modified: head/sys/arm/allwinner/clkng/ccu_a10.c
==============================================================================
--- head/sys/arm/allwinner/clkng/ccu_a10.c	Sat Aug 10 18:58:25 2019	(r350845)
+++ head/sys/arm/allwinner/clkng/ccu_a10.c	Sat Aug 10 19:02:50 2019	(r350846)
@@ -221,7 +221,8 @@ FRAC_CLK(pll_video0_clk,
     31, 0, 0,					/* gate, lock, lock retries */
     AW_CLK_HAS_GATE,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    15, 14);					/* mode sel, freq sel */
+    15, 14,					/* mode sel, freq sel */
+    27000000, 381000000);			/* min freq, max freq */
 static const char *pll_video0_2x_parents[] = {"pll_video0"};
 FIXED_CLK(pll_video0_2x_clk,
     CLK_PLL_VIDEO0_2X,				/* id */
@@ -240,7 +241,8 @@ FRAC_CLK(pll_video1_clk,
     31, 0, 0,					/* gate, lock, lock retries */
     AW_CLK_HAS_GATE,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    15, 14);					/* mode sel, freq sel */
+    15, 14,					/* mode sel, freq sel */
+    27000000, 381000000);			/* min freq, max freq */
 static const char *pll_video1_2x_parents[] = {"pll_video1"};
 FIXED_CLK(pll_video1_2x_clk,
     CLK_PLL_VIDEO1_2X,				/* id */

Modified: head/sys/arm/allwinner/clkng/ccu_a31.c
==============================================================================
--- head/sys/arm/allwinner/clkng/ccu_a31.c	Sat Aug 10 18:58:25 2019	(r350845)
+++ head/sys/arm/allwinner/clkng/ccu_a31.c	Sat Aug 10 19:02:50 2019	(r350846)
@@ -302,8 +302,8 @@ FRAC_CLK(pll_video0_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
-
+    24, 25,					/* mode sel, freq sel */
+    30000000, 600000000);			/* min freq, max freq */
 static const char *pll_video0_2x_parents[] = {"pll_video0"};
 FIXED_CLK(pll_video0_2x_clk,
     CLK_PLL_VIDEO0_2X,		/* id */
@@ -323,7 +323,8 @@ FRAC_CLK(pll_ve_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    30000000, 600000000);			/* min freq, max freq */
 
 NKMP_CLK_WITH_UPDATE(pll_ddr_clk,
     CLK_PLL_DDR,				/* id */
@@ -369,7 +370,8 @@ FRAC_CLK(pll_video1_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    30000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_video1_2x_parents[] = {"pll_video1"};
 FIXED_CLK(pll_video1_2x_clk,
@@ -390,7 +392,8 @@ FRAC_CLK(pll_gpu_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    30000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_mipi_parents[] = {"pll_video0", "pll_video1"};
 NKMP_CLK(pll_mipi_clk,
@@ -414,7 +417,8 @@ FRAC_CLK(pll9_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    30000000, 600000000);			/* min freq, max freq */
 
 FRAC_CLK(pll10_clk,
     CLK_PLL10,				/* id */
@@ -425,7 +429,8 @@ FRAC_CLK(pll10_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    30000000, 600000000);			/* min freq, max freq */
 
 static struct clk_div_table axi_div_table[] = {
 	{ .value = 0, .divider = 1, },

Modified: head/sys/arm/allwinner/clkng/ccu_a64.c
==============================================================================
--- head/sys/arm/allwinner/clkng/ccu_a64.c	Sat Aug 10 18:58:25 2019	(r350845)
+++ head/sys/arm/allwinner/clkng/ccu_a64.c	Sat Aug 10 19:02:50 2019	(r350846)
@@ -288,7 +288,8 @@ FRAC_CLK(pll_video0_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 static const char *pll_video0_2x_parents[] = {"pll_video0"};
 FIXED_CLK(pll_video0_2x_clk,
     CLK_PLL_VIDEO0_2X,			/* id */
@@ -309,7 +310,8 @@ FRAC_CLK(pll_ve_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_ddr0_parents[] = {"osc24M"};
 NKMP_CLK_WITH_UPDATE(pll_ddr0_clk,
@@ -379,7 +381,8 @@ FRAC_CLK(pll_video1_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_gpu_parents[] = {"osc24M"};
 FRAC_CLK(pll_gpu_clk,
@@ -391,7 +394,8 @@ FRAC_CLK(pll_gpu_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 /* PLL MIPI is missing */
 
@@ -405,7 +409,8 @@ FRAC_CLK(pll_hsic_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_de_parents[] = {"osc24M"};
 FRAC_CLK(pll_de_clk,
@@ -417,7 +422,8 @@ FRAC_CLK(pll_de_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_ddr1_parents[] = {"osc24M"};
 NKMP_CLK_WITH_UPDATE(pll_ddr1_clk,

Modified: head/sys/arm/allwinner/clkng/ccu_h3.c
==============================================================================
--- head/sys/arm/allwinner/clkng/ccu_h3.c	Sat Aug 10 18:58:25 2019	(r350845)
+++ head/sys/arm/allwinner/clkng/ccu_h3.c	Sat Aug 10 19:02:50 2019	(r350846)
@@ -306,7 +306,8 @@ FRAC_CLK(pll_video_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_ve_parents[] = {"osc24M"};
 FRAC_CLK(pll_ve_clk,
@@ -318,7 +319,8 @@ FRAC_CLK(pll_ve_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_ddr_parents[] = {"osc24M"};
 NKMP_CLK_WITH_UPDATE(pll_ddr_clk,
@@ -366,7 +368,8 @@ FRAC_CLK(pll_gpu_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 static const char *pll_periph1_parents[] = {"osc24M"};
 NKMP_CLK(pll_periph1_clk,
@@ -391,7 +394,8 @@ FRAC_CLK(pll_de_clk,
     31, 28, 1000,				/* gate, lock, lock retries */
     AW_CLK_HAS_LOCK,				/* flags */
     270000000, 297000000,			/* freq0, freq1 */
-    24, 25);					/* mode sel, freq sel */
+    24, 25,					/* mode sel, freq sel */
+    192000000, 600000000);			/* min freq, max freq */
 
 static const char *cpux_parents[] = {"osc32k", "osc24M", "pll_cpux", "pll_cpux"};
 MUX_CLK(cpux_clk,


More information about the svn-src-head mailing list