^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (c) 2003-2012 Advanced Micro Devices, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Maintainer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Andreas Herrmann <herrmann.der.user@googlemail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Based on the powernow-k7.c module written by Dave Jones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * (C) 2003 Dave Jones on behalf of SuSE Labs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * (C) 2004 Dominik Brodowski <linux@brodo.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * (C) 2004 Pavel Machek <pavel@ucw.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Based upon datasheets & sample CPUs kindly provided by AMD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Valuable input gratefully received from Dave Jones, Pavel Machek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Dominik Brodowski, Jacob Shin, and others.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Originally developed by Paul Devriendt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Processor information obtained from Chapter 9 (Power and Thermal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Management) of the "BIOS and Kernel Developer's Guide (BKDG) for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * the AMD Athlon 64 and AMD Opteron Processors" and section "2.x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Power Management" in BKDGs for newer AMD CPU families.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Tables for specific CPUs can be inferred from AMD's processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * power and thermal data sheets, (e.g. 30417.pdf, 30430.pdf, 43375.pdf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/cpumask.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <asm/msr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <asm/cpu_device_id.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <acpi/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define VERSION "version 2.20.00"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "powernow-k8.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* serialize freq changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static DEFINE_MUTEX(fidvid_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static struct cpufreq_driver cpufreq_amd64_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Return a frequency in MHz, given an input fid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static u32 find_freq_from_fid(u32 fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 800 + (fid * 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Return a frequency in KHz, given an input fid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static u32 find_khz_freq_from_fid(u32 fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return 1000 * find_freq_from_fid(fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Return the vco fid for an input fid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Each "low" fid has corresponding "high" fid, and you can get to "low" fids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * only from corresponding high fids. This returns "high" fid corresponding to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * "low" one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static u32 convert_fid_to_vco_fid(u32 fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (fid < HI_FID_TABLE_BOTTOM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return 8 + (2 * fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Return 1 if the pending bit is set. Unless we just instructed the processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * to transition to a new state, seeing this bit set is really bad news.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int pending_bit_stuck(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 lo, hi __always_unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) rdmsr(MSR_FIDVID_STATUS, lo, hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Update the global current fid / vid values from the status msr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Returns 1 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u32 lo, hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u32 i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (i++ > 10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pr_debug("detected change pending stuck\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) rdmsr(MSR_FIDVID_STATUS, lo, hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) } while (lo & MSR_S_LO_CHANGE_PENDING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) data->currvid = hi & MSR_S_HI_CURRENT_VID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) data->currfid = lo & MSR_S_LO_CURRENT_FID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* the isochronous relief time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static void count_off_irt(struct powernow_k8_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) udelay((1 << data->irt) * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* the voltage stabilization time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void count_off_vst(struct powernow_k8_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) udelay(data->vstable * VST_UNITS_20US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* need to init the control msr to a safe value (for each cpu) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static void fidvid_msr_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u32 lo, hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u8 fid, vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) rdmsr(MSR_FIDVID_STATUS, lo, hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) vid = hi & MSR_S_HI_CURRENT_VID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) fid = lo & MSR_S_LO_CURRENT_FID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) lo = fid | (vid << MSR_C_LO_VID_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) hi = MSR_C_HI_STP_GNT_BENIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pr_debug("cpu%d, init lo 0x%x, hi 0x%x\n", smp_processor_id(), lo, hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) wrmsr(MSR_FIDVID_CTL, lo, hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* write the new fid value along with the other control fields to the msr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int write_new_fid(struct powernow_k8_data *data, u32 fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u32 lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 savevid = data->currvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) u32 i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if ((fid & INVALID_FID_MASK) || (data->currvid & INVALID_VID_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) pr_err("internal error - overflow on fid write\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) lo = fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) lo |= (data->currvid << MSR_C_LO_VID_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) lo |= MSR_C_LO_INIT_FID_VID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) pr_debug("writing fid 0x%x, lo 0x%x, hi 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) fid, lo, data->plllock * PLL_LOCK_CONVERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (i++ > 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) pr_err("Hardware error - pending bit very stuck - no further pstate changes possible\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) } while (query_current_values_with_pending_wait(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) count_off_irt(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (savevid != data->currvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) pr_err("vid change on fid trans, old 0x%x, new 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) savevid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (fid != data->currfid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) pr_err("fid trans failed, fid 0x%x, curr 0x%x\n", fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* Write a new vid to the hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static int write_new_vid(struct powernow_k8_data *data, u32 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u32 lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u32 savefid = data->currfid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if ((data->currfid & INVALID_FID_MASK) || (vid & INVALID_VID_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) pr_err("internal error - overflow on vid write\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) lo = data->currfid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) lo |= (vid << MSR_C_LO_VID_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) lo |= MSR_C_LO_INIT_FID_VID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pr_debug("writing vid 0x%x, lo 0x%x, hi 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) vid, lo, STOP_GRANT_5NS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (i++ > 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) pr_err("internal error - pending bit very stuck - no further pstate changes possible\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) } while (query_current_values_with_pending_wait(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (savefid != data->currfid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) pr_err("fid changed on vid trans, old 0x%x new 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) savefid, data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (vid != data->currvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) pr_err("vid trans failed, vid 0x%x, curr 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) vid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * Reduce the vid by the max of step or reqvid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * Decreasing vid codes represent increasing voltages:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of VID_OFF is off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int decrease_vid_code_by_step(struct powernow_k8_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u32 reqvid, u32 step)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if ((data->currvid - reqvid) > step)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) reqvid = data->currvid - step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (write_new_vid(data, reqvid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) count_off_vst(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* Change Opteron/Athlon64 fid and vid, by the 3 phases. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int transition_fid_vid(struct powernow_k8_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u32 reqfid, u32 reqvid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (core_voltage_pre_transition(data, reqvid, reqfid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (core_frequency_transition(data, reqfid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (core_voltage_post_transition(data, reqvid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (query_current_values_with_pending_wait(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if ((reqfid != data->currfid) || (reqvid != data->currvid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) pr_err("failed (cpu%d): req 0x%x 0x%x, curr 0x%x 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) smp_processor_id(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) reqfid, reqvid, data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) pr_debug("transitioned (cpu%d): new fid 0x%x, vid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) smp_processor_id(), data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Phase 1 - core voltage transition ... setup voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int core_voltage_pre_transition(struct powernow_k8_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u32 reqvid, u32 reqfid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) u32 rvosteps = data->rvo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u32 savefid = data->currfid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u32 maxvid, lo __always_unused, rvomult = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) pr_debug("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) smp_processor_id(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) data->currfid, data->currvid, reqvid, data->rvo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if ((savefid < LO_FID_TABLE_TOP) && (reqfid < LO_FID_TABLE_TOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) rvomult = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) rvosteps *= rvomult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) maxvid = 0x1f & (maxvid >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) pr_debug("ph1 maxvid=0x%x\n", maxvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (reqvid < maxvid) /* lower numbers are higher voltages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) reqvid = maxvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) while (data->currvid > reqvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) pr_debug("ph1: curr 0x%x, req vid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) data->currvid, reqvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (decrease_vid_code_by_step(data, reqvid, data->vidmvs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) while ((rvosteps > 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ((rvomult * data->rvo + data->currvid) > reqvid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (data->currvid == maxvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) rvosteps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) pr_debug("ph1: changing vid for rvo, req 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) data->currvid - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (decrease_vid_code_by_step(data, data->currvid-1, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) rvosteps--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (query_current_values_with_pending_wait(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (savefid != data->currfid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) pr_err("ph1 err, currfid changed 0x%x\n", data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) pr_debug("ph1 complete, currfid 0x%x, currvid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* Phase 2 - core frequency transition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) u32 vcoreqfid, vcocurrfid, vcofiddiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) u32 fid_interval, savevid = data->currvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (data->currfid == reqfid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) pr_err("ph2 null fid transition 0x%x\n", data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) pr_debug("ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, reqfid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) smp_processor_id(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) data->currfid, data->currvid, reqfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) vcoreqfid = convert_fid_to_vco_fid(reqfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) vcocurrfid = convert_fid_to_vco_fid(data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) : vcoreqfid - vcocurrfid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if ((reqfid <= LO_FID_TABLE_TOP) && (data->currfid <= LO_FID_TABLE_TOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) vcofiddiff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) while (vcofiddiff > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (reqfid > data->currfid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (data->currfid > LO_FID_TABLE_TOP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (write_new_fid(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) data->currfid + fid_interval))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (write_new_fid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) (data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 2 + convert_fid_to_vco_fid(data->currfid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (write_new_fid(data, data->currfid - fid_interval))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) vcocurrfid = convert_fid_to_vco_fid(data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) : vcoreqfid - vcocurrfid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (write_new_fid(data, reqfid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (query_current_values_with_pending_wait(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (data->currfid != reqfid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) pr_err("ph2: mismatch, failed fid transition, curr 0x%x, req 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) data->currfid, reqfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (savevid != data->currvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) pr_err("ph2: vid changed, save 0x%x, curr 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) savevid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) pr_debug("ph2 complete, currfid 0x%x, currvid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* Phase 3 - core voltage transition flow ... jump to the final vid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static int core_voltage_post_transition(struct powernow_k8_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) u32 reqvid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) u32 savefid = data->currfid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) u32 savereqvid = reqvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pr_debug("ph3 (cpu%d): starting, currfid 0x%x, currvid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) smp_processor_id(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (reqvid != data->currvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (write_new_vid(data, reqvid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (savefid != data->currfid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) pr_err("ph3: bad fid change, save 0x%x, curr 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) savefid, data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (data->currvid != reqvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) pr_err("ph3: failed vid transition\n, req 0x%x, curr 0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) reqvid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (query_current_values_with_pending_wait(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (savereqvid != data->currvid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) pr_debug("ph3 failed, currvid 0x%x\n", data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (savefid != data->currfid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) pr_debug("ph3 failed, currfid changed 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) pr_debug("ph3 complete, currfid 0x%x, currvid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static const struct x86_cpu_id powernow_k8_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* IO based frequency switching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) X86_MATCH_VENDOR_FAM(AMD, 0xf, NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static void check_supported_cpu(void *_rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) u32 eax, ebx, ecx, edx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) int *rc = _rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) *rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) ((eax & CPUID_XMOD) > CPUID_XMOD_REV_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) pr_info("Processor cpuid %x not supported\n", eax);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) pr_info("No frequency change capabilities detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if ((edx & P_STATE_TRANSITION_CAPABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) != P_STATE_TRANSITION_CAPABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) pr_info("Power state transitions not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) *rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) u8 maxvid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) unsigned int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) u8 lastfid = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) for (j = 0; j < data->numps; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (pst[j].vid > LEAST_VID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) pr_err(FW_BUG "vid %d invalid : 0x%x\n", j,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) pst[j].vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (pst[j].vid < data->rvo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* vid + rvo >= 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) pr_err(FW_BUG "0 vid exceeded with pstate %d\n", j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (pst[j].vid < maxvid + data->rvo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* vid + rvo >= maxvid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) pr_err(FW_BUG "maxvid exceeded with pstate %d\n", j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (pst[j].fid > MAX_FID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) pr_err(FW_BUG "maxfid exceeded with pstate %d\n", j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* Only first fid is allowed to be in "low" range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) pr_err(FW_BUG "two low fids - %d : 0x%x\n", j,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) pst[j].fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (pst[j].fid < lastfid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) lastfid = pst[j].fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (lastfid & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pr_err(FW_BUG "lastfid invalid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (lastfid > LO_FID_TABLE_TOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) pr_info(FW_BUG "first fid not from lo freq table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static void invalidate_entry(struct cpufreq_frequency_table *powernow_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) unsigned int entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static void print_basics(struct powernow_k8_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) for (j = 0; j < data->numps; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (data->powernow_table[j].frequency !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) CPUFREQ_ENTRY_INVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) pr_info("fid 0x%x (%d MHz), vid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) data->powernow_table[j].driver_data & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) data->powernow_table[j].frequency/1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) data->powernow_table[j].driver_data >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (data->batps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) pr_info("Only %d pstates on battery\n", data->batps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static int fill_powernow_table(struct powernow_k8_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct pst_s *pst, u8 maxvid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct cpufreq_frequency_table *powernow_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) unsigned int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (data->batps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* use ACPI support to get full speed on mains power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) pr_warn("Only %d pstates usable (use ACPI driver for full range\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) data->batps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) data->numps = data->batps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) for (j = 1; j < data->numps; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (pst[j-1].fid >= pst[j].fid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) pr_err("PST out of sequence\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (data->numps < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) pr_err("no p states to transition\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (check_pst_table(data, pst, maxvid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) powernow_table = kzalloc((sizeof(*powernow_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * (data->numps + 1)), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (!powernow_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for (j = 0; j < data->numps; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) powernow_table[j].driver_data = pst[j].fid; /* lower 8 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) powernow_table[j].driver_data |= (pst[j].vid << 8); /* upper 8 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) freq = find_khz_freq_from_fid(pst[j].fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) powernow_table[j].frequency = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) powernow_table[data->numps].frequency = CPUFREQ_TABLE_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) powernow_table[data->numps].driver_data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (query_current_values_with_pending_wait(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) kfree(powernow_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) pr_debug("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) data->powernow_table = powernow_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (cpumask_first(topology_core_cpumask(data->cpu)) == data->cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) print_basics(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) for (j = 0; j < data->numps; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if ((pst[j].fid == data->currfid) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) (pst[j].vid == data->currvid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) pr_debug("currfid/vid do not match PST, ignoring\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /* Find and validate the PSB/PST table in BIOS. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static int find_psb_table(struct powernow_k8_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct psb_s *psb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) u32 mvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) u8 maxvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) u32 cpst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) u32 thiscpuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) for (i = 0xc0000; i < 0xffff0; i += 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* Scan BIOS looking for the signature. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* It can not be at ffff0 - it is too big. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) psb = phys_to_virt(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) pr_debug("found PSB header at 0x%p\n", psb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) pr_debug("table vers: 0x%x\n", psb->tableversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (psb->tableversion != PSB_VERSION_1_4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) pr_err(FW_BUG "PSB table is not v1.4\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) pr_debug("flags: 0x%x\n", psb->flags1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (psb->flags1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) pr_err(FW_BUG "unknown flags\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) data->vstable = psb->vstable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) pr_debug("voltage stabilization time: %d(*20us)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) data->vstable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) pr_debug("flags2: 0x%x\n", psb->flags2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) data->rvo = psb->flags2 & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) data->irt = ((psb->flags2) >> 2) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) mvs = ((psb->flags2) >> 4) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) data->vidmvs = 1 << mvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) data->batps = ((psb->flags2) >> 6) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) pr_debug("ramp voltage offset: %d\n", data->rvo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) pr_debug("isochronous relief time: %d\n", data->irt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) pr_debug("maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) pr_debug("numpst: 0x%x\n", psb->num_tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) cpst = psb->num_tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if ((psb->cpuid == 0x00000fc0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) (psb->cpuid == 0x00000fe0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) thiscpuid = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if ((thiscpuid == 0x00000fc0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) (thiscpuid == 0x00000fe0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) cpst = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (cpst != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) pr_err(FW_BUG "numpst must be 1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) data->plllock = psb->plllocktime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) pr_debug("plllocktime: 0x%x (units 1us)\n", psb->plllocktime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) pr_debug("maxfid: 0x%x\n", psb->maxfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) pr_debug("maxvid: 0x%x\n", psb->maxvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) maxvid = psb->maxvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) data->numps = psb->numps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) pr_debug("numpstates: 0x%x\n", data->numps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return fill_powernow_table(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) (struct pst_s *)(psb+1), maxvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * If you see this message, complain to BIOS manufacturer. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * he tells you "we do not support Linux" or some similar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * nonsense, remember that Windows 2000 uses the same legacy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * mechanism that the old Linux PSB driver uses. Tell them it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * is broken with Windows 2000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * The reference to the AMD documentation is chapter 9 in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * BIOS and Kernel Developer's Guide, which is available on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * www.amd.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) pr_err(FW_BUG "No PSB or ACPI _PSS objects\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) pr_err("Make sure that your BIOS is up to date and Cool'N'Quiet support is enabled in BIOS setup\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) unsigned int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) u64 control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (!data->acpi_data.state_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) control = data->acpi_data.states[index].control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) data->irt = (control >> IRT_SHIFT) & IRT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) data->rvo = (control >> RVO_SHIFT) & RVO_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) data->exttype = (control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) data->plllock = (control >> PLL_L_SHIFT) & PLL_L_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) data->vidmvs = 1 << ((control >> MVS_SHIFT) & MVS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) data->vstable = (control >> VST_SHIFT) & VST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct cpufreq_frequency_table *powernow_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) int ret_val = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) u64 control, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) pr_debug("register performance failed: bad ACPI data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /* verify the data contained in the ACPI structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (data->acpi_data.state_count <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) pr_debug("No ACPI P-States\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) control = data->acpi_data.control_register.space_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) status = data->acpi_data.status_register.space_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if ((control != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) (status != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) pr_debug("Invalid control/status registers (%llx - %llx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) control, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* fill in data->powernow_table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) powernow_table = kzalloc((sizeof(*powernow_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * (data->acpi_data.state_count + 1)), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (!powernow_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* fill in data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) data->numps = data->acpi_data.state_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) powernow_k8_acpi_pst_values(data, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) ret_val = fill_powernow_table_fidvid(data, powernow_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (ret_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) goto err_out_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) powernow_table[data->acpi_data.state_count].frequency =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) CPUFREQ_TABLE_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) data->powernow_table = powernow_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (cpumask_first(topology_core_cpumask(data->cpu)) == data->cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) print_basics(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* notify BIOS that we exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) acpi_processor_notify_smm(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (!zalloc_cpumask_var(&data->acpi_data.shared_cpu_map, GFP_KERNEL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) pr_err("unable to alloc powernow_k8_data cpumask\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) ret_val = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) goto err_out_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) err_out_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) kfree(powernow_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) acpi_processor_unregister_performance(data->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /* data->acpi_data.state_count informs us at ->exit()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * whether ACPI was used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) data->acpi_data.state_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return ret_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static int fill_powernow_table_fidvid(struct powernow_k8_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct cpufreq_frequency_table *powernow_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) for (i = 0; i < data->acpi_data.state_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) u32 fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) u32 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) u32 freq, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) u64 status, control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (data->exttype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) status = data->acpi_data.states[i].status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) fid = status & EXT_FID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) vid = (status >> VID_SHIFT) & EXT_VID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) control = data->acpi_data.states[i].control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) fid = control & FID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) vid = (control >> VID_SHIFT) & VID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) pr_debug(" %d : fid 0x%x, vid 0x%x\n", i, fid, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) index = fid | (vid<<8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) powernow_table[i].driver_data = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) freq = find_khz_freq_from_fid(fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) powernow_table[i].frequency = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* verify frequency is OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if ((freq > (MAX_FREQ * 1000)) || (freq < (MIN_FREQ * 1000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) pr_debug("invalid freq %u kHz, ignoring\n", freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) invalidate_entry(powernow_table, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /* verify voltage is OK -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * BIOSs are using "off" to indicate invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (vid == VID_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) pr_debug("invalid vid %u, ignoring\n", vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) invalidate_entry(powernow_table, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (freq != (data->acpi_data.states[i].core_frequency * 1000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) pr_info("invalid freq entries %u kHz vs. %u kHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) freq, (unsigned int)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) (data->acpi_data.states[i].core_frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * 1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) invalidate_entry(powernow_table, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (data->acpi_data.state_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) acpi_processor_unregister_performance(data->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) free_cpumask_var(data->acpi_data.shared_cpu_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static int get_transition_latency(struct powernow_k8_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) int max_latency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) for (i = 0; i < data->acpi_data.state_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int cur_latency = data->acpi_data.states[i].transition_latency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) + data->acpi_data.states[i].bus_master_latency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (cur_latency > max_latency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) max_latency = cur_latency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (max_latency == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) pr_err(FW_WARN "Invalid zero transition latency\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) max_latency = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) /* value in usecs, needs to be in nanoseconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return 1000 * max_latency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* Take a frequency, and issue the fid/vid transition command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static int transition_frequency_fidvid(struct powernow_k8_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) unsigned int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) u32 fid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) u32 vid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) struct cpufreq_freqs freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) pr_debug("cpu %d transition to index %u\n", smp_processor_id(), index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* fid/vid correctness check for k8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /* fid are the lower 8 bits of the index we stored into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) * the cpufreq frequency table in find_psb_table, vid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * are the upper 8 bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) fid = data->powernow_table[index].driver_data & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) vid = (data->powernow_table[index].driver_data & 0xFF00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) pr_debug("table matched fid 0x%x, giving vid 0x%x\n", fid, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (query_current_values_with_pending_wait(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if ((data->currvid == vid) && (data->currfid == fid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) pr_debug("target matches current values (fid 0x%x, vid 0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) fid, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) pr_debug("cpu %d, changing to fid 0x%x, vid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) smp_processor_id(), fid, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) freqs.old = find_khz_freq_from_fid(data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) freqs.new = find_khz_freq_from_fid(fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) cpufreq_freq_transition_begin(policy, &freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) res = transition_fid_vid(data, fid, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) cpufreq_freq_transition_end(policy, &freqs, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct powernowk8_target_arg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct cpufreq_policy *pol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) unsigned newstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) static long powernowk8_target_fn(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct powernowk8_target_arg *pta = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) struct cpufreq_policy *pol = pta->pol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) unsigned newstate = pta->newstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) u32 checkfid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u32 checkvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) checkfid = data->currfid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) checkvid = data->currvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (pending_bit_stuck()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) pr_err("failing targ, change pending bit set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) pr_debug("targ: cpu %d, %d kHz, min %d, max %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) pol->cpu, data->powernow_table[newstate].frequency, pol->min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) pol->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (query_current_values_with_pending_wait(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) pr_debug("targ: curr fid 0x%x, vid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if ((checkvid != data->currvid) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) (checkfid != data->currfid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) pr_info("error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) checkfid, data->currfid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) checkvid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) mutex_lock(&fidvid_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) powernow_k8_acpi_pst_values(data, newstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) ret = transition_frequency_fidvid(data, newstate, pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) pr_err("transition frequency failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) mutex_unlock(&fidvid_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) mutex_unlock(&fidvid_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) pol->cur = find_khz_freq_from_fid(data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /* Driver entry point to switch to the target frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static int powernowk8_target(struct cpufreq_policy *pol, unsigned index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) struct powernowk8_target_arg pta = { .pol = pol, .newstate = index };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct init_on_cpu {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) struct powernow_k8_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) static void powernowk8_cpu_init_on_cpu(void *_init_on_cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) struct init_on_cpu *init_on_cpu = _init_on_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (pending_bit_stuck()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) pr_err("failing init, change pending bit set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) init_on_cpu->rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (query_current_values_with_pending_wait(init_on_cpu->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) init_on_cpu->rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) fidvid_msr_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) init_on_cpu->rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) #define MISSING_PSS_MSG \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) FW_BUG "No compatible ACPI _PSS objects found.\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) FW_BUG "First, make sure Cool'N'Quiet is enabled in the BIOS.\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) FW_BUG "If that doesn't help, try upgrading your BIOS.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /* per CPU init entry point to the driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) static int powernowk8_cpu_init(struct cpufreq_policy *pol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) struct powernow_k8_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct init_on_cpu init_on_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) int rc, cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) data = kzalloc(sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) data->cpu = pol->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (powernow_k8_cpu_init_acpi(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) * Use the PSB BIOS structure. This is only available on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) * an UP version, and is deprecated by AMD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (num_online_cpus() != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) pr_err_once(MISSING_PSS_MSG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (pol->cpu != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) pr_err(FW_BUG "No ACPI _PSS objects for CPU other than CPU0. Complain to your BIOS vendor.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) rc = find_psb_table(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /* Take a crude guess here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * That guess was in microseconds, so multiply with 1000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) pol->cpuinfo.transition_latency = (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) ((data->rvo + 8) * data->vstable * VST_UNITS_20US) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) ((1 << data->irt) * 30)) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) } else /* ACPI _PSS objects available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) pol->cpuinfo.transition_latency = get_transition_latency(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* only run on specific CPU from here on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) init_on_cpu.data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) smp_call_function_single(data->cpu, powernowk8_cpu_init_on_cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) &init_on_cpu, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) rc = init_on_cpu.rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) goto err_out_exit_acpi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) cpumask_copy(pol->cpus, topology_core_cpumask(pol->cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) data->available_cores = pol->cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) pol->freq_table = data->powernow_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) data->currfid, data->currvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* Point all the CPUs in this policy to the same data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) for_each_cpu(cpu, pol->cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) per_cpu(powernow_data, cpu) = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) err_out_exit_acpi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) powernow_k8_cpu_exit_acpi(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) powernow_k8_cpu_exit_acpi(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) kfree(data->powernow_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) for_each_cpu(cpu, pol->cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) per_cpu(powernow_data, cpu) = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) static void query_values_on_cpu(void *_err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) int *err = _err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) struct powernow_k8_data *data = __this_cpu_read(powernow_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) *err = query_current_values_with_pending_wait(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static unsigned int powernowk8_get(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct powernow_k8_data *data = per_cpu(powernow_data, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) unsigned int khz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) smp_call_function_single(cpu, query_values_on_cpu, &err, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) khz = find_khz_freq_from_fid(data->currfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) static struct cpufreq_driver cpufreq_amd64_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) .flags = CPUFREQ_ASYNC_NOTIFICATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) .verify = cpufreq_generic_frequency_table_verify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) .target_index = powernowk8_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) .bios_limit = acpi_processor_get_bios_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) .init = powernowk8_cpu_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) .exit = powernowk8_cpu_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) .get = powernowk8_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) .name = "powernow-k8",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) .attr = cpufreq_generic_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) static void __request_acpi_cpufreq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) const char drv[] = "acpi-cpufreq";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) const char *cur_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) cur_drv = cpufreq_get_current_driver();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (!cur_drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) goto request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (strncmp(cur_drv, drv, min_t(size_t, strlen(cur_drv), strlen(drv))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) pr_warn("WTF driver: %s\n", cur_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) request:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) pr_warn("This CPU is not supported anymore, using acpi-cpufreq instead.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) request_module(drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /* driver entry point for init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) static int powernowk8_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) unsigned int i, supported_cpus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (boot_cpu_has(X86_FEATURE_HW_PSTATE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) __request_acpi_cpufreq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (!x86_match_cpu(powernow_k8_ids))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) for_each_online_cpu(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) smp_call_function_single(i, check_supported_cpu, &ret, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) supported_cpus++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (supported_cpus != num_online_cpus()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) ret = cpufreq_register_driver(&cpufreq_amd64_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) pr_info("Found %d %s (%d cpu cores) (" VERSION ")\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) num_online_nodes(), boot_cpu_data.x86_model_id, supported_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) /* driver entry point for term */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) static void __exit powernowk8_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) pr_debug("exit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) cpufreq_unregister_driver(&cpufreq_amd64_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) MODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@amd.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) late_initcall(powernowk8_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) module_exit(powernowk8_exit);