root/arch/i386/i386/longrun.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. longrun_init
  2. longrun_update
  3. longrun_setperf

    1 /* $OpenBSD: longrun.c,v 1.13 2007/05/25 20:32:29 krw Exp $ */
    2 /*
    3  * Copyright (c) 2003 Ted Unangst
    4  * Copyright (c) 2001 Tamotsu Hattori
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/sysctl.h>
   35 #include <sys/timeout.h>
   36 
   37 #include <machine/cpufunc.h>
   38 
   39 union msrinfo {
   40         u_int64_t msr;
   41         uint32_t regs[2];
   42 };
   43 
   44 /*
   45  * Crusoe model specific registers which interest us.
   46  */
   47 #define MSR_TMx86_LONGRUN       0x80868010
   48 #define MSR_TMx86_LONGRUN_FLAGS 0x80868011
   49 
   50 #define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f)
   51 #define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80)
   52 #define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | LONGRUN_MODE_MASK(y))
   53 
   54 void    longrun_update(void *);
   55 
   56 struct timeout longrun_timo;
   57 
   58 void
   59 longrun_init(void)
   60 {
   61         cpu_setperf = longrun_setperf;
   62 
   63         timeout_set(&longrun_timo, longrun_update, NULL);
   64         timeout_add(&longrun_timo, hz);
   65 }
   66 
   67 /*
   68  * These are the instantaneous values used by the CPU.
   69  * regs[0] = Frequency is self-evident.
   70  * regs[1] = Voltage is returned in millivolts.
   71  * regs[2] = Percent is amount of performance window being used, not
   72  * percentage of top megahertz.  (0 values are typical.)
   73  */
   74 void
   75 longrun_update(void *arg)
   76 {
   77         uint32_t eflags, regs[4];
   78 
   79         eflags = read_eflags();
   80         disable_intr();
   81         cpuid(0x80860007, regs);
   82         enable_intr();
   83         write_eflags(eflags);
   84 
   85         cpuspeed = regs[0];
   86 
   87         timeout_add(&longrun_timo, hz);
   88 }
   89 
   90 /*
   91  * Transmeta documentation says performance window boundaries
   92  * must be between 0 and 100 or a GP0 exception is generated.
   93  * mode is really only a bit, 0 or 1
   94  * These values will be rounded by the CPU to within the
   95  * limits it handles.  Typically, there are about 5 performance
   96  * levels selectable.
   97  */
   98 void
   99 longrun_setperf(int high)
  100 {
  101         uint32_t eflags, mode;
  102         union msrinfo msrinfo;
  103 
  104         if (high >= 50)
  105                 mode = 1;       /* power */
  106         else
  107                 mode = 0;       /* battery */
  108 
  109         eflags = read_eflags();
  110         disable_intr();
  111 
  112         msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
  113         msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0], 0); /* low */
  114         msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1], high);
  115         wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
  116 
  117         msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
  118         msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | mode;
  119         wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
  120 
  121         enable_intr();
  122         write_eflags(eflags);
  123 
  124         longrun_update(NULL);
  125 }
  126 

/* [<][>][^][v][top][bottom][index][help] */