Source-Changes-HG archive

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

[src/trunk]: src/sys/arch am335x: expect the board code to provide a set_mpu_...



details:   https://anonhg.NetBSD.org/src/rev/9b7625605911
branches:  trunk
changeset: 330784:9b7625605911
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sun Jul 20 23:08:43 2014 +0000

description:
am335x: expect the board code to provide a set_mpu_volt() function,
to change the MPU code voltage. When changing MPU frequency also request
a voltage change. provide frequency/voltage tables for the "blank" revision
and de A revision, based on documents from www.ti.com (this means
it's not possible anymore to request a beaglebone white to run at 1Ghz,
but this was not working anyway).
beagle_machdep.c: callback to the tps65217pmic to change the MPU voltage.

Tested on beaglebone, from 275 to 720Mhz, and on beaglebone black from
300 to 1000Mhz.

diffstat:

 sys/arch/arm/omap/am335x_prcm.c         |  124 ++++++++++++++++++++++++-------
 sys/arch/arm/omap/am335x_prcm.h         |    4 +-
 sys/arch/arm/omap/omap2_reg.h           |    7 +-
 sys/arch/evbarm/beagle/beagle_machdep.c |   21 ++++-
 4 files changed, 121 insertions(+), 35 deletions(-)

diffs (293 lines):

diff -r fd1bc2489c77 -r 9b7625605911 sys/arch/arm/omap/am335x_prcm.c
--- a/sys/arch/arm/omap/am335x_prcm.c   Sun Jul 20 23:01:22 2014 +0000
+++ b/sys/arch/arm/omap/am335x_prcm.c   Sun Jul 20 23:08:43 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: am335x_prcm.c,v 1.6 2013/08/17 00:40:10 matt Exp $     */
+/*     $NetBSD: am335x_prcm.c,v 1.7 2014/07/20 23:08:43 bouyer Exp $   */
 
 /*
  * TI OMAP Power, Reset, and Clock Management on the AM335x
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: am335x_prcm.c,v 1.6 2013/08/17 00:40:10 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: am335x_prcm.c,v 1.7 2014/07/20 23:08:43 bouyer Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -50,6 +50,8 @@
 #define   AM335X_CLKCTRL_MODULEMODE_DISABLED   0
 #define   AM335X_CLKCTRL_MODULEMODE_ENABLE     2
 
+uint32_t am335x_devid;
+
 static void
 am335x_prcm_check_clkctrl(bus_size_t cm_module,
     bus_size_t clkctrl_reg, uint32_t v)
@@ -98,19 +100,38 @@
        am335x_prcm_check_clkctrl(cm_module, clkctrl_reg, clkctrl);
 }
 
-static const uint16_t mpu_frequencies[] = {
-       550,
-       600,
-       650,
-       700,
-       720,
-       800,
-       900,
-       1000
+/*
+ * MPU frequency and power table, built from informations in
+ * http://processors.wiki.ti.com/index.php/AM335x_Power_Estimation_Tool
+ */
+
+struct mpu_frequency {
+       uint16_t freq; /* MPU frequency in Khz */
+       uint16_t mvolt; /* MPU voltage in millivolt */
 };
-static int mpu_frequency;
 
