#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rk_cru_mux.c,v 1.2 2018/06/30 17:54:07 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
#include <dev/clk/clk_backend.h>
#include <arm/rockchip/rk_cru.h>
const char *
rk_cru_mux_get_parent(struct rk_cru_softc *sc,
struct rk_cru_clk *clk)
{
struct rk_cru_mux *mux = &clk->u.mux;
const bool mux_grf = (mux->flags & RK_MUX_GRF) != 0;
uint32_t val;
KASSERT(clk->type == RK_CRU_MUX);
if (mux_grf) {
if (!HAS_GRF(sc))
return NULL;
syscon_lock(sc->sc_grf);
val = syscon_read_4(sc->sc_grf, mux->reg);
syscon_unlock(sc->sc_grf);
} else {
val = CRU_READ(sc, mux->reg);
}
const u_int index = __SHIFTOUT(val, mux->mask);
return mux->parents[index];
}
int
rk_cru_mux_set_parent(struct rk_cru_softc *sc,
struct rk_cru_clk *clk, const char *parent)
{
struct rk_cru_mux *mux = &clk->u.mux;
const bool mux_grf = (mux->flags & RK_MUX_GRF) != 0;
KASSERT(clk->type == RK_CRU_MUX);
if (mux_grf && !HAS_GRF(sc))
return ENXIO;
for (u_int index = 0; index < mux->nparents; index++) {
if (strcmp(mux->parents[index], parent) == 0) {
const uint32_t write_mask = mux->mask << 16;
const uint32_t write_val = __SHIFTIN(index, mux->mask);
if (mux_grf) {
syscon_lock(sc->sc_grf);
syscon_write_4(sc->sc_grf, mux->reg, write_mask | write_val);
syscon_unlock(sc->sc_grf);
} else
CRU_WRITE(sc, mux->reg, write_mask | write_val);
return 0;
}
}
return EINVAL;
}