svn commit: r310178 - head/sys/arm/allwinner/clk

Emmanuel Vadot manu at FreeBSD.org
Fri Dec 16 21:58:51 UTC 2016


Author: manu
Date: Fri Dec 16 21:58:48 2016
New Revision: 310178
URL: https://svnweb.freebsd.org/changeset/base/310178

Log:
  Honor the CLK_SET_DRYRUN for the *set_freq function for allwinner clocks.
  
  Reviewed by:	jmcneill
  MFC after:	1 month
  Differential Revision:	https://reviews.freebsd.org/D8821

Modified:
  head/sys/arm/allwinner/clk/aw_debeclk.c
  head/sys/arm/allwinner/clk/aw_hdmiclk.c
  head/sys/arm/allwinner/clk/aw_lcdclk.c
  head/sys/arm/allwinner/clk/aw_mmcclk.c
  head/sys/arm/allwinner/clk/aw_modclk.c
  head/sys/arm/allwinner/clk/aw_pll.c
  head/sys/arm/allwinner/clk/aw_thsclk.c

Modified: head/sys/arm/allwinner/clk/aw_debeclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_debeclk.c	Fri Dec 16 21:10:37 2016	(r310177)
+++ head/sys/arm/allwinner/clk/aw_debeclk.c	Fri Dec 16 21:58:48 2016	(r310178)
@@ -209,6 +209,12 @@ aw_debeclk_set_freq(struct clknode *clk,
 
 	m = howmany(fin, *fout) - 1;
 
+	*fout = fin / (m + 1);
+	*stop = 1;
+
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	DEBECLK_READ(sc, &val);
 	val &= ~CLK_RATIO_M;
@@ -216,9 +222,6 @@ aw_debeclk_set_freq(struct clknode *clk,
 	DEBECLK_WRITE(sc, val);
 	DEVICE_UNLOCK(sc);
 
-	*fout = fin / (m + 1);
-	*stop = 1;
-
 	return (0);
 }
 

Modified: head/sys/arm/allwinner/clk/aw_hdmiclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_hdmiclk.c	Fri Dec 16 21:10:37 2016	(r310177)
+++ head/sys/arm/allwinner/clk/aw_hdmiclk.c	Fri Dec 16 21:58:48 2016	(r310178)
@@ -188,6 +188,12 @@ aw_hdmiclk_set_freq(struct clknode *clk,
 	if (best_diff == (int64_t)*fout)
 		return (ERANGE);
 
+	*fout = fin / (1 << best_n) / (best_m + 1);
+	*stop = 1;
+
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	HDMICLK_READ(sc, &val);
 	val &= ~(CLK_RATIO_N | CLK_RATIO_M);
@@ -196,9 +202,6 @@ aw_hdmiclk_set_freq(struct clknode *clk,
 	HDMICLK_WRITE(sc, val);
 	DEVICE_UNLOCK(sc);
 
-	*fout = fin / (1 << best_n) / (best_m + 1);
-	*stop = 1;
-
 	return (0);
 }
 

Modified: head/sys/arm/allwinner/clk/aw_lcdclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_lcdclk.c	Fri Dec 16 21:10:37 2016	(r310177)
+++ head/sys/arm/allwinner/clk/aw_lcdclk.c	Fri Dec 16 21:58:48 2016	(r310178)
@@ -389,56 +389,69 @@ aw_lcdclk_set_freq(struct clknode *clk, 
     int flags, int *stop)
 {
 	struct aw_lcdclk_softc *sc;
+	struct clknode *parent_clk;
+	const char **parent_names;
 	uint64_t pll_freq;
 	uint32_t val, src_sel;
 	int error, tcon_pll_div;
 
 	sc = clknode_get_softc(clk);
 
-	switch (sc->type) {
-	case AW_LCD_CH0:
+	if (sc->type == AW_LCD_CH0) {
 		*stop = 0;
-		break;
-	case AW_LCD_CH1:
-		if (sc->id != CLK_IDX_CH1_SCLK2)
-			return (ENXIO);
+		return (0);
+	}
 
-		src_sel = calc_tcon_pll(fin, *fout, &pll_freq, &tcon_pll_div);
+	if (sc->id != CLK_IDX_CH1_SCLK2)
+		return (ENXIO);
 
-		/* Switch parent clock if necessary */
-		if (src_sel != clknode_get_parent_idx(clk)) {
-			error = clknode_set_parent_by_idx(clk, src_sel);
-			if (error != 0)
-				return (error);
-		}
+	src_sel = calc_tcon_pll(fin, *fout, &pll_freq, &tcon_pll_div);
 
-		error = clknode_set_freq(clknode_get_parent(clk), pll_freq,
-		    0, 0);
-		if (error != 0)
-			return (error);
-
-		error = clknode_enable(clknode_get_parent(clk));
-		if (error != 0)
-			return (error);
-
-		/* Fetch new input frequency */
-		error = clknode_get_freq(clknode_get_parent(clk), &pll_freq);
-		if (error != 0)
-			return (error);
-
-		/* Set LCD divisor */
-		DEVICE_LOCK(sc);
-		LCDCLK_READ(sc, &val);
-		val &= ~CH1_CLK_DIV_RATIO_M;
-		val |= ((tcon_pll_div - 1) << CH1_CLK_DIV_RATIO_M_SHIFT);
-		LCDCLK_WRITE(sc, val);
-		DEVICE_UNLOCK(sc);
+	parent_names = clknode_get_parent_names(clk);
+	parent_clk = clknode_find_by_name(parent_names[src_sel]);
 
-		*fout = pll_freq / tcon_pll_div;
-		*stop = 1;
+	if (parent_clk == NULL)
+		return (ERANGE);
 
-		break;
-	}
+	/* Fetch input frequency */
+	error = clknode_get_freq(parent_clk, &pll_freq);
+	if (error != 0)
+		return (error);
+
+	*fout = pll_freq / tcon_pll_div;
+	*stop = 1;
+
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
+	/* Switch parent clock if necessary */
+	error = clknode_set_parent_by_idx(clk, src_sel);
+	if (error != 0)
+		return (error);
+
+	error = clknode_set_freq(parent_clk, pll_freq,
+	    0, 0);
+	if (error != 0)
+		return (error);
+
+	/* Fetch new input frequency */
+	error = clknode_get_freq(parent_clk, &pll_freq);
+	if (error != 0)
+		return (error);
+
+	*fout = pll_freq / tcon_pll_div;
+
+	error = clknode_enable(parent_clk);
+	if (error != 0)
+		return (error);
+
+	/* Set LCD divisor */
+	DEVICE_LOCK(sc);
+	LCDCLK_READ(sc, &val);
+	val &= ~CH1_CLK_DIV_RATIO_M;
+	val |= ((tcon_pll_div - 1) << CH1_CLK_DIV_RATIO_M_SHIFT);
+	LCDCLK_WRITE(sc, val);
+	DEVICE_UNLOCK(sc);
 
 	return (0);
 }

Modified: head/sys/arm/allwinner/clk/aw_mmcclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_mmcclk.c	Fri Dec 16 21:10:37 2016	(r310177)
+++ head/sys/arm/allwinner/clk/aw_mmcclk.c	Fri Dec 16 21:58:48 2016	(r310178)
@@ -77,6 +77,20 @@ struct aw_mmcclk_sc {
 	bus_addr_t	reg;
 };
 
+struct phase_clk {
+	uint64_t	freq;
+	int		parent_idx;
+	uint32_t	ophase;
+	uint32_t	phase;
+	uint32_t	n;
+};
+
+static struct phase_clk aw_mmcclk_phase[] = {
+	{400000, CLK_SRC_SEL_OSC24M, 0, 0, 2},
+	{25000000, CLK_SRC_SEL_PLL6, 0, 5, 2},
+	{52000000, CLK_SRC_SEL_PLL6, 3, 5, 0},
+};
+
 #define	MODCLK_READ(sc, val)	CLKDEV_READ_4((sc)->clkdev, (sc)->reg, (val))
 #define	MODCLK_WRITE(sc, val)	CLKDEV_WRITE_4((sc)->clkdev, (sc)->reg, (val))
 #define	DEVICE_LOCK(sc)		CLKDEV_DEVICE_LOCK((sc)->clkdev)
@@ -166,8 +180,10 @@ aw_mmcclk_set_freq(struct clknode *clk, 
     int flags, int *stop)
 {
 	struct aw_mmcclk_sc *sc;
-	uint32_t val, m, n, phase, ophase;
-	int parent_idx, error;
+	struct clknode *parent_clk;
+	const char **parent_names;
+	uint32_t val, m;
+	int parent_idx, error, phase;
 
 	sc = clknode_get_softc(clk);
 
@@ -175,52 +191,49 @@ aw_mmcclk_set_freq(struct clknode *clk, 
 	 * The ophase/phase values should be set by the MMC driver, but
 	 * there is currently no way to do this with the clk API
 	 */
-	if (*fout <= 400000) {
-		parent_idx = CLK_SRC_SEL_OSC24M;
-		ophase = 0;
-		phase = 0;
-		n = 2;
-	} else if (*fout <= 25000000) {
-		parent_idx = CLK_SRC_SEL_PLL6;
-		ophase = 0;
-		phase = 5;
-		n = 2;
-	} else if (*fout <= 52000000) {
-		parent_idx = CLK_SRC_SEL_PLL6;
-		ophase = 3;
-		phase = 5;
-		n = 0;
-	} else
+	for (phase = 0; phase < nitems(aw_mmcclk_phase); phase++) {
+		if (*fout <= aw_mmcclk_phase[phase].freq)
+			break;
+	}
+
+	if (phase == nitems(aw_mmcclk_phase))
 		return (ERANGE);
 
-	/* Switch parent clock, if necessary */
-	if (parent_idx != clknode_get_parent_idx(clk)) {
-		error = clknode_set_parent_by_idx(clk, parent_idx);
-		if (error != 0)
-			return (error);
-
-		/* Fetch new input frequency */
-		error = clknode_get_freq(clknode_get_parent(clk), &fin);
-		if (error != 0)
-			return (error);
-	}
+	parent_names = clknode_get_parent_names(clk);
+	parent_idx = aw_mmcclk_phase[phase].parent_idx;
+	parent_clk = clknode_find_by_name(parent_names[parent_idx]);
+
+	if (parent_clk == NULL)
+		return (ERANGE);
+
+	error = clknode_get_freq(parent_clk, &fin);
+	if (error != 0)
+		return (error);
+
+	m = ((fin / (1 << aw_mmcclk_phase[phase].n)) / *fout) - 1;
+
+	*fout = fin / (1 << aw_mmcclk_phase[phase].n) / (m + 1);
+	*stop = 1;
+
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
 
-	m = ((fin / (1 << n)) / *fout) - 1;
+	/* Switch to the correct parent if needed */
+	error = clknode_set_parent_by_idx(clk, parent_idx);
+	if (error != 0)
+		return (error);
 
 	DEVICE_LOCK(sc);
 	MODCLK_READ(sc, &val);
 	val &= ~(CLK_RATIO_N | CLK_RATIO_M | CLK_PHASE_CTR |
 	    OUTPUT_CLK_PHASE_CTR);
-	val |= (n << CLK_RATIO_N_SHIFT);
+	val |= (aw_mmcclk_phase[phase].n << CLK_RATIO_N_SHIFT);
 	val |= (m << CLK_RATIO_M_SHIFT);
-	val |= (phase << CLK_PHASE_CTR_SHIFT);
-	val |= (ophase << OUTPUT_CLK_PHASE_CTR_SHIFT);
+	val |= (aw_mmcclk_phase[phase].phase << CLK_PHASE_CTR_SHIFT);
+	val |= (aw_mmcclk_phase[phase].ophase << OUTPUT_CLK_PHASE_CTR_SHIFT);
 	MODCLK_WRITE(sc, val);
 	DEVICE_UNLOCK(sc);
 
-	*fout = fin / (1 << n) / (m + 1);
-	*stop = 1;
-
 	return (0);
 }
 

Modified: head/sys/arm/allwinner/clk/aw_modclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_modclk.c	Fri Dec 16 21:10:37 2016	(r310177)
+++ head/sys/arm/allwinner/clk/aw_modclk.c	Fri Dec 16 21:58:48 2016	(r310178)
@@ -68,7 +68,6 @@ static struct ofw_compat_data compat_dat
 struct aw_modclk_sc {
 	device_t	clkdev;
 	bus_addr_t	reg;
-	u_int		parent_cnt;
 };
 
 #define	MODCLK_READ(sc, val)	CLKDEV_READ_4((sc)->clkdev, (sc)->reg, (val))
@@ -102,7 +101,7 @@ aw_modclk_set_mux(struct clknode *clk, i
 
 	sc = clknode_get_softc(clk);
 
-	if (index < 0 || index >= sc->parent_cnt)
+	if (index < 0 || index >= clknode_get_parents_num(clk))
 		return (ERANGE);
 
 	DEVICE_LOCK(sc);
@@ -160,6 +159,8 @@ aw_modclk_set_freq(struct clknode *clk, 
     int flags, int *stop)
 {
 	struct aw_modclk_sc *sc;
+	struct clknode *parent_clk, *best_parent;
+	const char **parent_names;
 	uint32_t val, m, n, src, best_m, best_n, best_src;
 	uint64_t cur_freq;
 	int64_t best_diff, cur_diff;
@@ -170,11 +171,12 @@ aw_modclk_set_freq(struct clknode *clk, 
 	best_diff = (int64_t)*fout; 
 	best_src = 0;
 
-	for (src = 0; src < sc->parent_cnt; src++) {
-		error = clknode_set_parent_by_idx(clk, src);
-		if (error != 0)
+	parent_names = clknode_get_parent_names(clk);
+	for (src = 0; src < clknode_get_parents_num(clk); src++) {
+		parent_clk = clknode_find_by_name(parent_names[src]);
+		if (parent_clk == NULL)
 			continue;
-		error = clknode_get_freq(clknode_get_parent(clk), &fin);
+		error = clknode_get_freq(parent_clk, &fin);
 		if (error != 0)
 			continue;
 
@@ -184,6 +186,7 @@ aw_modclk_set_freq(struct clknode *clk, 
 				cur_diff = (int64_t)*fout - cur_freq;
 				if (cur_diff >= 0 && cur_diff < best_diff) {
 					best_src = src;
+					best_parent = parent_clk;
 					best_diff = cur_diff;
 					best_m = m;
 					best_n = n;
@@ -194,10 +197,17 @@ aw_modclk_set_freq(struct clknode *clk, 
 	if (best_diff == (int64_t)*fout)
 		return (ERANGE);
 
-	error = clknode_set_parent_by_idx(clk, best_src);
+	error = clknode_get_freq(best_parent, &fin);
 	if (error != 0)
 		return (error);
-	error = clknode_get_freq(clknode_get_parent(clk), &fin);
+
+	*fout = fin / (1 << best_n) / (best_m + 1);
+	*stop = 1;
+
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
+	error = clknode_set_parent_by_idx(clk, best_src);
 	if (error != 0)
 		return (error);
 
@@ -209,9 +219,6 @@ aw_modclk_set_freq(struct clknode *clk, 
 	MODCLK_WRITE(sc, val);
 	DEVICE_UNLOCK(sc);
 
-	*fout = fin / (1 << best_n) / (best_m + 1);
-	*stop = 1;
-
 	return (0);
 }
 
@@ -299,7 +306,6 @@ aw_modclk_attach(device_t dev)
 	sc = clknode_get_softc(clk);
 	sc->reg = paddr;
 	sc->clkdev = device_get_parent(dev);
-	sc->parent_cnt = def.parent_cnt;
 
 	clknode_register(clkdom, clk);
 

Modified: head/sys/arm/allwinner/clk/aw_pll.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_pll.c	Fri Dec 16 21:10:37 2016	(r310177)
+++ head/sys/arm/allwinner/clk/aw_pll.c	Fri Dec 16 21:58:48 2016	(r310178)
@@ -342,6 +342,9 @@ a10_pll1_set_freq(struct aw_pll_sc *sc, 
 	if (f == NULL)
 		return (EINVAL);
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	PLL_READ(sc, &val);
 	val &= ~(A10_PLL1_FACTOR_N|A10_PLL1_FACTOR_K|A10_PLL1_FACTOR_M|
@@ -440,6 +443,9 @@ a10_pll2_set_freq(struct aw_pll_sc *sc, 
 	post_div = 4;
 	n = (*fout * pre_div * post_div * 2) / (2 * fin);
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	PLL_READ(sc, &val);
 	val &= ~(A10_PLL2_POST_DIV | A10_PLL2_FACTOR_N | A10_PLL2_PRE_DIV);
@@ -497,6 +503,9 @@ a10_pll3_set_freq(struct aw_pll_sc *sc, 
 		*fout = m * A10_PLL3_REF_FREQ;
 	}
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	PLL_READ(sc, &val);
 	val &= ~(A10_PLL3_MODE_SEL | A10_PLL3_FUNC_SET | A10_PLL3_FACTOR_M);
@@ -699,6 +708,9 @@ a13_pll2_set_freq(struct aw_pll_sc *sc, 
 	post_div = 4;
 	n = (*fout * pre_div * post_div * 2) / (2 * fin);
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	PLL_READ(sc, &val);
 	val &= ~(A13_PLL2_POST_DIV | A13_PLL2_FACTOR_N | A13_PLL2_PRE_DIV);
@@ -765,6 +777,9 @@ h3_pll2_set_freq(struct aw_pll_sc *sc, u
 	if (f == NULL)
 		return (EINVAL);
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	PLL_READ(sc, &val);
 	val &= ~(H3_PLL2_POST_DIV|H3_PLL2_FACTOR_N|H3_PLL2_PRE_DIV);
@@ -808,6 +823,9 @@ a23_pll1_set_freq(struct aw_pll_sc *sc, 
 	if (f == NULL)
 		return (EINVAL);
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	PLL_READ(sc, &val);
 	val &= ~(A23_PLL1_FACTOR_N|A23_PLL1_FACTOR_K|A23_PLL1_FACTOR_M|
@@ -860,6 +878,9 @@ h3_pll1_set_freq(struct aw_pll_sc *sc, u
 	if (f == NULL)
 		return (EINVAL);
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	PLL_READ(sc, &val);
 
@@ -1067,6 +1088,9 @@ a83t_pllcpux_set_freq(struct aw_pll_sc *
 	if (n < A83T_PLLCPUX_FACTOR_N_MIN || n > A83T_PLLCPUX_FACTOR_N_MAX)
 		return (EINVAL);
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	PLL_READ(sc, &val);
 	val &= ~A83T_PLLCPUX_FACTOR_N;

Modified: head/sys/arm/allwinner/clk/aw_thsclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_thsclk.c	Fri Dec 16 21:10:37 2016	(r310177)
+++ head/sys/arm/allwinner/clk/aw_thsclk.c	Fri Dec 16 21:58:48 2016	(r310178)
@@ -186,6 +186,9 @@ aw_thsclk_set_freq(struct clknode *clk, 
 	if (best_diff == (int64_t)*fout || best_n == 0)
 		return (ERANGE);
 
+	if ((flags & CLK_SET_DRYRUN) != 0)
+		return (0);
+
 	DEVICE_LOCK(sc);
 	THSCLK_READ(sc, &val);
 	val &= ~CLK_DIV_RATIO;


More information about the svn-src-all mailing list