Port-arm archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Add sunxi nkmp sdm support



Hi,
this feature is typically used by audio clocks.
In addition, the lock waiting is moved to nkmp_set_rate() for supporting
dynamic frequency adjustment.

-rxg
Index: sunxi_ccu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/sunxi/sunxi_ccu.h,v
retrieving revision 1.24
diff -u -p -r1.24 sunxi_ccu.h
--- sunxi_ccu.h	16 Sep 2024 23:37:13 -0000	1.24
+++ sunxi_ccu.h	26 Sep 2026 01:44:55 -0000
@@ -96,6 +96,11 @@ struct sunxi_ccu_nkmp_tbl {
 	uint32_t	k;
 	uint32_t	m;
 	uint32_t	p;
+	uint32_t	pat0;
+};
+
+struct sunxi_ccu_nkmp_pat0 {
+	bus_size_t	reg;
 };
 
 struct sunxi_ccu_nkmp {
@@ -106,8 +111,10 @@ struct sunxi_ccu_nkmp {
 	uint32_t	m;
 	uint32_t	p;
 	uint32_t	lock;
+	uint32_t	sdm_en;
 	uint32_t	enable;
 	uint32_t	flags;
+	const struct sunxi_ccu_nkmp_pat0 *pat0;
 	const struct sunxi_ccu_nkmp_tbl *table;
 #define	SUNXI_CCU_NKMP_DIVIDE_BY_TWO		__BIT(0)
 #define	SUNXI_CCU_NKMP_FACTOR_N_EXACT		__BIT(1)
@@ -126,8 +133,8 @@ int	sunxi_ccu_nkmp_set_rate(struct sunxi
 const char *sunxi_ccu_nkmp_get_parent(struct sunxi_ccu_softc *,
 				      struct sunxi_ccu_clk *);
 
-#define	SUNXI_CCU_NKMP_TABLE(_id, _name, _parent, _reg, _n, _k, _m, \
-		       _p, _enable, _lock, _tbl, _flags)	\
+#define	SUNXI_CCU_NKMP_SDM(_id, _name, _parent, _reg, _n, _k, _m, \
+			   _p, _enable, _lock, _sdm_en, _pat0, _tbl, _flags) \
 	[_id] = {						\
 		.type = SUNXI_CCU_NKMP,				\
 		.base.name = (_name),				\
@@ -140,6 +147,8 @@ const char *sunxi_ccu_nkmp_get_parent(st
 		.u.nkmp.enable = (_enable),			\
 		.u.nkmp.flags = (_flags),			\
 		.u.nkmp.lock = (_lock),				\
+		.u.nkmp.sdm_en = (_sdm_en),			\
+		.u.nkmp.pat0 = (_pat0),				\
 		.u.nkmp.table = (_tbl),				\
 		.enable = sunxi_ccu_nkmp_enable,		\
 		.get_rate = sunxi_ccu_nkmp_get_rate,		\
@@ -147,6 +156,10 @@ const char *sunxi_ccu_nkmp_get_parent(st
 		.get_parent = sunxi_ccu_nkmp_get_parent,	\
 	}
 
+#define	SUNXI_CCU_NKMP_TABLE(_id, _name, _parent, _reg, _n, _k, _m, \
+			     _p, _enable, _lock, _tbl, _flags)	\
+	SUNXI_CCU_NKMP_SDM(_id, _name, _parent, _reg, _n, _k, _m, \
+			   _p, _enable, _lock, 0, NULL, _tbl, _flags)
 #define	SUNXI_CCU_NKMP(_id, _name, _parent, _reg, _n, _k, _m,	\
 		       _p, _enable, _flags)			\
 	SUNXI_CCU_NKMP_TABLE(_id, _name, _parent, _reg, _n, _k, _m, \
Index: sunxi_ccu_nkmp.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/sunxi/sunxi_ccu_nkmp.c,v
retrieving revision 1.8
diff -u -p -r1.8 sunxi_ccu_nkmp.c
--- sunxi_ccu_nkmp.c	2 Jan 2019 19:33:06 -0000	1.8
+++ sunxi_ccu_nkmp.c	26 Sep 2026 01:44:55 -0000
@@ -42,7 +42,6 @@ sunxi_ccu_nkmp_enable(struct sunxi_ccu_s
 {
 	struct sunxi_ccu_nkmp *nkmp = &clk->u.nkmp;
 	uint32_t val;
-	int retry;
 
 	KASSERT(clk->type == SUNXI_CCU_NKMP);
 
@@ -56,17 +55,6 @@ sunxi_ccu_nkmp_enable(struct sunxi_ccu_s
 		val &= ~nkmp->enable;
 	CCU_WRITE(sc, nkmp->reg, val);
 
-	if (enable && nkmp->lock) {
-		for (retry = 1000; retry > 0; retry--) {
-			val = CCU_READ(sc, nkmp->reg);
-			if (val & nkmp->lock)
-				break;
-			delay(100);
-		}
-		if (retry == 0)
-			return ETIMEDOUT;
-	}
-
 	return 0;
 }
 
@@ -75,6 +63,7 @@ sunxi_ccu_nkmp_get_rate(struct sunxi_ccu
     struct sunxi_ccu_clk *clk)
 {
 	struct sunxi_ccu_nkmp *nkmp = &clk->u.nkmp;
+	const struct sunxi_ccu_nkmp_tbl *tab;
 	struct clk *clkp, *clkp_parent;
 	u_int rate, n, k, m, p;
 	uint32_t val;
@@ -111,6 +100,19 @@ sunxi_ccu_nkmp_get_rate(struct sunxi_ccu
 	if (nkmp->enable && !(val & nkmp->enable))
 		return 0;
 
+	if (nkmp->sdm_en && nkmp->pat0 != NULL) {
+		uint32_t pat0 = CCU_READ(sc, nkmp->pat0->reg);
+		for (tab = nkmp->table; tab->rate > 0; tab++)
+			if (tab->pat0 == pat0)
+				break;
+		if (tab->rate == 0)
+			return EINVAL;
+		if (tab->n == n && tab->k == k && tab->m == m && tab->p == p)
+			return tab->rate;
+		else
+			return EINVAL;
+	}
+
 	if ((nkmp->flags & SUNXI_CCU_NKMP_FACTOR_N_EXACT) == 0)
 		n++;
 
@@ -140,6 +142,7 @@ sunxi_ccu_nkmp_set_rate(struct sunxi_ccu
 	struct sunxi_ccu_nkmp *nkmp = &clk->u.nkmp;
 	const struct sunxi_ccu_nkmp_tbl *tab;
 	uint32_t val;
+	int retry;
 
 	KASSERT(clk->type == SUNXI_CCU_NKMP);
 
@@ -154,6 +157,9 @@ sunxi_ccu_nkmp_set_rate(struct sunxi_ccu
 
 	val = CCU_READ(sc, nkmp->reg);
 
+	if (nkmp->sdm_en)
+		val |= nkmp->sdm_en;
+
 	if (nkmp->flags & SUNXI_CCU_NKMP_SCALE_CLOCK) {
 		if (nkmp->p && __SHIFTOUT(val, nkmp->p) < tab->p) {
 			val &= ~nkmp->p;
@@ -209,6 +215,20 @@ sunxi_ccu_nkmp_set_rate(struct sunxi_ccu
 		CCU_WRITE(sc, nkmp->reg, val);
 	}
 
+	if (nkmp->pat0 != NULL)
+		CCU_WRITE(sc, nkmp->pat0->reg, tab->pat0);
+
+	if (nkmp->lock) {
+		for (retry = 1000; retry > 0; retry--) {
+			val = CCU_READ(sc, nkmp->reg);
+			if (val & nkmp->lock)
+				break;
+			delay(100);
+		}
+		if (retry == 0)
+			return ETIMEDOUT;
+	}
+
 	return 0;
 }
 


Home | Main Index | Thread Index | Old Index