Module Name:    src
Committed By:   matt
Date:           Sat Jun 29 20:21:41 UTC 2013

Modified Files:
        src/sys/arch/arm/omap: am335x_prcm.c am335x_prcm.h

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


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/omap/am335x_prcm.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/omap/am335x_prcm.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/omap/am335x_prcm.c
diff -u src/sys/arch/arm/omap/am335x_prcm.c:1.2 src/sys/arch/arm/omap/am335x_prcm.c:1.3
--- src/sys/arch/arm/omap/am335x_prcm.c:1.2	Fri Jun 28 02:31:16 2013
+++ src/sys/arch/arm/omap/am335x_prcm.c	Sat Jun 29 20:21:41 2013
@@ -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 @@ prcm_module_disable(const struct omap_mo
 	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 @@ prcm_mpu_pll_config(u_int mpupll_m)
 	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 @@ prcm_mpu_pll_config(u_int mpupll_m)
 		/* 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);
+}

Index: src/sys/arch/arm/omap/am335x_prcm.h
diff -u src/sys/arch/arm/omap/am335x_prcm.h:1.3 src/sys/arch/arm/omap/am335x_prcm.h:1.4
--- src/sys/arch/arm/omap/am335x_prcm.h:1.3	Fri Jun 28 02:31:16 2013
+++ src/sys/arch/arm/omap/am335x_prcm.h	Sat Jun 29 20:21:41 2013
@@ -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 @@ struct omap_module {
 #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 */

Reply via email to