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/i386/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/6.1/sys/i386/cpufreq/est.c 144881 2005-04-10 19:57:47Z njl $");
   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/md_var.h>
   42 
   43 #include <contrib/dev/acpica/acpi.h>
   44 #include <dev/acpica/acpivar.h>
   45 #include "acpi_if.h"
   46 
   47 /* Status/control registers (from the IA-32 System Programming Guide). */
   48 #define MSR_PERF_STATUS         0x198
   49 #define MSR_PERF_CTL            0x199
   50 
   51 /* Register and bit for enabling SpeedStep. */
   52 #define MSR_MISC_ENABLE         0x1a0
   53 #define MSR_SS_ENABLE           (1<<16)
   54 
   55 /* Frequency and MSR control values. */
   56 typedef struct {
   57         uint16_t        freq;
   58         uint16_t        volts;
   59         uint16_t        id16;
   60         int             power;
   61 } freq_info;
   62 
   63 /* Identifying characteristics of a processor and supported frequencies. */
   64 typedef struct {
   65         const char      *vendor;
   66         uint32_t        id32;
   67         uint32_t        bus_clk;
   68         freq_info       *freqtab;
   69 } cpu_info;
   70 
   71 struct est_softc {
   72         device_t        dev;
   73         int             acpi_settings;
   74         freq_info       *freq_list;
   75 };
   76 
   77 /* Convert MHz and mV into IDs for passing to the MSR. */
   78 #define ID16(MHz, mV, bus_clk)                          \
   79         (((MHz / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
   80 #define ID32(MHz_hi, mV_hi, MHz_lo, mV_lo, bus_clk)     \
   81         ((ID16(MHz_lo, mV_lo, bus_clk) << 16) | (ID16(MHz_hi, mV_hi, bus_clk)))
   82 
   83 /* Format for storing IDs in our table. */
   84 #define FREQ_INFO(MHz, mV, bus_clk)                     \
   85         { MHz, mV, ID16(MHz, mV, bus_clk), CPUFREQ_VAL_UNKNOWN }
   86 #define INTEL(tab, zhi, vhi, zlo, vlo, bus_clk)         \
   87         { GenuineIntel, ID32(zhi, vhi, zlo, vlo, bus_clk), bus_clk, tab }
   88 
   89 const char GenuineIntel[] = "GenuineIntel";
   90 
   91 /* Default bus clock value for Centrino processors. */
   92 #define INTEL_BUS_CLK           100
   93 
   94 /* XXX Update this if new CPUs have more settings. */
   95 #define EST_MAX_SETTINGS        10
   96 CTASSERT(EST_MAX_SETTINGS <= MAX_SETTINGS);
   97 
   98 /* Estimate in microseconds of latency for performing a transition. */
   99 #define EST_TRANS_LAT           10
  100 
  101 /*
  102  * Frequency (MHz) and voltage (mV) settings.  Data from the
  103  * Intel Pentium M Processor Datasheet (Order Number 252612), Table 5.
  104  *
  105  * Dothan processors have multiple VID#s with different settings for
  106  * each VID#.  Since we can't uniquely identify this info
  107  * without undisclosed methods from Intel, we can't support newer
  108  * processors with this table method.  If ACPI Px states are supported,
  109  * we get info from them.
  110  */
  111 static freq_info PM17_130[] = {
  112         /* 130nm 1.70GHz Pentium M */
  113         FREQ_INFO(1700, 1484, INTEL_BUS_CLK),
  114         FREQ_INFO(1400, 1308, INTEL_BUS_CLK),
  115         FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
  116         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  117         FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
  118         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  119         FREQ_INFO(   0,    0, 1),
  120 };
  121 static freq_info PM16_130[] = {
  122         /* 130nm 1.60GHz Pentium M */
  123         FREQ_INFO(1600, 1484, INTEL_BUS_CLK),
  124         FREQ_INFO(1400, 1420, INTEL_BUS_CLK),
  125         FREQ_INFO(1200, 1276, INTEL_BUS_CLK),
  126         FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
  127         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  128         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  129         FREQ_INFO(   0,    0, 1),
  130 };
  131 static freq_info PM15_130[] = {
  132         /* 130nm 1.50GHz Pentium M */
  133         FREQ_INFO(1500, 1484, INTEL_BUS_CLK),
  134         FREQ_INFO(1400, 1452, INTEL_BUS_CLK),
  135         FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
  136         FREQ_INFO(1000, 1228, INTEL_BUS_CLK),
  137         FREQ_INFO( 800, 1116, INTEL_BUS_CLK),
  138         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  139         FREQ_INFO(   0,    0, 1),
  140 };
  141 static freq_info PM14_130[] = {
  142         /* 130nm 1.40GHz Pentium M */
  143         FREQ_INFO(1400, 1484, INTEL_BUS_CLK),
  144         FREQ_INFO(1200, 1436, INTEL_BUS_CLK),
  145         FREQ_INFO(1000, 1308, INTEL_BUS_CLK),
  146         FREQ_INFO( 800, 1180, INTEL_BUS_CLK),
  147         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  148         FREQ_INFO(   0,    0, 1),
  149 };
  150 static freq_info PM13_130[] = {
  151         /* 130nm 1.30GHz Pentium M */
  152         FREQ_INFO(1300, 1388, INTEL_BUS_CLK),
  153         FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
  154         FREQ_INFO(1000, 1292, INTEL_BUS_CLK),
  155         FREQ_INFO( 800, 1260, INTEL_BUS_CLK),
  156         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  157         FREQ_INFO(   0,    0, 1),
  158 };
  159 static freq_info PM13_LV_130[] = {
  160         /* 130nm 1.30GHz Low Voltage Pentium M */
  161         FREQ_INFO(1300, 1180, INTEL_BUS_CLK),
  162         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  163         FREQ_INFO(1100, 1100, INTEL_BUS_CLK),
  164         FREQ_INFO(1000, 1020, INTEL_BUS_CLK),
  165         FREQ_INFO( 900, 1004, INTEL_BUS_CLK),
  166         FREQ_INFO( 800,  988, INTEL_BUS_CLK),
  167         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  168         FREQ_INFO(   0,    0, 1),
  169 };
  170 static freq_info PM12_LV_130[] = {
  171         /* 130 nm 1.20GHz Low Voltage Pentium M */
  172         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  173         FREQ_INFO(1100, 1164, INTEL_BUS_CLK),
  174         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  175         FREQ_INFO( 900, 1020, INTEL_BUS_CLK),
  176         FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
  177         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  178         FREQ_INFO(   0,    0, 1),
  179 };
  180 static freq_info PM11_LV_130[] = {
  181         /* 130 nm 1.10GHz Low Voltage Pentium M */
  182         FREQ_INFO(1100, 1180, INTEL_BUS_CLK),
  183         FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
  184         FREQ_INFO( 900, 1100, INTEL_BUS_CLK),
  185         FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
  186         FREQ_INFO( 600,  956, INTEL_BUS_CLK),
  187         FREQ_INFO(   0,    0, 1),
  188 };
  189 static freq_info PM11_ULV_130[] = {
  190         /* 130 nm 1.10GHz Ultra Low Voltage Pentium M */
  191         FREQ_INFO(1100, 1004, INTEL_BUS_CLK),
  192         FREQ_INFO(1000,  988, INTEL_BUS_CLK),
  193         FREQ_INFO( 900,  972, INTEL_BUS_CLK),
  194         FREQ_INFO( 800,  956, INTEL_BUS_CLK),
  195         FREQ_INFO( 600,  844, INTEL_BUS_CLK),
  196         FREQ_INFO(   0,    0, 1),
  197 };
  198 static freq_info PM10_ULV_130[] = {
  199         /* 130 nm 1.00GHz Ultra Low Voltage Pentium M */
  200         FREQ_INFO(1000, 1004, INTEL_BUS_CLK),
  201         FREQ_INFO( 900,  988, INTEL_BUS_CLK),
  202         FREQ_INFO( 800,  972, INTEL_BUS_CLK),
  203         FREQ_INFO( 600,  844, INTEL_BUS_CLK),
  204         FREQ_INFO(   0,    0, 1),
  205 };
  206 
  207 /*
  208  * Data from "Intel Pentium M Processor on 90nm Process with
  209  * 2-MB L2 Cache Datasheet", Order Number 302189, Table 5.
  210  */
  211 static freq_info PM_765A_90[] = {
  212         /* 90 nm 2.10GHz Pentium M, VID #A */
  213         FREQ_INFO(2100, 1340, INTEL_BUS_CLK),
  214         FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
  215         FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
  216         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  217         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  218         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  219         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  220         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  221         FREQ_INFO(   0,    0, 1),
  222 };
  223 static freq_info PM_765B_90[] = {
  224         /* 90 nm 2.10GHz Pentium M, VID #B */
  225         FREQ_INFO(2100, 1324, INTEL_BUS_CLK),
  226         FREQ_INFO(1800, 1260, INTEL_BUS_CLK),
  227         FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
  228         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  229         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  230         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  231         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  232         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  233         FREQ_INFO(   0,    0, 1),
  234 };
  235 static freq_info PM_765C_90[] = {
  236         /* 90 nm 2.10GHz Pentium M, VID #C */
  237         FREQ_INFO(2100, 1308, INTEL_BUS_CLK),
  238         FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
  239         FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
  240         FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
  241         FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
  242         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  243         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  244         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  245         FREQ_INFO(   0,    0, 1),
  246 };
  247 static freq_info PM_765E_90[] = {
  248         /* 90 nm 2.10GHz Pentium M, VID #E */
  249         FREQ_INFO(2100, 1356, INTEL_BUS_CLK),
  250         FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
  251         FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
  252         FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
  253         FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
  254         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  255         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  256         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  257         FREQ_INFO(   0,    0, 1),
  258 };
  259 static freq_info PM_755A_90[] = {
  260         /* 90 nm 2.00GHz Pentium M, VID #A */
  261         FREQ_INFO(2000, 1340, INTEL_BUS_CLK),
  262         FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
  263         FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
  264         FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
  265         FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
  266         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  267         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  268         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  269         FREQ_INFO(   0,    0, 1),
  270 };
  271 static freq_info PM_755B_90[] = {
  272         /* 90 nm 2.00GHz Pentium M, VID #B */
  273         FREQ_INFO(2000, 1324, INTEL_BUS_CLK),
  274         FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
  275         FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
  276         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  277         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  278         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  279         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  280         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  281         FREQ_INFO(   0,    0, 1),
  282 };
  283 static freq_info PM_755C_90[] = {
  284         /* 90 nm 2.00GHz Pentium M, VID #C */
  285         FREQ_INFO(2000, 1308, INTEL_BUS_CLK),
  286         FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
  287         FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
  288         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  289         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  290         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  291         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  292         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  293         FREQ_INFO(   0,    0, 1),
  294 };
  295 static freq_info PM_755D_90[] = {
  296         /* 90 nm 2.00GHz Pentium M, VID #D */
  297         FREQ_INFO(2000, 1276, INTEL_BUS_CLK),
  298         FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
  299         FREQ_INFO(1600, 1196, INTEL_BUS_CLK),
  300         FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
  301         FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
  302         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  303         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  304         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  305         FREQ_INFO(   0,    0, 1),
  306 };
  307 static freq_info PM_745A_90[] = {
  308         /* 90 nm 1.80GHz Pentium M, VID #A */
  309         FREQ_INFO(1800, 1340, INTEL_BUS_CLK),
  310         FREQ_INFO(1600, 1292, INTEL_BUS_CLK),
  311         FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
  312         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  313         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  314         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  315         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  316         FREQ_INFO(   0,    0, 1),
  317 };
  318 static freq_info PM_745B_90[] = {
  319         /* 90 nm 1.80GHz Pentium M, VID #B */
  320         FREQ_INFO(1800, 1324, INTEL_BUS_CLK),
  321         FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
  322         FREQ_INFO(1400, 1212, 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_745C_90[] = {
  330         /* 90 nm 1.80GHz Pentium M, VID #C */
  331         FREQ_INFO(1800, 1308, INTEL_BUS_CLK),
  332         FREQ_INFO(1600, 1260, INTEL_BUS_CLK),
  333         FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
  334         FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
  335         FREQ_INFO(1000, 1100, 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_745D_90[] = {
  341         /* 90 nm 1.80GHz Pentium M, VID #D */
  342         FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
  343         FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
  344         FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
  345         FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
  346         FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
  347         FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
  348         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  349         FREQ_INFO(   0,    0, 1),
  350 };
  351 static freq_info PM_735A_90[] = {
  352         /* 90 nm 1.70GHz Pentium M, VID #A */
  353         FREQ_INFO(1700, 1340, INTEL_BUS_CLK),
  354         FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
  355         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  356         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  357         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  358         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  359         FREQ_INFO(   0,    0, 1),
  360 };
  361 static freq_info PM_735B_90[] = {
  362         /* 90 nm 1.70GHz Pentium M, VID #B */
  363         FREQ_INFO(1700, 1324, INTEL_BUS_CLK),
  364         FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
  365         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  366         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  367         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  368         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  369         FREQ_INFO(   0,    0, 1),
  370 };
  371 static freq_info PM_735C_90[] = {
  372         /* 90 nm 1.70GHz Pentium M, VID #C */
  373         FREQ_INFO(1700, 1308, INTEL_BUS_CLK),
  374         FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
  375         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  376         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  377         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  378         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  379         FREQ_INFO(   0,    0, 1),
  380 };
  381 static freq_info PM_735D_90[] = {
  382         /* 90 nm 1.70GHz Pentium M, VID #D */
  383         FREQ_INFO(1700, 1276, INTEL_BUS_CLK),
  384         FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
  385         FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
  386         FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
  387         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  388         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  389         FREQ_INFO(   0,    0, 1),
  390 };
  391 static freq_info PM_725A_90[] = {
  392         /* 90 nm 1.60GHz Pentium M, VID #A */
  393         FREQ_INFO(1600, 1340, INTEL_BUS_CLK),
  394         FREQ_INFO(1400, 1276, INTEL_BUS_CLK),
  395         FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
  396         FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
  397         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  398         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  399         FREQ_INFO(   0,    0, 1),
  400 };
  401 static freq_info PM_725B_90[] = {
  402         /* 90 nm 1.60GHz Pentium M, VID #B */
  403         FREQ_INFO(1600, 1324, INTEL_BUS_CLK),
  404         FREQ_INFO(1400, 1260, INTEL_BUS_CLK),
  405         FREQ_INFO(1200, 1196, INTEL_BUS_CLK),
  406         FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
  407         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  408         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  409         FREQ_INFO(   0,    0, 1),
  410 };
  411 static freq_info PM_725C_90[] = {
  412         /* 90 nm 1.60GHz Pentium M, VID #C */
  413         FREQ_INFO(1600, 1308, INTEL_BUS_CLK),
  414         FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
  415         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  416         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  417         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  418         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  419         FREQ_INFO(   0,    0, 1),
  420 };
  421 static freq_info PM_725D_90[] = {
  422         /* 90 nm 1.60GHz Pentium M, VID #D */
  423         FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
  424         FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
  425         FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
  426         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  427         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  428         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  429         FREQ_INFO(   0,    0, 1),
  430 };
  431 static freq_info PM_715A_90[] = {
  432         /* 90 nm 1.50GHz Pentium M, VID #A */
  433         FREQ_INFO(1500, 1340, INTEL_BUS_CLK),
  434         FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
  435         FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
  436         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  437         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  438         FREQ_INFO(   0,    0, 1),
  439 };
  440 static freq_info PM_715B_90[] = {
  441         /* 90 nm 1.50GHz Pentium M, VID #B */
  442         FREQ_INFO(1500, 1324, INTEL_BUS_CLK),
  443         FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
  444         FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
  445         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  446         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  447         FREQ_INFO(   0,    0, 1),
  448 };
  449 static freq_info PM_715C_90[] = {
  450         /* 90 nm 1.50GHz Pentium M, VID #C */
  451         FREQ_INFO(1500, 1308, INTEL_BUS_CLK),
  452         FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
  453         FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
  454         FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
  455         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  456         FREQ_INFO(   0,    0, 1),
  457 };
  458 static freq_info PM_715D_90[] = {
  459         /* 90 nm 1.50GHz Pentium M, VID #D */
  460         FREQ_INFO(1500, 1276, INTEL_BUS_CLK),
  461         FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
  462         FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
  463         FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
  464         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  465         FREQ_INFO(   0,    0, 1),
  466 };
  467 static freq_info PM_738_90[] = {
  468         /* 90 nm 1.40GHz Low Voltage Pentium M */
  469         FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
  470         FREQ_INFO(1300, 1116, INTEL_BUS_CLK),
  471         FREQ_INFO(1200, 1100, INTEL_BUS_CLK),
  472         FREQ_INFO(1100, 1068, INTEL_BUS_CLK),
  473         FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
  474         FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
  475         FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
  476         FREQ_INFO( 600,  988, INTEL_BUS_CLK),
  477         FREQ_INFO(   0,    0, 1),
  478 };
  479 static freq_info PM_733_90[] = {
  480         /* 90 nm 1.10GHz Ultra Low Voltage Pentium M */
  481         FREQ_INFO(1100,  940, INTEL_BUS_CLK),
  482         FREQ_INFO(1000,  924, INTEL_BUS_CLK),
  483         FREQ_INFO( 900,  892, INTEL_BUS_CLK),
  484         FREQ_INFO( 800,  876, INTEL_BUS_CLK),
  485         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  486         FREQ_INFO(   0,    0, 1),
  487 };
  488 static freq_info PM_723_90[] = {
  489         /* 90 nm 1.00GHz Ultra Low Voltage Pentium M */
  490         FREQ_INFO(1000,  940, INTEL_BUS_CLK),
  491         FREQ_INFO( 900,  908, INTEL_BUS_CLK),
  492         FREQ_INFO( 800,  876, INTEL_BUS_CLK),
  493         FREQ_INFO( 600,  812, INTEL_BUS_CLK),
  494         FREQ_INFO(   0,    0, 1),
  495 };
  496 
  497 static cpu_info ESTprocs[] = {
  498         INTEL(PM17_130,         1700, 1484, 600, 956, INTEL_BUS_CLK),
  499         INTEL(PM16_130,         1600, 1484, 600, 956, INTEL_BUS_CLK),
  500         INTEL(PM15_130,         1500, 1484, 600, 956, INTEL_BUS_CLK),
  501         INTEL(PM14_130,         1400, 1484, 600, 956, INTEL_BUS_CLK),
  502         INTEL(PM13_130,         1300, 1388, 600, 956, INTEL_BUS_CLK),
  503         INTEL(PM13_LV_130,      1300, 1180, 600, 956, INTEL_BUS_CLK),
  504         INTEL(PM12_LV_130,      1200, 1180, 600, 956, INTEL_BUS_CLK),
  505         INTEL(PM11_LV_130,      1100, 1180, 600, 956, INTEL_BUS_CLK),
  506         INTEL(PM11_ULV_130,     1100, 1004, 600, 844, INTEL_BUS_CLK),
  507         INTEL(PM10_ULV_130,     1000, 1004, 600, 844, INTEL_BUS_CLK),
  508         INTEL(PM_765A_90,       2100, 1340, 600, 988, INTEL_BUS_CLK),
  509         INTEL(PM_765B_90,       2100, 1324, 600, 988, INTEL_BUS_CLK),
  510         INTEL(PM_765C_90,       2100, 1308, 600, 988, INTEL_BUS_CLK),
  511         INTEL(PM_765E_90,       2100, 1356, 600, 988, INTEL_BUS_CLK),
  512         INTEL(PM_755A_90,       2000, 1340, 600, 988, INTEL_BUS_CLK),
  513         INTEL(PM_755B_90,       2000, 1324, 600, 988, INTEL_BUS_CLK),
  514         INTEL(PM_755C_90,       2000, 1308, 600, 988, INTEL_BUS_CLK),
  515         INTEL(PM_755D_90,       2000, 1276, 600, 988, INTEL_BUS_CLK),
  516         INTEL(PM_745A_90,       1800, 1340, 600, 988, INTEL_BUS_CLK),
  517         INTEL(PM_745B_90,       1800, 1324, 600, 988, INTEL_BUS_CLK),
  518         INTEL(PM_745C_90,       1800, 1308, 600, 988, INTEL_BUS_CLK),
  519         INTEL(PM_745D_90,       1800, 1276, 600, 988, INTEL_BUS_CLK),
  520         INTEL(PM_735A_90,       1700, 1340, 600, 988, INTEL_BUS_CLK),
  521         INTEL(PM_735B_90,       1700, 1324, 600, 988, INTEL_BUS_CLK),
  522         INTEL(PM_735C_90,       1700, 1308, 600, 988, INTEL_BUS_CLK),
  523         INTEL(PM_735D_90,       1700, 1276, 600, 988, INTEL_BUS_CLK),
  524         INTEL(PM_725A_90,       1600, 1340, 600, 988, INTEL_BUS_CLK),
  525         INTEL(PM_725B_90,       1600, 1324, 600, 988, INTEL_BUS_CLK),
  526         INTEL(PM_725C_90,       1600, 1308, 600, 988, INTEL_BUS_CLK),
  527         INTEL(PM_725D_90,       1600, 1276, 600, 988, INTEL_BUS_CLK),
  528         INTEL(PM_715A_90,       1500, 1340, 600, 988, INTEL_BUS_CLK),
  529         INTEL(PM_715B_90,       1500, 1324, 600, 988, INTEL_BUS_CLK),
  530         INTEL(PM_715C_90,       1500, 1308, 600, 988, INTEL_BUS_CLK),
  531         INTEL(PM_715D_90,       1500, 1276, 600, 988, INTEL_BUS_CLK),
  532         INTEL(PM_738_90,        1400, 1116, 600, 988, INTEL_BUS_CLK),
  533         INTEL(PM_733_90,        1100,  940, 600, 812, INTEL_BUS_CLK),
  534         INTEL(PM_723_90,        1000,  940, 600, 812, INTEL_BUS_CLK),
  535         { NULL, 0, 0, NULL },
  536 };
  537 
  538 static void     est_identify(driver_t *driver, device_t parent);
  539 static int      est_features(driver_t *driver, u_int *features);
  540 static int      est_probe(device_t parent);
  541 static int      est_attach(device_t parent);
  542 static int      est_detach(device_t parent);
  543 static int      est_get_info(device_t dev);
  544 static int      est_acpi_info(device_t dev, freq_info **freqs);
  545 static int      est_table_info(device_t dev, uint64_t msr, uint32_t bus_clk,
  546                     freq_info **freqs);
  547 static freq_info *est_get_current(freq_info *freq_list);
  548 static int      est_settings(device_t dev, struct cf_setting *sets, int *count);
  549 static int      est_set(device_t dev, const struct cf_setting *set);
  550 static int      est_get(device_t dev, struct cf_setting *set);
  551 static int      est_type(device_t dev, int *type);
  552 
  553 static device_method_t est_methods[] = {
  554         /* Device interface */
  555         DEVMETHOD(device_identify,      est_identify),
  556         DEVMETHOD(device_probe,         est_probe),
  557         DEVMETHOD(device_attach,        est_attach),
  558         DEVMETHOD(device_detach,        est_detach),
  559 
  560         /* cpufreq interface */
  561         DEVMETHOD(cpufreq_drv_set,      est_set),
  562         DEVMETHOD(cpufreq_drv_get,      est_get),
  563         DEVMETHOD(cpufreq_drv_type,     est_type),
  564         DEVMETHOD(cpufreq_drv_settings, est_settings),
  565 
  566         /* ACPI interface */
  567         DEVMETHOD(acpi_get_features,    est_features),
  568 
  569         {0, 0}
  570 };
  571 
  572 static driver_t est_driver = {
  573         "est",
  574         est_methods,
  575         sizeof(struct est_softc),
  576 };
  577 
  578 static devclass_t est_devclass;
  579 DRIVER_MODULE(est, cpu, est_driver, est_devclass, 0, 0);
  580 
  581 static int
  582 est_features(driver_t *driver, u_int *features)
  583 {
  584 
  585         /* Notify the ACPI CPU that we support direct access to MSRs */
  586         *features = ACPI_CAP_PERF_MSRS;
  587         return (0);
  588 }
  589 
  590 static void
  591 est_identify(driver_t *driver, device_t parent)
  592 {
  593         device_t child;
  594         u_int p[4];
  595 
  596         /* Make sure we're not being doubly invoked. */
  597         if (device_find_child(parent, "est", -1) != NULL)
  598                 return;
  599 
  600         /* Check that CPUID is supported and the vendor is Intel.*/
  601         if (cpu_high == 0 || strcmp(cpu_vendor, GenuineIntel) != 0)
  602                 return;
  603 
  604         /* Read capability bits and check if the CPU supports EST. */
  605         do_cpuid(1, p);
  606         if ((p[2] & 0x80) == 0)
  607                 return;
  608 
  609         /*
  610          * We add a child for each CPU since settings must be performed
  611          * on each CPU in the SMP case.
  612          */
  613         child = BUS_ADD_CHILD(parent, 0, "est", -1);
  614         if (child == NULL)
  615                 device_printf(parent, "add est child failed\n");
  616 }
  617 
  618 static int
  619 est_probe(device_t dev)
  620 {
  621         device_t perf_dev;
  622         uint64_t msr;
  623         int error, type;
  624         
  625         if (resource_disabled("est", 0))
  626                 return (ENXIO);
  627 
  628         /*
  629          * If the ACPI perf driver has attached and is not just offering
  630          * info, let it manage things.
  631          */
  632         perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
  633         if (perf_dev && device_is_attached(perf_dev)) {
  634                 error = CPUFREQ_DRV_TYPE(perf_dev, &type);
  635                 if (error == 0 && (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
  636                         return (ENXIO);
  637         }
  638 
  639         /* Attempt to enable SpeedStep if not currently enabled. */
  640         msr = rdmsr(MSR_MISC_ENABLE);
  641         if ((msr & MSR_SS_ENABLE) == 0) {
  642                 wrmsr(MSR_MISC_ENABLE, msr | MSR_SS_ENABLE);
  643                 if (bootverbose)
  644                         device_printf(dev, "enabling SpeedStep\n");
  645 
  646                 /* Check if the enable failed. */
  647                 msr = rdmsr(MSR_MISC_ENABLE);
  648                 if ((msr & MSR_SS_ENABLE) == 0) {
  649                         device_printf(dev, "failed to enable SpeedStep\n");
  650                         return (ENXIO);
  651                 }
  652         }
  653 
  654         device_set_desc(dev, "Enhanced SpeedStep Frequency Control");
  655         return (0);
  656 }
  657 
  658 static int
  659 est_attach(device_t dev)
  660 {
  661         struct est_softc *sc;
  662 
  663         sc = device_get_softc(dev);
  664         sc->dev = dev;
  665 
  666         /* Check CPU for supported settings. */
  667         if (est_get_info(dev))
  668                 return (ENXIO);
  669 
  670         cpufreq_register(dev);
  671         return (0);
  672 }
  673 
  674 static int
  675 est_detach(device_t dev)
  676 {
  677         struct est_softc *sc;
  678 
  679         sc = device_get_softc(dev);
  680         if (sc->acpi_settings)
  681                 free(sc->freq_list, M_DEVBUF);
  682         return (ENXIO);
  683 }
  684 
  685 /*
  686  * Probe for supported CPU settings.  First, check our static table of
  687  * settings.  If no match, try using the ones offered by acpi_perf
  688  * (i.e., _PSS).  We use ACPI second because some systems (IBM R/T40
  689  * series) export both legacy SMM IO-based access and direct MSR access
  690  * but the direct access specifies invalid values for _PSS.
  691  */
  692 static int
  693 est_get_info(device_t dev)
  694 {
  695         struct est_softc *sc;
  696         uint64_t msr;
  697         int error;
  698 
  699         sc = device_get_softc(dev);
  700         msr = rdmsr(MSR_PERF_STATUS);
  701         error = est_table_info(dev, msr, INTEL_BUS_CLK, &sc->freq_list);
  702         if (error)
  703                 error = est_acpi_info(dev, &sc->freq_list);
  704 
  705         if (error) {
  706                 printf(
  707         "est: CPU supports Enhanced Speedstep, but is not recognized.\n"
  708         "est: Please update driver or contact the maintainer.\n"
  709         "est: cpu_vendor %s, msr %0jx, bus_clk, %x\n",
  710                     cpu_vendor, msr, INTEL_BUS_CLK);
  711                 return (ENXIO);
  712         }
  713 
  714         return (0);
  715 }
  716 
  717 static int
  718 est_acpi_info(device_t dev, freq_info **freqs)
  719 {
  720         struct est_softc *sc;
  721         struct cf_setting *sets;
  722         freq_info *table;
  723         device_t perf_dev;
  724         int count, error, i;
  725 
  726         perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
  727         if (perf_dev == NULL || !device_is_attached(perf_dev))
  728                 return (ENXIO);
  729 
  730         /* Fetch settings from acpi_perf. */
  731         sc = device_get_softc(dev);
  732         table = NULL;
  733         sets = malloc(MAX_SETTINGS * sizeof(*sets), M_TEMP, M_NOWAIT);
  734         if (sets == NULL)
  735                 return (ENOMEM);
  736         error = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
  737         if (error)
  738                 goto out;
  739 
  740         /* Parse settings into our local table format. */
  741         table = malloc((count + 1) * sizeof(freq_info), M_DEVBUF, M_NOWAIT);
  742         if (table == NULL) {
  743                 error = ENOMEM;
  744                 goto out;
  745         }
  746         for (i = 0; i < count; i++) {
  747                 /*
  748                  * TODO: Figure out validity checks for id16.  Linux checks
  749                  * that the control and status values match.
  750                  */
  751                 table[i].freq = sets[i].freq;
  752                 table[i].volts = sets[i].volts;
  753                 table[i].id16 = sets[i].spec[0];
  754                 table[i].power = sets[i].power;
  755         }
  756 
  757         /* Mark end of table with a terminator. */
  758         bzero(&table[i], sizeof(freq_info));
  759 
  760         sc->acpi_settings = TRUE;
  761         *freqs = table;
  762         error = 0;
  763 
  764 out:
  765         if (sets)
  766                 free(sets, M_TEMP);
  767         if (error && table)
  768                 free(table, M_DEVBUF);
  769         return (error);
  770 }
  771 
  772 static int
  773 est_table_info(device_t dev, uint64_t msr, uint32_t bus_clk, freq_info **freqs)
  774 {
  775         cpu_info *p;
  776         uint32_t id;
  777 
  778         /* Find a table which matches (vendor, id, bus_clk). */
  779         id = msr >> 32;
  780         for (p = ESTprocs; p->id32 != 0; p++) {
  781                 if (strcmp(p->vendor, cpu_vendor) == 0 && p->id32 == id &&
  782                     p->bus_clk == bus_clk)
  783                         break;
  784         }
  785         if (p->id32 == 0)
  786                 return (EOPNOTSUPP);
  787 
  788         /* Make sure the current setpoint is valid. */
  789         if (est_get_current(p->freqtab) == NULL) {
  790                 device_printf(dev, "current setting not found in table\n");
  791                 return (EOPNOTSUPP);
  792         }
  793 
  794         *freqs = p->freqtab;
  795         return (0);
  796 }
  797 
  798 static freq_info *
  799 est_get_current(freq_info *freq_list)
  800 {
  801         freq_info *f;
  802         int i;
  803         uint16_t id16;
  804 
  805         /*
  806          * Try a few times to get a valid value.  Sometimes, if the CPU
  807          * is in the middle of an asynchronous transition (i.e., P4TCC),
  808          * we get a temporary invalid result.
  809          */
  810         for (i = 0; i < 5; i++) {
  811                 id16 = rdmsr(MSR_PERF_STATUS) & 0xffff;
  812                 for (f = freq_list; f->id16 != 0; f++) {
  813                         if (f->id16 == id16)
  814                                 return (f);
  815                 }
  816                 DELAY(100);
  817         }
  818         return (NULL);
  819 }
  820 
  821 static int
  822 est_settings(device_t dev, struct cf_setting *sets, int *count)
  823 {
  824         struct est_softc *sc;
  825         freq_info *f;
  826         int i;
  827 
  828         sc = device_get_softc(dev);
  829         if (*count < EST_MAX_SETTINGS)
  830                 return (E2BIG);
  831 
  832         i = 0;
  833         for (f = sc->freq_list; f->freq != 0; f++, i++) {
  834                 sets[i].freq = f->freq;
  835                 sets[i].volts = f->volts;
  836                 sets[i].power = f->power;
  837                 sets[i].lat = EST_TRANS_LAT;
  838                 sets[i].dev = dev;
  839         }
  840         *count = i;
  841 
  842         return (0);
  843 }
  844 
  845 static int
  846 est_set(device_t dev, const struct cf_setting *set)
  847 {
  848         struct est_softc *sc;
  849         freq_info *f;
  850         uint64_t msr;
  851 
  852         /* Find the setting matching the requested one. */
  853         sc = device_get_softc(dev);
  854         for (f = sc->freq_list; f->freq != 0; f++) {
  855                 if (f->freq == set->freq)
  856                         break;
  857         }
  858         if (f->freq == 0)
  859                 return (EINVAL);
  860 
  861         /* Read the current register, mask out the old, set the new id. */
  862         msr = rdmsr(MSR_PERF_CTL);
  863         msr = (msr & ~0xffff) | f->id16;
  864         wrmsr(MSR_PERF_CTL, msr);
  865 
  866         /* Wait a short while for the new setting.  XXX Is this necessary? */
  867         DELAY(EST_TRANS_LAT);
  868 
  869         return (0);
  870 }
  871 
  872 static int
  873 est_get(device_t dev, struct cf_setting *set)
  874 {
  875         struct est_softc *sc;
  876         freq_info *f;
  877 
  878         sc = device_get_softc(dev);
  879         f = est_get_current(sc->freq_list);
  880         if (f == NULL)
  881                 return (ENXIO);
  882 
  883         set->freq = f->freq;
  884         set->volts = f->volts;
  885         set->power = f->power;
  886         set->lat = EST_TRANS_LAT;
  887         set->dev = dev;
  888         return (0);
  889 }
  890 
  891 static int
  892 est_type(device_t dev, int *type)
  893 {
  894 
  895         if (type == NULL)
  896                 return (EINVAL);
  897 
  898         *type = CPUFREQ_TYPE_ABSOLUTE;
  899         return (0);
  900 }

Cache object: 9573ebe21d1c84e4e7301f127a3b1d94


[ 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.