From owner-svn-src-all@freebsd.org Sat Aug 10 19:02:51 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id E004CC32BE; Sat, 10 Aug 2019 19:02:51 +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.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 465WhW6MBzz42vJ; Sat, 10 Aug 2019 19:02:51 +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 BB6BD24D8; Sat, 10 Aug 2019 19:02:51 +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 x7AJ2phm041888; Sat, 10 Aug 2019 19:02:51 GMT (envelope-from manu@FreeBSD.org) Received: (from manu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x7AJ2ojd041881; Sat, 10 Aug 2019 19:02:50 GMT (envelope-from manu@FreeBSD.org) Message-Id: <201908101902.x7AJ2ojd041881@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: manu set sender to manu@FreeBSD.org using -f From: Emmanuel Vadot Date: Sat, 10 Aug 2019 19:02:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r350846 - head/sys/arm/allwinner/clkng X-SVN-Group: head X-SVN-Commit-Author: manu X-SVN-Commit-Paths: head/sys/arm/allwinner/clkng X-SVN-Commit-Revision: 350846 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Aug 2019 19:02:51 -0000 Author: manu Date: Sat Aug 10 19:02:50 2019 New Revision: 350846 URL: https://svnweb.freebsd.org/changeset/base/350846 Log: allwinner: Add support to min/max in aw_clk_frac The Fractionals clock in Allwinner device have some min/max frequencies that they can do. Add support for it. Modified: head/sys/arm/allwinner/clkng/aw_clk.h head/sys/arm/allwinner/clkng/aw_clk_frac.c head/sys/arm/allwinner/clkng/aw_clk_frac.h head/sys/arm/allwinner/clkng/ccu_a10.c head/sys/arm/allwinner/clkng/ccu_a31.c head/sys/arm/allwinner/clkng/ccu_a64.c head/sys/arm/allwinner/clkng/ccu_h3.c Modified: head/sys/arm/allwinner/clkng/aw_clk.h ============================================================================== --- head/sys/arm/allwinner/clkng/aw_clk.h Sat Aug 10 18:58:25 2019 (r350845) +++ head/sys/arm/allwinner/clkng/aw_clk.h Sat Aug 10 19:02:50 2019 (r350846) @@ -314,13 +314,15 @@ aw_clk_factor_get_value(struct aw_clk_factor *factor, _nshift, _nwidth, _nvalue, _nflags, \ _mshift, _mwidth, _mvalue, _mflags, \ _gate_shift, _lock_shift,_lock_retries, \ - _flags, _freq0, _freq1, _mode_sel, _freq_sel) \ + _flags, _freq0, _freq1, _mode_sel, _freq_sel, \ + _min_freq, _max_freq) \ static struct aw_clk_frac_def _clkname = { \ .clkdef = { \ .id = _id, \ .name = _name, \ .parent_names = _pnames, \ .parent_cnt = nitems(_pnames), \ + .flags = CLK_NODE_GLITCH_FREE, \ }, \ .offset = _offset, \ .n.shift = _nshift, \ @@ -339,6 +341,8 @@ aw_clk_factor_get_value(struct aw_clk_factor *factor, .frac.freq1 = _freq1, \ .frac.mode_sel = _mode_sel, \ .frac.freq_sel = _freq_sel, \ + .min_freq = _min_freq, \ + .max_freq = _max_freq, \ } #define M_CLK(_clkname, _id, _name, _pnames, \ Modified: head/sys/arm/allwinner/clkng/aw_clk_frac.c ============================================================================== --- head/sys/arm/allwinner/clkng/aw_clk_frac.c Sat Aug 10 18:58:25 2019 (r350845) +++ head/sys/arm/allwinner/clkng/aw_clk_frac.c Sat Aug 10 19:02:50 2019 (r350846) @@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$"); #include "clkdev_if.h" +/* #define dprintf(format, arg...) printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg) */ +#define dprintf(format, arg...) + /* * clknode for clocks matching the formula : * @@ -54,6 +57,9 @@ struct aw_clk_frac_sc { struct aw_clk_factor n; struct aw_clk_frac frac; + uint64_t min_freq; + uint64_t max_freq; + uint32_t mux_shift; uint32_t mux_mask; uint32_t gate_shift; @@ -89,6 +95,7 @@ aw_clk_frac_init(struct clknode *clk, device_t dev) idx = (val & sc->mux_mask) >> sc->mux_shift; } + dprintf("init parent idx %d\n", idx); clknode_init_parent_idx(clk, idx); return (0); } @@ -104,6 +111,7 @@ aw_clk_frac_set_gate(struct clknode *clk, bool enable) if ((sc->flags & AW_CLK_HAS_GATE) == 0) return (0); + dprintf("%sabling gate\n", enable ? "En" : "Dis"); DEVICE_LOCK(clk); READ4(clk, sc->offset, &val); if (enable) @@ -127,6 +135,7 @@ aw_clk_frac_set_mux(struct clknode *clk, int index) if ((sc->flags & AW_CLK_HAS_MUX) == 0) return (0); + dprintf("Set mux to %d\n", index); DEVICE_LOCK(clk); READ4(clk, sc->offset, &val); val &= ~sc->mux_mask; @@ -138,7 +147,7 @@ aw_clk_frac_set_mux(struct clknode *clk, int index) } static uint64_t -aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint64_t fparent, uint64_t *fout, +aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint64_t fparent, uint64_t fout, uint32_t *factor_n, uint32_t *factor_m) { uint64_t cur, best; @@ -150,18 +159,27 @@ aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint6 max_m = aw_clk_factor_get_max(&sc->m); max_n = aw_clk_factor_get_max(&sc->n); min_m = aw_clk_factor_get_min(&sc->m); - min_n = aw_clk_factor_get_min(&sc->n); + min_n = sc->min_freq / fparent; for (n = min_n; n <= max_n; n++) { for (m = min_m; m <= max_m; m++) { cur = fparent * n / m; - if ((*fout - cur) < (*fout - best)) { + if (cur < sc->min_freq) { + continue; + } + if (cur > sc->max_freq) { + continue; + } + if (cur == fout) { + *factor_n = n; + *factor_m = m; + return (cur); + } + if (abs((fout - cur)) < abs((fout - best))) { best = cur; *factor_n = n; *factor_m = m; } - if (best == *fout) - return (best); } } @@ -175,32 +193,73 @@ aw_clk_frac_set_freq(struct clknode *clk, uint64_t fpa struct aw_clk_frac_sc *sc; uint64_t cur, best, best_frac; uint32_t val, m, n, best_m, best_n; - int retry; + int retry, multiple, max_mult, best_mult; sc = clknode_get_softc(clk); best = best_frac = cur = 0; + best_mult = 0; + max_mult = 1; - if (*fout == sc->frac.freq0) - best = best_frac = sc->frac.freq0; - else if (*fout == sc->frac.freq1) - best = best_frac = sc->frac.freq1; - else - best = aw_clk_frac_find_best(sc, fparent, fout, - &best_n, &best_m); + dprintf("Trying to find freq %ju with parent %ju\n", *fout, fparent); + if ((flags & CLK_SET_ROUND_MULTIPLE) != 0) + max_mult = 10; + for (multiple = 1; multiple <= max_mult; multiple++) { + /* First test the fractional frequencies */ + dprintf("Testing with multiple %d\n", multiple); + if (*fout * multiple == sc->frac.freq0) { + best = best_frac = sc->frac.freq0; + best_mult = multiple; + dprintf("Found with using frac.freq0 and multiple %d\n", multiple); + break; + } + else if (*fout * multiple == sc->frac.freq1) { + best = best_frac = sc->frac.freq1; + best_mult = multiple; + dprintf("Found with using frac.freq1 and multiple %d\n", multiple); + break; + } + else { + cur = aw_clk_frac_find_best(sc, fparent, *fout * multiple, + &n, &m); + dprintf("Got %ju with n=%d, m=%d\n", cur, n, m); + if (cur == (*fout * multiple)) { + best = cur; + best_mult = multiple; + best_n = n; + best_m = m; + dprintf("This is the one: n=%d m=%d mult=%d\n", best_n, best_m, best_mult); + break; + } + if (abs(((*fout * multiple) - cur)) < abs(((*fout * multiple) - best))) { + best = cur; + best_mult = multiple; + best_n = n; + best_m = m; + dprintf("This is the best for now: n=%d m=%d mult=%d\n", best_n, best_m, best_mult); + } + } + } + if (best < sc->min_freq || + best > sc->max_freq) { + printf("%s: Cannot set %ju for %s (min=%ju max=%ju)\n", + __func__, best, clknode_get_name(clk), + sc->min_freq, sc->max_freq); + return (ERANGE); + } if ((flags & CLK_SET_DRYRUN) != 0) { *fout = best; *stop = 1; return (0); } - if ((best < *fout) && + if ((best < (*fout * best_mult)) && ((flags & CLK_SET_ROUND_DOWN) == 0)) { *stop = 1; return (ERANGE); } - if ((best > *fout) && + if ((best > *fout * best_mult) && ((flags & CLK_SET_ROUND_UP) == 0)) { *stop = 1; return (ERANGE); @@ -271,7 +330,6 @@ aw_clk_frac_recalc(struct clknode *clk, uint64_t *freq } else { m = aw_clk_get_factor(val, &sc->m); n = aw_clk_get_factor(val, &sc->n); - *freq = *freq * n / m; } @@ -321,6 +379,9 @@ aw_clk_frac_register(struct clkdom *clkdom, struct aw_ sc->frac.freq1 = clkdef->frac.freq1; sc->frac.mode_sel = 1 << clkdef->frac.mode_sel; sc->frac.freq_sel = 1 << clkdef->frac.freq_sel; + + sc->min_freq = clkdef->min_freq; + sc->max_freq = clkdef->max_freq; sc->mux_shift = clkdef->mux_shift; sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift; Modified: head/sys/arm/allwinner/clkng/aw_clk_frac.h ============================================================================== --- head/sys/arm/allwinner/clkng/aw_clk_frac.h Sat Aug 10 18:58:25 2019 (r350845) +++ head/sys/arm/allwinner/clkng/aw_clk_frac.h Sat Aug 10 19:02:50 2019 (r350846) @@ -38,6 +38,9 @@ struct aw_clk_frac_def { struct aw_clk_factor n; struct aw_clk_frac frac; + uint64_t min_freq; + uint64_t max_freq; + uint32_t mux_shift; uint32_t mux_width; uint32_t gate_shift; Modified: head/sys/arm/allwinner/clkng/ccu_a10.c ============================================================================== --- head/sys/arm/allwinner/clkng/ccu_a10.c Sat Aug 10 18:58:25 2019 (r350845) +++ head/sys/arm/allwinner/clkng/ccu_a10.c Sat Aug 10 19:02:50 2019 (r350846) @@ -221,7 +221,8 @@ FRAC_CLK(pll_video0_clk, 31, 0, 0, /* gate, lock, lock retries */ AW_CLK_HAS_GATE, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 15, 14); /* mode sel, freq sel */ + 15, 14, /* mode sel, freq sel */ + 27000000, 381000000); /* min freq, max freq */ static const char *pll_video0_2x_parents[] = {"pll_video0"}; FIXED_CLK(pll_video0_2x_clk, CLK_PLL_VIDEO0_2X, /* id */ @@ -240,7 +241,8 @@ FRAC_CLK(pll_video1_clk, 31, 0, 0, /* gate, lock, lock retries */ AW_CLK_HAS_GATE, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 15, 14); /* mode sel, freq sel */ + 15, 14, /* mode sel, freq sel */ + 27000000, 381000000); /* min freq, max freq */ static const char *pll_video1_2x_parents[] = {"pll_video1"}; FIXED_CLK(pll_video1_2x_clk, CLK_PLL_VIDEO1_2X, /* id */ Modified: head/sys/arm/allwinner/clkng/ccu_a31.c ============================================================================== --- head/sys/arm/allwinner/clkng/ccu_a31.c Sat Aug 10 18:58:25 2019 (r350845) +++ head/sys/arm/allwinner/clkng/ccu_a31.c Sat Aug 10 19:02:50 2019 (r350846) @@ -302,8 +302,8 @@ FRAC_CLK(pll_video0_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ - + 24, 25, /* mode sel, freq sel */ + 30000000, 600000000); /* min freq, max freq */ static const char *pll_video0_2x_parents[] = {"pll_video0"}; FIXED_CLK(pll_video0_2x_clk, CLK_PLL_VIDEO0_2X, /* id */ @@ -323,7 +323,8 @@ FRAC_CLK(pll_ve_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 30000000, 600000000); /* min freq, max freq */ NKMP_CLK_WITH_UPDATE(pll_ddr_clk, CLK_PLL_DDR, /* id */ @@ -369,7 +370,8 @@ FRAC_CLK(pll_video1_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 30000000, 600000000); /* min freq, max freq */ static const char *pll_video1_2x_parents[] = {"pll_video1"}; FIXED_CLK(pll_video1_2x_clk, @@ -390,7 +392,8 @@ FRAC_CLK(pll_gpu_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 30000000, 600000000); /* min freq, max freq */ static const char *pll_mipi_parents[] = {"pll_video0", "pll_video1"}; NKMP_CLK(pll_mipi_clk, @@ -414,7 +417,8 @@ FRAC_CLK(pll9_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 30000000, 600000000); /* min freq, max freq */ FRAC_CLK(pll10_clk, CLK_PLL10, /* id */ @@ -425,7 +429,8 @@ FRAC_CLK(pll10_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 30000000, 600000000); /* min freq, max freq */ static struct clk_div_table axi_div_table[] = { { .value = 0, .divider = 1, }, Modified: head/sys/arm/allwinner/clkng/ccu_a64.c ============================================================================== --- head/sys/arm/allwinner/clkng/ccu_a64.c Sat Aug 10 18:58:25 2019 (r350845) +++ head/sys/arm/allwinner/clkng/ccu_a64.c Sat Aug 10 19:02:50 2019 (r350846) @@ -288,7 +288,8 @@ FRAC_CLK(pll_video0_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *pll_video0_2x_parents[] = {"pll_video0"}; FIXED_CLK(pll_video0_2x_clk, CLK_PLL_VIDEO0_2X, /* id */ @@ -309,7 +310,8 @@ FRAC_CLK(pll_ve_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *pll_ddr0_parents[] = {"osc24M"}; NKMP_CLK_WITH_UPDATE(pll_ddr0_clk, @@ -379,7 +381,8 @@ FRAC_CLK(pll_video1_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *pll_gpu_parents[] = {"osc24M"}; FRAC_CLK(pll_gpu_clk, @@ -391,7 +394,8 @@ FRAC_CLK(pll_gpu_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ /* PLL MIPI is missing */ @@ -405,7 +409,8 @@ FRAC_CLK(pll_hsic_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *pll_de_parents[] = {"osc24M"}; FRAC_CLK(pll_de_clk, @@ -417,7 +422,8 @@ FRAC_CLK(pll_de_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *pll_ddr1_parents[] = {"osc24M"}; NKMP_CLK_WITH_UPDATE(pll_ddr1_clk, Modified: head/sys/arm/allwinner/clkng/ccu_h3.c ============================================================================== --- head/sys/arm/allwinner/clkng/ccu_h3.c Sat Aug 10 18:58:25 2019 (r350845) +++ head/sys/arm/allwinner/clkng/ccu_h3.c Sat Aug 10 19:02:50 2019 (r350846) @@ -306,7 +306,8 @@ FRAC_CLK(pll_video_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *pll_ve_parents[] = {"osc24M"}; FRAC_CLK(pll_ve_clk, @@ -318,7 +319,8 @@ FRAC_CLK(pll_ve_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *pll_ddr_parents[] = {"osc24M"}; NKMP_CLK_WITH_UPDATE(pll_ddr_clk, @@ -366,7 +368,8 @@ FRAC_CLK(pll_gpu_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *pll_periph1_parents[] = {"osc24M"}; NKMP_CLK(pll_periph1_clk, @@ -391,7 +394,8 @@ FRAC_CLK(pll_de_clk, 31, 28, 1000, /* gate, lock, lock retries */ AW_CLK_HAS_LOCK, /* flags */ 270000000, 297000000, /* freq0, freq1 */ - 24, 25); /* mode sel, freq sel */ + 24, 25, /* mode sel, freq sel */ + 192000000, 600000000); /* min freq, max freq */ static const char *cpux_parents[] = {"osc32k", "osc24M", "pll_cpux", "pll_cpux"}; MUX_CLK(cpux_clk,