Date: Fri, 8 Nov 2019 19:15:50 +0000 (UTC) From: Michal Meloun <mmel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r354557 - head/sys/arm64/rockchip/clk Message-ID: <201911081915.xA8JFokc004173@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mmel Date: Fri Nov 8 19:15:50 2019 New Revision: 354557 URL: https://svnweb.freebsd.org/changeset/base/354557 Log: Tidy up Rockchip composite clock. - add support for log2 based dividers - use proper write mask when writing to divider register MFC after: 3 weeks Reviewed by: manu Differential Revision: https://reviews.freebsd.org/D22283 Modified: head/sys/arm64/rockchip/clk/rk_clk_composite.c head/sys/arm64/rockchip/clk/rk_clk_composite.h Modified: head/sys/arm64/rockchip/clk/rk_clk_composite.c ============================================================================== --- head/sys/arm64/rockchip/clk/rk_clk_composite.c Fri Nov 8 19:13:11 2019 (r354556) +++ head/sys/arm64/rockchip/clk/rk_clk_composite.c Fri Nov 8 19:15:50 2019 (r354557) @@ -158,31 +158,44 @@ rk_clk_composite_recalc(struct clknode *clk, uint64_t DEVICE_UNLOCK(clk); - div = ((reg & sc->div_mask) >> sc->div_shift) + 1; - dprintf("parent_freq=%lu, div=%u\n", *freq, div); + div = ((reg & sc->div_mask) >> sc->div_shift); + if (sc->flags & RK_CLK_COMPOSITE_DIV_EXP) + div = 1 << div; + else + div += 1; + dprintf("parent_freq=%ju, div=%u\n", *freq, div); *freq = *freq / div; - dprintf("Final freq=%ju\n", *freq); return (0); } static uint32_t rk_clk_composite_find_best(struct rk_clk_composite_sc *sc, uint64_t fparent, - uint64_t freq) + uint64_t freq, uint32_t *reg) { uint64_t best, cur; - uint32_t best_div, div; + uint32_t best_div, best_div_reg; + uint32_t div, div_reg; - for (best = 0, best_div = 0, div = 0; - div <= ((sc->div_mask >> sc->div_shift) + 1); div++) { + best = 0; + best_div = 0; + best_div_reg = 0; + + for (div_reg = 0; div_reg <= ((sc->div_mask >> sc->div_shift) + 1); + div_reg++) { + if (sc->flags == RK_CLK_COMPOSITE_DIV_EXP) + div = 1 << div_reg; + else + div = div_reg + 1; cur = fparent / div; if ((freq - cur) < (freq - best)) { best = cur; best_div = div; + best_div_reg = div_reg; break; } } - + *reg = div_reg; return (best_div); } @@ -194,11 +207,10 @@ rk_clk_composite_set_freq(struct clknode *clk, uint64_ struct clknode *p_clk; const char **p_names; uint64_t best, cur; - uint32_t div, best_div, val = 0; + uint32_t div, div_reg, best_div, best_div_reg, val; int p_idx, best_parent; sc = clknode_get_softc(clk); - dprintf("Finding best parent/div for target freq of %ju\n", *fout); p_names = clknode_get_parent_names(clk); for (best_div = 0, best = 0, p_idx = 0; @@ -207,34 +219,31 @@ rk_clk_composite_set_freq(struct clknode *clk, uint64_ clknode_get_freq(p_clk, &fparent); dprintf("Testing with parent %s (%d) at freq %ju\n", clknode_get_name(p_clk), p_idx, fparent); - div = rk_clk_composite_find_best(sc, fparent, *fout); + div = rk_clk_composite_find_best(sc, fparent, *fout, &div_reg); cur = fparent / div; if ((*fout - cur) < (*fout - best)) { best = cur; best_div = div; + best_div_reg = div_reg; best_parent = p_idx; dprintf("Best parent so far %s (%d) with best freq at " "%ju\n", clknode_get_name(p_clk), p_idx, best); } } + *stop = 1; if (best_div == 0) - return (0); + return (ERANGE); - if ((best < *fout) && - ((flags & CLK_SET_ROUND_DOWN) == 0)) { - *stop = 1; + if ((best < *fout) && ((flags & CLK_SET_ROUND_DOWN) == 0)) return (ERANGE); - } - if ((best > *fout) && - ((flags & CLK_SET_ROUND_UP) == 0)) { - *stop = 1; + + if ((best > *fout) && ((flags & CLK_SET_ROUND_UP) == 0)) { return (ERANGE); } if ((flags & CLK_SET_DRYRUN) != 0) { *fout = best; - *stop = 1; return (0); } @@ -245,17 +254,18 @@ rk_clk_composite_set_freq(struct clknode *clk, uint64_ clknode_set_parent_by_idx(clk, best_parent); } - dprintf("Setting divider to %d\n", best_div); + dprintf("Setting divider to %d (reg: %d)\n", best_div, best_div_reg); + dprintf(" div_mask: 0x%X, div_shift: %d\n", sc->div_mask, + sc->div_shift); + DEVICE_LOCK(clk); - val |= (best_div - 1) << sc->div_shift; - val |= (sc->div_mask << sc->div_shift) << RK_CLK_COMPOSITE_MASK_SHIFT; + val = best_div_reg << sc->div_shift; + val |= sc->div_mask << RK_CLK_COMPOSITE_MASK_SHIFT; dprintf("Write: muxdiv_offset=%x, val=%x\n", sc->muxdiv_offset, val); WRITE4(clk, sc->muxdiv_offset, val); DEVICE_UNLOCK(clk); *fout = best; - *stop = 1; - return (0); } Modified: head/sys/arm64/rockchip/clk/rk_clk_composite.h ============================================================================== --- head/sys/arm64/rockchip/clk/rk_clk_composite.h Fri Nov 8 19:13:11 2019 (r354556) +++ head/sys/arm64/rockchip/clk/rk_clk_composite.h Fri Nov 8 19:15:50 2019 (r354557) @@ -52,7 +52,8 @@ struct rk_clk_composite_def { #define RK_CLK_COMPOSITE_HAVE_MUX 0x0001 #define RK_CLK_COMPOSITE_HAVE_GATE 0x0002 - +#define RK_CLK_COMPOSITE_DIV_EXP 0x0004 /* Register 0, 1, 2, 2, ... */ + /* Divider 1, 2, 4, 8, ... */ int rk_clk_composite_register(struct clkdom *clkdom, struct rk_clk_composite_def *clkdef);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911081915.xA8JFokc004173>