allwinner: nkmp: Add MUX capability

Some NKMP clocks have a mux options.
Add the capability to aw_clk_nkmp.
This commit is contained in:
manu 2017-02-28 15:11:33 +00:00
parent 755fb5b45d
commit bf7132992c
3 changed files with 86 additions and 1 deletions

View File

@ -219,6 +219,48 @@ aw_clk_factor_get_value(struct aw_clk_factor *factor, uint32_t raw)
.flags = _flags, \ .flags = _flags, \
} }
#define NKMP_CLK_WITH_MUX(_clkname, \
_id, _name, _pnames, \
_offset, \
_n_shift, _n_width, _n_value, _n_flags, \
_k_shift, _k_width, _k_value, _k_flags, \
_m_shift, _m_width, _m_value, _m_flags, \
_p_shift, _p_width, _p_value, _p_flags, \
_mux_shift, _mux_width, _gate, \
_lock, _lock_retries, \
_flags) \
static struct aw_clk_nkmp_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
}, \
.offset = _offset, \
.n.shift = _n_shift, \
.n.width = _n_width, \
.n.value = _n_value, \
.n.flags = _n_flags, \
.k.shift = _k_shift, \
.k.width = _k_width, \
.k.value = _k_value, \
.k.flags = _k_flags, \
.m.shift = _m_shift, \
.m.width = _m_width, \
.m.value = _m_value, \
.m.flags = _m_flags, \
.p.shift = _p_shift, \
.p.width = _p_width, \
.p.value = _p_value, \
.p.flags = _p_flags, \
.mux_shift = _mux_shift, \
.mux_width = _mux_width, \
.gate_shift = _gate, \
.lock_shift = _lock, \
.lock_retries = _lock_retries, \
.flags = _flags, \
}
#define NKMP_CLK_WITH_UPDATE(_clkname, \ #define NKMP_CLK_WITH_UPDATE(_clkname, \
_id, _name, _pnames, \ _id, _name, _pnames, \
_offset, \ _offset, \

View File

@ -55,6 +55,8 @@ struct aw_clk_nkmp_sc {
struct aw_clk_factor m; struct aw_clk_factor m;
struct aw_clk_factor p; struct aw_clk_factor p;
uint32_t mux_shift;
uint32_t mux_mask;
uint32_t gate_shift; uint32_t gate_shift;
uint32_t lock_shift; uint32_t lock_shift;
uint32_t lock_retries; uint32_t lock_retries;
@ -77,7 +79,21 @@ struct aw_clk_nkmp_sc {
static int static int
aw_clk_nkmp_init(struct clknode *clk, device_t dev) aw_clk_nkmp_init(struct clknode *clk, device_t dev)
{ {
clknode_init_parent_idx(clk, 0); struct aw_clk_nkmp_sc *sc;
uint32_t val, idx;
sc = clknode_get_softc(clk);
idx = 0;
if ((sc->flags & AW_CLK_HAS_MUX) != 0) {
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
DEVICE_UNLOCK(clk);
idx = (val & sc->mux_mask) >> sc->mux_shift;
}
clknode_init_parent_idx(clk, idx);
return (0); return (0);
} }
@ -104,6 +120,27 @@ aw_clk_nkmp_set_gate(struct clknode *clk, bool enable)
return (0); return (0);
} }
static int
aw_clk_nkmp_set_mux(struct clknode *clk, int index)
{
struct aw_clk_nkmp_sc *sc;
uint32_t val;
sc = clknode_get_softc(clk);
if ((sc->flags & AW_CLK_HAS_MUX) != 0)
return (0);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
val &= ~(sc->mux_mask >> sc->mux_shift);
val |= index << sc->mux_shift;
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);
return (0);
}
static uint64_t static uint64_t
aw_clk_nkmp_find_best(struct aw_clk_nkmp_sc *sc, uint64_t fparent, uint64_t *fout, aw_clk_nkmp_find_best(struct aw_clk_nkmp_sc *sc, uint64_t fparent, uint64_t *fout,
uint32_t *factor_n, uint32_t *factor_k, uint32_t *factor_m, uint32_t *factor_p) uint32_t *factor_n, uint32_t *factor_k, uint32_t *factor_m, uint32_t *factor_p)
@ -314,6 +351,7 @@ static clknode_method_t aw_nkmp_clknode_methods[] = {
/* Device interface */ /* Device interface */
CLKNODEMETHOD(clknode_init, aw_clk_nkmp_init), CLKNODEMETHOD(clknode_init, aw_clk_nkmp_init),
CLKNODEMETHOD(clknode_set_gate, aw_clk_nkmp_set_gate), CLKNODEMETHOD(clknode_set_gate, aw_clk_nkmp_set_gate),
CLKNODEMETHOD(clknode_set_mux, aw_clk_nkmp_set_mux),
CLKNODEMETHOD(clknode_recalc_freq, aw_clk_nkmp_recalc), CLKNODEMETHOD(clknode_recalc_freq, aw_clk_nkmp_recalc),
CLKNODEMETHOD(clknode_set_freq, aw_clk_nkmp_set_freq), CLKNODEMETHOD(clknode_set_freq, aw_clk_nkmp_set_freq),
CLKNODEMETHOD_END CLKNODEMETHOD_END
@ -360,6 +398,9 @@ aw_clk_nkmp_register(struct clkdom *clkdom, struct aw_clk_nkmp_def *clkdef)
sc->p.value = clkdef->p.value; sc->p.value = clkdef->p.value;
sc->p.flags = clkdef->p.flags; sc->p.flags = clkdef->p.flags;
sc->mux_shift = clkdef->mux_shift;
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;
sc->gate_shift = clkdef->gate_shift; sc->gate_shift = clkdef->gate_shift;
sc->lock_shift = clkdef->lock_shift; sc->lock_shift = clkdef->lock_shift;
sc->lock_retries = clkdef->lock_retries; sc->lock_retries = clkdef->lock_retries;

View File

@ -41,6 +41,8 @@ struct aw_clk_nkmp_def {
struct aw_clk_factor n; struct aw_clk_factor n;
struct aw_clk_factor p; struct aw_clk_factor p;
uint32_t mux_shift;
uint32_t mux_width;
uint32_t gate_shift; uint32_t gate_shift;
uint32_t lock_shift; uint32_t lock_shift;
uint32_t lock_retries; uint32_t lock_retries;