[BACK]Return to powernow.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / i386

Annotation of sys/arch/i386/i386/powernow.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: powernow.c,v 1.3 2006/12/12 23:14:27 dim Exp $        */
                      2: /*
                      3:  * Copyright (c) 2004 Ted Unangst
                      4:  * All rights reserved.
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: /*
                     20:  * AMD K6 PowerNow driver, see AMD tech doc #23525
                     21:  * Numerous hints from Linux cpufreq driver
                     22:  */
                     23:
                     24: #include <sys/param.h>
                     25: #include <sys/sysctl.h>
                     26:
                     27: #include <machine/cpu.h>
                     28: #include <machine/cpufunc.h>
                     29: #include <machine/specialreg.h>
                     30: #include <machine/pio.h>
                     31:
                     32: /* table 27 in amd 23535.  entries after 45 taken from linux cpufreq */
                     33: struct {
                     34:        int mult;       /* not actually used, maybe for cpuspeed */
                     35:        int magic;
                     36: } k6_multipliers[] = {
                     37:        { 20, 4 },
                     38:        { 30, 5 },
                     39:        { 35, 7 },
                     40:        { 40, 2 },
                     41:        { 45, 0 },
                     42:        { 55, 3 },
                     43:        { 50, 1 },
                     44:        { 60, 6 },
                     45: };
                     46: #define NUM_K6_ENTRIES (sizeof k6_multipliers / sizeof k6_multipliers[0])
                     47:
                     48: int    k6_maxindex;    /* no setting higher than this */
                     49:
                     50: /* linux says: "it doesn't matter where, as long as it is unused */
                     51: #define K6PORT 0xfff0
                     52:
                     53: void
                     54: k6_powernow_init(void)
                     55: {
                     56:        uint64_t msrval;
                     57:        uint32_t portval;
                     58:        int i;
                     59:
                     60:        /* on */
                     61:        msrval = K6PORT | 0x1;
                     62:        wrmsr(MSR_K6_EPMR, msrval);
                     63:        /* read */
                     64:        portval = inl(K6PORT + 8);
                     65:        /* off */
                     66:        wrmsr(MSR_K6_EPMR, 0LL);
                     67:
                     68:        portval = (portval >> 5) & 7;
                     69:
                     70:        for (i = 0; i < NUM_K6_ENTRIES; i++)
                     71:                if (portval == k6_multipliers[i].magic) {
                     72:                        k6_maxindex = i;
                     73:                        break;
                     74:                }
                     75:        if (i == NUM_K6_ENTRIES) {
                     76:                printf("bad value for current multiplier\n");
                     77:                return;
                     78:        }
                     79:
                     80:        cpu_setperf = k6_powernow_setperf;
                     81: }
                     82:
                     83: void
                     84: k6_powernow_setperf(int level)
                     85: {
                     86:        uint64_t msrval;
                     87:        uint32_t portval;
                     88:        int index;
                     89:
                     90:        index = level * k6_maxindex / 100;
                     91:
                     92:        /* on */
                     93:        msrval = K6PORT | 0x1;
                     94:        wrmsr(MSR_K6_EPMR, msrval);
                     95:        /* read and update */
                     96:        portval = inl(K6PORT + 8);
                     97:        portval &= 0xf;
                     98:        portval |= 1 << 12 | 1 << 10 | 1 << 9 |
                     99:            k6_multipliers[index].magic << 5;
                    100:        outl(K6PORT + 8, portval);
                    101:        /* off */
                    102:        wrmsr(MSR_K6_EPMR, 0LL);
                    103: }

CVSweb