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