-void
+static const struct mpu_frequency mpu_frequencies_rev0_zcz[] = {
+       {275,  1100},
+       {500,  1100},
+       {600,  1200},
+       {720,  1260},
+       {0,       0},
+};
+static const struct mpu_frequency mpu_frequencies_revA_zcz[] = {
+       {300,   950},
+       {550,  1100},
+       {600,  1100},
+       {720,  1200},
+       {800,  1260},
+       {900,  1325},
+       {1000, 1325},
+       {0,       0},
+};
+static const struct mpu_frequency *mpu_frequencies = NULL;
+
+static struct mpu_frequency mpu_frequency;
+
+static void
 prcm_mpu_pll_config(u_int mpupll_m)
 {
        uint32_t clkmode = prcm_read_4(AM335X_PRCM_CM_WKUP, AM335X_PRCM_CM_CLKMODE_DPLL_MPU);
@@ -144,12 +165,15 @@
 mpu_current_frequency_sysctl_helper(SYSCTLFN_ARGS)
 {
        struct sysctlnode node = *rnode;
-       int freq = mpu_frequency;
+       int freq = mpu_frequency.freq;
        int old_freq = freq;
+       int old_mvolt = mpu_frequency.mvolt;
+       struct mpu_frequency new_mpu_frequency;
 
-       KASSERTMSG(curcpu()->ci_data.cpu_cc_freq == mpu_frequency * 1000000,
+       KASSERTMSG(
+           curcpu()->ci_data.cpu_cc_freq == mpu_frequency.freq * 1000000,
            "cc_freq %"PRIu64" mpu_freq %u000000",
-           curcpu()->ci_data.cpu_cc_freq, mpu_frequency);
+           curcpu()->ci_data.cpu_cc_freq, mpu_frequency.freq);
 
        node.sysctl_data = &freq;
 
@@ -158,11 +182,12 @@
        if (error || newp == NULL)
                return error;
 
-       KASSERT(old_freq == mpu_frequency);
+       KASSERT(old_freq == mpu_frequency.freq);
 
        error = EINVAL;
-       for (size_t i = 0; i < __arraycount(mpu_frequencies); i++) {
-               if (mpu_frequencies[i] == freq) {
+       for (size_t i = 0; mpu_frequencies[i].freq > 0; i++) {
+               if (mpu_frequencies[i].freq == freq) {
+                       new_mpu_frequency = mpu_frequencies[i];
                        error = 0;
                        break;
                }
@@ -171,11 +196,30 @@
                return EINVAL;
 
        if (freq != old_freq) {
-               const int s = splhigh();
+               int s;
+               if (new_mpu_frequency.mvolt > old_mvolt) {
+                       /* need to raise VMPU before raising freq */
+                       error  = set_mpu_volt(new_mpu_frequency.mvolt);
+               }
+               if (error)
+                       return error;
+               s = splhigh();
                prcm_mpu_pll_config(freq);
                curcpu()->ci_data.cpu_cc_freq = freq * 1000000;
-               mpu_frequency = freq;
+               mpu_frequency = new_mpu_frequency;
                splx(s);
+               if (mpu_frequency.mvolt < old_mvolt) {
+                       /* need to lower VMPU after lowering freq */
+                       error = set_mpu_volt(mpu_frequency.mvolt);
+                       if (error) {
+                               /* if we failed to lower VMPU, record it */
+                               aprint_error_dev(curcpu()->ci_dev, 
+                                  "warning: failed to change MPU voltage from "
+                                  "%d to %d\n",
+                                  old_mvolt, mpu_frequency.mvolt);
+                               mpu_frequency.mvolt = old_mvolt;
+                       }
+               }
                aprint_normal_dev(curcpu()->ci_dev,
                    "frequency changed from %d MHz to %d MHz\n",
                    old_freq, freq);
@@ -188,16 +232,36 @@
 SYSCTL_SETUP(sysctl_am335x_machdep_setup, "sysctl am335x machdep subtree setup")
 {
        const struct sysctlnode *freqnode, *node;
+       int i;
+       int cc_freq = curcpu()->ci_data.cpu_cc_freq / 1000000;
 
-       static char mpu_available_frequencies[__arraycount(mpu_frequencies)*6];
+       static char mpu_available_frequencies[__arraycount(mpu_frequencies_revA_zcz)*6];
+       char cur_cpu_freq[6];
 
-       __CTASSERT(__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]);
-       mpu_frequency = curcpu()->ci_data.cpu_cc_freq / 1000000;
+       if (TI_AM335X_CTLMOD_DEVID_REV(am335x_devid) == 0) 
+               mpu_frequencies = mpu_frequencies_rev0_zcz;
+       else
+               mpu_frequencies = mpu_frequencies_revA_zcz;
+       mpu_available_frequencies[0] = '\0';
+       for (i = 0 ; mpu_frequencies[i].freq > 0; i++) {
+               snprintf(cur_cpu_freq, sizeof(cur_cpu_freq), "%u",
+                   mpu_frequencies[i].freq);
+               if (i > 0) {
+                       strlcat(mpu_available_frequencies, " ",
+                           sizeof(mpu_available_frequencies));
+               }
+               strlcat(mpu_available_frequencies, cur_cpu_freq,
+                   sizeof(mpu_available_frequencies));
+       }
+       /* locate current freq in array */
+       for (i = 0; mpu_frequencies[i].freq > 0; i++) {
+               if (mpu_frequencies[i].freq >= cc_freq) {
+                       mpu_frequency = mpu_frequencies[i];
+                       mpu_frequency.freq = cc_freq;
+                       break;
+               }
+       }
+       KASSERT(mpu_frequency.mvolt > 0);
 
        sysctl_createv(clog, 0, NULL, &node,
                       CTLFLAG_PERMANENT,
@@ -234,6 +298,8 @@
        const uint32_t control_status = bus_space_read_4(&omap_bs_tag,
                ctlmode_ioh, CTLMOD_CONTROL_STATUS);
        omap_sys_clk = sys_clks[__SHIFTOUT(control_status, CTLMOD_CONTROL_STATUS_SYSBOOT1)];
+
+       am335x_devid = bus_space_read_4(&omap_bs_tag, ctlmode_ioh, TI_AM335X_CTLMOD_DEVID);
 }
 
 void
diff -r fd1bc2489c77 -r 9b7625605911 sys/arch/arm/omap/am335x_prcm.h
--- a/sys/arch/arm/omap/am335x_prcm.h   Sun Jul 20 23:01:22 2014 +0000
+++ b/sys/arch/arm/omap/am335x_prcm.h   Sun Jul 20 23:08:43 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: am335x_prcm.h,v 1.7 2014/07/16 18:24:35 bouyer Exp $   */
+/*     $NetBSD: am335x_prcm.h,v 1.8 2014/07/20 23:08:43 bouyer Exp $   */
 
 /*
  * TI OMAP Power, Reset, and Clock Management on the AM335x
@@ -149,7 +149,7 @@
 #define RST_GLOBAL_COLD_SW     __BIT(1)
 
 #ifdef _KERNEL
-void prcm_mpu_pll_config(u_int);
+int  set_mpu_volt(int);
 void am335x_sys_clk(bus_space_handle_t);
 void am335x_cpu_clk(void);
 #endif
diff -r fd1bc2489c77 -r 9b7625605911 sys/arch/arm/omap/omap2_reg.h
--- a/sys/arch/arm/omap/omap2_reg.h     Sun Jul 20 23:01:22 2014 +0000
+++ b/sys/arch/arm/omap/omap2_reg.h     Sun Jul 20 23:08:43 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: omap2_reg.h,v 1.27 2014/04/04 21:33:19 matt Exp $ */
+/* $NetBSD: omap2_reg.h,v 1.28 2014/07/20 23:08:43 bouyer Exp $ */
 
 /*
  * Copyright (c) 2007 Microsoft
@@ -882,8 +882,11 @@
 
 #ifdef TI_AM335X
 #define        TI_AM335X_CTLMOD_BASE           0x44e10000
-#define        CTLMOD_CONTROL_STATUS           0x40
+#define        CTLMOD_CONTROL_STATUS           0x0040
 #define        CTLMOD_CONTROL_STATUS_SYSBOOT1  __BITS(23,22)
+
+#define TI_AM335X_CTLMOD_DEVID         0x0600
+#define TI_AM335X_CTLMOD_DEVID_REV(x)  (((x) >> 28) & 0xf)
 #endif
 #if defined(OMAP4) || defined(TI_AM335X)
 #define        EMIF_SDRAM_CONFIG               8
diff -r fd1bc2489c77 -r 9b7625605911 sys/arch/evbarm/beagle/beagle_machdep.c
--- a/sys/arch/evbarm/beagle/beagle_machdep.c   Sun Jul 20 23:01:22 2014 +0000
+++ b/sys/arch/evbarm/beagle/beagle_machdep.c   Sun Jul 20 23:08:43 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: beagle_machdep.c,v 1.58 2014/07/19 18:16:50 bouyer Exp $ */
+/*     $NetBSD: beagle_machdep.c,v 1.59 2014/07/20 23:08:43 bouyer Exp $ */
 
 /*
  * Machine dependent functions for kernel setup for TI OSK5912 board.
@@ -125,7 +125,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: beagle_machdep.c,v 1.58 2014/07/19 18:16:50 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: beagle_machdep.c,v 1.59 2014/07/20 23:08:43 bouyer Exp $");
 
 #include "opt_machdep.h"
 #include "opt_ddb.h"
@@ -189,6 +189,7 @@
 #  error no prcm device configured.
 # endif
 # include <arm/omap/am335x_prcm.h>
+# include <dev/i2c/tps65217pmicvar.h>
 # if NSDHC > 0
 #  include <arm/omap/omap2_obiovar.h>
 #  include <arm/omap/omap3_sdmmcreg.h>
@@ -238,6 +239,9 @@
 #ifdef CPU_CORTEXA15
 uint32_t omap5_cnt_frq;
 #endif
+#if defined(TI_AM335X)
+device_t pmic_dev = NULL;
+#endif
 
 /*
  * Macros to translate between physical and virtual for a subset of the
@@ -1107,4 +1111,17 @@
                if (use_fb_console)
                        prop_dictionary_set_bool(dict, "is_console", false);
        }
+       if (device_is_a(self, "tps65217pmic")) {
+               pmic_dev = self;
+       }
 }
+
+int
+set_mpu_volt(int mvolt)
+{
+       if (pmic_dev == NULL)
+               return ENODEV;
+
+       /* MPU voltage is on vdcd2 */
+       return tps65217pmic_set_volt(pmic_dev, "DCDC2", mvolt);
+}



Home | Main Index | Thread Index | Old Index