From owner-svn-src-head@freebsd.org Mon May 7 07:28:11 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5A627FA9097; Mon, 7 May 2018 07:28:11 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 106677BDF1; Mon, 7 May 2018 07:28:11 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 0B72718302; Mon, 7 May 2018 07:28:11 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w477SAc3071729; Mon, 7 May 2018 07:28:10 GMT (envelope-from manu@FreeBSD.org) Received: (from manu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w477SAmV071727; Mon, 7 May 2018 07:28:10 GMT (envelope-from manu@FreeBSD.org) Message-Id: <201805070728.w477SAmV071727@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: manu set sender to manu@FreeBSD.org using -f From: Emmanuel Vadot Date: Mon, 7 May 2018 07:28:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r333315 - head/sys/arm64/rockchip/clk X-SVN-Group: head X-SVN-Commit-Author: manu X-SVN-Commit-Paths: head/sys/arm64/rockchip/clk X-SVN-Commit-Revision: 333315 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 May 2018 07:28:11 -0000 Author: manu Date: Mon May 7 07:28:10 2018 New Revision: 333315 URL: https://svnweb.freebsd.org/changeset/base/333315 Log: arm64: rk: Add support for setting pll rate Add support for setting pll rate. On RockChip SoC two kind of plls are supported, integer mode and fractional mode. The two modes are intended to support more frequencies for the core plls. While here change the recalc method as it appears that the datasheet is wrong on the calculation method. Modified: head/sys/arm64/rockchip/clk/rk_clk_pll.c head/sys/arm64/rockchip/clk/rk_clk_pll.h Modified: head/sys/arm64/rockchip/clk/rk_clk_pll.c ============================================================================== --- head/sys/arm64/rockchip/clk/rk_clk_pll.c Mon May 7 07:26:48 2018 (r333314) +++ head/sys/arm64/rockchip/clk/rk_clk_pll.c Mon May 7 07:28:10 2018 (r333315) @@ -48,6 +48,9 @@ struct rk_clk_pll_sc { uint32_t gate_shift; uint32_t flags; + + struct rk_clk_pll_rate *rates; + struct rk_clk_pll_rate *frac_rates; }; #define WRITE4(_clk, off, val) \ @@ -59,14 +62,6 @@ struct rk_clk_pll_sc { #define DEVICE_UNLOCK(_clk) \ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk)) -#define RK_CLK_PLL_DSMPD_OFFSET 4 -#define RK_CLK_PLL_DSMPD_SHIFT 12 -#define RK_CLK_PLL_DSMPD_MASK 0x1000 - -#define RK_CLK_PLL_REFDIV_OFFSET 4 -#define RK_CLK_PLL_REFDIV_SHIFT 0 -#define RK_CLK_PLL_REFDIV_MASK 0x3F - #define RK_CLK_PLL_FBDIV_OFFSET 0 #define RK_CLK_PLL_FBDIV_SHIFT 0 #define RK_CLK_PLL_FBDIV_MASK 0xFFF @@ -75,6 +70,14 @@ struct rk_clk_pll_sc { #define RK_CLK_PLL_POSTDIV1_SHIFT 12 #define RK_CLK_PLL_POSTDIV1_MASK 0x7000 +#define RK_CLK_PLL_DSMPD_OFFSET 4 +#define RK_CLK_PLL_DSMPD_SHIFT 12 +#define RK_CLK_PLL_DSMPD_MASK 0x1000 + +#define RK_CLK_PLL_REFDIV_OFFSET 4 +#define RK_CLK_PLL_REFDIV_SHIFT 0 +#define RK_CLK_PLL_REFDIV_MASK 0x3F + #define RK_CLK_PLL_POSTDIV2_OFFSET 4 #define RK_CLK_PLL_POSTDIV2_SHIFT 6 #define RK_CLK_PLL_POSTDIV2_MASK 0x1C0 @@ -83,6 +86,10 @@ struct rk_clk_pll_sc { #define RK_CLK_PLL_FRAC_SHIFT 0 #define RK_CLK_PLL_FRAC_MASK 0xFFFFFF +#define RK_CLK_PLL_LOCK_MASK 0x400 + +#define RK_CLK_PLL_WRITE_MASK 0xFFFF0000 + static int rk_clk_pll_init(struct clknode *clk, device_t dev) { @@ -122,10 +129,10 @@ static int rk_clk_pll_recalc(struct clknode *clk, uint64_t *freq) { struct rk_clk_pll_sc *sc; - uint64_t foutvco; + uint64_t rate; uint32_t dsmpd, refdiv, fbdiv; uint32_t postdiv1, postdiv2, frac; - uint32_t raw1, raw2; + uint32_t raw1, raw2, raw3; sc = clknode_get_softc(clk); @@ -133,46 +140,107 @@ rk_clk_pll_recalc(struct clknode *clk, uint64_t *freq) READ4(clk, sc->base_offset, &raw1); READ4(clk, sc->base_offset + 4, &raw2); + READ4(clk, sc->base_offset + 8, &raw3); - READ4(clk, sc->base_offset + RK_CLK_PLL_DSMPD_OFFSET, &dsmpd); - dsmpd = (dsmpd & RK_CLK_PLL_DSMPD_MASK) >> RK_CLK_PLL_DSMPD_SHIFT; + fbdiv = (raw1 & RK_CLK_PLL_FBDIV_MASK) >> RK_CLK_PLL_FBDIV_SHIFT; + postdiv1 = (raw1 & RK_CLK_PLL_POSTDIV1_MASK) >> RK_CLK_PLL_POSTDIV1_SHIFT; - READ4(clk, sc->base_offset + RK_CLK_PLL_REFDIV_OFFSET, &refdiv); - refdiv = (refdiv & RK_CLK_PLL_REFDIV_MASK) >> RK_CLK_PLL_REFDIV_SHIFT; + dsmpd = (raw2 & RK_CLK_PLL_DSMPD_MASK) >> RK_CLK_PLL_DSMPD_SHIFT; + refdiv = (raw2 & RK_CLK_PLL_REFDIV_MASK) >> RK_CLK_PLL_REFDIV_SHIFT; + postdiv2 = (raw2 & RK_CLK_PLL_POSTDIV2_MASK) >> RK_CLK_PLL_POSTDIV2_SHIFT; - READ4(clk, sc->base_offset + RK_CLK_PLL_FBDIV_OFFSET, &fbdiv); - fbdiv = (fbdiv & RK_CLK_PLL_FBDIV_MASK) >> RK_CLK_PLL_FBDIV_SHIFT; + frac = (raw3 & RK_CLK_PLL_FRAC_MASK) >> RK_CLK_PLL_FRAC_SHIFT; - READ4(clk, sc->base_offset + RK_CLK_PLL_POSTDIV1_OFFSET, &postdiv1); - postdiv1 = (postdiv1 & RK_CLK_PLL_POSTDIV1_MASK) >> RK_CLK_PLL_POSTDIV1_SHIFT; - - READ4(clk, sc->base_offset + RK_CLK_PLL_POSTDIV2_OFFSET, &postdiv2); - postdiv2 = (postdiv2 & RK_CLK_PLL_POSTDIV2_MASK) >> RK_CLK_PLL_POSTDIV2_SHIFT; - - READ4(clk, sc->base_offset + RK_CLK_PLL_FRAC_OFFSET, &frac); - frac = (frac & RK_CLK_PLL_FRAC_MASK) >> RK_CLK_PLL_FRAC_SHIFT; - DEVICE_UNLOCK(clk); + rate = *freq * fbdiv / refdiv; if (dsmpd == 0) { /* Fractional mode */ - foutvco = *freq / refdiv * (fbdiv + frac / 224); - } else { - /* Integer mode */ + uint64_t frac_rate; - foutvco = *freq / refdiv * fbdiv; + frac_rate = *freq * frac / refdiv; + rate += frac_rate >> 24; } - *freq = foutvco / postdiv1 / postdiv2; + *freq = rate / postdiv1 / postdiv2; + if (*freq % 2) + *freq = *freq + 1; + return (0); } +static int +rk_clk_pll_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout, + int flags, int *stop) +{ + struct rk_clk_pll_rate *rates; + struct rk_clk_pll_sc *sc; + uint32_t reg; + int timeout; + + sc = clknode_get_softc(clk); + + if (sc->rates) + rates = sc->rates; + else if (sc->frac_rates) + rates = sc->frac_rates; + else + return (EINVAL); + + for (; rates->freq; rates++) { + if (rates->freq == *fout) + break; + } + if (rates->freq == 0) { + *stop = 1; + return (EINVAL); + } + + DEVICE_LOCK(clk); + + /* Setting postdiv1 and fbdiv */ + READ4(clk, sc->base_offset, ®); + reg &= ~(RK_CLK_PLL_POSTDIV1_MASK | RK_CLK_PLL_FBDIV_MASK); + reg |= rates->postdiv1 << RK_CLK_PLL_POSTDIV1_SHIFT; + reg |= rates->fbdiv << RK_CLK_PLL_FBDIV_SHIFT; + WRITE4(clk, sc->base_offset, reg | RK_CLK_PLL_WRITE_MASK); + + /* Setting dsmpd, postdiv2 and refdiv */ + READ4(clk, sc->base_offset + 0x4, ®); + reg &= ~(RK_CLK_PLL_DSMPD_MASK | RK_CLK_PLL_POSTDIV2_MASK | + RK_CLK_PLL_REFDIV_MASK); + reg |= rates->dsmpd << RK_CLK_PLL_DSMPD_SHIFT; + reg |= rates->postdiv2 << RK_CLK_PLL_POSTDIV2_SHIFT; + reg |= rates->refdiv << RK_CLK_PLL_REFDIV_SHIFT; + WRITE4(clk, sc->base_offset + 0x4, reg | RK_CLK_PLL_WRITE_MASK); + + /* Setting frac */ + READ4(clk, sc->base_offset + 0x8, ®); + reg &= ~RK_CLK_PLL_FRAC_MASK; + reg |= rates->frac << RK_CLK_PLL_FRAC_SHIFT; + WRITE4(clk, sc->base_offset + 0x8, reg); + + /* Reading lock */ + for (timeout = 1000; timeout; timeout--) { + READ4(clk, sc->base_offset + 0x4, ®); + if ((reg & RK_CLK_PLL_LOCK_MASK) == 0) + break; + DELAY(1); + } + + DEVICE_UNLOCK(clk); + + *stop = 1; + return (0); +} + static clknode_method_t rk_clk_pll_clknode_methods[] = { /* Device interface */ CLKNODEMETHOD(clknode_init, rk_clk_pll_init), CLKNODEMETHOD(clknode_set_gate, rk_clk_pll_set_gate), CLKNODEMETHOD(clknode_recalc_freq, rk_clk_pll_recalc), + CLKNODEMETHOD(clknode_set_freq, rk_clk_pll_set_freq), CLKNODEMETHOD_END }; @@ -196,6 +264,8 @@ rk_clk_pll_register(struct clkdom *clkdom, struct rk_c sc->gate_offset = clkdef->gate_offset; sc->gate_shift = clkdef->gate_shift; sc->flags = clkdef->flags; + sc->rates = clkdef->rates; + sc->frac_rates = clkdef->frac_rates; clknode_register(clkdom, clk); Modified: head/sys/arm64/rockchip/clk/rk_clk_pll.h ============================================================================== --- head/sys/arm64/rockchip/clk/rk_clk_pll.h Mon May 7 07:26:48 2018 (r333314) +++ head/sys/arm64/rockchip/clk/rk_clk_pll.h Mon May 7 07:28:10 2018 (r333315) @@ -33,6 +33,16 @@ #include +struct rk_clk_pll_rate { + uint32_t freq; + uint32_t refdiv; + uint32_t fbdiv; + uint32_t postdiv1; + uint32_t postdiv2; + uint32_t dsmpd; + uint32_t frac; +}; + struct rk_clk_pll_def { struct clknode_init_def clkdef; uint32_t base_offset; @@ -41,6 +51,9 @@ struct rk_clk_pll_def { uint32_t gate_shift; uint32_t flags; + + struct rk_clk_pll_rate *rates; + struct rk_clk_pll_rate *frac_rates; }; #define RK_CLK_PLL_HAVE_GATE 0x1