Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/omap Add code to allow changing the cpu frequency.



details:   https://anonhg.NetBSD.org/src/rev/d5fb55e82c10
branches:  trunk
changeset: 787723:d5fb55e82c10
user:      matt <matt%NetBSD.org@localhost>
date:      Sat Jun 29 20:21:41 2013 +0000

description:
Add code to allow changing the cpu frequency.
XXX the sysctl_createv fails for "current" with ENOENT.

diffstat:

 sys/arch/arm/omap/am335x_prcm.c |  101 ++++++++++++++++++++++++++++++++++++++-
 sys/arch/arm/omap/am335x_prcm.h |    6 +-
 2 files changed, 102 insertions(+), 5 deletions(-)

diffs (158 lines):

diff -r 5f2a9b9276fa -r d5fb55e82c10 sys/arch/arm/omap/am335x_prcm.c
--- a/sys/arch/arm/omap/am335x_prcm.c   Sat Jun 29 20:20:17 2013 +0000
+++ b/sys/arch/arm/omap/am335x_prcm.c   Sat Jun 29 20:21:41 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: am335x_prcm.c,v 1.2 2013/06/28 02:31:16 matt Exp $     */
+/*     $NetBSD: am335x_prcm.c,v 1.3 2013/06/29 20:21:41 matt Exp $     */
 
 /*
  * TI OMAP Power, Reset, and Clock Management on the AM335x
@@ -34,10 +34,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: am335x_prcm.c,v 1.2 2013/06/28 02:31:16 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: am335x_prcm.c,v 1.3 2013/06/29 20:21:41 matt Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
+#include <sys/sysctl.h>
 
 #include <arm/omap/am335x_prcm.h>
 #include <arm/omap/omap2_prcm.h>
@@ -94,6 +95,18 @@
        am335x_prcm_check_clkctrl(cm_module, clkctrl_reg, clkctrl);
 }
 
+static const uint16_t mpu_frequencies[] = {
+       550,
+       600,
+       650,
+       700,
+       720,
+       800,
+       900,
+       1000
+};
+static int mpu_frequency;
+
 void
 prcm_mpu_pll_config(u_int mpupll_m)
 {
@@ -101,10 +114,10 @@
        uint32_t clksel = prcm_read_4(AM335X_PRCM_CM_WKUP, AM335X_PRCM_CM_CLKSEL_DPLL_MPU);
        //uint32_t div_m2 = prcm_read_4(AM335X_PRCM_CM_WKUP, AM335X_PRCM_CM_DIV_M2_DPLL_MPU);
 
-       /* Request the DPLL to be put into bypass mode */
+       /* Request the DPLL be put into bypass mode */
        prcm_write_4(AM335X_PRCM_CM_WKUP, AM335X_PRCM_CM_CLKMODE_DPLL_MPU, AM335X_PRCM_CM_CLKMODE_DPLL_MN_BYP_MODE);
 
-       /* Wait for it to be put into bypass */
+       /* Wait for it to go into bypass */
        while (prcm_read_4(AM335X_PRCM_CM_WKUP, AM335X_PRCM_CM_IDLEST_DPLL_MPU) != AM335X_PRCM_CM_IDLEST_DPLL_ST_DPLL_CLK_MN_BYPASS) {
                /* nothing */
        }
@@ -123,3 +136,83 @@
                /* nothing */
        }
 }
