p4tcc.c revision 250487
12175Sjp161948/*-
22175Sjp161948 * Copyright (c) 2005 Nate Lawson
32175Sjp161948 * All rights reserved.
42175Sjp161948 *
52175Sjp161948 * Redistribution and use in source and binary forms, with or without
62175Sjp161948 * modification, are permitted provided that the following conditions
72175Sjp161948 * are met:
82175Sjp161948 * 1. Redistributions of source code must retain the above copyright
92175Sjp161948 *    notice, this list of conditions and the following disclaimer.
102175Sjp161948 * 2. Redistributions in binary form must reproduce the above copyright
112175Sjp161948 *    notice, this list of conditions and the following disclaimer in the
122175Sjp161948 *    documentation and/or other materials provided with the distribution.
132175Sjp161948 *
142175Sjp161948 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
152175Sjp161948 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
162175Sjp161948 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
172175Sjp161948 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
182175Sjp161948 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
192175Sjp161948 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
202175Sjp161948 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
212175Sjp161948 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
222175Sjp161948 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232175Sjp161948 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242175Sjp161948 * SUCH DAMAGE.
252175Sjp161948 */
262175Sjp161948
272175Sjp161948/*
282175Sjp161948 * Throttle clock frequency by using the thermal control circuit.  This
292175Sjp161948 * operates independently of SpeedStep and ACPI throttling and is supported
302175Sjp161948 * on Pentium 4 and later models (feature TM).
312175Sjp161948 *
322175Sjp161948 * Reference:  Intel Developer's manual v.3 #245472-012
332175Sjp161948 *
342175Sjp161948 * The original version of this driver was written by Ted Unangst for
352175Sjp161948 * OpenBSD and imported by Maxim Sobolev.  It was rewritten by Nate Lawson
362175Sjp161948 * for use with the cpufreq framework.
372175Sjp161948 */
382175Sjp161948
392175Sjp161948#include <sys/cdefs.h>
402175Sjp161948__FBSDID("$FreeBSD: head/sys/x86/cpufreq/p4tcc.c 250487 2013-05-10 22:43:27Z hiren $");
412175Sjp161948
422175Sjp161948#include <sys/param.h>
432175Sjp161948#include <sys/systm.h>
442175Sjp161948#include <sys/bus.h>
452175Sjp161948#include <sys/cpu.h>
462175Sjp161948#include <sys/kernel.h>
472175Sjp161948#include <sys/module.h>
482175Sjp161948
492175Sjp161948#include <machine/md_var.h>
502175Sjp161948#include <machine/specialreg.h>
512175Sjp161948
522175Sjp161948#include "cpufreq_if.h"
532175Sjp161948
542175Sjp161948#include <contrib/dev/acpica/include/acpi.h>
552175Sjp161948
562175Sjp161948#include <dev/acpica/acpivar.h>
572175Sjp161948#include "acpi_if.h"
582175Sjp161948
592175Sjp161948struct p4tcc_softc {
602175Sjp161948	device_t	dev;
612175Sjp161948	int		set_count;
622175Sjp161948	int		lowest_val;
632175Sjp161948	int		auto_mode;
642175Sjp161948};
652175Sjp161948
662175Sjp161948#define TCC_NUM_SETTINGS	8
672175Sjp161948
682175Sjp161948#define TCC_ENABLE_ONDEMAND	(1<<4)
692175Sjp161948#define TCC_REG_OFFSET		1
702175Sjp161948#define TCC_SPEED_PERCENT(x)	((10000 * (x)) / TCC_NUM_SETTINGS)
712175Sjp161948
722175Sjp161948static int	p4tcc_features(driver_t *driver, u_int *features);
732175Sjp161948static void	p4tcc_identify(driver_t *driver, device_t parent);
742175Sjp161948static int	p4tcc_probe(device_t dev);
752175Sjp161948static int	p4tcc_attach(device_t dev);
762175Sjp161948static int	p4tcc_detach(device_t dev);
772175Sjp161948static int	p4tcc_settings(device_t dev, struct cf_setting *sets,
782175Sjp161948		    int *count);
792175Sjp161948static int	p4tcc_set(device_t dev, const struct cf_setting *set);
802175Sjp161948static int	p4tcc_get(device_t dev, struct cf_setting *set);
812175Sjp161948static int	p4tcc_type(device_t dev, int *type);
822175Sjp161948
832175Sjp161948static device_method_t p4tcc_methods[] = {
842175Sjp161948	/* Device interface */
852175Sjp161948	DEVMETHOD(device_identify,	p4tcc_identify),
862175Sjp161948	DEVMETHOD(device_probe,		p4tcc_probe),
872175Sjp161948	DEVMETHOD(device_attach,	p4tcc_attach),
882175Sjp161948	DEVMETHOD(device_detach,	p4tcc_detach),
892175Sjp161948
902175Sjp161948	/* cpufreq interface */
912175Sjp161948	DEVMETHOD(cpufreq_drv_set,	p4tcc_set),
922175Sjp161948	DEVMETHOD(cpufreq_drv_get,	p4tcc_get),
932175Sjp161948	DEVMETHOD(cpufreq_drv_type,	p4tcc_type),
942175Sjp161948	DEVMETHOD(cpufreq_drv_settings,	p4tcc_settings),
952175Sjp161948
962175Sjp161948	/* ACPI interface */
972175Sjp161948	DEVMETHOD(acpi_get_features,	p4tcc_features),
982175Sjp161948
992175Sjp161948	{0, 0}
1002175Sjp161948};
1012175Sjp161948
1022175Sjp161948static driver_t p4tcc_driver = {
1032175Sjp161948	"p4tcc",
1042175Sjp161948	p4tcc_methods,
1052175Sjp161948	sizeof(struct p4tcc_softc),
1062175Sjp161948};
1072175Sjp161948
1082175Sjp161948static devclass_t p4tcc_devclass;
1092175Sjp161948DRIVER_MODULE(p4tcc, cpu, p4tcc_driver, p4tcc_devclass, 0, 0);
1102175Sjp161948
1112175Sjp161948static int
1122175Sjp161948p4tcc_features(driver_t *driver, u_int *features)
1132175Sjp161948{
1142175Sjp161948
1152175Sjp161948	/* Notify the ACPI CPU that we support direct access to MSRs */
1162175Sjp161948	*features = ACPI_CAP_THR_MSRS;
1172175Sjp161948	return (0);
1182175Sjp161948}
1192175Sjp161948
1202175Sjp161948static void
1212175Sjp161948p4tcc_identify(driver_t *driver, device_t parent)
1222175Sjp161948{
1232175Sjp161948
1242175Sjp161948	if ((cpu_feature & (CPUID_ACPI | CPUID_TM)) != (CPUID_ACPI | CPUID_TM))
1252175Sjp161948		return;
1262175Sjp161948
1272175Sjp161948	/* Make sure we're not being doubly invoked. */
1282175Sjp161948	if (device_find_child(parent, "p4tcc", -1) != NULL)
1292175Sjp161948		return;
1302175Sjp161948
1312175Sjp161948	/*
1322175Sjp161948	 * We attach a p4tcc child for every CPU since settings need to
1332175Sjp161948	 * be performed on every CPU in the SMP case.  See section 13.15.3
1342175Sjp161948	 * of the IA32 Intel Architecture Software Developer's Manual,
1352175Sjp161948	 * Volume 3, for more info.
1362175Sjp161948	 */
1372175Sjp161948	if (BUS_ADD_CHILD(parent, 10, "p4tcc", -1) == NULL)
1382175Sjp161948		device_printf(parent, "add p4tcc child failed\n");
1392175Sjp161948}
1402175Sjp161948
1412175Sjp161948static int
1422175Sjp161948p4tcc_probe(device_t dev)
1432175Sjp161948{
1442175Sjp161948
1452175Sjp161948	if (resource_disabled("p4tcc", 0))
1462175Sjp161948		return (ENXIO);
1472175Sjp161948
1482175Sjp161948	device_set_desc(dev, "CPU Frequency Thermal Control");
1492175Sjp161948	return (0);
1502175Sjp161948}
1512175Sjp161948
1522175Sjp161948static int
1532175Sjp161948p4tcc_attach(device_t dev)
1542175Sjp161948{
1552175Sjp161948	struct p4tcc_softc *sc;
1562175Sjp161948	struct cf_setting set;
1572175Sjp161948
1582175Sjp161948	sc = device_get_softc(dev);
1592175Sjp161948	sc->dev = dev;
1602175Sjp161948	sc->set_count = TCC_NUM_SETTINGS;
1612175Sjp161948
1622175Sjp161948	/*
1632175Sjp161948	 * On boot, the TCC is usually in Automatic mode where reading the
1642175Sjp161948	 * current performance level is likely to produce bogus results.
1652175Sjp161948	 * We record that state here and don't trust the contents of the
1662175Sjp161948	 * status MSR until we've set it ourselves.
1672175Sjp161948	 */
1682175Sjp161948	sc->auto_mode = TRUE;
1692175Sjp161948
1702175Sjp161948	/*
1712175Sjp161948	 * XXX: After a cursory glance at various Intel specification
1722175Sjp161948	 * XXX: updates it seems like these tests for errata is bogus.
1732175Sjp161948	 * XXX: As far as I can tell, the failure mode is benign, in
1742175Sjp161948	 * XXX: that cpus with no errata will have their bottom two
1752175Sjp161948	 * XXX: STPCLK# rates disabled, so rather than waste more time
1762175Sjp161948	 * XXX: hunting down intel docs, just document it and punt. /phk
1772175Sjp161948	 */
1782175Sjp161948	switch (cpu_id & 0xff) {
1792175Sjp161948	case 0x22:
1802175Sjp161948	case 0x24:
1812175Sjp161948	case 0x25:
1822175Sjp161948	case 0x27:
1832175Sjp161948	case 0x29:
1842175Sjp161948		/*
1852175Sjp161948		 * These CPU models hang when set to 12.5%.
1862175Sjp161948		 * See Errata O50, P44, and Z21.
1872175Sjp161948		 */
1882175Sjp161948		sc->set_count -= 1;
1892175Sjp161948		break;
1902175Sjp161948	case 0x07:	/* errata N44 and P18 */
1912175Sjp161948	case 0x0a:
1922175Sjp161948	case 0x12:
1932175Sjp161948	case 0x13:
1942175Sjp161948	case 0x62:	/* Pentium D B1: errata AA21 */
1952175Sjp161948	case 0x64:	/* Pentium D C1: errata AA21 */
1962175Sjp161948	case 0x65:	/* Pentium D D0: errata AA21 */
1972175Sjp161948		/*
1982175Sjp161948		 * These CPU models hang when set to 12.5% or 25%.
1992175Sjp161948		 * See Errata N44, P18l and AA21.
2002175Sjp161948		 */
2012175Sjp161948		sc->set_count -= 2;
2022175Sjp161948		break;
2032175Sjp161948	}
2042175Sjp161948	sc->lowest_val = TCC_NUM_SETTINGS - sc->set_count + 1;
2052175Sjp161948
2062175Sjp161948	/*
2072175Sjp161948	 * Before we finish attach, switch to 100%.  It's possible the BIOS
2082175Sjp161948	 * set us to a lower rate.  The user can override this after boot.
2092175Sjp161948	 */
2102175Sjp161948	set.freq = 10000;
2112175Sjp161948	p4tcc_set(dev, &set);
2122175Sjp161948
2132175Sjp161948	cpufreq_register(dev);
2142175Sjp161948	return (0);
2152175Sjp161948}
2162175Sjp161948
2172175Sjp161948static int
2182175Sjp161948p4tcc_detach(device_t dev)
2192175Sjp161948{
2202175Sjp161948	struct cf_setting set;
2212175Sjp161948	int error;
2222175Sjp161948
2232175Sjp161948	error = cpufreq_unregister(dev);
2242175Sjp161948	if (error)
2252175Sjp161948		return (error);
2262175Sjp161948
2272175Sjp161948	/*
2282175Sjp161948	 * Before we finish detach, switch to Automatic mode.
2292175Sjp161948	 */
2302175Sjp161948	set.freq = 10000;
2312175Sjp161948	p4tcc_set(dev, &set);
2322175Sjp161948	return(0);
2332175Sjp161948}
2342175Sjp161948
2352175Sjp161948static int
2362175Sjp161948p4tcc_settings(device_t dev, struct cf_setting *sets, int *count)
2372175Sjp161948{
2382175Sjp161948	struct p4tcc_softc *sc;
2392175Sjp161948	int i, val;
2402175Sjp161948
2412175Sjp161948	sc = device_get_softc(dev);
2422175Sjp161948	if (sets == NULL || count == NULL)
2432175Sjp161948		return (EINVAL);
2442175Sjp161948	if (*count < sc->set_count)
2452175Sjp161948		return (E2BIG);
2462175Sjp161948
2472175Sjp161948	/* Return a list of valid settings for this driver. */
2482175Sjp161948	memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * sc->set_count);
2492175Sjp161948	val = TCC_NUM_SETTINGS;
2502175Sjp161948	for (i = 0; i < sc->set_count; i++, val--) {
2512175Sjp161948		sets[i].freq = TCC_SPEED_PERCENT(val);
2522175Sjp161948		sets[i].dev = dev;
2532175Sjp161948	}
2542175Sjp161948	*count = sc->set_count;
2552175Sjp161948
2562175Sjp161948	return (0);
2572175Sjp161948}
2582175Sjp161948
2592175Sjp161948static int
2602175Sjp161948p4tcc_set(device_t dev, const struct cf_setting *set)
2612175Sjp161948{
2622175Sjp161948	struct p4tcc_softc *sc;
2632175Sjp161948	uint64_t mask, msr;
2642175Sjp161948	int val;
2652175Sjp161948
2662175Sjp161948	if (set == NULL)
2672175Sjp161948		return (EINVAL);
2682175Sjp161948	sc = device_get_softc(dev);
2692175Sjp161948
2702175Sjp161948	/*
2712175Sjp161948	 * Validate requested state converts to a setting that is an integer
2722175Sjp161948	 * from [sc->lowest_val .. TCC_NUM_SETTINGS].
2732175Sjp161948	 */
2742175Sjp161948	val = set->freq * TCC_NUM_SETTINGS / 10000;
2752175Sjp161948	if (val * 10000 != set->freq * TCC_NUM_SETTINGS ||
2762175Sjp161948	    val < sc->lowest_val || val > TCC_NUM_SETTINGS)
2772175Sjp161948		return (EINVAL);
2782175Sjp161948
2792175Sjp161948	/*
2802175Sjp161948	 * Read the current register and mask off the old setting and
2812175Sjp161948	 * On-Demand bit.  If the new val is < 100%, set it and the On-Demand
2822175Sjp161948	 * bit, otherwise just return to Automatic mode.
2832175Sjp161948	 */
2842175Sjp161948	msr = rdmsr(MSR_THERM_CONTROL);
2852175Sjp161948	mask = (TCC_NUM_SETTINGS - 1) << TCC_REG_OFFSET;
2862175Sjp161948	msr &= ~(mask | TCC_ENABLE_ONDEMAND);
2872175Sjp161948	if (val < TCC_NUM_SETTINGS)
2882175Sjp161948		msr |= (val << TCC_REG_OFFSET) | TCC_ENABLE_ONDEMAND;
2892175Sjp161948	wrmsr(MSR_THERM_CONTROL, msr);
2902175Sjp161948
2912175Sjp161948	/*
2922175Sjp161948	 * Record whether we're now in Automatic or On-Demand mode.  We have
2932175Sjp161948	 * to cache this since there is no reliable way to check if TCC is in
2942175Sjp161948	 * Automatic mode (i.e., at 100% or possibly 50%).  Reading bit 4 of
2952175Sjp161948	 * the ACPI Thermal Monitor Control Register produces 0 no matter
2962175Sjp161948	 * what the current mode.
2972175Sjp161948	 */
2982175Sjp161948	if (msr & TCC_ENABLE_ONDEMAND)
2992175Sjp161948		sc->auto_mode = FALSE;
3002175Sjp161948	else
3012175Sjp161948		sc->auto_mode = TRUE;
3022175Sjp161948
3032175Sjp161948	return (0);
3042175Sjp161948}
3052175Sjp161948
3062175Sjp161948static int
3072175Sjp161948p4tcc_get(device_t dev, struct cf_setting *set)
3082175Sjp161948{
3092175Sjp161948	struct p4tcc_softc *sc;
3102175Sjp161948	uint64_t msr;
3112175Sjp161948	int val;
3122175Sjp161948
3132175Sjp161948	if (set == NULL)
3142175Sjp161948		return (EINVAL);
3152175Sjp161948	sc = device_get_softc(dev);
3162175Sjp161948
3172175Sjp161948	/*
3182175Sjp161948	 * Read the current register and extract the current setting.  If
3192175Sjp161948	 * in automatic mode, assume we're at TCC_NUM_SETTINGS (100%).
3202175Sjp161948	 *
3212175Sjp161948	 * XXX This is not completely reliable since at high temperatures
3222175Sjp161948	 * the CPU may be automatically throttling to 50% but it's the best
3232175Sjp161948	 * we can do.
3242175Sjp161948	 */
3252175Sjp161948	if (!sc->auto_mode) {
3262175Sjp161948		msr = rdmsr(MSR_THERM_CONTROL);
3272175Sjp161948		val = (msr >> TCC_REG_OFFSET) & (TCC_NUM_SETTINGS - 1);
3282175Sjp161948	} else
3292175Sjp161948		val = TCC_NUM_SETTINGS;
3302175Sjp161948
3312175Sjp161948	memset(set, CPUFREQ_VAL_UNKNOWN, sizeof(*set));
3322175Sjp161948	set->freq = TCC_SPEED_PERCENT(val);
3332175Sjp161948	set->dev = dev;
3342175Sjp161948
3352175Sjp161948	return (0);
3362175Sjp161948}
3372175Sjp161948
3382175Sjp161948static int
3392175Sjp161948p4tcc_type(device_t dev, int *type)
3402175Sjp161948{
3412175Sjp161948
3422175Sjp161948	if (type == NULL)
3432175Sjp161948		return (EINVAL);
3442175Sjp161948
3452175Sjp161948	*type = CPUFREQ_TYPE_RELATIVE;
3462175Sjp161948	return (0);
3472175Sjp161948}
3482175Sjp161948