Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Dec 2016 20:52:48 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r309767 - stable/11/sys/arm/allwinner/clk
Message-ID:  <201612092052.uB9KqmKq061461@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Fri Dec  9 20:52:48 2016
New Revision: 309767
URL: https://svnweb.freebsd.org/changeset/base/309767

Log:
  MFC r304796, r308233 (jmcneill)
  
  r304796:
  Switch parent clock when setting frequency if a new parent is a better
  candidate for the target rate.
  
  Reviewed by:	andrew, manu
  
  r308233:
  The DTS may report fewer than 4 parents for a module clock. Avoid setting
  the module clock parent to an out-of-range index in these cases.

Modified:
  stable/11/sys/arm/allwinner/clk/aw_modclk.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/arm/allwinner/clk/aw_modclk.c
==============================================================================
--- stable/11/sys/arm/allwinner/clk/aw_modclk.c	Fri Dec  9 20:50:35 2016	(r309766)
+++ stable/11/sys/arm/allwinner/clk/aw_modclk.c	Fri Dec  9 20:52:48 2016	(r309767)
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
 #define	SCLK_GATING		(1 << 31)
 #define	CLK_SRC_SEL		(0x3 << 24)
 #define	CLK_SRC_SEL_SHIFT	24
-#define	CLK_SRC_SEL_MAX		0x3
 #define	CLK_RATIO_N		(0x3 << 16)
 #define	CLK_RATIO_N_SHIFT	16
 #define	CLK_RATIO_N_MAX		0x3
@@ -69,6 +68,7 @@ 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 +102,7 @@ aw_modclk_set_mux(struct clknode *clk, i
 
 	sc = clknode_get_softc(clk);
 
-	if (index < 0 || index > CLK_SRC_SEL_MAX)
+	if (index < 0 || index >= sc->parent_cnt)
 		return (ERANGE);
 
 	DEVICE_LOCK(sc);
@@ -160,28 +160,47 @@ aw_modclk_set_freq(struct clknode *clk, 
     int flags, int *stop)
 {
 	struct aw_modclk_sc *sc;
-	uint32_t val, m, n, best_m, best_n;
+	uint32_t val, m, n, src, best_m, best_n, best_src;
 	uint64_t cur_freq;
 	int64_t best_diff, cur_diff;
+	int error;
 
 	sc = clknode_get_softc(clk);
 	best_n = best_m = 0;
 	best_diff = (int64_t)*fout; 
+	best_src = 0;
 
-	for (n = 0; n <= CLK_RATIO_N_MAX; n++)
-		for (m = 0; m <= CLK_RATIO_M_MAX; m++) {
-			cur_freq = fin / (1 << n) / (m + 1);
-			cur_diff = (int64_t)*fout - cur_freq;
-			if (cur_diff >= 0 && cur_diff < best_diff) {
-				best_diff = cur_diff;
-				best_m = m;
-				best_n = n;
+	for (src = 0; src < sc->parent_cnt; src++) {
+		error = clknode_set_parent_by_idx(clk, src);
+		if (error != 0)
+			continue;
+		error = clknode_get_freq(clknode_get_parent(clk), &fin);
+		if (error != 0)
+			continue;
+
+		for (n = 0; n <= CLK_RATIO_N_MAX; n++)
+			for (m = 0; m <= CLK_RATIO_M_MAX; m++) {
+				cur_freq = fin / (1 << n) / (m + 1);
+				cur_diff = (int64_t)*fout - cur_freq;
+				if (cur_diff >= 0 && cur_diff < best_diff) {
+					best_src = src;
+					best_diff = cur_diff;
+					best_m = m;
+					best_n = n;
+				}
 			}
-		}
+	}
 
 	if (best_diff == (int64_t)*fout)
 		return (ERANGE);
 
+	error = clknode_set_parent_by_idx(clk, best_src);
+	if (error != 0)
+		return (error);
+	error = clknode_get_freq(clknode_get_parent(clk), &fin);
+	if (error != 0)
+		return (error);
+
 	DEVICE_LOCK(sc);
 	MODCLK_READ(sc, &val);
 	val &= ~(CLK_RATIO_N | CLK_RATIO_M);
@@ -280,6 +299,7 @@ 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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612092052.uB9KqmKq061461>