Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/imx make "machdep.imx7.frequency.arm_a7" and "m...



details:   https://anonhg.NetBSD.org/src/rev/c744db40814a
branches:  trunk
changeset: 348491:c744db40814a
user:      ryo <ryo%NetBSD.org@localhost>
date:      Thu Oct 20 16:50:11 2016 +0000

description:
make "machdep.imx7.frequency.arm_a7" and "machdep.imx7.frequency.arm_m4" sysctl node changeable.

diffstat:

 sys/arch/arm/imx/imx7_ccm.c |  82 +++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 76 insertions(+), 6 deletions(-)

diffs (144 lines):

diff -r 6e0b6e9c61d1 -r c744db40814a sys/arch/arm/imx/imx7_ccm.c
--- a/sys/arch/arm/imx/imx7_ccm.c       Thu Oct 20 16:05:04 2016 +0000
+++ b/sys/arch/arm/imx/imx7_ccm.c       Thu Oct 20 16:50:11 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: imx7_ccm.c,v 1.1 2016/05/17 06:44:45 ryo Exp $ */
+/*     $NetBSD: imx7_ccm.c,v 1.2 2016/10/20 16:50:11 ryo Exp $ */
 
 /*
  * Copyright (c) 2010-2012, 2014  Genetec Corporation.  All rights reserved.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx7_ccm.c,v 1.1 2016/05/17 06:44:45 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx7_ccm.c,v 1.2 2016/10/20 16:50:11 ryo Exp $");
 
 #include "opt_imx.h"
 
@@ -1059,10 +1059,12 @@
 
        if (rnode->sysctl_num == sc->sc_sysctlnode_arm_pll)
                return imx7_set_clock(IMX7CLK_ARM_PLL, value);
-       if (rnode->sysctl_num == sc->sc_sysctlnode_arm_a7_clk)
+       else if (rnode->sysctl_num == sc->sc_sysctlnode_arm_a7_clk)
                return imx7_set_clock(IMX7CLK_ARM_A7_CLK_ROOT, value);
+       else if (rnode->sysctl_num == sc->sc_sysctlnode_arm_m4_clk)
+               return imx7_set_clock(IMX7CLK_ARM_M4_CLK_ROOT, value);
 
-       return 0;
+       return EOPNOTSUPP;
 }
 
 
@@ -1105,7 +1107,7 @@
 }
 
 static uint64_t
-rootclk(int clk)
+rootclk(int clk, bool nodiv)
 {
        uint32_t d, v;
        uint64_t freq;
@@ -1126,6 +1128,9 @@
        }
 #endif
 
+       if (nodiv)
+               return freq;
+
        /* eval TARGET_ROOT[PRE_PODF] */
        if ((imx7clkroottbl[clk].type != CLKTYPE_CORE) &&
            (imx7clkroottbl[clk].type != CLKTYPE_DRAM) &&
@@ -1449,7 +1454,7 @@
        case IMX7CLK_AUDIO_MCLK_CLK_ROOT:
        case IMX7CLK_CCM_CLKO1:
        case IMX7CLK_CCM_CLKO2:
-               freq = rootclk(clk);
+               freq = rootclk(clk, false);
                break;
 
        default:
@@ -1461,10 +1466,45 @@
        return freq;
 }
 
+/*
+ * resolve two clock divisors d3 and d6.
+ * freq = maxfreq / d3(3bit) / d6(6bit)
+ */
+static void
+getrootclkdiv(uint32_t maxfreq, uint32_t freq, uint32_t *d3p, uint32_t *d6p)
+{
+       uint32_t c_dif, c_d3, c_d6;
+       uint32_t dif, d3, d6;
+       uint32_t lim, base, f;
+
+       c_dif = 0xffffffff;
+       c_d3 = c_d6 = 0;
+       for (d3 = 0; d3 < 8; d3++) {
+               base = 0;
+               for (lim = 64; lim != 0; lim >>= 1) {
+                       d6 = (lim >> 1) + base;
+                       f = maxfreq / (d3 + 1) / (d6 + 1);
+                       if (freq < f) {
+                               base = d6 + 1;
+                               lim--;
+                       }
+                       dif = (freq > f) ? freq - f : f - freq;
+                       if (c_dif > dif) {
+                               c_dif = dif;
+                               c_d3 = d3;
+                               c_d6 = d6;
+                       }
+               }
+       }
+       *d3p = c_d3;
+       *d6p = c_d6;
+}
+
 int
 imx7_set_clock(enum imx7_clock clk, uint32_t freq)
 {
        uint32_t v, x;
+       uint32_t d3, d6, maxfreq;
 
        if (ccm_softc == NULL)
                return 0;
@@ -1477,6 +1517,36 @@
                v |=  __SHIFTIN(x, CCM_ANALOG_PLL_ARM_DIV_SELECT);
                imx7_ccm_analog_write(CCM_ANALOG_PLL_ARM, v);
                break;
+
+       /* core type clock */
+       case IMX7CLK_ARM_A7_CLK_ROOT:
+               maxfreq = rootclk(clk, true);
+               getrootclkdiv(maxfreq, freq, &d3, &d6);
+               v = imx7_ccm_read(imx7clkroottbl[clk].targetroot);
+               /* core type clocks use AUTO_PODF and POST_PODF */
+               v &= ~CCM_TARGET_ROOT_AUTO_PODF;
+               v |= __SHIFTIN(d3, CCM_TARGET_ROOT_AUTO_PODF);
+               v |= CCM_TARGET_ROOT_AUTO_ENABLE;
+               v &= ~CCM_TARGET_ROOT_POST_PODF;
+               v |= __SHIFTIN(d6, CCM_TARGET_ROOT_POST_PODF);
+               imx7_ccm_write(imx7clkroottbl[clk].targetroot, v);
+               break;
+
+       /* bus type clocks */
+       case IMX7CLK_ARM_M4_CLK_ROOT:
+       case IMX7CLK_MAIN_AXI_CLK_ROOT:
+       case IMX7CLK_DISP_AXI_CLK_ROOT:
+               maxfreq = rootclk(clk, true);
+               getrootclkdiv(maxfreq, freq, &d3, &d6);
+               /* bus type clocks use PRE_PODF and POST_PODF */
+               v = imx7_ccm_read(imx7clkroottbl[clk].targetroot);
+               v &= ~CCM_TARGET_ROOT_PRE_PODF;
+               v |= __SHIFTIN(d3, CCM_TARGET_ROOT_PRE_PODF);
+               v &= ~CCM_TARGET_ROOT_POST_PODF;
+               v |= __SHIFTIN(d6, CCM_TARGET_ROOT_POST_PODF);
+               imx7_ccm_write(imx7clkroottbl[clk].targetroot, v);
+               break;
+
        default:
                aprint_error_dev(ccm_softc->sc_dev,
                    "%s: clockid %d: not supported\n", __func__, clk);



Home | Main Index | Thread Index | Old Index