162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Intel SpeedStep SMI driver. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (C) 2003 Hiroshi Miura <miura@da-cha.org> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/********************************************************************* 1062306a36Sopenharmony_ci * SPEEDSTEP - DEFINITIONS * 1162306a36Sopenharmony_ci *********************************************************************/ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define pr_fmt(fmt) "cpufreq: " fmt 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/moduleparam.h> 1862306a36Sopenharmony_ci#include <linux/init.h> 1962306a36Sopenharmony_ci#include <linux/cpufreq.h> 2062306a36Sopenharmony_ci#include <linux/delay.h> 2162306a36Sopenharmony_ci#include <linux/io.h> 2262306a36Sopenharmony_ci#include <asm/ist.h> 2362306a36Sopenharmony_ci#include <asm/cpu_device_id.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "speedstep-lib.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* speedstep system management interface port/command. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * These parameters are got from IST-SMI BIOS call. 3062306a36Sopenharmony_ci * If user gives it, these are used. 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_cistatic int smi_port; 3462306a36Sopenharmony_cistatic int smi_cmd; 3562306a36Sopenharmony_cistatic unsigned int smi_sig; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* info about the processor */ 3862306a36Sopenharmony_cistatic enum speedstep_processor speedstep_processor; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci * There are only two frequency states for each processor. Values 4262306a36Sopenharmony_ci * are in kHz for the time being. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_cistatic struct cpufreq_frequency_table speedstep_freqs[] = { 4562306a36Sopenharmony_ci {0, SPEEDSTEP_HIGH, 0}, 4662306a36Sopenharmony_ci {0, SPEEDSTEP_LOW, 0}, 4762306a36Sopenharmony_ci {0, 0, CPUFREQ_TABLE_END}, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define GET_SPEEDSTEP_OWNER 0 5162306a36Sopenharmony_ci#define GET_SPEEDSTEP_STATE 1 5262306a36Sopenharmony_ci#define SET_SPEEDSTEP_STATE 2 5362306a36Sopenharmony_ci#define GET_SPEEDSTEP_FREQS 4 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* how often shall the SMI call be tried if it failed, e.g. because 5662306a36Sopenharmony_ci * of DMA activity going on? */ 5762306a36Sopenharmony_ci#define SMI_TRIES 5 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/** 6062306a36Sopenharmony_ci * speedstep_smi_ownership 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_cistatic int speedstep_smi_ownership(void) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci u32 command, result, magic, dummy; 6562306a36Sopenharmony_ci u32 function = GET_SPEEDSTEP_OWNER; 6662306a36Sopenharmony_ci unsigned char magic_data[] = "Copyright (c) 1999 Intel Corporation"; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); 6962306a36Sopenharmony_ci magic = virt_to_phys(magic_data); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci pr_debug("trying to obtain ownership with command %x at port %x\n", 7262306a36Sopenharmony_ci command, smi_port); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci __asm__ __volatile__( 7562306a36Sopenharmony_ci "push %%ebp\n" 7662306a36Sopenharmony_ci "out %%al, (%%dx)\n" 7762306a36Sopenharmony_ci "pop %%ebp\n" 7862306a36Sopenharmony_ci : "=D" (result), 7962306a36Sopenharmony_ci "=a" (dummy), "=b" (dummy), "=c" (dummy), "=d" (dummy), 8062306a36Sopenharmony_ci "=S" (dummy) 8162306a36Sopenharmony_ci : "a" (command), "b" (function), "c" (0), "d" (smi_port), 8262306a36Sopenharmony_ci "D" (0), "S" (magic) 8362306a36Sopenharmony_ci : "memory" 8462306a36Sopenharmony_ci ); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci pr_debug("result is %x\n", result); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return result; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/** 9262306a36Sopenharmony_ci * speedstep_smi_get_freqs - get SpeedStep preferred & current freq. 9362306a36Sopenharmony_ci * @low: the low frequency value is placed here 9462306a36Sopenharmony_ci * @high: the high frequency value is placed here 9562306a36Sopenharmony_ci * 9662306a36Sopenharmony_ci * Only available on later SpeedStep-enabled systems, returns false results or 9762306a36Sopenharmony_ci * even hangs [cf. bugme.osdl.org # 1422] on earlier systems. Empirical testing 9862306a36Sopenharmony_ci * shows that the latter occurs if !(ist_info.event & 0xFFFF). 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_cistatic int speedstep_smi_get_freqs(unsigned int *low, unsigned int *high) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci u32 command, result = 0, edi, high_mhz, low_mhz, dummy; 10362306a36Sopenharmony_ci u32 state = 0; 10462306a36Sopenharmony_ci u32 function = GET_SPEEDSTEP_FREQS; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci if (!(ist_info.event & 0xFFFF)) { 10762306a36Sopenharmony_ci pr_debug("bug #1422 -- can't read freqs from BIOS\n"); 10862306a36Sopenharmony_ci return -ENODEV; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci pr_debug("trying to determine frequencies with command %x at port %x\n", 11462306a36Sopenharmony_ci command, smi_port); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci __asm__ __volatile__( 11762306a36Sopenharmony_ci "push %%ebp\n" 11862306a36Sopenharmony_ci "out %%al, (%%dx)\n" 11962306a36Sopenharmony_ci "pop %%ebp" 12062306a36Sopenharmony_ci : "=a" (result), 12162306a36Sopenharmony_ci "=b" (high_mhz), 12262306a36Sopenharmony_ci "=c" (low_mhz), 12362306a36Sopenharmony_ci "=d" (state), "=D" (edi), "=S" (dummy) 12462306a36Sopenharmony_ci : "a" (command), 12562306a36Sopenharmony_ci "b" (function), 12662306a36Sopenharmony_ci "c" (state), 12762306a36Sopenharmony_ci "d" (smi_port), "S" (0), "D" (0) 12862306a36Sopenharmony_ci ); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci pr_debug("result %x, low_freq %u, high_freq %u\n", 13162306a36Sopenharmony_ci result, low_mhz, high_mhz); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* abort if results are obviously incorrect... */ 13462306a36Sopenharmony_ci if ((high_mhz + low_mhz) < 600) 13562306a36Sopenharmony_ci return -EINVAL; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci *high = high_mhz * 1000; 13862306a36Sopenharmony_ci *low = low_mhz * 1000; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return result; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/** 14462306a36Sopenharmony_ci * speedstep_set_state - set the SpeedStep state 14562306a36Sopenharmony_ci * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci */ 14862306a36Sopenharmony_cistatic void speedstep_set_state(unsigned int state) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci unsigned int result = 0, command, new_state, dummy; 15162306a36Sopenharmony_ci unsigned long flags; 15262306a36Sopenharmony_ci unsigned int function = SET_SPEEDSTEP_STATE; 15362306a36Sopenharmony_ci unsigned int retry = 0; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (state > 0x1) 15662306a36Sopenharmony_ci return; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* Disable IRQs */ 15962306a36Sopenharmony_ci preempt_disable(); 16062306a36Sopenharmony_ci local_irq_save(flags); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci pr_debug("trying to set frequency to state %u " 16562306a36Sopenharmony_ci "with command %x at port %x\n", 16662306a36Sopenharmony_ci state, command, smi_port); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci do { 16962306a36Sopenharmony_ci if (retry) { 17062306a36Sopenharmony_ci /* 17162306a36Sopenharmony_ci * We need to enable interrupts, otherwise the blockage 17262306a36Sopenharmony_ci * won't resolve. 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * We disable preemption so that other processes don't 17562306a36Sopenharmony_ci * run. If other processes were running, they could 17662306a36Sopenharmony_ci * submit more DMA requests, making the blockage worse. 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_ci pr_debug("retry %u, previous result %u, waiting...\n", 17962306a36Sopenharmony_ci retry, result); 18062306a36Sopenharmony_ci local_irq_enable(); 18162306a36Sopenharmony_ci mdelay(retry * 50); 18262306a36Sopenharmony_ci local_irq_disable(); 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci retry++; 18562306a36Sopenharmony_ci __asm__ __volatile__( 18662306a36Sopenharmony_ci "push %%ebp\n" 18762306a36Sopenharmony_ci "out %%al, (%%dx)\n" 18862306a36Sopenharmony_ci "pop %%ebp" 18962306a36Sopenharmony_ci : "=b" (new_state), "=D" (result), 19062306a36Sopenharmony_ci "=c" (dummy), "=a" (dummy), 19162306a36Sopenharmony_ci "=d" (dummy), "=S" (dummy) 19262306a36Sopenharmony_ci : "a" (command), "b" (function), "c" (state), 19362306a36Sopenharmony_ci "d" (smi_port), "S" (0), "D" (0) 19462306a36Sopenharmony_ci ); 19562306a36Sopenharmony_ci } while ((new_state != state) && (retry <= SMI_TRIES)); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* enable IRQs */ 19862306a36Sopenharmony_ci local_irq_restore(flags); 19962306a36Sopenharmony_ci preempt_enable(); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (new_state == state) 20262306a36Sopenharmony_ci pr_debug("change to %u MHz succeeded after %u tries " 20362306a36Sopenharmony_ci "with result %u\n", 20462306a36Sopenharmony_ci (speedstep_freqs[new_state].frequency / 1000), 20562306a36Sopenharmony_ci retry, result); 20662306a36Sopenharmony_ci else 20762306a36Sopenharmony_ci pr_err("change to state %u failed with new_state %u and result %u\n", 20862306a36Sopenharmony_ci state, new_state, result); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci return; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci/** 21562306a36Sopenharmony_ci * speedstep_target - set a new CPUFreq policy 21662306a36Sopenharmony_ci * @policy: new policy 21762306a36Sopenharmony_ci * @index: index of new freq 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * Sets a new CPUFreq policy/freq. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_cistatic int speedstep_target(struct cpufreq_policy *policy, unsigned int index) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci speedstep_set_state(index); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic int speedstep_cpu_init(struct cpufreq_policy *policy) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci int result; 23262306a36Sopenharmony_ci unsigned int *low, *high; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* capability check */ 23562306a36Sopenharmony_ci if (policy->cpu != 0) 23662306a36Sopenharmony_ci return -ENODEV; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci result = speedstep_smi_ownership(); 23962306a36Sopenharmony_ci if (result) { 24062306a36Sopenharmony_ci pr_debug("fails in acquiring ownership of a SMI interface.\n"); 24162306a36Sopenharmony_ci return -EINVAL; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* detect low and high frequency */ 24562306a36Sopenharmony_ci low = &speedstep_freqs[SPEEDSTEP_LOW].frequency; 24662306a36Sopenharmony_ci high = &speedstep_freqs[SPEEDSTEP_HIGH].frequency; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci result = speedstep_smi_get_freqs(low, high); 24962306a36Sopenharmony_ci if (result) { 25062306a36Sopenharmony_ci /* fall back to speedstep_lib.c dection mechanism: 25162306a36Sopenharmony_ci * try both states out */ 25262306a36Sopenharmony_ci pr_debug("could not detect low and high frequencies " 25362306a36Sopenharmony_ci "by SMI call.\n"); 25462306a36Sopenharmony_ci result = speedstep_get_freqs(speedstep_processor, 25562306a36Sopenharmony_ci low, high, 25662306a36Sopenharmony_ci NULL, 25762306a36Sopenharmony_ci &speedstep_set_state); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (result) { 26062306a36Sopenharmony_ci pr_debug("could not detect two different speeds" 26162306a36Sopenharmony_ci " -- aborting.\n"); 26262306a36Sopenharmony_ci return result; 26362306a36Sopenharmony_ci } else 26462306a36Sopenharmony_ci pr_debug("workaround worked.\n"); 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci policy->freq_table = speedstep_freqs; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return 0; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic unsigned int speedstep_get(unsigned int cpu) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci if (cpu) 27562306a36Sopenharmony_ci return -ENODEV; 27662306a36Sopenharmony_ci return speedstep_get_frequency(speedstep_processor); 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic int speedstep_resume(struct cpufreq_policy *policy) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci int result = speedstep_smi_ownership(); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (result) 28562306a36Sopenharmony_ci pr_debug("fails in re-acquiring ownership of a SMI interface.\n"); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci return result; 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic struct cpufreq_driver speedstep_driver = { 29162306a36Sopenharmony_ci .name = "speedstep-smi", 29262306a36Sopenharmony_ci .flags = CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING, 29362306a36Sopenharmony_ci .verify = cpufreq_generic_frequency_table_verify, 29462306a36Sopenharmony_ci .target_index = speedstep_target, 29562306a36Sopenharmony_ci .init = speedstep_cpu_init, 29662306a36Sopenharmony_ci .get = speedstep_get, 29762306a36Sopenharmony_ci .resume = speedstep_resume, 29862306a36Sopenharmony_ci .attr = cpufreq_generic_attr, 29962306a36Sopenharmony_ci}; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic const struct x86_cpu_id ss_smi_ids[] = { 30262306a36Sopenharmony_ci X86_MATCH_VENDOR_FAM_MODEL(INTEL, 6, 0x8, 0), 30362306a36Sopenharmony_ci X86_MATCH_VENDOR_FAM_MODEL(INTEL, 6, 0xb, 0), 30462306a36Sopenharmony_ci X86_MATCH_VENDOR_FAM_MODEL(INTEL, 15, 0x2, 0), 30562306a36Sopenharmony_ci {} 30662306a36Sopenharmony_ci}; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/** 30962306a36Sopenharmony_ci * speedstep_init - initializes the SpeedStep CPUFreq driver 31062306a36Sopenharmony_ci * 31162306a36Sopenharmony_ci * Initializes the SpeedStep support. Returns -ENODEV on unsupported 31262306a36Sopenharmony_ci * BIOS, -EINVAL on problems during initiatization, and zero on 31362306a36Sopenharmony_ci * success. 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_cistatic int __init speedstep_init(void) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci if (!x86_match_cpu(ss_smi_ids)) 31862306a36Sopenharmony_ci return -ENODEV; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci speedstep_processor = speedstep_detect_processor(); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci switch (speedstep_processor) { 32362306a36Sopenharmony_ci case SPEEDSTEP_CPU_PIII_T: 32462306a36Sopenharmony_ci case SPEEDSTEP_CPU_PIII_C: 32562306a36Sopenharmony_ci case SPEEDSTEP_CPU_PIII_C_EARLY: 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci default: 32862306a36Sopenharmony_ci speedstep_processor = 0; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (!speedstep_processor) { 33262306a36Sopenharmony_ci pr_debug("No supported Intel CPU detected.\n"); 33362306a36Sopenharmony_ci return -ENODEV; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci pr_debug("signature:0x%.8x, command:0x%.8x, " 33762306a36Sopenharmony_ci "event:0x%.8x, perf_level:0x%.8x.\n", 33862306a36Sopenharmony_ci ist_info.signature, ist_info.command, 33962306a36Sopenharmony_ci ist_info.event, ist_info.perf_level); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* Error if no IST-SMI BIOS or no PARM 34262306a36Sopenharmony_ci sig= 'ISGE' aka 'Intel Speedstep Gate E' */ 34362306a36Sopenharmony_ci if ((ist_info.signature != 0x47534943) && ( 34462306a36Sopenharmony_ci (smi_port == 0) || (smi_cmd == 0))) 34562306a36Sopenharmony_ci return -ENODEV; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci if (smi_sig == 1) 34862306a36Sopenharmony_ci smi_sig = 0x47534943; 34962306a36Sopenharmony_ci else 35062306a36Sopenharmony_ci smi_sig = ist_info.signature; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* setup smi_port from MODLULE_PARM or BIOS */ 35362306a36Sopenharmony_ci if ((smi_port > 0xff) || (smi_port < 0)) 35462306a36Sopenharmony_ci return -EINVAL; 35562306a36Sopenharmony_ci else if (smi_port == 0) 35662306a36Sopenharmony_ci smi_port = ist_info.command & 0xff; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if ((smi_cmd > 0xff) || (smi_cmd < 0)) 35962306a36Sopenharmony_ci return -EINVAL; 36062306a36Sopenharmony_ci else if (smi_cmd == 0) 36162306a36Sopenharmony_ci smi_cmd = (ist_info.command >> 16) & 0xff; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return cpufreq_register_driver(&speedstep_driver); 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/** 36862306a36Sopenharmony_ci * speedstep_exit - unregisters SpeedStep support 36962306a36Sopenharmony_ci * 37062306a36Sopenharmony_ci * Unregisters SpeedStep support. 37162306a36Sopenharmony_ci */ 37262306a36Sopenharmony_cistatic void __exit speedstep_exit(void) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci cpufreq_unregister_driver(&speedstep_driver); 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cimodule_param_hw(smi_port, int, ioport, 0444); 37862306a36Sopenharmony_cimodule_param(smi_cmd, int, 0444); 37962306a36Sopenharmony_cimodule_param(smi_sig, uint, 0444); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ciMODULE_PARM_DESC(smi_port, "Override the BIOS-given IST port with this value " 38262306a36Sopenharmony_ci "-- Intel's default setting is 0xb2"); 38362306a36Sopenharmony_ciMODULE_PARM_DESC(smi_cmd, "Override the BIOS-given IST command with this value " 38462306a36Sopenharmony_ci "-- Intel's default setting is 0x82"); 38562306a36Sopenharmony_ciMODULE_PARM_DESC(smi_sig, "Set to 1 to fake the IST signature when using the " 38662306a36Sopenharmony_ci "SMI interface."); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ciMODULE_AUTHOR("Hiroshi Miura"); 38962306a36Sopenharmony_ciMODULE_DESCRIPTION("Speedstep driver for IST applet SMI interface."); 39062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cimodule_init(speedstep_init); 39362306a36Sopenharmony_cimodule_exit(speedstep_exit); 394