The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/x86/cpufreq/est.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2004 Colin Percival
    3  * Copyright (c) 2005 Nate Lawson
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted providing that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR``AS IS'' AND ANY EXPRESS OR 
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
   17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 
   19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
   24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   25  * POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/8.2/sys/x86/cpufreq/est.c 215026 2010-11-09 01:57:56Z attilio $");
   30 
   31 #include <sys/param.h>
   32 #include <sys/bus.h>
   33 #include <sys/cpu.h>
   34 #include <sys/kernel.h>
   35 #include <sys/malloc.h>
   36 #include <sys/module.h>
   37 #include <sys/smp.h>
   38 #include <sys/systm.h>
   39 
   40 #include "cpufreq_if.h"
   41 #include <machine/clock.h>
   42 #include <machine/cputypes.h>
   43 #include <machine/md_var.h>
   44 #include <machine/specialreg.h>
   45 
   46 #include <contrib/dev/acpica/include/acpi.h>
   47 
   48 #include <dev/acpica/acpivar.h>
   49 #include "acpi_if.h"
   50 
   51 /* Status/control registers (from the IA-32 System Programming Guide). */
   52 #define MSR_PERF_STATUS         0x198
   53 #define MSR_PERF_CTL            0x199
   54 
   55 /* Register and bit for enabling SpeedStep. */
   56 #define MSR_MISC_ENABLE         0x1a0
   57 #define MSR_SS_ENABLE           (1<<16)
   58 
   59 /* Frequency and MSR control values. */
   60 typedef struct {
   61         uint16_t        freq;
   62         uint16_t        volts;
   63         uint16_t        id16;
   64         int             power;
   65 } freq_info;
   66 
   67 /* Identifying characteristics of a processor and supported frequencies. */
   68 typedef struct {
   69         const u_int     vendor_id;
   70         uint32_t        id32;
   71         freq_info       *freqtab;
   72 } cpu_info;
   73 
   74 struct est_softc {
   75         device_t        dev;
   76         int             acpi_settings;
   77         int             msr_settings;
   78         freq_info       *freq_list;
   79 };
   80 
   81 /* Convert MHz and mV into IDs for passing to the MSR. */
   82 #define ID16(MHz, mV, bus_clk)                          \
   83         (((MHz / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
   84 #define ID32(MHz_hi, mV_hi, MHz_lo, mV_lo, bus_clk)     \
   85         ((ID16(MHz_lo, mV_lo, bus_clk) << 16) | (ID16(MHz_hi, mV_hi, bus_clk)))
   86 
   87 /* Format for storing IDs in our table. */
   88 #define FREQ_INFO_PWR(MHz, mV, bus_clk, mW)             \
   89         { MHz, mV, ID16(MHz, mV, bus_clk), mW }
   90 #define FREQ_INFO(MHz, mV, bus_clk)                     \
   91         FREQ_INFO_PWR(MHz, mV, bus_clk, CPUFREQ_VAL_UNKNOWN)
   92 #define INTEL(tab, zhi, vhi, zlo, vlo, bus_clk)         \
   93         { CPU_VENDOR_INTEL, ID32(zhi, vhi, zlo, vlo, bus_clk), tab }
   94 #define CENTAUR(tab, zhi, vhi, zlo, vlo, bus_clk)       \
   95         { CPU_VENDOR_CENTAUR, ID32(zhi, vhi, zlo, vlo, bus_clk), tab }
   96 
   97 static int msr_info_enabled = 0;
   98 TUNABLE_INT("hw.est.msr_info", &msr_info_enabled);
   99 static int strict = -1;
  100 TUNABLE_INT("hw.est.strict", &strict);
  101 
  102 /* Default bus clock value for Centrino processors. */
  103 #define INTEL_BUS_CLK           100
  104 
  105 /* XXX Update this if new CPUs have more settings. */
  106 #define EST_MAX_SETTINGS        10
  107 CTASSERT(EST_MAX_SETTINGS <= MAX_SETTINGS);
  108 
  109 /* Estimate in microseconds of latency for performing a transition. */
  110 #define EST_TRANS_LAT           1000
  111 
  112 /*
  113  * Frequency (MHz) and voltage (mV) settings.  Data from the
  114  * Intel Pentium M Processor Datasheet (Order Number 252612), Table 5.
  115  *
  116  * Dothan processors have multiple VID#s with different settings for
  117  * each VID#.  Since we can't uniquely identify this info
  118  * without undisclosed methods from Intel, we can't support newer
  119  * processors with this table method.  If ACPI Px states are supported,
  120  * we get info from them.
  121  */
  122 static freq_info PM17_130[] = {
  123         /* 130nm 1.70GHz Pentium M */
  124         FREQ_INFO(1700, 1484, INTEL_BUS_CLK),
  125         FREQ_INFO(1400, 1308, INTEL_BUS_CLK),
  126         FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
  127         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  128         FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
  129         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  130         FREQ_INFO(   0,    0, 1),
  131 };
  132 static freq_info PM16_130[] = {
  133         /* 130nm 1.60GHz Pentium M */
  134         FREQ_INFO(1600, 1484, INTEL_BUS_CLK),
  135         FREQ_INFO(1400, 1420, INTEL_BUS_CLK),
  136         FREQ_INFO(1200, 1276, INTEL_BUS_CLK),
  137         FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
  138         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  139         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  140         FREQ_INFO(   0,    0, 1),
  141 };
  142 static freq_info PM15_130[] = {
  143         /* 130nm 1.50GHz Pentium M */
  144         FREQ_INFO(1500, 1484, INTEL_BUS_CLK),
  145         FREQ_INFO(1400, 1452, INTEL_BUS_CLK),
  146         FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
  147         FREQ_INFO(1000, 1228, INTEL_BUS_CLK),
  148         FREQ_INFO( 800, 1116, INTEL_BUS_CLK),
  149         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  150         FREQ_INFO(   0,    0, 1),
  151 };
  152 static freq_info PM14_130[] = {
  153         /* 130nm 1.40GHz Pentium M */
  154         FREQ_INFO(1400, 1484, INTEL_BUS_CLK),
  155         FREQ_INFO(1200, 1436, INTEL_BUS_CLK),
  156         FREQ_INFO(1000, 1308, INTEL_BUS_CLK),
  157         FREQ_INFO( 800, 1180, INTEL_BUS_CLK),
  158         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  159         FREQ_INFO(   0,    0, 1),
  160 };
  161 static freq_info PM13_130[] = {
  162         /* 130nm 1.30GHz Pentium M */
  163         FREQ_INFO(1300, 1388, INTEL_BUS_CLK),
  164         FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
  165         FREQ_INFO(1000, 1292, INTEL_BUS_CLK),
  166         FREQ_INFO( 800, 1260, INTEL_BUS_CLK),
  167         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  168         FREQ_INFO(   0,    0, 1),
  169 };
  170 static freq_info PM13_LV_130[] = {
  171         /* 130nm 1.30GHz Low Voltage Pentium M */
  172         FREQ_INFO(1300, 1180, INTEL_BUS_CLK),
  173         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  174         FREQ_INFO(1100, 1100, INTEL_BUS_CLK),
  175         FREQ_INFO(1000, 1020, INTEL_BUS_CLK),
  176         FREQ_INFO( 900, 1004, INTEL_BUS_CLK),
  177         FREQ_INFO( 800,  988, INTEL_BUS_CLK),
  178         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  179         FREQ_INFO(   0,    0, 1),
  180 };
  181 static freq_info PM12_LV_130[] = {
  182         /* 130 nm 1.20GHz Low Voltage Pentium M */
  183         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  184         FREQ_INFO(1100, 1164, INTEL_BUS_CLK),
  185         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  186         FREQ_INFO( 900, 1020, INTEL_BUS_CLK),
  187         FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
  188         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  189         FREQ_INFO(   0,    0, 1),
  190 };
  191 static freq_info PM11_LV_130[] = {
  192         /* 130 nm 1.10GHz Low Voltage Pentium M */
  193         FREQ_INFO(1100, 1180, INTEL_BUS_CLK),
  194         FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
  195         FREQ_INFO( 900, 1100, INTEL_BUS_CLK),
  196         FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
  197         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  198         FREQ_INFO(   0,    0, 1),
  199 };
  200 static freq_info PM11_ULV_130[] = {
  201         /* 130 nm 1.10GHz Ultra Low Voltage Pentium M */
  202         FREQ_INFO(1100, 1004, INTEL_BUS_CLK),
  203         FREQ_INFO(1000,  988, INTEL_BUS_CLK),
  204         FREQ_INFO( 900,  972, INTEL_BUS_CLK),
  205         FREQ_INFO( 800,  956, INTEL_BUS_CLK),
  206         FREQ_INFO( 600,  844, INTEL_BUS_CLK),
  207         FREQ_INFO(   0,    0, 1),
  208 };
  209 static freq_info PM10_ULV_130[] = {
  210         /* 130 nm 1.00GHz Ultra Low Voltage Pentium M */
  211         FREQ_INFO(1000, 1004, INTEL_BUS_CLK),
  212         FREQ_INFO( 900,  988, INTEL_BUS_CLK),
  213         FREQ_INFO( 800,  972, INTEL_BUS_CLK),
  214         FREQ_INFO( 600,  844, INTEL_BUS_CLK),
  215         FREQ_INFO(   0,    0, 1),
  216 };
  217 
  218 /*
  219  * Data from "Intel Pentium M Processor on 90nm Process with
  220  * 2-MB L2 Cache Datasheet", Order Number 302189, Table 5.
  221  */
  222 static freq_info PM_765A_90[] = {
  223         /* 90 nm 2.10GHz Pentium M, VID #A */
  224         FREQ_INFO(2100, 1340, INTEL_BUS_CLK),
  225         FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
  226         FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
  227         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  228         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  229         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  230         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  231         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  232         FREQ_INFO(   0,    0, 1),
  233 };
  234 static freq_info PM_765B_90[] = {
  235         /* 90 nm 2.10GHz Pentium M, VID #B */
  236         FREQ_INFO(2100, 1324, INTEL_BUS_CLK),
  237         FREQ_INFO(1800, 1260, INTEL_BUS_CLK),
  238         FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
  239         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  240         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  241         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  242         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  243         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  244         FREQ_INFO(   0,    0, 1),
  245 };
  246 static freq_info PM_765C_90[] = {
  247         /* 90 nm 2.10GHz Pentium M, VID #C */
  248         FREQ_INFO(2100, 1308, INTEL_BUS_CLK),
  249         FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
  250         FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
  251         FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
  252         FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
  253         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  254         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  255         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  256         FREQ_INFO(   0,    0, 1),
  257 };
  258 static freq_info PM_765E_90[] = {
  259         /* 90 nm 2.10GHz Pentium M, VID #E */
  260         FREQ_INFO(2100, 1356, INTEL_BUS_CLK),
  261         FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
  262         FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
  263         FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
  264         FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
  265         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  266         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  267         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  268         FREQ_INFO(   0,    0, 1),
  269 };
  270 static freq_info PM_755A_90[] = {
  271         /* 90 nm 2.00GHz Pentium M, VID #A */
  272         FREQ_INFO(2000, 1340, INTEL_BUS_CLK),
  273         FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
  274         FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
  275         FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
  276         FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
  277         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  278         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  279         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  280         FREQ_INFO(   0,    0, 1),
  281 };
  282 static freq_info PM_755B_90[] = {
  283         /* 90 nm 2.00GHz Pentium M, VID #B */
  284         FREQ_INFO(2000, 1324, INTEL_BUS_CLK),
  285         FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
  286         FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
  287         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  288         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  289         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  290         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  291         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  292         FREQ_INFO(   0,    0, 1),
  293 };
  294 static freq_info PM_755C_90[] = {
  295         /* 90 nm 2.00GHz Pentium M, VID #C */
  296         FREQ_INFO(2000, 1308, INTEL_BUS_CLK),
  297         FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
  298         FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
  299         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  300         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  301         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  302         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  303         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  304         FREQ_INFO(   0,    0, 1),
  305 };
  306 static freq_info PM_755D_90[] = {
  307         /* 90 nm 2.00GHz Pentium M, VID #D */
  308         FREQ_INFO(2000, 1276, INTEL_BUS_CLK),
  309         FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
  310         FREQ_INFO(1600, 1196, INTEL_BUS_CLK),
  311         FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
  312         FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
  313         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  314         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  315         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  316         FREQ_INFO(   0,    0, 1),
  317 };
  318 static freq_info PM_745A_90[] = {
  319         /* 90 nm 1.80GHz Pentium M, VID #A */
  320         FREQ_INFO(1800, 1340, INTEL_BUS_CLK),
  321         FREQ_INFO(1600, 1292, INTEL_BUS_CLK),
  322         FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
  323         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  324         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  325         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  326         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  327         FREQ_INFO(   0,    0, 1),
  328 };
  329 static freq_info PM_745B_90[] = {
  330         /* 90 nm 1.80GHz Pentium M, VID #B */
  331         FREQ_INFO(1800, 1324, INTEL_BUS_CLK),
  332         FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
  333         FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
  334         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  335         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  336         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  337         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  338         FREQ_INFO(   0,    0, 1),
  339 };
  340 static freq_info PM_745C_90[] = {
  341         /* 90 nm 1.80GHz Pentium M, VID #C */
  342         FREQ_INFO(1800, 1308, INTEL_BUS_CLK),
  343         FREQ_INFO(1600, 1260, INTEL_BUS_CLK),
  344         FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
  345         FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
  346         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  347         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  348         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  349         FREQ_INFO(   0,    0, 1),
  350 };
  351 static freq_info PM_745D_90[] = {
  352         /* 90 nm 1.80GHz Pentium M, VID #D */
  353         FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
  354         FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
  355         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  356         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  357         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  358         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  359         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  360         FREQ_INFO(   0,    0, 1),
  361 };
  362 static freq_info PM_735A_90[] = {
  363         /* 90 nm 1.70GHz Pentium M, VID #A */
  364         FREQ_INFO(1700, 1340, INTEL_BUS_CLK),
  365         FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
  366         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  367         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  368         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  369         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  370         FREQ_INFO(   0,    0, 1),
  371 };
  372 static freq_info PM_735B_90[] = {
  373         /* 90 nm 1.70GHz Pentium M, VID #B */
  374         FREQ_INFO(1700, 1324, INTEL_BUS_CLK),
  375         FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
  376         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  377         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  378         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  379         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  380         FREQ_INFO(   0,    0, 1),
  381 };
  382 static freq_info PM_735C_90[] = {
  383         /* 90 nm 1.70GHz Pentium M, VID #C */
  384         FREQ_INFO(1700, 1308, INTEL_BUS_CLK),
  385         FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
  386         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  387         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  388         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  389         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  390         FREQ_INFO(   0,    0, 1),
  391 };
  392 static freq_info PM_735D_90[] = {
  393         /* 90 nm 1.70GHz Pentium M, VID #D */
  394         FREQ_INFO(1700, 1276, INTEL_BUS_CLK),
  395         FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
  396         FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
  397         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  398         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  399         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  400         FREQ_INFO(   0,    0, 1),
  401 };
  402 static freq_info PM_725A_90[] = {
  403         /* 90 nm 1.60GHz Pentium M, VID #A */
  404         FREQ_INFO(1600, 1340, INTEL_BUS_CLK),
  405         FREQ_INFO(1400, 1276, INTEL_BUS_CLK),
  406         FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
  407         FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
  408         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  409         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  410         FREQ_INFO(   0,    0, 1),
  411 };
  412 static freq_info PM_725B_90[] = {
  413         /* 90 nm 1.60GHz Pentium M, VID #B */
  414         FREQ_INFO(1600, 1324, INTEL_BUS_CLK),
  415         FREQ_INFO(1400, 1260, INTEL_BUS_CLK),
  416         FREQ_INFO(1200, 1196, INTEL_BUS_CLK),
  417         FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
  418         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  419         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  420         FREQ_INFO(   0,    0, 1),
  421 };
  422 static freq_info PM_725C_90[] = {
  423         /* 90 nm 1.60GHz Pentium M, VID #C */
  424         FREQ_INFO(1600, 1308, INTEL_BUS_CLK),
  425         FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
  426         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  427         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  428         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  429         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  430         FREQ_INFO(   0,    0, 1),
  431 };
  432 static freq_info PM_725D_90[] = {
  433         /* 90 nm 1.60GHz Pentium M, VID #D */
  434         FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
  435         FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
  436         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  437         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  438         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  439         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  440         FREQ_INFO(   0,    0, 1),
  441 };
  442 static freq_info PM_715A_90[] = {
  443         /* 90 nm 1.50GHz Pentium M, VID #A */
  444         FREQ_INFO(1500, 1340, INTEL_BUS_CLK),
  445         FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
  446         FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
  447         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  448         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  449         FREQ_INFO(   0,    0, 1),
  450 };
  451 static freq_info PM_715B_90[] = {
  452         /* 90 nm 1.50GHz Pentium M, VID #B */
  453         FREQ_INFO(1500, 1324, INTEL_BUS_CLK),
  454         FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
  455         FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
  456         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  457         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  458         FREQ_INFO(   0,    0, 1),
  459 };
  460 static freq_info PM_715C_90[] = {
  461         /* 90 nm 1.50GHz Pentium M, VID #C */
  462         FREQ_INFO(1500, 1308, INTEL_BUS_CLK),
  463         FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
  464         FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
  465         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  466         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  467         FREQ_INFO(   0,    0, 1),
  468 };
  469 static freq_info PM_715D_90[] = {
  470         /* 90 nm 1.50GHz Pentium M, VID #D */
  471         FREQ_INFO(1500, 1276, INTEL_BUS_CLK),
  472         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  473         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  474         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  475         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  476         FREQ_INFO(   0,    0, 1),
  477 };
  478 static freq_info PM_778_90[] = {
  479         /* 90 nm 1.60GHz Low Voltage Pentium M */
  480         FREQ_INFO(1600, 1116, INTEL_BUS_CLK),
  481         FREQ_INFO(1500, 1116, INTEL_BUS_CLK),
  482         FREQ_INFO(1400, 1100, INTEL_BUS_CLK),
  483         FREQ_INFO(1300, 1084, INTEL_BUS_CLK),
  484         FREQ_INFO(1200, 1068, INTEL_BUS_CLK),
  485         FREQ_INFO(1100, 1052, INTEL_BUS_CLK),
  486         FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
  487         FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
  488         FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
  489         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  490         FREQ_INFO(   0,    0, 1),
  491 };
  492 static freq_info PM_758_90[] = {
  493         /* 90 nm 1.50GHz Low Voltage Pentium M */
  494         FREQ_INFO(1500, 1116, INTEL_BUS_CLK),
  495         FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
  496         FREQ_INFO(1300, 1100, INTEL_BUS_CLK),
  497         FREQ_INFO(1200, 1084, INTEL_BUS_CLK),
  498         FREQ_INFO(1100, 1068, INTEL_BUS_CLK),
  499         FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
  500         FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
  501         FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
  502         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  503         FREQ_INFO(   0,    0, 1),
  504 };
  505 static freq_info PM_738_90[] = {
  506         /* 90 nm 1.40GHz Low Voltage Pentium M */
  507         FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
  508         FREQ_INFO(1300, 1116, INTEL_BUS_CLK),
  509         FREQ_INFO(1200, 1100, INTEL_BUS_CLK),
  510         FREQ_INFO(1100, 1068, INTEL_BUS_CLK),
  511         FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
  512         FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
  513         FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
  514         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  515         FREQ_INFO(   0,    0, 1),
  516 };
  517 static freq_info PM_773G_90[] = {
  518         /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #G */
  519         FREQ_INFO(1300,  956, INTEL_BUS_CLK),
  520         FREQ_INFO(1200,  940, INTEL_BUS_CLK),
  521         FREQ_INFO(1100,  924, INTEL_BUS_CLK),
  522         FREQ_INFO(1000,  908, INTEL_BUS_CLK),
  523         FREQ_INFO( 900,  876, INTEL_BUS_CLK),
  524         FREQ_INFO( 800,  860, INTEL_BUS_CLK),
  525         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  526 };
  527 static freq_info PM_773H_90[] = {
  528         /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #H */
  529         FREQ_INFO(1300,  940, INTEL_BUS_CLK),
  530         FREQ_INFO(1200,  924, INTEL_BUS_CLK),
  531         FREQ_INFO(1100,  908, INTEL_BUS_CLK),
  532         FREQ_INFO(1000,  892, INTEL_BUS_CLK),
  533         FREQ_INFO( 900,  876, INTEL_BUS_CLK),
  534         FREQ_INFO( 800,  860, INTEL_BUS_CLK),
  535         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  536 };
  537 static freq_info PM_773I_90[] = {
  538         /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #I */
  539         FREQ_INFO(1300,  924, INTEL_BUS_CLK),
  540         FREQ_INFO(1200,  908, INTEL_BUS_CLK),
  541         FREQ_INFO(1100,  892, INTEL_BUS_CLK),
  542         FREQ_INFO(1000,  876, INTEL_BUS_CLK),
  543         FREQ_INFO( 900,  860, INTEL_BUS_CLK),
  544         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  545         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  546 };
  547 static freq_info PM_773J_90[] = {
  548         /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #J */
  549         FREQ_INFO(1300,  908, INTEL_BUS_CLK),
  550         FREQ_INFO(1200,  908, INTEL_BUS_CLK),
  551         FREQ_INFO(1100,  892, INTEL_BUS_CLK),
  552         FREQ_INFO(1000,  876, INTEL_BUS_CLK),
  553         FREQ_INFO( 900,  860, INTEL_BUS_CLK),
  554         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  555         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  556 };
  557 static freq_info PM_773K_90[] = {
  558         /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #K */
  559         FREQ_INFO(1300,  892, INTEL_BUS_CLK),
  560         FREQ_INFO(1200,  892, INTEL_BUS_CLK),
  561         FREQ_INFO(1100,  876, INTEL_BUS_CLK),
  562         FREQ_INFO(1000,  860, INTEL_BUS_CLK),
  563         FREQ_INFO( 900,  860, INTEL_BUS_CLK),
  564         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  565         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  566 };
  567 static freq_info PM_773L_90[] = {
  568         /* 90 nm 1.30GHz Ultra Low Voltage Pentium M, VID #L */
  569         FREQ_INFO(1300,  876, INTEL_BUS_CLK),
  570         FREQ_INFO(1200,  876, INTEL_BUS_CLK),
  571         FREQ_INFO(1100,  860, INTEL_BUS_CLK),
  572         FREQ_INFO(1000,  860, INTEL_BUS_CLK),
  573         FREQ_INFO( 900,  844, INTEL_BUS_CLK),
  574         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  575         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  576 };
  577 static freq_info PM_753G_90[] = {
  578         /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #G */
  579         FREQ_INFO(1200,  956, INTEL_BUS_CLK),
  580         FREQ_INFO(1100,  940, INTEL_BUS_CLK),
  581         FREQ_INFO(1000,  908, INTEL_BUS_CLK),
  582         FREQ_INFO( 900,  892, INTEL_BUS_CLK),
  583         FREQ_INFO( 800,  860, INTEL_BUS_CLK),
  584         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  585 };
  586 static freq_info PM_753H_90[] = {
  587         /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #H */
  588         FREQ_INFO(1200,  940, INTEL_BUS_CLK),
  589         FREQ_INFO(1100,  924, INTEL_BUS_CLK),
  590         FREQ_INFO(1000,  908, INTEL_BUS_CLK),
  591         FREQ_INFO( 900,  876, INTEL_BUS_CLK),
  592         FREQ_INFO( 800,  860, INTEL_BUS_CLK),
  593         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  594 };
  595 static freq_info PM_753I_90[] = {
  596         /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #I */
  597         FREQ_INFO(1200,  924, INTEL_BUS_CLK),
  598         FREQ_INFO(1100,  908, INTEL_BUS_CLK),
  599         FREQ_INFO(1000,  892, INTEL_BUS_CLK),
  600         FREQ_INFO( 900,  876, INTEL_BUS_CLK),
  601         FREQ_INFO( 800,  860, INTEL_BUS_CLK),
  602         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  603 };
  604 static freq_info PM_753J_90[] = {
  605         /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #J */
  606         FREQ_INFO(1200,  908, INTEL_BUS_CLK),
  607         FREQ_INFO(1100,  892, INTEL_BUS_CLK),
  608         FREQ_INFO(1000,  876, INTEL_BUS_CLK),
  609         FREQ_INFO( 900,  860, INTEL_BUS_CLK),
  610         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  611         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  612 };
  613 static freq_info PM_753K_90[] = {
  614         /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #K */
  615         FREQ_INFO(1200,  892, INTEL_BUS_CLK),
  616         FREQ_INFO(1100,  892, INTEL_BUS_CLK),
  617         FREQ_INFO(1000,  876, INTEL_BUS_CLK),
  618         FREQ_INFO( 900,  860, INTEL_BUS_CLK),
  619         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  620         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  621 };
  622 static freq_info PM_753L_90[] = {
  623         /* 90 nm 1.20GHz Ultra Low Voltage Pentium M, VID #L */
  624         FREQ_INFO(1200,  876, INTEL_BUS_CLK),
  625         FREQ_INFO(1100,  876, INTEL_BUS_CLK),
  626         FREQ_INFO(1000,  860, INTEL_BUS_CLK),
  627         FREQ_INFO( 900,  844, INTEL_BUS_CLK),
  628         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  629         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  630 };
  631 
  632 static freq_info PM_733JG_90[] = {
  633         /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #G */
  634         FREQ_INFO(1100,  956, INTEL_BUS_CLK),
  635         FREQ_INFO(1000,  940, INTEL_BUS_CLK),
  636         FREQ_INFO( 900,  908, INTEL_BUS_CLK),
  637         FREQ_INFO( 800,  876, INTEL_BUS_CLK),
  638         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  639 };
  640 static freq_info PM_733JH_90[] = {
  641         /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #H */
  642         FREQ_INFO(1100,  940, INTEL_BUS_CLK),
  643         FREQ_INFO(1000,  924, INTEL_BUS_CLK),
  644         FREQ_INFO( 900,  892, INTEL_BUS_CLK),
  645         FREQ_INFO( 800,  876, INTEL_BUS_CLK),
  646         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  647 };
  648 static freq_info PM_733JI_90[] = {
  649         /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #I */
  650         FREQ_INFO(1100,  924, INTEL_BUS_CLK),
  651         FREQ_INFO(1000,  908, INTEL_BUS_CLK),
  652         FREQ_INFO( 900,  892, INTEL_BUS_CLK),
  653         FREQ_INFO( 800,  860, INTEL_BUS_CLK),
  654         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  655 };
  656 static freq_info PM_733JJ_90[] = {
  657         /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #J */
  658         FREQ_INFO(1100,  908, INTEL_BUS_CLK),
  659         FREQ_INFO(1000,  892, INTEL_BUS_CLK),
  660         FREQ_INFO( 900,  876, INTEL_BUS_CLK),
  661         FREQ_INFO( 800,  860, INTEL_BUS_CLK),
  662         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  663 };
  664 static freq_info PM_733JK_90[] = {
  665         /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #K */
  666         FREQ_INFO(1100,  892, INTEL_BUS_CLK),
  667         FREQ_INFO(1000,  876, INTEL_BUS_CLK),
  668         FREQ_INFO( 900,  860, INTEL_BUS_CLK),
  669         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  670         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  671 };
  672 static freq_info PM_733JL_90[] = {
  673         /* 90 nm 1.10GHz Ultra Low Voltage Pentium M, VID #L */
  674         FREQ_INFO(1100,  876, INTEL_BUS_CLK),
  675         FREQ_INFO(1000,  876, INTEL_BUS_CLK),
  676         FREQ_INFO( 900,  860, INTEL_BUS_CLK),
  677         FREQ_INFO( 800,  844, INTEL_BUS_CLK),
  678         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  679 };
  680 static freq_info PM_733_90[] = {
  681         /* 90 nm 1.10GHz Ultra Low Voltage Pentium M */
  682         FREQ_INFO(1100,  940, INTEL_BUS_CLK),
  683         FREQ_INFO(1000,  924, INTEL_BUS_CLK),
  684         FREQ_INFO( 900,  892, INTEL_BUS_CLK),
  685         FREQ_INFO( 800,  876, INTEL_BUS_CLK),
  686         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  687         FREQ_INFO(   0,    0, 1),
  688 };
  689 static freq_info PM_723_90[] = {
  690         /* 90 nm 1.00GHz Ultra Low Voltage Pentium M */
  691         FREQ_INFO(1000,  940, INTEL_BUS_CLK),
  692         FREQ_INFO( 900,  908, INTEL_BUS_CLK),
  693         FREQ_INFO( 800,  876, INTEL_BUS_CLK),
  694         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  695         FREQ_INFO(   0,    0, 1),
  696 };
  697 
  698 /*
  699  * VIA C7-M 500 MHz FSB, 400 MHz FSB, and ULV variants.
  700  * Data from the "VIA C7-M Processor BIOS Writer's Guide (v2.17)" datasheet.
  701  */
  702 static freq_info C7M_795[] = {
  703         /* 2.00GHz Centaur C7-M 533 Mhz FSB */
  704         FREQ_INFO_PWR(2000, 1148, 133, 20000),
  705         FREQ_INFO_PWR(1867, 1132, 133, 18000),
  706         FREQ_INFO_PWR(1600, 1100, 133, 15000),
  707         FREQ_INFO_PWR(1467, 1052, 133, 13000),
  708         FREQ_INFO_PWR(1200, 1004, 133, 10000),
  709         FREQ_INFO_PWR( 800,  844, 133,  7000),
  710         FREQ_INFO_PWR( 667,  844, 133,  6000),
  711         FREQ_INFO_PWR( 533,  844, 133,  5000),
  712         FREQ_INFO(0, 0, 1),
  713 };
  714 static freq_info C7M_785[] = {
  715         /* 1.80GHz Centaur C7-M 533 Mhz FSB */
  716         FREQ_INFO_PWR(1867, 1148, 133, 18000),
  717         FREQ_INFO_PWR(1600, 1100, 133, 15000),
  718         FREQ_INFO_PWR(1467, 1052, 133, 13000),
  719         FREQ_INFO_PWR(1200, 1004, 133, 10000),
  720         FREQ_INFO_PWR( 800,  844, 133,  7000),
  721         FREQ_INFO_PWR( 667,  844, 133,  6000),
  722         FREQ_INFO_PWR( 533,  844, 133,  5000),
  723         FREQ_INFO(0, 0, 1),
  724 };
  725 static freq_info C7M_765[] = {
  726         /* 1.60GHz Centaur C7-M 533 Mhz FSB */
  727         FREQ_INFO_PWR(1600, 1084, 133, 15000),
  728         FREQ_INFO_PWR(1467, 1052, 133, 13000),
  729         FREQ_INFO_PWR(1200, 1004, 133, 10000),
  730         FREQ_INFO_PWR( 800,  844, 133,  7000),
  731         FREQ_INFO_PWR( 667,  844, 133,  6000),
  732         FREQ_INFO_PWR( 533,  844, 133,  5000),
  733         FREQ_INFO(0, 0, 1),
  734 };
  735 
  736 static freq_info C7M_794[] = {
  737         /* 2.00GHz Centaur C7-M 400 Mhz FSB */
  738         FREQ_INFO_PWR(2000, 1148, 100, 20000),
  739         FREQ_INFO_PWR(1800, 1132, 100, 18000),
  740         FREQ_INFO_PWR(1600, 1100, 100, 15000),
  741         FREQ_INFO_PWR(1400, 1052, 100, 13000),
  742         FREQ_INFO_PWR(1000, 1004, 100, 10000),
  743         FREQ_INFO_PWR( 800,  844, 100,  7000),
  744         FREQ_INFO_PWR( 600,  844, 100,  6000),
  745         FREQ_INFO_PWR( 400,  844, 100,  5000),
  746         FREQ_INFO(0, 0, 1),
  747 };
  748 static freq_info C7M_784[] = {
  749         /* 1.80GHz Centaur C7-M 400 Mhz FSB */
  750         FREQ_INFO_PWR(1800, 1148, 100, 18000),
  751         FREQ_INFO_PWR(1600, 1100, 100, 15000),
  752         FREQ_INFO_PWR(1400, 1052, 100, 13000),
  753         FREQ_INFO_PWR(1000, 1004, 100, 10000),
  754         FREQ_INFO_PWR( 800,  844, 100,  7000),
  755         FREQ_INFO_PWR( 600,  844, 100,  6000),
  756         FREQ_INFO_PWR( 400,  844, 100,  5000),
  757         FREQ_INFO(0, 0, 1),
  758 };
  759 static freq_info C7M_764[] = {
  760         /* 1.60GHz Centaur C7-M 400 Mhz FSB */
  761         FREQ_INFO_PWR(1600, 1084, 100, 15000),
  762         FREQ_INFO_PWR(1400, 1052, 100, 13000),
  763         FREQ_INFO_PWR(1000, 1004, 100, 10000),
  764         FREQ_INFO_PWR( 800,  844, 100,  7000),
  765         FREQ_INFO_PWR( 600,  844, 100,  6000),
  766         FREQ_INFO_PWR( 400,  844, 100,  5000),
  767         FREQ_INFO(0, 0, 1),
  768 };
  769 static freq_info C7M_754[] = {
  770         /* 1.50GHz Centaur C7-M 400 Mhz FSB */
  771         FREQ_INFO_PWR(1500, 1004, 100, 12000),
  772         FREQ_INFO_PWR(1400,  988, 100, 11000),
  773         FREQ_INFO_PWR(1000,  940, 100,  9000),
  774         FREQ_INFO_PWR( 800,  844, 100,  7000),
  775         FREQ_INFO_PWR( 600,  844, 100,  6000),
  776         FREQ_INFO_PWR( 400,  844, 100,  5000),
  777         FREQ_INFO(0, 0, 1),
  778 };
  779 static freq_info C7M_771[] = {
  780         /* 1.20GHz Centaur C7-M 400 Mhz FSB */
  781         FREQ_INFO_PWR(1200,  860, 100,  7000),
  782         FREQ_INFO_PWR(1000,  860, 100,  6000),
  783         FREQ_INFO_PWR( 800,  844, 100,  5500),
  784         FREQ_INFO_PWR( 600,  844, 100,  5000),
  785         FREQ_INFO_PWR( 400,  844, 100,  4000),
  786         FREQ_INFO(0, 0, 1),
  787 };
  788 
  789 static freq_info C7M_775_ULV[] = {
  790         /* 1.50GHz Centaur C7-M ULV */
  791         FREQ_INFO_PWR(1500,  956, 100,  7500),
  792         FREQ_INFO_PWR(1400,  940, 100,  6000),
  793         FREQ_INFO_PWR(1000,  860, 100,  5000),
  794         FREQ_INFO_PWR( 800,  828, 100,  2800),
  795         FREQ_INFO_PWR( 600,  796, 100,  2500),
  796         FREQ_INFO_PWR( 400,  796, 100,  2000),
  797         FREQ_INFO(0, 0, 1),
  798 };
  799 static freq_info C7M_772_ULV[] = {
  800         /* 1.20GHz Centaur C7-M ULV */
  801         FREQ_INFO_PWR(1200,  844, 100,  5000),
  802         FREQ_INFO_PWR(1000,  844, 100,  4000),
  803         FREQ_INFO_PWR( 800,  828, 100,  2800),
  804         FREQ_INFO_PWR( 600,  796, 100,  2500),
  805         FREQ_INFO_PWR( 400,  796, 100,  2000),
  806         FREQ_INFO(0, 0, 1),
  807 };
  808 static freq_info C7M_779_ULV[] = {
  809         /* 1.00GHz Centaur C7-M ULV */
  810         FREQ_INFO_PWR(1000,  796, 100,  3500),
  811         FREQ_INFO_PWR( 800,  796, 100,  2800),
  812         FREQ_INFO_PWR( 600,  796, 100,  2500),
  813         FREQ_INFO_PWR( 400,  796, 100,  2000),
  814         FREQ_INFO(0, 0, 1),
  815 };
  816 static freq_info C7M_770_ULV[] = {
  817         /* 1.00GHz Centaur C7-M ULV */
  818         FREQ_INFO_PWR(1000,  844, 100,  5000),
  819         FREQ_INFO_PWR( 800,  796, 100,  2800),
  820         FREQ_INFO_PWR( 600,  796, 100,  2500),
  821         FREQ_INFO_PWR( 400,  796, 100,  2000),
  822         FREQ_INFO(0, 0, 1),
  823 };
  824 
  825 static cpu_info ESTprocs[] = {
  826         INTEL(PM17_130,         1700, 1484, 600, 956, INTEL_BUS_CLK),
  827         INTEL(PM16_130,         1600, 1484, 600, 956, INTEL_BUS_CLK),
  828         INTEL(PM15_130,         1500, 1484, 600, 956, INTEL_BUS_CLK),
  829         INTEL(PM14_130,         1400, 1484, 600, 956, INTEL_BUS_CLK),
  830         INTEL(PM13_130,         1300, 1388, 600, 956, INTEL_BUS_CLK),
  831         INTEL(PM13_LV_130,      1300, 1180, 600, 956, INTEL_BUS_CLK),
  832         INTEL(PM12_LV_130,      1200, 1180, 600, 956, INTEL_BUS_CLK),
  833         INTEL(PM11_LV_130,      1100, 1180, 600, 956, INTEL_BUS_CLK),
  834         INTEL(PM11_ULV_130,     1100, 1004, 600, 844, INTEL_BUS_CLK),
  835         INTEL(PM10_ULV_130,     1000, 1004, 600, 844, INTEL_BUS_CLK),
  836         INTEL(PM_765A_90,       2100, 1340, 600, 988, INTEL_BUS_CLK),
  837         INTEL(PM_765B_90,       2100, 1324, 600, 988, INTEL_BUS_CLK),
  838         INTEL(PM_765C_90,       2100, 1308, 600, 988, INTEL_BUS_CLK),
  839         INTEL(PM_765E_90,       2100, 1356, 600, 988, INTEL_BUS_CLK),
  840         INTEL(PM_755A_90,       2000, 1340, 600, 988, INTEL_BUS_CLK),
  841         INTEL(PM_755B_90,       2000, 1324, 600, 988, INTEL_BUS_CLK),
  842         INTEL(PM_755C_90,       2000, 1308, 600, 988, INTEL_BUS_CLK),
  843         INTEL(PM_755D_90,       2000, 1276, 600, 988, INTEL_BUS_CLK),
  844         INTEL(PM_745A_90,       1800, 1340, 600, 988, INTEL_BUS_CLK),
  845         INTEL(PM_745B_90,       1800, 1324, 600, 988, INTEL_BUS_CLK),
  846         INTEL(PM_745C_90,       1800, 1308, 600, 988, INTEL_BUS_CLK),
  847         INTEL(PM_745D_90,       1800, 1276, 600, 988, INTEL_BUS_CLK),
  848         INTEL(PM_735A_90,       1700, 1340, 600, 988, INTEL_BUS_CLK),
  849         INTEL(PM_735B_90,       1700, 1324, 600, 988, INTEL_BUS_CLK),
  850         INTEL(PM_735C_90,       1700, 1308, 600, 988, INTEL_BUS_CLK),
  851         INTEL(PM_735D_90,       1700, 1276, 600, 988, INTEL_BUS_CLK),
  852         INTEL(PM_725A_90,       1600, 1340, 600, 988, INTEL_BUS_CLK),
  853         INTEL(PM_725B_90,       1600, 1324, 600, 988, INTEL_BUS_CLK),
  854         INTEL(PM_725C_90,       1600, 1308, 600, 988, INTEL_BUS_CLK),
  855         INTEL(PM_725D_90,       1600, 1276, 600, 988, INTEL_BUS_CLK),
  856         INTEL(PM_715A_90,       1500, 1340, 600, 988, INTEL_BUS_CLK),
  857         INTEL(PM_715B_90,       1500, 1324, 600, 988, INTEL_BUS_CLK),
  858         INTEL(PM_715C_90,       1500, 1308, 600, 988, INTEL_BUS_CLK),
  859         INTEL(PM_715D_90,       1500, 1276, 600, 988, INTEL_BUS_CLK),
  860         INTEL(PM_778_90,        1600, 1116, 600, 988, INTEL_BUS_CLK),
  861         INTEL(PM_758_90,        1500, 1116, 600, 988, INTEL_BUS_CLK),
  862         INTEL(PM_738_90,        1400, 1116, 600, 988, INTEL_BUS_CLK),
  863         INTEL(PM_773G_90,       1300,  956, 600, 812, INTEL_BUS_CLK),
  864         INTEL(PM_773H_90,       1300,  940, 600, 812, INTEL_BUS_CLK),
  865         INTEL(PM_773I_90,       1300,  924, 600, 812, INTEL_BUS_CLK),
  866         INTEL(PM_773J_90,       1300,  908, 600, 812, INTEL_BUS_CLK),
  867         INTEL(PM_773K_90,       1300,  892, 600, 812, INTEL_BUS_CLK),
  868         INTEL(PM_773L_90,       1300,  876, 600, 812, INTEL_BUS_CLK),
  869         INTEL(PM_753G_90,       1200,  956, 600, 812, INTEL_BUS_CLK),
  870         INTEL(PM_753H_90,       1200,  940, 600, 812, INTEL_BUS_CLK),
  871         INTEL(PM_753I_90,       1200,  924, 600, 812, INTEL_BUS_CLK),
  872         INTEL(PM_753J_90,       1200,  908, 600, 812, INTEL_BUS_CLK),
  873         INTEL(PM_753K_90,       1200,  892, 600, 812, INTEL_BUS_CLK),
  874         INTEL(PM_753L_90,       1200,  876, 600, 812, INTEL_BUS_CLK),
  875         INTEL(PM_733JG_90,      1100,  956, 600, 812, INTEL_BUS_CLK),
  876         INTEL(PM_733JH_90,      1100,  940, 600, 812, INTEL_BUS_CLK),
  877         INTEL(PM_733JI_90,      1100,  924, 600, 812, INTEL_BUS_CLK),
  878         INTEL(PM_733JJ_90,      1100,  908, 600, 812, INTEL_BUS_CLK),
  879         INTEL(PM_733JK_90,      1100,  892, 600, 812, INTEL_BUS_CLK),
  880         INTEL(PM_733JL_90,      1100,  876, 600, 812, INTEL_BUS_CLK),
  881         INTEL(PM_733_90,        1100,  940, 600, 812, INTEL_BUS_CLK),
  882         INTEL(PM_723_90,        1000,  940, 600, 812, INTEL_BUS_CLK),
  883 
  884         CENTAUR(C7M_795,        2000, 1148, 533, 844, 133),
  885         CENTAUR(C7M_794,        2000, 1148, 400, 844, 100),
  886         CENTAUR(C7M_785,        1867, 1148, 533, 844, 133),
  887         CENTAUR(C7M_784,        1800, 1148, 400, 844, 100),
  888         CENTAUR(C7M_765,        1600, 1084, 533, 844, 133),
  889         CENTAUR(C7M_764,        1600, 1084, 400, 844, 100),
  890         CENTAUR(C7M_754,        1500, 1004, 400, 844, 100),
  891         CENTAUR(C7M_775_ULV,    1500,  956, 400, 796, 100),
  892         CENTAUR(C7M_771,        1200,  860, 400, 844, 100),
  893         CENTAUR(C7M_772_ULV,    1200,  844, 400, 796, 100),
  894         CENTAUR(C7M_779_ULV,    1000,  796, 400, 796, 100),
  895         CENTAUR(C7M_770_ULV,    1000,  844, 400, 796, 100),
  896         { 0, 0, NULL },
  897 };
  898 
  899 static void     est_identify(driver_t *driver, device_t parent);
  900 static int      est_features(driver_t *driver, u_int *features);
  901 static int      est_probe(device_t parent);
  902 static int      est_attach(device_t parent);
  903 static int      est_detach(device_t parent);
  904 static int      est_get_info(device_t dev);
  905 static int      est_acpi_info(device_t dev, freq_info **freqs);
  906 static int      est_table_info(device_t dev, uint64_t msr, freq_info **freqs);
  907 static int      est_msr_info(device_t dev, uint64_t msr, freq_info **freqs);
  908 static freq_info *est_get_current(freq_info *freq_list);
  909 static int      est_settings(device_t dev, struct cf_setting *sets, int *count);
  910 static int      est_set(device_t dev, const struct cf_setting *set);
  911 static int      est_get(device_t dev, struct cf_setting *set);
  912 static int      est_type(device_t dev, int *type);
  913 static int      est_set_id16(device_t dev, uint16_t id16, int need_check);
  914 static void     est_get_id16(uint16_t *id16_p);
  915 
  916 static device_method_t est_methods[] = {
  917         /* Device interface */
  918         DEVMETHOD(device_identify,      est_identify),
  919         DEVMETHOD(device_probe,         est_probe),
  920         DEVMETHOD(device_attach,        est_attach),
  921         DEVMETHOD(device_detach,        est_detach),
  922 
  923         /* cpufreq interface */
  924         DEVMETHOD(cpufreq_drv_set,      est_set),
  925         DEVMETHOD(cpufreq_drv_get,      est_get),
  926         DEVMETHOD(cpufreq_drv_type,     est_type),
  927         DEVMETHOD(cpufreq_drv_settings, est_settings),
  928 
  929         /* ACPI interface */
  930         DEVMETHOD(acpi_get_features,    est_features),
  931 
  932         {0, 0}
  933 };
  934 
  935 static driver_t est_driver = {
  936         "est",
  937         est_methods,
  938         sizeof(struct est_softc),
  939 };
  940 
  941 static devclass_t est_devclass;
  942 DRIVER_MODULE(est, cpu, est_driver, est_devclass, 0, 0);
  943 
  944 static int
  945 est_features(driver_t *driver, u_int *features)
  946 {
  947 
  948         /* Notify the ACPI CPU that we support direct access to MSRs */
  949         *features = ACPI_CAP_PERF_MSRS;
  950         return (0);
  951 }
  952 
  953 static void
  954 est_identify(driver_t *driver, device_t parent)
  955 {
  956         device_t child;
  957 
  958         /* Make sure we're not being doubly invoked. */
  959         if (device_find_child(parent, "est", -1) != NULL)
  960                 return;
  961 
  962         /* Check that CPUID is supported and the vendor is Intel.*/
  963         if (cpu_high == 0 || (cpu_vendor_id != CPU_VENDOR_INTEL &&
  964             cpu_vendor_id != CPU_VENDOR_CENTAUR))
  965                 return;
  966 
  967         /*
  968          * Check if the CPU supports EST.
  969          */
  970         if (!(cpu_feature2 & CPUID2_EST))
  971                 return;
  972 
  973         /*
  974          * We add a child for each CPU since settings must be performed
  975          * on each CPU in the SMP case.
  976          */
  977         child = BUS_ADD_CHILD(parent, 10, "est", -1);
  978         if (child == NULL)
  979                 device_printf(parent, "add est child failed\n");
  980 }
  981 
  982 static int
  983 est_probe(device_t dev)
  984 {
  985         device_t perf_dev;
  986         uint64_t msr;
  987         int error, type;
  988         
  989         if (resource_disabled("est", 0))
  990                 return (ENXIO);
  991 
  992         /*
  993          * If the ACPI perf driver has attached and is not just offering
  994          * info, let it manage things.
  995          */
  996         perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
  997         if (perf_dev && device_is_attached(perf_dev)) {
  998                 error = CPUFREQ_DRV_TYPE(perf_dev, &type);
  999                 if (error == 0 && (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
 1000                         return (ENXIO);
 1001         }
 1002 
 1003         /* Attempt to enable SpeedStep if not currently enabled. */
 1004         msr = rdmsr(MSR_MISC_ENABLE);
 1005         if ((msr & MSR_SS_ENABLE) == 0) {
 1006                 wrmsr(MSR_MISC_ENABLE, msr | MSR_SS_ENABLE);
 1007                 if (bootverbose)
 1008                         device_printf(dev, "enabling SpeedStep\n");
 1009 
 1010                 /* Check if the enable failed. */
 1011                 msr = rdmsr(MSR_MISC_ENABLE);
 1012                 if ((msr & MSR_SS_ENABLE) == 0) {
 1013                         device_printf(dev, "failed to enable SpeedStep\n");
 1014                         return (ENXIO);
 1015                 }
 1016         }
 1017 
 1018         device_set_desc(dev, "Enhanced SpeedStep Frequency Control");
 1019         return (0);
 1020 }
 1021 
 1022 static int
 1023 est_attach(device_t dev)
 1024 {
 1025         struct est_softc *sc;
 1026 
 1027         sc = device_get_softc(dev);
 1028         sc->dev = dev;
 1029 
 1030         /* On SMP system we can't guarantie independent freq setting. */
 1031         if (strict == -1 && mp_ncpus > 1)
 1032                 strict = 0;
 1033         /* Check CPU for supported settings. */
 1034         if (est_get_info(dev))
 1035                 return (ENXIO);
 1036 
 1037         cpufreq_register(dev);
 1038         return (0);
 1039 }
 1040 
 1041 static int
 1042 est_detach(device_t dev)
 1043 {
 1044         struct est_softc *sc;
 1045         int error;
 1046 
 1047         error = cpufreq_unregister(dev);
 1048         if (error)
 1049                 return (error);
 1050 
 1051         sc = device_get_softc(dev);
 1052         if (sc->acpi_settings || sc->msr_settings)
 1053                 free(sc->freq_list, M_DEVBUF);
 1054         return (0);
 1055 }
 1056 
 1057 /*
 1058  * Probe for supported CPU settings.  First, check our static table of
 1059  * settings.  If no match, try using the ones offered by acpi_perf
 1060  * (i.e., _PSS).  We use ACPI second because some systems (IBM R/T40
 1061  * series) export both legacy SMM IO-based access and direct MSR access
 1062  * but the direct access specifies invalid values for _PSS.
 1063  */
 1064 static int
 1065 est_get_info(device_t dev)
 1066 {
 1067         struct est_softc *sc;
 1068         uint64_t msr;
 1069         int error;
 1070 
 1071         sc = device_get_softc(dev);
 1072         msr = rdmsr(MSR_PERF_STATUS);
 1073         error = est_table_info(dev, msr, &sc->freq_list);
 1074         if (error)
 1075                 error = est_acpi_info(dev, &sc->freq_list);
 1076         if (error)
 1077                 error = est_msr_info(dev, msr, &sc->freq_list);
 1078 
 1079         if (error) {
 1080                 printf(
 1081         "est: CPU supports Enhanced Speedstep, but is not recognized.\n"
 1082         "est: cpu_vendor %s, msr %0jx\n", cpu_vendor, msr);
 1083                 return (ENXIO);
 1084         }
 1085 
 1086         return (0);
 1087 }
 1088 
 1089 static int
 1090 est_acpi_info(device_t dev, freq_info **freqs)
 1091 {
 1092         struct est_softc *sc;
 1093         struct cf_setting *sets;
 1094         freq_info *table;
 1095         device_t perf_dev;
 1096         int count, error, i, j;
 1097         uint16_t saved_id16;
 1098 
 1099         perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
 1100         if (perf_dev == NULL || !device_is_attached(perf_dev))
 1101                 return (ENXIO);
 1102 
 1103         /* Fetch settings from acpi_perf. */
 1104         sc = device_get_softc(dev);
 1105         table = NULL;
 1106         sets = malloc(MAX_SETTINGS * sizeof(*sets), M_TEMP, M_NOWAIT);
 1107         if (sets == NULL)
 1108                 return (ENOMEM);
 1109         count = MAX_SETTINGS;
 1110         error = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
 1111         if (error)
 1112                 goto out;
 1113 
 1114         /* Parse settings into our local table format. */
 1115         table = malloc((count + 1) * sizeof(freq_info), M_DEVBUF, M_NOWAIT);
 1116         if (table == NULL) {
 1117                 error = ENOMEM;
 1118                 goto out;
 1119         }
 1120         est_get_id16(&saved_id16);
 1121         for (i = 0, j = 0; i < count; i++) {
 1122                 /*
 1123                  * Confirm id16 value is correct.
 1124                  */
 1125                 if (sets[i].freq > 0) {
 1126                         error = est_set_id16(dev, sets[i].spec[0], 1);
 1127                         if (error != 0 && strict) {
 1128                                 if (bootverbose) 
 1129                                         device_printf(dev, "Invalid freq %u, "
 1130                                             "ignored.\n", sets[i].freq);
 1131                                 continue;
 1132                         } else if (error != 0 && bootverbose) {
 1133                                 device_printf(dev, "Can't check freq %u, "
 1134                                     "it may be invalid\n",
 1135                                     sets[i].freq);
 1136                         }
 1137                         table[j].freq = sets[i].freq;
 1138                         table[j].volts = sets[i].volts;
 1139                         table[j].id16 = sets[i].spec[0];
 1140                         table[j].power = sets[i].power;
 1141                         ++j;
 1142                 }
 1143         }
 1144         /* restore saved setting */
 1145         est_set_id16(dev, saved_id16, 0);
 1146 
 1147         /* Mark end of table with a terminator. */
 1148         bzero(&table[j], sizeof(freq_info));
 1149 
 1150         sc->acpi_settings = TRUE;
 1151         *freqs = table;
 1152         error = 0;
 1153 
 1154 out:
 1155         if (sets)
 1156                 free(sets, M_TEMP);
 1157         if (error && table)
 1158                 free(table, M_DEVBUF);
 1159         return (error);
 1160 }
 1161 
 1162 static int
 1163 est_table_info(device_t dev, uint64_t msr, freq_info **freqs)
 1164 {
 1165         cpu_info *p;
 1166         uint32_t id;
 1167 
 1168         /* Find a table which matches (vendor, id32). */
 1169         id = msr >> 32;
 1170         for (p = ESTprocs; p->id32 != 0; p++) {
 1171                 if (p->vendor_id == cpu_vendor_id && p->id32 == id)
 1172                         break;
 1173         }
 1174         if (p->id32 == 0)
 1175                 return (EOPNOTSUPP);
 1176 
 1177         /* Make sure the current setpoint is valid. */
 1178         if (est_get_current(p->freqtab) == NULL) {
 1179                 device_printf(dev, "current setting not found in table\n");
 1180                 return (EOPNOTSUPP);
 1181         }
 1182 
 1183         *freqs = p->freqtab;
 1184         return (0);
 1185 }
 1186 
 1187 static int
 1188 bus_speed_ok(int bus)
 1189 {
 1190 
 1191         switch (bus) {
 1192         case 100:
 1193         case 133:
 1194         case 333:
 1195                 return (1);
 1196         default:
 1197                 return (0);
 1198         }
 1199 }
 1200 
 1201 /*
 1202  * Flesh out a simple rate table containing the high and low frequencies
 1203  * based on the current clock speed and the upper 32 bits of the MSR.
 1204  */
 1205 static int
 1206 est_msr_info(device_t dev, uint64_t msr, freq_info **freqs)
 1207 {
 1208         struct est_softc *sc;
 1209         freq_info *fp;
 1210         int bus, freq, volts;
 1211         uint16_t id;
 1212 
 1213         if (!msr_info_enabled)
 1214                 return (EOPNOTSUPP);
 1215 
 1216         /* Figure out the bus clock. */
 1217         freq = tsc_freq / 1000000;
 1218         id = msr >> 32;
 1219         bus = freq / (id >> 8);
 1220         device_printf(dev, "Guessed bus clock (high) of %d MHz\n", bus);
 1221         if (!bus_speed_ok(bus)) {
 1222                 /* We may be running on the low frequency. */
 1223                 id = msr >> 48;
 1224                 bus = freq / (id >> 8);
 1225                 device_printf(dev, "Guessed bus clock (low) of %d MHz\n", bus);
 1226                 if (!bus_speed_ok(bus))
 1227                         return (EOPNOTSUPP);
 1228                 
 1229                 /* Calculate high frequency. */
 1230                 id = msr >> 32;
 1231                 freq = ((id >> 8) & 0xff) * bus;
 1232         }
 1233 
 1234         /* Fill out a new freq table containing just the high and low freqs. */
 1235         sc = device_get_softc(dev);
 1236         fp = malloc(sizeof(freq_info) * 3, M_DEVBUF, M_WAITOK | M_ZERO);
 1237 
 1238         /* First, the high frequency. */
 1239         volts = id & 0xff;
 1240         if (volts != 0) {
 1241                 volts <<= 4;
 1242                 volts += 700;
 1243         }
 1244         fp[0].freq = freq;
 1245         fp[0].volts = volts;
 1246         fp[0].id16 = id;
 1247         fp[0].power = CPUFREQ_VAL_UNKNOWN;
 1248         device_printf(dev, "Guessed high setting of %d MHz @ %d Mv\n", freq,
 1249             volts);
 1250 
 1251         /* Second, the low frequency. */
 1252         id = msr >> 48;
 1253         freq = ((id >> 8) & 0xff) * bus;
 1254         volts = id & 0xff;
 1255         if (volts != 0) {
 1256                 volts <<= 4;
 1257                 volts += 700;
 1258         }
 1259         fp[1].freq = freq;
 1260         fp[1].volts = volts;
 1261         fp[1].id16 = id;
 1262         fp[1].power = CPUFREQ_VAL_UNKNOWN;
 1263         device_printf(dev, "Guessed low setting of %d MHz @ %d Mv\n", freq,
 1264             volts);
 1265 
 1266         /* Table is already terminated due to M_ZERO. */
 1267         sc->msr_settings = TRUE;
 1268         *freqs = fp;
 1269         return (0);
 1270 }
 1271 
 1272 static void
 1273 est_get_id16(uint16_t *id16_p)
 1274 {
 1275         *id16_p = rdmsr(MSR_PERF_STATUS) & 0xffff;
 1276 }
 1277 
 1278 static int
 1279 est_set_id16(device_t dev, uint16_t id16, int need_check)
 1280 {
 1281         uint64_t msr;
 1282         uint16_t new_id16;
 1283         int ret = 0;
 1284 
 1285         /* Read the current register, mask out the old, set the new id. */
 1286         msr = rdmsr(MSR_PERF_CTL);
 1287         msr = (msr & ~0xffff) | id16;
 1288         wrmsr(MSR_PERF_CTL, msr);
 1289         
 1290         /* Wait a short while for the new setting.  XXX Is this necessary? */
 1291         DELAY(EST_TRANS_LAT);
 1292         
 1293         if  (need_check) {
 1294                 est_get_id16(&new_id16);                
 1295                 if (new_id16 != id16) {
 1296                         if (bootverbose) 
 1297                                 device_printf(dev, "Invalid id16 (set, cur) "
 1298                                     "= (%u, %u)\n", id16, new_id16);
 1299                         ret = ENXIO;
 1300                 }
 1301         }
 1302         return (ret);
 1303 }
 1304 
 1305 static freq_info *
 1306 est_get_current(freq_info *freq_list)
 1307 {
 1308         freq_info *f;
 1309         int i;
 1310         uint16_t id16;
 1311 
 1312         /*
 1313          * Try a few times to get a valid value.  Sometimes, if the CPU
 1314          * is in the middle of an asynchronous transition (i.e., P4TCC),
 1315          * we get a temporary invalid result.
 1316          */
 1317         for (i = 0; i < 5; i++) {
 1318                 est_get_id16(&id16);
 1319                 for (f = freq_list; f->id16 != 0; f++) {
 1320                         if (f->id16 == id16)
 1321                                 return (f);
 1322                 }
 1323                 DELAY(100);
 1324         }
 1325         return (NULL);
 1326 }
 1327 
 1328 static int
 1329 est_settings(device_t dev, struct cf_setting *sets, int *count)
 1330 {
 1331         struct est_softc *sc;
 1332         freq_info *f;
 1333         int i;
 1334 
 1335         sc = device_get_softc(dev);
 1336         if (*count < EST_MAX_SETTINGS)
 1337                 return (E2BIG);
 1338 
 1339         i = 0;
 1340         for (f = sc->freq_list; f->freq != 0; f++, i++) {
 1341                 sets[i].freq = f->freq;
 1342                 sets[i].volts = f->volts;
 1343                 sets[i].power = f->power;
 1344                 sets[i].lat = EST_TRANS_LAT;
 1345                 sets[i].dev = dev;
 1346         }
 1347         *count = i;
 1348 
 1349         return (0);
 1350 }
 1351 
 1352 static int
 1353 est_set(device_t dev, const struct cf_setting *set)
 1354 {
 1355         struct est_softc *sc;
 1356         freq_info *f;
 1357 
 1358         /* Find the setting matching the requested one. */
 1359         sc = device_get_softc(dev);
 1360         for (f = sc->freq_list; f->freq != 0; f++) {
 1361                 if (f->freq == set->freq)
 1362                         break;
 1363         }
 1364         if (f->freq == 0)
 1365                 return (EINVAL);
 1366 
 1367         /* Read the current register, mask out the old, set the new id. */
 1368         est_set_id16(dev, f->id16, 0);
 1369 
 1370         return (0);
 1371 }
 1372 
 1373 static int
 1374 est_get(device_t dev, struct cf_setting *set)
 1375 {
 1376         struct est_softc *sc;
 1377         freq_info *f;
 1378 
 1379         sc = device_get_softc(dev);
 1380         f = est_get_current(sc->freq_list);
 1381         if (f == NULL)
 1382                 return (ENXIO);
 1383 
 1384         set->freq = f->freq;
 1385         set->volts = f->volts;
 1386         set->power = f->power;
 1387         set->lat = EST_TRANS_LAT;
 1388         set->dev = dev;
 1389         return (0);
 1390 }
 1391 
 1392 static int
 1393 est_type(device_t dev, int *type)
 1394 {
 1395 
 1396         if (type == NULL)
 1397                 return (EINVAL);
 1398 
 1399         *type = CPUFREQ_TYPE_ABSOLUTE;
 1400         return (0);
 1401 }

Cache object: a87e1583160fc0b25dd52acdc002832c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.