Index: sys/dev/extres/clk/clk.h =================================================================== --- sys/dev/extres/clk/clk.h +++ sys/dev/extres/clk/clk.h @@ -100,6 +100,8 @@ #endif void clknode_init_parent_idx(struct clknode *clknode, int idx); +void clknode_init_freq_value(struct clknode *clknode, uint64_t freq); +void clknode_init_gate_value(struct clknode *clknode, bool gate_val); int clknode_set_parent_by_idx(struct clknode *clk, int idx); int clknode_set_parent_by_name(struct clknode *clk, const char *name); const char *clknode_get_name(struct clknode *clk); @@ -115,6 +117,8 @@ int clknode_get_freq(struct clknode *clknode, uint64_t *freq); int clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags, int enablecnt); +int clknode_set_freq2(struct clknode *clknode, uint64_t *freq, int flags, + int enablecnt); int clknode_enable(struct clknode *clknode); int clknode_disable(struct clknode *clknode); int clknode_stop(struct clknode *clknode, int depth); Index: sys/dev/extres/clk/clk.c =================================================================== --- sys/dev/extres/clk/clk.c +++ sys/dev/extres/clk/clk.c @@ -119,6 +119,8 @@ struct sx lock; /* Lock for this clock */ int ref_cnt; /* Reference counter */ int enable_cnt; /* Enabled counter */ + int enabled; /* Whether it's enabled; + * -1 if unknown */ /* Cached values. */ uint64_t freq; /* Actual frequency */ @@ -622,6 +624,7 @@ clknode->parent_cnt = def->parent_cnt; clknode->parent = NULL; clknode->parent_idx = CLKNODE_IDX_NONE; + clknode->enabled = -1; /* don't know yet */ if (replaced) return (clknode); @@ -661,6 +664,10 @@ SYSCTL_CHILDREN(clknode_oid), OID_AUTO, "enable_cnt", CTLFLAG_RD, &clknode->enable_cnt, 0, "The clock enable counter"); + SYSCTL_ADD_INT(&clknode->sysctl_ctx, + SYSCTL_CHILDREN(clknode_oid), + OID_AUTO, "enabled", + CTLFLAG_RD, &clknode->enabled, 0, "whether the clock is enabled"); return (clknode); } @@ -756,6 +763,26 @@ clknode->parent_idx = idx; } +/* + * Set initial frequency value - init function. + */ +void +clknode_init_freq_value(struct clknode *clknode, uint64_t freq) +{ + + clknode->freq = freq; +} + +/* + * Set initial gate status - init function. + */ +void +clknode_init_gate_value(struct clknode *clknode, bool gate_val) +{ + + clknode->enabled = (int) gate_val; +} + int clknode_set_parent_by_idx(struct clknode *clknode, int idx) { @@ -946,6 +973,14 @@ clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags, int enablecnt) { + + return (clknode_set_freq2(clknode, &freq, flags, enablecnt)); +} + +int +clknode_set_freq2(struct clknode *clknode, uint64_t *freq, int flags, + int enablecnt) +{ int rv, done; uint64_t parent_freq; @@ -953,7 +988,7 @@ CLK_TOPO_XASSERT(); /* Check for no change */ - if (clknode->freq == freq) + if (clknode->freq == *freq) return (0); parent_freq = 0; @@ -980,7 +1015,7 @@ } /* Set frequency for this clock. */ - rv = CLKNODE_SET_FREQ(clknode, parent_freq, &freq, flags, &done); + rv = CLKNODE_SET_FREQ(clknode, parent_freq, freq, flags, &done); if (rv != 0) { printf("Cannot set frequency for clk: %s, error: %d\n", clknode->name, rv); @@ -992,7 +1027,7 @@ if (done) { /* Success - invalidate frequency cache for all children. */ if ((flags & CLK_SET_DRYRUN) == 0) { - clknode->freq = freq; + clknode->freq = *freq; /* Clock might have reparent during set_freq */ if (clknode->parent_cnt > 0) { rv = clknode_get_freq(clknode->parent, @@ -1005,7 +1040,7 @@ } } else if (clknode->parent != NULL) { /* Nothing changed, pass request to parent. */ - rv = clknode_set_freq(clknode->parent, freq, flags, enablecnt); + rv = clknode_set_freq2(clknode->parent, freq, flags, enablecnt); } else { /* End of chain without action. */ printf("Cannot set frequency for clk: %s, end of chain\n", @@ -1041,6 +1076,7 @@ } } clknode->enable_cnt++; + clknode->enabled = 1; CLKNODE_UNLOCK(clknode); return (0); } @@ -1062,6 +1098,7 @@ CLKNODE_UNLOCK(clknode); return (rv); } + clknode->enabled = 0; } clknode->enable_cnt--; CLKNODE_UNLOCK(clknode);