summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/i386/conf/files.i3863
-rw-r--r--sys/arch/i386/i386/machdep.c8
-rw-r--r--sys/arch/i386/i386/powernow.c105
-rw-r--r--sys/arch/i386/include/cpu.h6
-rw-r--r--sys/arch/i386/include/specialreg.h5
5 files changed, 123 insertions, 4 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index 2a2b58a6abc..eae2de26a13 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.111 2003/12/20 18:23:17 tedu Exp $
+# $OpenBSD: files.i386,v 1.112 2004/04/02 22:28:40 tedu Exp $
# $NetBSD: files.i386,v 1.73 1996/05/07 00:58:36 thorpej Exp $
#
# new style config file for i386 architecture
@@ -33,6 +33,7 @@ file arch/i386/i386/microtime.s
file arch/i386/i386/ns_cksum.c ns
file arch/i386/i386/p4tcc.c !small_kernel & i686_cpu
file arch/i386/i386/pmap.c
+file arch/i386/i386/powernow.c !small_kernel
file arch/i386/i386/process_machdep.c
file arch/i386/i386/procfs_machdep.c procfs
file arch/i386/i386/random.s
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index c9476af4188..04f78890f05 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.287 2004/03/26 04:00:59 drahn Exp $ */
+/* $OpenBSD: machdep.c,v 1.288 2004/04/02 22:28:40 tedu Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -1641,6 +1641,12 @@ amd_family5_setup(cpu_device, model, step)
* XXX the pmap somehow. How does the MP branch do this?
*/
break;
+ case 12:
+ case 13:
+#ifndef SMALL_KERNEL
+ k6_powernow_init();
+#endif
+ break;
}
}
diff --git a/sys/arch/i386/i386/powernow.c b/sys/arch/i386/i386/powernow.c
new file mode 100644
index 00000000000..ef9982a36b3
--- /dev/null
+++ b/sys/arch/i386/i386/powernow.c
@@ -0,0 +1,105 @@
+/* $OpenBSD */
+/*
+ * Copyright (c) 2004 Ted Unangst
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * AMD K6 PowerNow driver, see AMD tech doc #23525
+ * Numerous hints from Linux cpufreq driver
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+#include <machine/pio.h>
+
+/* table 27 in amd 23535. entries after 45 taken from linux cpufreq */
+struct {
+ int mult; /* not actually used, maybe for cpuspeed */
+ int magic;
+} k6_multipliers[] = {
+ { 20, 4 },
+ { 30, 5 },
+ { 35, 7 },
+ { 40, 2 },
+ { 45, 0 },
+ { 55, 3 },
+ { 50, 1 },
+ { 60, 6 },
+};
+#define NUM_K6_ENTRIES (sizeof k6_multipliers / sizeof k6_multipliers[0])
+
+int k6_maxindex; /* no setting higher than this */
+
+/* linux says: "it doesn't matter where, as long as it is unused */
+#define K6PORT 0xfff0
+
+void
+k6_powernow_init(void)
+{
+ uint64_t msrval;
+ uint32_t portval;
+ int i;
+
+ /* on */
+ msrval = K6PORT | 0x1;
+ wrmsr(MSR_K6_EPMR, msrval);
+ /* read */
+ portval = inl(K6PORT + 8);
+ /* off */
+ wrmsr(MSR_K6_EPMR, 0LL);
+
+ portval = (portval >> 5) & 7;
+
+ for (i = 0; i < NUM_K6_ENTRIES; i++)
+ if (portval == k6_multipliers[i].magic) {
+ k6_maxindex = i;
+ break;
+ }
+ if (i == NUM_K6_ENTRIES) {
+ printf("bad value for current multiplier\n");
+ return;
+ }
+
+ cpu_setperf = k6_powernow_setperf;
+}
+
+int
+k6_powernow_setperf(int level)
+{
+ uint64_t msrval;
+ uint32_t portval;
+ int index;
+
+ index = level * k6_maxindex / 100;
+
+ /* on */
+ msrval = K6PORT | 0x1;
+ wrmsr(MSR_K6_EPMR, msrval);
+ /* read and update */
+ portval = inl(K6PORT + 8);
+ portval &= 0xf;
+ portval |= 1 << 12 | 1 << 10 | 1 << 9 |
+ k6_multipliers[index].magic << 5;
+ outl(K6PORT + 8, portval);
+ /* off */
+ wrmsr(MSR_K6_EPMR, 0LL);
+
+ return (0);
+}
diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h
index 13b9e47a513..a82def3a6ce 100644
--- a/sys/arch/i386/include/cpu.h
+++ b/sys/arch/i386/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.58 2004/02/14 15:09:22 grange Exp $ */
+/* $OpenBSD: cpu.h,v 1.59 2004/04/02 22:28:41 tedu Exp $ */
/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */
/*-
@@ -208,6 +208,10 @@ void p4tcc_init(int, int);
int p4tcc_setperf(int);
#endif
+void k6_powernow_init(void);
+int k6_powernow_setperf(int);
+
+
/* npx.c */
void npxdrop(void);
void npxsave(void);
diff --git a/sys/arch/i386/include/specialreg.h b/sys/arch/i386/include/specialreg.h
index fbcc328e6f5..15c87a430ab 100644
--- a/sys/arch/i386/include/specialreg.h
+++ b/sys/arch/i386/include/specialreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: specialreg.h,v 1.21 2004/02/19 22:33:29 grange Exp $ */
+/* $OpenBSD: specialreg.h,v 1.22 2004/04/02 22:28:41 tedu Exp $ */
/* $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $ */
/*-
@@ -233,6 +233,9 @@
#define MSR_MC3_ADDR 0x412
#define MSR_MC3_MISC 0x413
+/* AMD MSRs */
+#define MSR_K6_EPMR 0xc0000086
+
/*
* Constants related to MTRRs
*/