+
+static int
+mpu_current_frequency_sysctl_helper(SYSCTLFN_ARGS)
+{
+       struct sysctlnode node = *rnode;
+       int freq = mpu_frequency;
+       int old_freq = freq;
+
+       KASSERT(curcpu()->ci_data.cpu_cc_freq == mpu_frequency * 1000);
+
+       node.sysctl_data = &freq;
+
+       int error = sysctl_lookup(SYSCTLFN_CALL(&node));
+
+       if (error || newp == NULL)
+               return error;
+
+       KASSERT(old_freq == mpu_frequency);
+
+       error = EINVAL;
+       for (size_t i = 0; i < __arraycount(mpu_frequencies); i++) {
+               if (mpu_frequencies[i] == freq) {
+                       error = 0;
+                       break;
+               }
+       }
+       if (error)
+               return EINVAL;
+
+       if (freq != old_freq) {
+               const int s = splhigh();
+               prcm_mpu_pll_config(freq);
+               curcpu()->ci_data.cpu_cc_freq = freq * 1000000;
+               mpu_frequency = freq;
+               splx(s);
+               aprint_normal_dev(curcpu()->ci_dev,
+                   "frequency changed from %d MHz to %d MHz\n",
+                   old_freq, freq);
+       }
+
+       return 0;
+}
+
+SYSCTL_SETUP(sysctl_am335x_machdep_setup, "sysctl am335x machdep subtree setup")
+{
+       const struct sysctlnode *freqnode, *node;
+
+       static char mpu_available_frequencies[__arraycount(mpu_frequencies)*6];
+
+       KASSERT(__arraycount(mpu_frequencies) == 8);
+       snprintf(mpu_available_frequencies, sizeof(mpu_available_frequencies),
+          "%u %u %u %u %u %u %u %u",
+          mpu_frequencies[0], mpu_frequencies[1], mpu_frequencies[2],
+          mpu_frequencies[3], mpu_frequencies[4], mpu_frequencies[5],
+          mpu_frequencies[6], mpu_frequencies[7]);
+
+       sysctl_createv(clog, 0, NULL, &node,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "machdep", NULL,
+                      NULL, 0, NULL, 0,
+                      CTL_MACHDEP, CTL_EOL);
+
+       sysctl_createv(clog, 0, &node, &freqnode,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "frequency", NULL,
+                      NULL, 0, NULL, 0,
+                      CTL_CREATE, CTL_EOL);
+
+       sysctl_createv(clog, 0, &freqnode, NULL,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_STRING, "available", NULL,
+                      NULL, 0, mpu_available_frequencies,
+                      strlen(mpu_available_frequencies),
+                      CTL_CREATE, CTL_EOL);
+       sysctl_createv(clog, 0, &freqnode, NULL,
+                      CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+                      CTLTYPE_INT, "current", NULL,
+                      mpu_current_frequency_sysctl_helper, 0, NULL, 0
+                      CTL_CREATE, CTL_EOL);
+}
diff -r 5f2a9b9276fa -r d5fb55e82c10 sys/arch/arm/omap/am335x_prcm.h
--- a/sys/arch/arm/omap/am335x_prcm.h   Sat Jun 29 20:20:17 2013 +0000
+++ b/sys/arch/arm/omap/am335x_prcm.h   Sat Jun 29 20:21:41 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: am335x_prcm.h,v 1.3 2013/06/28 02:31:16 matt Exp $     */
+/*     $NetBSD: am335x_prcm.h,v 1.4 2013/06/29 20:21:41 matt Exp $     */
 
 /*
  * TI OMAP Power, Reset, and Clock Management on the AM335x
@@ -73,6 +73,10 @@
 #define  AM335X_PRCM_CM_CLKMODE_DPLL_MN_BYP_MODE       4
 #define  AM335X_PRCM_CM_CLKMODE_DPLL_LOCK_MODE         7
 #define        AM335X_PRCM_CM_DIV_M2_DPLL_MPU  0xa8
+#define         AM335X_PRCM_CM_DIV_M2_DPLL_ST_DPLL_CLKOUT      __BIT(9)
+#define         AM335X_PRCM_CM_DIV_M2_DPLL_CLKOUT_GATE_CTRL    __BIT(8)
+#define         AM335X_PRCM_CM_DIV_M2_DPLL_CLKOUT_DIVCHACK     __BIT(5)
+#define         AM335X_PRCM_CM_DIV_M2_DPLL_CLKOUT_DIV          __BITS(4,0)
 
 
 #define PRM_RSTCTRL            0x00    /* offset from AM335X_PRCM_PRM_DEVICE */



Home | Main Index | Thread Index | Old Index