// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2009-2010 Intel Corporation
*
* Authors:
* Jesse Barnes <jbarnes@virtuousgeek.org>
*/
/*
* Some Intel Ibex Peak based platforms support so-called "intelligent
* power sharing", which allows the CPU and GPU to cooperate to maximize
* performance within a given TDP (thermal design point). This driver
* performs the coordination between the CPU and GPU, monitors thermal and
* power statistics in the platform, and initializes power monitoring
* hardware. It also provides a few tunables to control behavior. Its
* primary purpose is to safely allow CPU and GPU turbo modes to be enabled
* by tracking power and thermal budget; secondarily it can boost turbo
* performance by allocating more power or thermal budget to the CPU or GPU
* based on available headroom and activity.
*
* The basic algorithm is driven by a 5s moving average of temperature. If
* thermal headroom is available, the CPU and/or GPU power clamps may be
* adjusted upwards. If we hit the thermal ceiling or a thermal trigger,
* we scale back the clamp. Aside from trigger events (when we're critically
* close or over our TDP) we don't adjust the clamps more than once every
* five seconds.
*
* The thermal device (device 31, function 6) has a set of registers that
* are updated by the ME firmware. The ME should also take the clamp values
* written to those registers and write them to the CPU, but we currently
* bypass that functionality and write the CPU MSR directly.
*
* UNSUPPORTED:
* - dual MCP configs
*
* TODO:
* - handle CPU hotplug
* - provide turbo enable/disable api
*
* Related documents:
* - CDI 403777, 403778 - Auburndale EDS vol 1 & 2
* - CDI 401376 - Ibex Peak EDS
* - ref 26037, 26641 - IPS BIOS spec
* - ref 26489 - Nehalem BIOS writer's guide
* - ref 26921 - Ibex Peak BIOS Specification
*/
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/sched/loadavg.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/tick.h>
#include <linux/timer.h>
#include <linux/dmi.h>
#include <drm/i915_drm.h>
#include <asm/msr.h>
#include <asm/processor.h>
#include "intel_ips.h"
#include <linux/io-64-nonatomic-lo-hi.h>
#define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
/*
* Package level MSRs for monitor/control
*/
#define PLATFORM_INFO 0xce
#define PLATFORM_TDP (1<<29)
#define PLATFORM_RATIO (1<<28)
#define IA32_MISC_ENABLE 0x1a0
#define IA32_MISC_TURBO_EN (1ULL<<38)
#define TURBO_POWER_CURRENT_LIMIT 0x1ac
#define TURBO_TDC_OVR_EN (1UL<<31)
#define TURBO_TDC_MASK (0x000000007fff0000UL)
#define TURBO_TDC_SHIFT (16)
#define TURBO_TDP_OVR_EN (1UL<<15)
#define TURBO_TDP_MASK (0x0000000000003fffUL)
/*
* Core/thread MSRs for monitoring
*/
#define IA32_PERF_CTL 0x199
#define IA32_PERF_TURBO_DIS (1ULL<<32)
/*
* Thermal PCI device regs
*/
#define THM_CFG_TBAR 0x10
#define THM_CFG_TBAR_HI 0x14
#define THM_TSIU 0x00
#define THM_TSE 0x01
#define TSE_EN 0xb8
#define THM_TSS 0x02
#define THM_TSTR 0x03
#define THM_TSTTP 0x04
#define THM_TSCO 0x08
#define THM_TSES 0x0c
#define THM_TSGPEN 0x0d
#define TSGPEN_HOT_LOHI (1<<1)
#define TSGPEN_CRIT_LOHI (1<<2)
#define THM_TSPC 0x0e
#define THM_PPEC 0x10
#define THM_CTA 0x12
#define THM_PTA 0x14
#define PTA_SLOPE_MASK (0xff00)
#define PTA_SLOPE_SHIFT 8
#define PTA_OFFSET_MASK (0x00ff)
#define THM_MGTA 0x16
#define MGTA_SLOPE_MASK (0xff00)
#define MGTA_SLOPE_SHIFT 8
#define MGTA_OFFSET_MASK (0x00ff)
#define THM_TRC 0x1a
#define TRC_CORE2_EN (1<<15)
#define TRC_THM_EN (1<<12)
#define TRC_C6_WAR (1<<8)
#define TRC_CORE1_EN (1<<7)
#define TRC_CORE_PWR (1<<6)
#define TRC_PCH_EN (1<<5)
#define TRC_MCH_EN (1<<4)
#define TRC_DIMM4 (1<<3)
#define TRC_DIMM3 (1<<2)
#define TRC_DIMM2 (1<&l
|