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